/* * Copyright (C) 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "WebPluginSiteDataManager.h" #include "ImmutableArray.h" #include "PluginProcessManager.h" #include "WebContext.h" #include "WebProcessMessages.h" using namespace WebCore; namespace WebKit { #if ENABLE(PLUGIN_PROCESS) class WebPluginSiteDataManager::GetSitesWithDataState { public: explicit GetSitesWithDataState(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID) : m_webPluginSiteDataManager(webPluginSiteDataManager) , m_callbackID(callbackID) , m_plugins(webPluginSiteDataManager->m_webContext->pluginInfoStore()->plugins()) { } void getSitesWithDataForNextPlugin() { if (m_plugins.isEmpty()) { Vector sites; copyToVector(m_sites, sites); m_webPluginSiteDataManager->didGetSitesWithDataForAllPlugins(sites, m_callbackID); return; } PluginProcessManager::shared().getSitesWithData(m_plugins.last(), m_webPluginSiteDataManager, m_callbackID); m_plugins.removeLast(); } void didGetSitesWithDataForSinglePlugin(const Vector& sites) { for (size_t i = 0; i < sites.size(); ++i) m_sites.add(sites[i]); getSitesWithDataForNextPlugin(); } private: WebPluginSiteDataManager* m_webPluginSiteDataManager; uint64_t m_callbackID; Vector m_plugins; HashSet m_sites; }; class WebPluginSiteDataManager::ClearSiteDataState { public: explicit ClearSiteDataState(WebPluginSiteDataManager* webPluginSiteDataManager, const Vector& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID) : m_webPluginSiteDataManager(webPluginSiteDataManager) , m_sites(sites) , m_flags(flags) , m_maxAgeInSeconds(maxAgeInSeconds) , m_callbackID(callbackID) , m_plugins(webPluginSiteDataManager->m_webContext->pluginInfoStore()->plugins()) { } void clearSiteDataForNextPlugin() { if (m_plugins.isEmpty()) { m_webPluginSiteDataManager->didClearSiteDataForAllPlugins(m_callbackID); return; } PluginProcessManager::shared().clearSiteData(m_plugins.last(), m_webPluginSiteDataManager, m_sites, m_flags, m_maxAgeInSeconds, m_callbackID); m_plugins.removeLast(); } void didClearSiteDataForSinglePlugin() { clearSiteDataForNextPlugin(); } private: WebPluginSiteDataManager* m_webPluginSiteDataManager; Vector m_sites; uint64_t m_flags; uint64_t m_maxAgeInSeconds; uint64_t m_callbackID; Vector m_plugins; }; #endif // ENABLE(PLUGIN_PROCESS) PassRefPtr WebPluginSiteDataManager::create(WebContext* webContext) { return adoptRef(new WebPluginSiteDataManager(webContext)); } WebPluginSiteDataManager::WebPluginSiteDataManager(WebContext* webContext) : m_webContext(webContext) { } WebPluginSiteDataManager::~WebPluginSiteDataManager() { ASSERT(m_arrayCallbacks.isEmpty()); ASSERT(m_voidCallbacks.isEmpty()); #if ENABLE(PLUGIN_PROCESS) ASSERT(m_pendingGetSitesWithData.isEmpty()); ASSERT(m_pendingClearSiteData.isEmpty()); #endif } void WebPluginSiteDataManager::invalidate() { invalidateCallbackMap(m_arrayCallbacks); #if ENABLE(PLUGIN_PROCESS) deleteAllValues(m_pendingGetSitesWithData); m_pendingGetSitesWithData.clear(); deleteAllValues(m_pendingClearSiteData); m_pendingClearSiteData.clear(); #endif } void WebPluginSiteDataManager::getSitesWithData(PassRefPtr prpCallback) { RefPtr callback = prpCallback; if (!m_webContext) { callback->invalidate(); return; } uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); #if ENABLE(PLUGIN_PROCESS) ASSERT(!m_pendingGetSitesWithData.contains(callbackID)); GetSitesWithDataState* state = new GetSitesWithDataState(this, callbackID); m_pendingGetSitesWithData.set(callbackID, state); state->getSitesWithDataForNextPlugin(); #else m_webContext->relaunchProcessIfNecessary(); Vector pluginPaths; m_webContext->pluginInfoStore()->getPluginPaths(pluginPaths); m_webContext->ensureWebProcess(); m_webContext->process()->send(Messages::WebProcess::GetSitesWithPluginData(pluginPaths, callbackID), 0); #endif } void WebPluginSiteDataManager::didGetSitesWithData(const Vector& sites, uint64_t callbackID) { RefPtr callback = m_arrayCallbacks.take(callbackID); if (!callback) { // FIXME: Log error or assert. return; } Vector > sitesWK(sites.size()); for (size_t i = 0; i < sites.size(); ++i) sitesWK[i] = WebString::create(sites[i]); RefPtr resultArray = ImmutableArray::adopt(sitesWK); callback->performCallbackWithReturnValue(resultArray.get()); } void WebPluginSiteDataManager::clearSiteData(ImmutableArray* sites, uint64_t flags, uint64_t maxAgeInSeconds, PassRefPtr prpCallback) { RefPtr callback = prpCallback; if (!m_webContext) { callback->invalidate(); return; } Vector sitesVector; // If the array is empty, don't do anything. if (sites) { if (!sites->size()) { callback->performCallback(); return; } for (size_t i = 0; i < sites->size(); ++i) { if (WebString* site = sites->at(i)) sitesVector.append(site->string()); } } uint64_t callbackID = callback->callbackID(); m_voidCallbacks.set(callbackID, callback.release()); #if ENABLE(PLUGIN_PROCESS) ASSERT(!m_pendingClearSiteData.contains(callbackID)); ClearSiteDataState* state = new ClearSiteDataState(this, sitesVector, flags, maxAgeInSeconds, callbackID); m_pendingClearSiteData.set(callbackID, state); state->clearSiteDataForNextPlugin(); #else m_webContext->relaunchProcessIfNecessary(); Vector pluginPaths; m_webContext->pluginInfoStore()->getPluginPaths(pluginPaths); m_webContext->ensureWebProcess(); m_webContext->process()->send(Messages::WebProcess::ClearPluginSiteData(pluginPaths, sitesVector, flags, maxAgeInSeconds, callbackID), 0); #endif } void WebPluginSiteDataManager::didClearSiteData(uint64_t callbackID) { RefPtr callback = m_voidCallbacks.take(callbackID); if (!callback) { // FIXME: Log error or assert. return; } callback->performCallback(); } bool WebPluginSiteDataManager::shouldTerminate(WebProcessProxy*) const { #if ENABLE(PLUGIN_PROCESS) // When out of process plug-ins are enabled, the web process is not involved in fetching site data. return true; #else return m_arrayCallbacks.isEmpty() && m_voidCallbacks.isEmpty(); #endif } #if ENABLE(PLUGIN_PROCESS) void WebPluginSiteDataManager::didGetSitesWithDataForSinglePlugin(const Vector& sites, uint64_t callbackID) { GetSitesWithDataState* state = m_pendingGetSitesWithData.get(callbackID); ASSERT(state); state->didGetSitesWithDataForSinglePlugin(sites); } void WebPluginSiteDataManager::didGetSitesWithDataForAllPlugins(const Vector& sites, uint64_t callbackID) { OwnPtr state = adoptPtr(m_pendingGetSitesWithData.take(callbackID)); ASSERT(state); didGetSitesWithData(sites, callbackID); } void WebPluginSiteDataManager::didClearSiteDataForSinglePlugin(uint64_t callbackID) { ClearSiteDataState* state = m_pendingClearSiteData.get(callbackID); ASSERT(state); state->didClearSiteDataForSinglePlugin(); } void WebPluginSiteDataManager::didClearSiteDataForAllPlugins(uint64_t callbackID) { OwnPtr state = adoptPtr(m_pendingClearSiteData.take(callbackID)); ASSERT(state); didClearSiteData(callbackID); } #endif } // namespace WebKit