Home | History | Annotate | Download | only in Plugins
      1 /*
      2  * Copyright (C) 2011 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "WebPluginSiteDataManager.h"
     28 
     29 #include "ImmutableArray.h"
     30 #include "PluginProcessManager.h"
     31 #include "WebContext.h"
     32 #include "WebProcessMessages.h"
     33 
     34 using namespace WebCore;
     35 
     36 namespace WebKit {
     37 
     38 #if ENABLE(PLUGIN_PROCESS)
     39 class WebPluginSiteDataManager::GetSitesWithDataState {
     40 public:
     41     explicit GetSitesWithDataState(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID)
     42         : m_webPluginSiteDataManager(webPluginSiteDataManager)
     43         , m_callbackID(callbackID)
     44         , m_plugins(webPluginSiteDataManager->m_webContext->pluginInfoStore()->plugins())
     45     {
     46     }
     47 
     48     void getSitesWithDataForNextPlugin()
     49     {
     50         if (m_plugins.isEmpty()) {
     51             Vector<String> sites;
     52             copyToVector(m_sites, sites);
     53 
     54             m_webPluginSiteDataManager->didGetSitesWithDataForAllPlugins(sites, m_callbackID);
     55             return;
     56         }
     57 
     58         PluginProcessManager::shared().getSitesWithData(m_plugins.last(), m_webPluginSiteDataManager, m_callbackID);
     59         m_plugins.removeLast();
     60     }
     61 
     62     void didGetSitesWithDataForSinglePlugin(const Vector<String>& sites)
     63     {
     64         for (size_t i = 0; i < sites.size(); ++i)
     65             m_sites.add(sites[i]);
     66 
     67         getSitesWithDataForNextPlugin();
     68     }
     69 
     70 private:
     71     WebPluginSiteDataManager* m_webPluginSiteDataManager;
     72     uint64_t m_callbackID;
     73     Vector<PluginInfoStore::Plugin> m_plugins;
     74     HashSet<String> m_sites;
     75 };
     76 
     77 class WebPluginSiteDataManager::ClearSiteDataState {
     78 public:
     79     explicit ClearSiteDataState(WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
     80         : m_webPluginSiteDataManager(webPluginSiteDataManager)
     81         , m_sites(sites)
     82         , m_flags(flags)
     83         , m_maxAgeInSeconds(maxAgeInSeconds)
     84         , m_callbackID(callbackID)
     85         , m_plugins(webPluginSiteDataManager->m_webContext->pluginInfoStore()->plugins())
     86     {
     87     }
     88 
     89     void clearSiteDataForNextPlugin()
     90     {
     91         if (m_plugins.isEmpty()) {
     92             m_webPluginSiteDataManager->didClearSiteDataForAllPlugins(m_callbackID);
     93             return;
     94         }
     95 
     96         PluginProcessManager::shared().clearSiteData(m_plugins.last(), m_webPluginSiteDataManager, m_sites, m_flags, m_maxAgeInSeconds, m_callbackID);
     97         m_plugins.removeLast();
     98     }
     99 
    100     void didClearSiteDataForSinglePlugin()
    101     {
    102         clearSiteDataForNextPlugin();
    103     }
    104 
    105 private:
    106     WebPluginSiteDataManager* m_webPluginSiteDataManager;
    107     Vector<String> m_sites;
    108     uint64_t m_flags;
    109     uint64_t m_maxAgeInSeconds;
    110     uint64_t m_callbackID;
    111     Vector<PluginInfoStore::Plugin> m_plugins;
    112 };
    113 #endif // ENABLE(PLUGIN_PROCESS)
    114 
    115 PassRefPtr<WebPluginSiteDataManager> WebPluginSiteDataManager::create(WebContext* webContext)
    116 {
    117     return adoptRef(new WebPluginSiteDataManager(webContext));
    118 }
    119 
    120 WebPluginSiteDataManager::WebPluginSiteDataManager(WebContext* webContext)
    121     : m_webContext(webContext)
    122 {
    123 }
    124 
    125 WebPluginSiteDataManager::~WebPluginSiteDataManager()
    126 {
    127     ASSERT(m_arrayCallbacks.isEmpty());
    128     ASSERT(m_voidCallbacks.isEmpty());
    129 #if ENABLE(PLUGIN_PROCESS)
    130     ASSERT(m_pendingGetSitesWithData.isEmpty());
    131     ASSERT(m_pendingClearSiteData.isEmpty());
    132 #endif
    133 }
    134 
    135 void WebPluginSiteDataManager::invalidate()
    136 {
    137     invalidateCallbackMap(m_arrayCallbacks);
    138 
    139 #if ENABLE(PLUGIN_PROCESS)
    140     deleteAllValues(m_pendingGetSitesWithData);
    141     m_pendingGetSitesWithData.clear();
    142     deleteAllValues(m_pendingClearSiteData);
    143     m_pendingClearSiteData.clear();
    144 #endif
    145 }
    146 
    147 void WebPluginSiteDataManager::getSitesWithData(PassRefPtr<ArrayCallback> prpCallback)
    148 {
    149     RefPtr<ArrayCallback> callback = prpCallback;
    150 
    151     if (!m_webContext) {
    152         callback->invalidate();
    153         return;
    154     }
    155 
    156     uint64_t callbackID = callback->callbackID();
    157     m_arrayCallbacks.set(callbackID, callback.release());
    158 
    159 #if ENABLE(PLUGIN_PROCESS)
    160     ASSERT(!m_pendingGetSitesWithData.contains(callbackID));
    161 
    162     GetSitesWithDataState* state = new GetSitesWithDataState(this, callbackID);
    163     m_pendingGetSitesWithData.set(callbackID, state);
    164     state->getSitesWithDataForNextPlugin();
    165 #else
    166     m_webContext->relaunchProcessIfNecessary();
    167 
    168     Vector<String> pluginPaths;
    169     m_webContext->pluginInfoStore()->getPluginPaths(pluginPaths);
    170 
    171     // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this,
    172     // so this code should just be removed.
    173     m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::GetSitesWithPluginData(pluginPaths, callbackID));
    174 #endif
    175 }
    176 
    177 void WebPluginSiteDataManager::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID)
    178 {
    179     RefPtr<ArrayCallback> callback = m_arrayCallbacks.take(callbackID);
    180     if (!callback) {
    181         // FIXME: Log error or assert.
    182         return;
    183     }
    184 
    185     Vector<RefPtr<APIObject> > sitesWK(sites.size());
    186 
    187     for (size_t i = 0; i < sites.size(); ++i)
    188         sitesWK[i] = WebString::create(sites[i]);
    189 
    190     RefPtr<ImmutableArray> resultArray = ImmutableArray::adopt(sitesWK);
    191     callback->performCallbackWithReturnValue(resultArray.get());
    192 }
    193 
    194 void WebPluginSiteDataManager::clearSiteData(ImmutableArray* sites, uint64_t flags, uint64_t maxAgeInSeconds, PassRefPtr<VoidCallback> prpCallback)
    195 {
    196     RefPtr<VoidCallback> callback = prpCallback;
    197     if (!m_webContext) {
    198         callback->invalidate();
    199         return;
    200     }
    201 
    202     Vector<String> sitesVector;
    203 
    204     // If the array is empty, don't do anything.
    205     if (sites) {
    206         if (!sites->size()) {
    207             callback->performCallback();
    208             return;
    209         }
    210 
    211         for (size_t i = 0; i < sites->size(); ++i) {
    212             if (WebString* site = sites->at<WebString>(i))
    213                 sitesVector.append(site->string());
    214         }
    215     }
    216 
    217     uint64_t callbackID = callback->callbackID();
    218     m_voidCallbacks.set(callbackID, callback.release());
    219 
    220 #if ENABLE(PLUGIN_PROCESS)
    221     ASSERT(!m_pendingClearSiteData.contains(callbackID));
    222 
    223     ClearSiteDataState* state = new ClearSiteDataState(this, sitesVector, flags, maxAgeInSeconds, callbackID);
    224     m_pendingClearSiteData.set(callbackID, state);
    225     state->clearSiteDataForNextPlugin();
    226 #else
    227 
    228     m_webContext->relaunchProcessIfNecessary();
    229     Vector<String> pluginPaths;
    230     m_webContext->pluginInfoStore()->getPluginPaths(pluginPaths);
    231 
    232     // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this,
    233     // so this code should just be removed.
    234     m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::ClearPluginSiteData(pluginPaths, sitesVector, flags, maxAgeInSeconds, callbackID));
    235 #endif
    236 }
    237 
    238 void WebPluginSiteDataManager::didClearSiteData(uint64_t callbackID)
    239 {
    240     RefPtr<VoidCallback> callback = m_voidCallbacks.take(callbackID);
    241     if (!callback) {
    242         // FIXME: Log error or assert.
    243         return;
    244     }
    245 
    246     callback->performCallback();
    247 }
    248 
    249 bool WebPluginSiteDataManager::shouldTerminate(WebProcessProxy*) const
    250 {
    251 #if ENABLE(PLUGIN_PROCESS)
    252     // When out of process plug-ins are enabled, the web process is not involved in fetching site data.
    253     return true;
    254 #else
    255     return m_arrayCallbacks.isEmpty() && m_voidCallbacks.isEmpty();
    256 #endif
    257 }
    258 
    259 #if ENABLE(PLUGIN_PROCESS)
    260 void WebPluginSiteDataManager::didGetSitesWithDataForSinglePlugin(const Vector<String>& sites, uint64_t callbackID)
    261 {
    262     GetSitesWithDataState* state = m_pendingGetSitesWithData.get(callbackID);
    263     ASSERT(state);
    264 
    265     state->didGetSitesWithDataForSinglePlugin(sites);
    266 }
    267 
    268 void WebPluginSiteDataManager::didGetSitesWithDataForAllPlugins(const Vector<String>& sites, uint64_t callbackID)
    269 {
    270     OwnPtr<GetSitesWithDataState> state = adoptPtr(m_pendingGetSitesWithData.take(callbackID));
    271     ASSERT(state);
    272 
    273     didGetSitesWithData(sites, callbackID);
    274 }
    275 
    276 void WebPluginSiteDataManager::didClearSiteDataForSinglePlugin(uint64_t callbackID)
    277 {
    278     ClearSiteDataState* state = m_pendingClearSiteData.get(callbackID);
    279     ASSERT(state);
    280 
    281     state->didClearSiteDataForSinglePlugin();
    282 }
    283 
    284 void WebPluginSiteDataManager::didClearSiteDataForAllPlugins(uint64_t callbackID)
    285 {
    286     OwnPtr<ClearSiteDataState> state = adoptPtr(m_pendingClearSiteData.take(callbackID));
    287     ASSERT(state);
    288 
    289     didClearSiteData(callbackID);
    290 }
    291 
    292 #endif
    293 
    294 } // namespace WebKit
    295 
    296