summaryrefslogtreecommitdiff
path: root/Source/WebKit2/UIProcess/WebContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/UIProcess/WebContext.cpp')
-rw-r--r--Source/WebKit2/UIProcess/WebContext.cpp739
1 files changed, 483 insertions, 256 deletions
diff --git a/Source/WebKit2/UIProcess/WebContext.cpp b/Source/WebKit2/UIProcess/WebContext.cpp
index 3f818d1c1..e1ef1021d 100644
--- a/Source/WebKit2/UIProcess/WebContext.cpp
+++ b/Source/WebKit2/UIProcess/WebContext.cpp
@@ -38,28 +38,31 @@
#include "WebApplicationCacheManagerProxy.h"
#include "WebContextMessageKinds.h"
#include "WebContextMessages.h"
+#include "WebContextSupplement.h"
#include "WebContextUserMessageCoders.h"
#include "WebCookieManagerProxy.h"
#include "WebCoreArgumentCoders.h"
#include "WebDatabaseManagerProxy.h"
#include "WebGeolocationManagerProxy.h"
#include "WebIconDatabase.h"
-#include "WebKeyValueStorageManagerProxy.h"
+#include "WebKeyValueStorageManager.h"
#include "WebMediaCacheManagerProxy.h"
#include "WebNotificationManagerProxy.h"
#include "WebPluginSiteDataManager.h"
#include "WebPageGroup.h"
+#include "WebPreferences.h"
#include "WebMemorySampler.h"
#include "WebProcessCreationParameters.h"
#include "WebProcessMessages.h"
#include "WebProcessProxy.h"
#include "WebResourceCacheManagerProxy.h"
+#include <WebCore/InitializeLogging.h>
#include <WebCore/Language.h>
#include <WebCore/LinkHash.h>
-#include <WebCore/Logging.h>
#include <WebCore/ResourceRequest.h>
#include <WebCore/RunLoop.h>
#include <runtime/InitializeThreading.h>
+#include <runtime/Operations.h>
#include <wtf/CurrentTime.h>
#include <wtf/MainThread.h>
@@ -72,7 +75,13 @@
#endif
#if ENABLE(NETWORK_PROCESS)
-#include "NetworkProcessManager.h"
+#include "NetworkProcessCreationParameters.h"
+#include "NetworkProcessMessages.h"
+#include "NetworkProcessProxy.h"
+#endif
+
+#if ENABLE(CUSTOM_PROTOCOLS)
+#include "CustomProtocolManagerMessages.h"
#endif
#if USE(SOUP)
@@ -96,9 +105,6 @@ PassRefPtr<WebContext> WebContext::create(const String& injectedBundlePath)
JSC::initializeThreading();
WTF::initializeMainThread();
RunLoop::initializeMainRunLoop();
-#if PLATFORM(MAC)
- WebContext::initializeProcessSuppressionSupport();
-#endif
return adoptRef(new WebContext(ProcessModelSharedSecondaryProcess, injectedBundlePath));
}
@@ -116,54 +122,62 @@ const Vector<WebContext*>& WebContext::allContexts()
WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePath)
: m_processModel(processModel)
+ , m_webProcessCountLimit(UINT_MAX)
, m_haveInitialEmptyProcess(false)
+ , m_processWithPageCache(0)
, m_defaultPageGroup(WebPageGroup::create())
, m_injectedBundlePath(injectedBundlePath)
, m_visitedLinkProvider(this)
+ , m_plugInAutoStartProvider(this)
, m_alwaysUsesComplexTextCodePath(false)
, m_shouldUseFontSmoothing(true)
, m_cacheModel(CacheModelDocumentViewer)
, m_memorySamplerEnabled(false)
, m_memorySamplerInterval(1400.0)
-#if PLATFORM(WIN)
- , m_shouldPaintNativeControls(true)
- , m_initialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicyAlways)
+ , m_storageManager(StorageManager::create())
+#if USE(SOUP)
+ , m_initialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicyOnlyFromMainDocumentDomain)
#endif
, m_processTerminationEnabled(true)
#if ENABLE(NETWORK_PROCESS)
, m_usesNetworkProcess(false)
#endif
+#if PLATFORM(MAC)
+ , m_processSuppressionEnabled(true)
+#endif
+#if USE(SOUP)
+ , m_ignoreTLSErrors(true)
+#endif
{
+ platformInitialize();
+
addMessageReceiver(Messages::WebContext::messageReceiverName(), this);
- addMessageReceiver(CoreIPC::MessageKindTraits<WebContextLegacyMessage::Kind>::messageReceiverName(), this);
+ addMessageReceiver(WebContextLegacyMessages::messageReceiverName(), this);
// NOTE: These sub-objects must be initialized after m_messageReceiverMap..
- m_applicationCacheManagerProxy = WebApplicationCacheManagerProxy::create(this);
-#if ENABLE(BATTERY_STATUS)
- m_batteryManagerProxy = WebBatteryManagerProxy::create(this);
-#endif
- m_cookieManagerProxy = WebCookieManagerProxy::create(this);
-#if ENABLE(SQL_DATABASE)
- m_databaseManagerProxy = WebDatabaseManagerProxy::create(this);
-#endif
- m_geolocationManagerProxy = WebGeolocationManagerProxy::create(this);
m_iconDatabase = WebIconDatabase::create(this);
- m_keyValueStorageManagerProxy = WebKeyValueStorageManagerProxy::create(this);
- m_mediaCacheManagerProxy = WebMediaCacheManagerProxy::create(this);
-#if ENABLE(NETWORK_INFO)
- m_networkInfoManagerProxy = WebNetworkInfoManagerProxy::create(this);
-#endif
- m_notificationManagerProxy = WebNotificationManagerProxy::create(this);
#if ENABLE(NETSCAPE_PLUGIN_API)
m_pluginSiteDataManager = WebPluginSiteDataManager::create(this);
#endif // ENABLE(NETSCAPE_PLUGIN_API)
- m_resourceCacheManagerProxy = WebResourceCacheManagerProxy::create(this);
+
+ addSupplement<WebApplicationCacheManagerProxy>();
+ addSupplement<WebCookieManagerProxy>();
+ addSupplement<WebGeolocationManagerProxy>();
+ addSupplement<WebKeyValueStorageManager>();
+ addSupplement<WebMediaCacheManagerProxy>();
+ addSupplement<WebNotificationManagerProxy>();
+ addSupplement<WebResourceCacheManagerProxy>();
+#if ENABLE(SQL_DATABASE)
+ addSupplement<WebDatabaseManagerProxy>();
+#endif
#if USE(SOUP)
- m_soupRequestManagerProxy = WebSoupRequestManagerProxy::create(this);
+ addSupplement<WebSoupRequestManagerProxy>();
#endif
-
-#if !LOG_DISABLED
- WebKit::initializeLogChannelsIfNecessary();
+#if ENABLE(BATTERY_STATUS)
+ addSupplement<WebBatteryManagerProxy>();
+#endif
+#if ENABLE(NETWORK_INFO)
+ addSupplement<WebNetworkInfoManagerProxy>();
#endif
contexts().append(this);
@@ -172,13 +186,26 @@ WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePa
#if !LOG_DISABLED
WebCore::initializeLoggingChannelsIfNecessary();
+ WebKit::initializeLogChannelsIfNecessary();
#endif // !LOG_DISABLED
+#if ENABLE(NETSCAPE_PLUGIN_API)
+ m_pluginInfoStore.setClient(this);
+#endif
+
#ifndef NDEBUG
webContextCounter.increment();
#endif
+
+ m_storageManager->setLocalStorageDirectory(localStorageDirectory());
}
+#if !PLATFORM(MAC)
+void WebContext::platformInitialize()
+{
+}
+#endif
+
WebContext::~WebContext()
{
ASSERT(contexts().find(this) != notFound);
@@ -188,64 +215,39 @@ WebContext::~WebContext()
m_messageReceiverMap.invalidate();
- m_applicationCacheManagerProxy->invalidate();
- m_applicationCacheManagerProxy->clearContext();
-
-#if ENABLE(BATTERY_STATUS)
- m_batteryManagerProxy->invalidate();
- m_batteryManagerProxy->clearContext();
-#endif
-
- m_cookieManagerProxy->invalidate();
- m_cookieManagerProxy->clearContext();
-
-#if ENABLE(SQL_DATABASE)
- m_databaseManagerProxy->invalidate();
- m_databaseManagerProxy->clearContext();
-#endif
-
- m_geolocationManagerProxy->invalidate();
- m_geolocationManagerProxy->clearContext();
+ WebContextSupplementMap::const_iterator it = m_supplements.begin();
+ WebContextSupplementMap::const_iterator end = m_supplements.end();
+ for (; it != end; ++it) {
+ it->value->contextDestroyed();
+ it->value->clearContext();
+ }
m_iconDatabase->invalidate();
m_iconDatabase->clearContext();
- m_keyValueStorageManagerProxy->invalidate();
- m_keyValueStorageManagerProxy->clearContext();
-
- m_mediaCacheManagerProxy->invalidate();
- m_mediaCacheManagerProxy->clearContext();
-
-#if ENABLE(NETWORK_INFO)
- m_networkInfoManagerProxy->invalidate();
- m_networkInfoManagerProxy->clearContext();
-#endif
-
- m_notificationManagerProxy->invalidate();
- m_notificationManagerProxy->clearContext();
-
#if ENABLE(NETSCAPE_PLUGIN_API)
m_pluginSiteDataManager->invalidate();
m_pluginSiteDataManager->clearContext();
#endif
- m_resourceCacheManagerProxy->invalidate();
- m_resourceCacheManagerProxy->clearContext();
-
-#if USE(SOUP)
- m_soupRequestManagerProxy->invalidate();
- m_soupRequestManagerProxy->clearContext();
-#endif
-
invalidateCallbackMap(m_dictionaryCallbacks);
platformInvalidateContext();
-
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+ m_pluginInfoStore.setClient(0);
+#endif
+
#ifndef NDEBUG
webContextCounter.decrement();
#endif
}
+void WebContext::initializeClient(const WKContextClient* client)
+{
+ m_client.initialize(client);
+}
+
void WebContext::initializeInjectedBundleClient(const WKContextInjectedBundleClient* client)
{
m_injectedBundleClient.initialize(client);
@@ -285,12 +287,37 @@ void WebContext::setProcessModel(ProcessModel processModel)
m_processModel = processModel;
}
-WebProcessProxy* WebContext::deprecatedSharedProcess()
+void WebContext::setMaximumNumberOfProcesses(unsigned maximumNumberOfProcesses)
{
- ASSERT(m_processModel == ProcessModelSharedSecondaryProcess);
- if (m_processes.isEmpty())
- return 0;
- return m_processes[0].get();
+ // Guard against API misuse.
+ if (!m_processes.isEmpty())
+ CRASH();
+
+ if (maximumNumberOfProcesses == 0)
+ m_webProcessCountLimit = UINT_MAX;
+ else
+ m_webProcessCountLimit = maximumNumberOfProcesses;
+}
+
+CoreIPC::Connection* WebContext::networkingProcessConnection()
+{
+ switch (m_processModel) {
+ case ProcessModelSharedSecondaryProcess:
+#if ENABLE(NETWORK_PROCESS)
+ if (m_usesNetworkProcess)
+ return m_networkProcess->connection();
+#endif
+ return m_processes[0]->connection();
+ case ProcessModelMultipleSecondaryProcesses:
+#if ENABLE(NETWORK_PROCESS)
+ ASSERT(m_usesNetworkProcess);
+ return m_networkProcess->connection();
+#else
+ break;
+#endif
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
}
void WebContext::languageChanged(void* context)
@@ -322,6 +349,119 @@ void WebContext::setUsesNetworkProcess(bool usesNetworkProcess)
#endif
}
+bool WebContext::usesNetworkProcess() const
+{
+#if ENABLE(NETWORK_PROCESS)
+ return m_usesNetworkProcess;
+#else
+ return false;
+#endif
+}
+
+#if ENABLE(NETWORK_PROCESS)
+void WebContext::ensureNetworkProcess()
+{
+ if (m_networkProcess)
+ return;
+
+ m_networkProcess = NetworkProcessProxy::create(this);
+
+ NetworkProcessCreationParameters parameters;
+
+ parameters.diskCacheDirectory = diskCacheDirectory();
+ if (!parameters.diskCacheDirectory.isEmpty())
+ SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle);
+
+ parameters.privateBrowsingEnabled = WebPreferences::anyPageGroupsAreUsingPrivateBrowsing();
+
+ parameters.cacheModel = m_cacheModel;
+
+ // Add any platform specific parameters
+ platformInitializeNetworkProcess(parameters);
+
+ // Initialize the network process.
+ m_networkProcess->send(Messages::NetworkProcess::InitializeNetworkProcess(parameters), 0);
+}
+
+void WebContext::networkProcessCrashed(NetworkProcessProxy* networkProcessProxy)
+{
+ ASSERT(m_networkProcess);
+ ASSERT(networkProcessProxy == m_networkProcess.get());
+
+ WebContextSupplementMap::const_iterator it = m_supplements.begin();
+ WebContextSupplementMap::const_iterator end = m_supplements.end();
+ for (; it != end; ++it)
+ it->value->processDidClose(networkProcessProxy);
+
+ m_networkProcess = nullptr;
+
+ m_client.networkProcessDidCrash(this);
+}
+
+void WebContext::getNetworkProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> reply)
+{
+ ASSERT(reply);
+
+ ensureNetworkProcess();
+ ASSERT(m_networkProcess);
+
+ m_networkProcess->getNetworkProcessConnection(reply);
+}
+#endif
+
+
+void WebContext::willStartUsingPrivateBrowsing()
+{
+ const Vector<WebContext*>& contexts = allContexts();
+ for (size_t i = 0, count = contexts.size(); i < count; ++i) {
+#if ENABLE(NETWORK_PROCESS)
+ if (contexts[i]->usesNetworkProcess() && contexts[i]->networkProcess())
+ contexts[i]->networkProcess()->send(Messages::NetworkProcess::EnsurePrivateBrowsingSession(), 0);
+#endif
+ contexts[i]->sendToAllProcesses(Messages::WebProcess::EnsurePrivateBrowsingSession());
+ }
+}
+
+void WebContext::willStopUsingPrivateBrowsing()
+{
+ const Vector<WebContext*>& contexts = allContexts();
+ for (size_t i = 0, count = contexts.size(); i < count; ++i) {
+#if ENABLE(NETWORK_PROCESS)
+ if (contexts[i]->usesNetworkProcess() && contexts[i]->networkProcess())
+ contexts[i]->networkProcess()->send(Messages::NetworkProcess::DestroyPrivateBrowsingSession(), 0);
+#endif
+
+ contexts[i]->sendToAllProcesses(Messages::WebProcess::DestroyPrivateBrowsingSession());
+ }
+}
+
+void (*s_invalidMessageCallback)(WKStringRef messageName);
+
+void WebContext::setInvalidMessageCallback(void (*invalidMessageCallback)(WKStringRef messageName))
+{
+ s_invalidMessageCallback = invalidMessageCallback;
+}
+
+void WebContext::didReceiveInvalidMessage(const CoreIPC::StringReference& messageReceiverName, const CoreIPC::StringReference& messageName)
+{
+ if (!s_invalidMessageCallback)
+ return;
+
+ StringBuilder messageNameStringBuilder;
+ messageNameStringBuilder.append(messageReceiverName.data(), messageReceiverName.size());
+ messageNameStringBuilder.append(".");
+ messageNameStringBuilder.append(messageName.data(), messageName.size());
+
+ s_invalidMessageCallback(toAPI(WebString::create(messageNameStringBuilder.toString()).get()));
+}
+
+void WebContext::processDidCachePage(WebProcessProxy* process)
+{
+ if (m_processWithPageCache && m_processWithPageCache != process)
+ m_processWithPageCache->releasePageCache();
+ m_processWithPageCache = process;
+}
+
WebProcessProxy* WebContext::ensureSharedWebProcess()
{
ASSERT(m_processModel == ProcessModelSharedSecondaryProcess);
@@ -330,11 +470,11 @@ WebProcessProxy* WebContext::ensureSharedWebProcess()
return m_processes[0].get();
}
-PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess()
+WebProcessProxy* WebContext::createNewWebProcess()
{
#if ENABLE(NETWORK_PROCESS)
if (m_usesNetworkProcess)
- NetworkProcessManager::shared().ensureNetworkProcess();
+ ensureNetworkProcess();
#endif
RefPtr<WebProcessProxy> process = WebProcessProxy::create(this);
@@ -363,7 +503,7 @@ PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess()
parameters.cookieStorageDirectory = cookieStorageDirectory();
if (!parameters.cookieStorageDirectory.isEmpty())
- SandboxExtension::createHandle(parameters.cookieStorageDirectory, SandboxExtension::ReadWrite, parameters.cookieStorageDirectoryExtensionHandle);
+ SandboxExtension::createHandleForReadWriteDirectory(parameters.cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
parameters.shouldTrackVisitedLinks = m_historyClient.shouldTrackVisitedLinks();
parameters.cacheModel = m_cacheModel;
@@ -391,13 +531,17 @@ PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess()
parameters.defaultRequestTimeoutInterval = WebURLRequest::defaultTimeoutInterval();
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
- m_notificationManagerProxy->populateCopyOfNotificationPermissions(parameters.notificationPermissions);
+ // FIXME: There should be a generic way for supplements to add to the intialization parameters.
+ supplement<WebNotificationManagerProxy>()->populateCopyOfNotificationPermissions(parameters.notificationPermissions);
#endif
#if ENABLE(NETWORK_PROCESS)
parameters.usesNetworkProcess = m_usesNetworkProcess;
#endif
+ parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy();
+ copyToVector(m_plugInAutoStartProvider.autoStartOrigins(), parameters.plugInAutoStartOrigins);
+
// Add any platform specific parameters
platformInitializeWebProcess(parameters);
@@ -406,11 +550,14 @@ PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess()
injectedBundleInitializationUserData = m_injectedBundleInitializationUserData;
process->send(Messages::WebProcess::InitializeWebProcess(parameters, WebContextUserMessageEncoder(injectedBundleInitializationUserData.get())), 0);
+ if (WebPreferences::anyPageGroupsAreUsingPrivateBrowsing())
+ process->send(Messages::WebProcess::EnsurePrivateBrowsingSession(), 0);
+
m_processes.append(process);
if (m_processModel == ProcessModelSharedSecondaryProcess) {
for (size_t i = 0; i != m_messagesToInjectedBundlePostedToEmptyContext.size(); ++i) {
- pair<String, RefPtr<APIObject> >& message = m_messagesToInjectedBundlePostedToEmptyContext[i];
+ pair<String, RefPtr<APIObject>>& message = m_messagesToInjectedBundlePostedToEmptyContext[i];
OwnPtr<CoreIPC::ArgumentEncoder> messageData = CoreIPC::ArgumentEncoder::create();
@@ -422,8 +569,7 @@ PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess()
} else
ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());
-
- return process.release();
+ return process.get();
}
void WebContext::warmInitialProcess()
@@ -433,6 +579,9 @@ void WebContext::warmInitialProcess()
return;
}
+ if (m_processes.size() >= m_webProcessCountLimit)
+ return;
+
createNewWebProcess();
m_haveInitialEmptyProcess = true;
}
@@ -440,7 +589,7 @@ void WebContext::warmInitialProcess()
void WebContext::enableProcessTermination()
{
m_processTerminationEnabled = true;
- Vector<RefPtr<WebProcessProxy> > processes = m_processes;
+ Vector<RefPtr<WebProcessProxy>> processes = m_processes;
for (size_t i = 0; i < processes.size(); ++i) {
if (shouldTerminate(processes[i].get()))
processes[i]->terminate();
@@ -454,31 +603,31 @@ bool WebContext::shouldTerminate(WebProcessProxy* process)
if (!m_processTerminationEnabled)
return false;
- if (!m_downloads.isEmpty())
- return false;
+ WebContextSupplementMap::const_iterator it = m_supplements.begin();
+ WebContextSupplementMap::const_iterator end = m_supplements.end();
+ for (; it != end; ++it) {
+ if (!it->value->shouldTerminate(process))
+ return false;
+ }
- if (!m_applicationCacheManagerProxy->shouldTerminate(process))
- return false;
- if (!m_cookieManagerProxy->shouldTerminate(process))
- return false;
-#if ENABLE(SQL_DATABASE)
- if (!m_databaseManagerProxy->shouldTerminate(process))
- return false;
-#endif
- if (!m_keyValueStorageManagerProxy->shouldTerminate(process))
- return false;
- if (!m_mediaCacheManagerProxy->shouldTerminate(process))
- return false;
#if ENABLE(NETSCAPE_PLUGIN_API)
if (!m_pluginSiteDataManager->shouldTerminate(process))
return false;
#endif
- if (!m_resourceCacheManagerProxy->shouldTerminate(process))
- return false;
return true;
}
+void WebContext::processWillOpenConnection(WebProcessProxy* process)
+{
+ m_storageManager->processWillOpenConnection(process);
+}
+
+void WebContext::processWillCloseConnection(WebProcessProxy* process)
+{
+ m_storageManager->processWillCloseConnection(process);
+}
+
void WebContext::processDidFinishLaunching(WebProcessProxy* process)
{
ASSERT(m_processes.contains(process));
@@ -491,7 +640,7 @@ void WebContext::processDidFinishLaunching(WebProcessProxy* process)
SandboxExtension::Handle sampleLogSandboxHandle;
double now = WTF::currentTime();
String sampleLogFilePath = String::format("WebProcess%llupid%d", static_cast<unsigned long long>(now), process->processIdentifier());
- sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::WriteOnly, sampleLogSandboxHandle);
+ sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
}
@@ -508,41 +657,20 @@ void WebContext::disconnectProcess(WebProcessProxy* process)
if (m_haveInitialEmptyProcess && process == m_processes.last())
m_haveInitialEmptyProcess = false;
- // FIXME (Multi-WebProcess): <rdar://problem/12239765> All the invalidation calls below are still necessary in multi-process mode, but they should only affect data structures pertaining to the process being disconnected.
+ // FIXME (Multi-WebProcess): <rdar://problem/12239765> Some of the invalidation calls below are still necessary in multi-process mode, but they should only affect data structures pertaining to the process being disconnected.
// Clearing everything causes assertion failures, so it's less trouble to skip that for now.
if (m_processModel != ProcessModelSharedSecondaryProcess) {
RefPtr<WebProcessProxy> protect(process);
+ if (m_processWithPageCache == process)
+ m_processWithPageCache = 0;
m_processes.remove(m_processes.find(process));
return;
}
- // Invalidate all outstanding downloads.
- for (HashMap<uint64_t, RefPtr<DownloadProxy> >::iterator::Values it = m_downloads.begin().values(), end = m_downloads.end().values(); it != end; ++it) {
- (*it)->processDidClose();
- (*it)->invalidate();
- }
-
- m_downloads.clear();
-
- m_applicationCacheManagerProxy->invalidate();
-#if ENABLE(BATTERY_STATUS)
- m_batteryManagerProxy->invalidate();
-#endif
- m_cookieManagerProxy->invalidate();
-#if ENABLE(SQL_DATABASE)
- m_databaseManagerProxy->invalidate();
-#endif
- m_geolocationManagerProxy->invalidate();
- m_keyValueStorageManagerProxy->invalidate();
- m_mediaCacheManagerProxy->invalidate();
-#if ENABLE(NETWORK_INFO)
- m_networkInfoManagerProxy->invalidate();
-#endif
- m_notificationManagerProxy->invalidate();
- m_resourceCacheManagerProxy->invalidate();
-#if USE(SOUP)
- m_soupRequestManagerProxy->invalidate();
-#endif
+ WebContextSupplementMap::const_iterator it = m_supplements.begin();
+ WebContextSupplementMap::const_iterator end = m_supplements.end();
+ for (; it != end; ++it)
+ it->value->processDidClose(process);
// When out of process plug-ins are enabled, we don't want to invalidate the plug-in site data
// manager just because the web process crashes since it's not involved.
@@ -554,9 +682,28 @@ void WebContext::disconnectProcess(WebProcessProxy* process)
// Since vector elements are destroyed in place, we would recurse into WebProcessProxy destructor
// if it were invoked from Vector::remove(). RefPtr delays destruction until it's safe.
RefPtr<WebProcessProxy> protect(process);
+ if (m_processWithPageCache == process)
+ m_processWithPageCache = 0;
m_processes.remove(m_processes.find(process));
}
+WebProcessProxy* WebContext::createNewWebProcessRespectingProcessCountLimit()
+{
+ if (m_processes.size() < m_webProcessCountLimit)
+ return createNewWebProcess();
+
+ // Choose a process with fewest pages, to achieve flat distribution.
+ WebProcessProxy* result = 0;
+ unsigned fewestPagesSeen = UINT_MAX;
+ for (unsigned i = 0; i < m_processes.size(); ++i) {
+ if (fewestPagesSeen > m_processes[i]->pages().size()) {
+ result = m_processes[i].get();
+ fewestPagesSeen = m_processes[i]->pages().size();
+ }
+ }
+ return result;
+}
+
PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient* pageClient, WebPageGroup* pageGroup, WebPageProxy* relatedPage)
{
RefPtr<WebProcessProxy> process;
@@ -569,10 +716,8 @@ PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient* pageClient, WebPa
} else if (relatedPage) {
// Sharing processes, e.g. when creating the page via window.open().
process = relatedPage->process();
- } else {
- // FIXME (Multi-WebProcess): <rdar://problem/12239661> Consider limiting the number of web processes in per-tab process model.
- process = createNewWebProcess();
- }
+ } else
+ process = createNewWebProcessRespectingProcessCountLimit();
}
if (!pageGroup)
@@ -583,24 +728,24 @@ PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient* pageClient, WebPa
DownloadProxy* WebContext::download(WebPageProxy* initiatingPage, const ResourceRequest& request)
{
- if (m_processModel == ProcessModelSharedSecondaryProcess) {
- ensureSharedWebProcess();
+ DownloadProxy* downloadProxy = createDownloadProxy();
+ uint64_t initiatingPageID = initiatingPage ? initiatingPage->pageID() : 0;
- DownloadProxy* download = createDownloadProxy();
- uint64_t initiatingPageID = initiatingPage ? initiatingPage->pageID() : 0;
+#if ENABLE(NETWORK_PROCESS)
+ if (usesNetworkProcess() && networkProcess()) {
+ // FIXME (NetworkProcess): Replicate whatever FrameLoader::setOriginalURLForDownloadRequest does with the request here.
+ networkProcess()->connection()->send(Messages::NetworkProcess::DownloadRequest(downloadProxy->downloadID(), request), 0);
+ return downloadProxy;
+ }
+#endif
#if PLATFORM(QT)
- ASSERT(initiatingPage); // Our design does not suppport downloads without a WebPage.
- initiatingPage->handleDownloadRequest(download);
+ ASSERT(initiatingPage); // Our design does not suppport downloads without a WebPage.
+ initiatingPage->handleDownloadRequest(downloadProxy);
#endif
- m_processes[0]->send(Messages::WebProcess::DownloadRequest(download->downloadID(), initiatingPageID, request), 0);
- return download;
-
- } else {
- // FIXME (Multi-WebProcess): <rdar://problem/12239483> Make downloading work.
- return 0;
- }
+ m_processes[0]->send(Messages::WebProcess::DownloadRequest(downloadProxy->downloadID(), initiatingPageID, request), 0);
+ return downloadProxy;
}
void WebContext::postMessageToInjectedBundle(const String& messageName, APIObject* messageBody)
@@ -714,6 +859,8 @@ void WebContext::setCacheModel(CacheModel cacheModel)
{
m_cacheModel = cacheModel;
sendToAllProcesses(Messages::WebProcess::SetCacheModel(static_cast<uint32_t>(m_cacheModel)));
+
+ // FIXME: Inform the Network Process if in use.
}
void WebContext::setDefaultRequestTimeoutInterval(double timeoutInterval)
@@ -737,31 +884,12 @@ void WebContext::addVisitedLinkHash(LinkHash linkHash)
DownloadProxy* WebContext::createDownloadProxy()
{
- RefPtr<DownloadProxy> downloadProxy = DownloadProxy::create(this);
- m_downloads.set(downloadProxy->downloadID(), downloadProxy);
- addMessageReceiver(Messages::DownloadProxy::messageReceiverName(), downloadProxy->downloadID(), this);
- return downloadProxy.get();
-}
-
-void WebContext::downloadFinished(DownloadProxy* downloadProxy)
-{
- ASSERT(m_downloads.contains(downloadProxy->downloadID()));
-
- downloadProxy->invalidate();
- removeMessageReceiver(Messages::DownloadProxy::messageReceiverName(), downloadProxy->downloadID());
- m_downloads.remove(downloadProxy->downloadID());
-}
-
-// FIXME: This is not the ideal place for this function.
-HashSet<String, CaseFoldingHash> WebContext::pdfAndPostScriptMIMETypes()
-{
- HashSet<String, CaseFoldingHash> mimeTypes;
+#if ENABLE(NETWORK_PROCESS)
+ if (usesNetworkProcess())
+ return m_networkProcess->createDownloadProxy();
+#endif
- mimeTypes.add("application/pdf");
- mimeTypes.add("application/postscript");
- mimeTypes.add("text/pdf");
-
- return mimeTypes;
+ return ensureSharedWebProcess()->createDownloadProxy();
}
void WebContext::addMessageReceiver(CoreIPC::StringReference messageReceiverName, CoreIPC::MessageReceiver* messageReceiver)
@@ -779,83 +907,66 @@ void WebContext::removeMessageReceiver(CoreIPC::StringReference messageReceiverN
m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
}
-bool WebContext::dispatchMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder)
+bool WebContext::dispatchMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder)
{
- return m_messageReceiverMap.dispatchMessage(connection, messageID, decoder);
+ return m_messageReceiverMap.dispatchMessage(connection, decoder);
}
-bool WebContext::dispatchSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder)
+bool WebContext::dispatchSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder)
{
- return m_messageReceiverMap.dispatchSyncMessage(connection, messageID, decoder, replyEncoder);
+ return m_messageReceiverMap.dispatchSyncMessage(connection, decoder, replyEncoder);
}
-void WebContext::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder)
+void WebContext::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder)
{
- if (messageID.is<CoreIPC::MessageClassWebContext>()) {
- didReceiveWebContextMessage(connection, messageID, decoder);
+ if (decoder.messageReceiverName() == Messages::WebContext::messageReceiverName()) {
+ didReceiveWebContextMessage(connection, decoder);
return;
}
- if (messageID.is<CoreIPC::MessageClassDownloadProxy>()) {
- if (DownloadProxy* downloadProxy = m_downloads.get(decoder.destinationID()).get())
- downloadProxy->didReceiveDownloadProxyMessage(connection, messageID, decoder);
-
- return;
- }
-
- switch (messageID.get<WebContextLegacyMessage::Kind>()) {
- case WebContextLegacyMessage::PostMessage: {
- String messageName;
- RefPtr<APIObject> messageBody;
- WebContextUserMessageDecoder messageBodyDecoder(messageBody, WebProcessProxy::fromConnection(connection));
- if (!decoder.decode(messageName))
- return;
- if (!decoder.decode(messageBodyDecoder))
- return;
-
- didReceiveMessageFromInjectedBundle(messageName, messageBody.get());
+ if (decoder.messageReceiverName() == WebContextLegacyMessages::messageReceiverName()
+ && decoder.messageName() == WebContextLegacyMessages::postMessageMessageName()) {
+ String messageName;
+ RefPtr<APIObject> messageBody;
+ WebContextUserMessageDecoder messageBodyDecoder(messageBody, WebProcessProxy::fromConnection(connection));
+ if (!decoder.decode(messageName))
return;
- }
- case WebContextLegacyMessage::PostSynchronousMessage:
- ASSERT_NOT_REACHED();
+ if (!decoder.decode(messageBodyDecoder))
+ return;
+
+ didReceiveMessageFromInjectedBundle(messageName, messageBody.get());
+ return;
}
ASSERT_NOT_REACHED();
}
-void WebContext::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder)
+void WebContext::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder)
{
- if (messageID.is<CoreIPC::MessageClassWebContext>()) {
- didReceiveSyncWebContextMessage(connection, messageID, decoder, replyEncoder);
+ if (decoder.messageReceiverName() == Messages::WebContext::messageReceiverName()) {
+ didReceiveSyncWebContextMessage(connection, decoder, replyEncoder);
return;
}
- if (messageID.is<CoreIPC::MessageClassDownloadProxy>()) {
- if (DownloadProxy* downloadProxy = m_downloads.get(decoder.destinationID()).get())
- downloadProxy->didReceiveSyncDownloadProxyMessage(connection, messageID, decoder, replyEncoder);
- return;
- }
+ if (decoder.messageReceiverName() == WebContextLegacyMessages::messageReceiverName()
+ && decoder.messageName() == WebContextLegacyMessages::postSynchronousMessageMessageName()) {
+ // FIXME: We should probably encode something in the case that the arguments do not decode correctly.
- switch (messageID.get<WebContextLegacyMessage::Kind>()) {
- case WebContextLegacyMessage::PostSynchronousMessage: {
- // FIXME: We should probably encode something in the case that the arguments do not decode correctly.
-
- String messageName;
- RefPtr<APIObject> messageBody;
- WebContextUserMessageDecoder messageBodyDecoder(messageBody, WebProcessProxy::fromConnection(connection));
- if (!decoder.decode(messageName))
- return;
- if (!decoder.decode(messageBodyDecoder))
- return;
-
- RefPtr<APIObject> returnData;
- didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody.get(), returnData);
- replyEncoder->encode(WebContextUserMessageEncoder(returnData.get()));
+ String messageName;
+ RefPtr<APIObject> messageBody;
+ WebContextUserMessageDecoder messageBodyDecoder(messageBody, WebProcessProxy::fromConnection(connection));
+ if (!decoder.decode(messageName))
return;
- }
- case WebContextLegacyMessage::PostMessage:
- ASSERT_NOT_REACHED();
+ if (!decoder.decode(messageBodyDecoder))
+ return;
+
+ RefPtr<APIObject> returnData;
+ didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody.get(), returnData);
+ replyEncoder->encode(WebContextUserMessageEncoder(returnData.get()));
+ return;
}
+
+ ASSERT_NOT_REACHED();
}
void WebContext::setEnhancedAccessibility(bool flag)
@@ -878,7 +989,7 @@ void WebContext::startMemorySampler(const double interval)
SandboxExtension::Handle sampleLogSandboxHandle;
double now = WTF::currentTime();
String sampleLogFilePath = String::format("WebProcess%llu", static_cast<unsigned long long>(now));
- sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::WriteOnly, sampleLogSandboxHandle);
+ sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
}
@@ -896,6 +1007,14 @@ void WebContext::stopMemorySampler()
sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
}
+String WebContext::applicationCacheDirectory() const
+{
+ if (!m_overrideApplicationCacheDirectory.isEmpty())
+ return m_overrideApplicationCacheDirectory;
+
+ return platformDefaultApplicationCacheDirectory();
+}
+
String WebContext::databaseDirectory() const
{
if (!m_overrideDatabaseDirectory.isEmpty())
@@ -918,6 +1037,12 @@ String WebContext::iconDatabasePath() const
return platformDefaultIconDatabasePath();
}
+void WebContext::setLocalStorageDirectory(const String& directory)
+{
+ m_overrideLocalStorageDirectory = directory;
+ m_storageManager->setLocalStorageDirectory(localStorageDirectory());
+}
+
String WebContext::localStorageDirectory() const
{
if (!m_overrideLocalStorageDirectory.isEmpty())
@@ -942,6 +1067,21 @@ String WebContext::cookieStorageDirectory() const
return platformDefaultCookieStorageDirectory();
}
+void WebContext::allowSpecificHTTPSCertificateForHost(const WebCertificateInfo* certificate, const String& host)
+{
+#if ENABLE(NETWORK_PROCESS)
+ if (m_usesNetworkProcess && m_networkProcess) {
+ m_networkProcess->send(Messages::NetworkProcess::AllowSpecificHTTPSCertificateForHost(certificate->platformCertificateInfo(), host), 0);
+ return;
+ }
+#else
+ UNUSED_PARAM(certificate);
+ UNUSED_PARAM(host);
+#endif
+ // FIXME: It's unclear whether we want this SPI to be exposed and used for clients that don't use the NetworkProcess.
+ ASSERT_NOT_REACHED();
+}
+
void WebContext::setHTTPPipeliningEnabled(bool enabled)
{
#if PLATFORM(MAC)
@@ -960,32 +1100,58 @@ bool WebContext::httpPipeliningEnabled() const
#endif
}
-void WebContext::getWebCoreStatistics(PassRefPtr<DictionaryCallback> callback)
+void WebContext::getStatistics(uint32_t statisticsMask, PassRefPtr<DictionaryCallback> callback)
+{
+ if (!statisticsMask) {
+ callback->invalidate();
+ return;
+ }
+
+ RefPtr<StatisticsRequest> request = StatisticsRequest::create(callback);
+
+ if (statisticsMask & StatisticsRequestTypeWebContent)
+ requestWebContentStatistics(request.get());
+
+ if (statisticsMask & StatisticsRequestTypeNetworking)
+ requestNetworkingStatistics(request.get());
+}
+
+void WebContext::requestWebContentStatistics(StatisticsRequest* request)
{
if (m_processModel == ProcessModelSharedSecondaryProcess) {
- if (m_processes.isEmpty()) {
- callback->invalidate();
+ if (m_processes.isEmpty())
return;
- }
- uint64_t callbackID = callback->callbackID();
- m_dictionaryCallbacks.set(callbackID, callback.get());
- m_processes[0]->send(Messages::WebProcess::GetWebCoreStatistics(callbackID), 0);
+ uint64_t requestID = request->addOutstandingRequest();
+ m_statisticsRequests.set(requestID, request);
+ m_processes[0]->send(Messages::WebProcess::GetWebCoreStatistics(requestID), 0);
} else {
- // FIXME (Multi-WebProcess): <rdar://problem/12239483> Make downloading work.
- callback->invalidate();
+ // FIXME (Multi-WebProcess) <rdar://problem/13200059>: Make getting statistics from multiple WebProcesses work.
}
}
-static PassRefPtr<MutableDictionary> createDictionaryFromHashMap(const HashMap<String, uint64_t>& map)
+void WebContext::requestNetworkingStatistics(StatisticsRequest* request)
{
- RefPtr<MutableDictionary> result = MutableDictionary::create();
- HashMap<String, uint64_t>::const_iterator end = map.end();
- for (HashMap<String, uint64_t>::const_iterator it = map.begin(); it != end; ++it)
- result->set(it->key, RefPtr<WebUInt64>(WebUInt64::create(it->value)).get());
-
- return result;
+ bool networkProcessUnavailable;
+#if ENABLE(NETWORK_PROCESS)
+ networkProcessUnavailable = !m_usesNetworkProcess || !m_networkProcess;
+#else
+ networkProcessUnavailable = true;
+#endif
+
+ if (networkProcessUnavailable) {
+ LOG_ERROR("Attempt to get NetworkProcess statistics but the NetworkProcess is unavailable");
+ return;
+ }
+
+#if ENABLE(NETWORK_PROCESS)
+ uint64_t requestID = request->addOutstandingRequest();
+ m_statisticsRequests.set(requestID, request);
+ m_networkProcess->send(Messages::NetworkProcess::GetNetworkProcessStatistics(requestID), 0);
+#else
+ UNUSED_PARAM(request);
+#endif
}
#if !PLATFORM(MAC)
@@ -994,25 +1160,15 @@ void WebContext::dummy(bool&)
}
#endif
-void WebContext::didGetWebCoreStatistics(const StatisticsData& statisticsData, uint64_t callbackID)
+void WebContext::didGetStatistics(const StatisticsData& statisticsData, uint64_t requestID)
{
- RefPtr<DictionaryCallback> callback = m_dictionaryCallbacks.take(callbackID);
- if (!callback) {
- // FIXME: Log error or assert.
+ RefPtr<StatisticsRequest> request = m_statisticsRequests.take(requestID);
+ if (!request) {
+ LOG_ERROR("Cannot report networking statistics.");
return;
}
- RefPtr<MutableDictionary> statistics = createDictionaryFromHashMap(statisticsData.statisticsNumbers);
- statistics->set("JavaScriptProtectedObjectTypeCounts", createDictionaryFromHashMap(statisticsData.javaScriptProtectedObjectTypeCounts).get());
- statistics->set("JavaScriptObjectTypeCounts", createDictionaryFromHashMap(statisticsData.javaScriptObjectTypeCounts).get());
-
- size_t cacheStatisticsCount = statisticsData.webCoreCacheStatistics.size();
- Vector<RefPtr<APIObject> > cacheStatisticsVector(cacheStatisticsCount);
- for (size_t i = 0; i < cacheStatisticsCount; ++i)
- cacheStatisticsVector[i] = createDictionaryFromHashMap(statisticsData.webCoreCacheStatistics[i]);
- statistics->set("WebCoreCacheStatistics", ImmutableArray::adopt(cacheStatisticsVector).get());
-
- callback->performCallbackWithReturnValue(statistics.get());
+ request->completedRequest(requestID, statisticsData);
}
void WebContext::garbageCollectJavaScriptObjects()
@@ -1025,4 +1181,75 @@ void WebContext::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
sendToAllProcesses(Messages::WebProcess::SetJavaScriptGarbageCollectorTimerEnabled(flag));
}
+void WebContext::addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash)
+{
+ m_plugInAutoStartProvider.addAutoStartOriginHash(pageOrigin, plugInOriginHash);
+}
+
+void WebContext::plugInDidReceiveUserInteraction(unsigned plugInOriginHash)
+{
+ m_plugInAutoStartProvider.didReceiveUserInteraction(plugInOriginHash);
+}
+
+PassRefPtr<ImmutableDictionary> WebContext::plugInAutoStartOriginHashes() const
+{
+ return m_plugInAutoStartProvider.autoStartOriginsTableCopy();
+}
+
+void WebContext::setPlugInAutoStartOriginHashes(ImmutableDictionary& dictionary)
+{
+ m_plugInAutoStartProvider.setAutoStartOriginsTable(dictionary);
+}
+
+void WebContext::setPlugInAutoStartOrigins(ImmutableArray& array)
+{
+ m_plugInAutoStartProvider.setAutoStartOriginsArray(array);
+}
+
+#if ENABLE(CUSTOM_PROTOCOLS)
+void WebContext::registerSchemeForCustomProtocol(const String& scheme)
+{
+ sendToNetworkingProcess(Messages::CustomProtocolManager::RegisterScheme(scheme));
+}
+
+void WebContext::unregisterSchemeForCustomProtocol(const String& scheme)
+{
+ sendToNetworkingProcess(Messages::CustomProtocolManager::UnregisterScheme(scheme));
+}
+#endif
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+void WebContext::pluginInfoStoreDidLoadPlugins(PluginInfoStore* store)
+{
+#ifdef NDEBUG
+ UNUSED_PARAM(store);
+#endif
+ ASSERT(store == &m_pluginInfoStore);
+
+ Vector<RefPtr<APIObject>> pluginArray;
+
+ Vector<PluginModuleInfo> plugins = m_pluginInfoStore.plugins();
+ for (size_t i = 0; i < plugins.size(); ++i) {
+ PluginModuleInfo& plugin = plugins[i];
+ ImmutableDictionary::MapType map;
+ map.set(ASCIILiteral("path"), WebString::create(plugin.path));
+ map.set(ASCIILiteral("name"), WebString::create(plugin.info.name));
+ map.set(ASCIILiteral("file"), WebString::create(plugin.info.file));
+ map.set(ASCIILiteral("desc"), WebString::create(plugin.info.desc));
+ Vector<RefPtr<APIObject>> mimeArray;
+ for (size_t j = 0; j < plugin.info.mimes.size(); ++j)
+ mimeArray.append(WebString::create(plugin.info.mimes[j].type));
+ map.set(ASCIILiteral("mimes"), ImmutableArray::adopt(mimeArray));
+#if PLATFORM(MAC)
+ map.set(ASCIILiteral("bundleId"), WebString::create(plugin.bundleIdentifier));
+ map.set(ASCIILiteral("version"), WebString::create(plugin.versionString));
+#endif
+
+ pluginArray.append(ImmutableDictionary::adopt(map));
+ }
+
+ m_client.plugInInformationBecameAvailable(this, ImmutableArray::adopt(pluginArray).get());
+}
+#endif
+
} // namespace WebKit