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