Remove WebContext::sharedProcessContext()
[WebKit-https.git] / Source / WebKit2 / UIProcess / WebContext.cpp
1 /*
2  * Copyright (C) 2010, 2011, 2012, 2013 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 "WebContext.h"
28
29 #include "APIArray.h"
30 #include "DownloadProxy.h"
31 #include "DownloadProxyMessages.h"
32 #include "Logging.h"
33 #include "MutableDictionary.h"
34 #include "SandboxExtension.h"
35 #include "StatisticsData.h"
36 #include "TextChecker.h"
37 #include "WKContextPrivate.h"
38 #include "WebApplicationCacheManagerProxy.h"
39 #include "WebContextMessageKinds.h"
40 #include "WebContextMessages.h"
41 #include "WebContextSupplement.h"
42 #include "WebContextUserMessageCoders.h"
43 #include "WebCookieManagerProxy.h"
44 #include "WebCoreArgumentCoders.h"
45 #include "WebDatabaseManagerProxy.h"
46 #include "WebGeolocationManagerProxy.h"
47 #include "WebIconDatabase.h"
48 #include "WebKeyValueStorageManager.h"
49 #include "WebKit2Initialize.h"
50 #include "WebMediaCacheManagerProxy.h"
51 #include "WebNotificationManagerProxy.h"
52 #include "WebPluginSiteDataManager.h"
53 #include "WebPageGroup.h"
54 #include "WebPreferences.h"
55 #include "WebMemorySampler.h"
56 #include "WebProcessCreationParameters.h"
57 #include "WebProcessMessages.h"
58 #include "WebProcessProxy.h"
59 #include "WebResourceCacheManagerProxy.h"
60 #include <WebCore/Language.h>
61 #include <WebCore/LinkHash.h>
62 #include <WebCore/Logging.h>
63 #include <WebCore/ResourceRequest.h>
64 #include <runtime/Operations.h>
65 #include <wtf/CurrentTime.h>
66 #include <wtf/MainThread.h>
67 #include <wtf/RunLoop.h>
68
69 #if ENABLE(BATTERY_STATUS)
70 #include "WebBatteryManagerProxy.h"
71 #endif
72
73 #if ENABLE(NETWORK_INFO)
74 #include "WebNetworkInfoManagerProxy.h"
75 #endif
76
77 #if ENABLE(DATABASE_PROCESS)
78 #include "DatabaseProcessCreationParameters.h"
79 #include "DatabaseProcessMessages.h"
80 #endif
81
82 #if ENABLE(NETWORK_PROCESS)
83 #include "NetworkProcessCreationParameters.h"
84 #include "NetworkProcessMessages.h"
85 #include "NetworkProcessProxy.h"
86 #endif
87
88 #if ENABLE(CUSTOM_PROTOCOLS)
89 #include "CustomProtocolManagerMessages.h"
90 #endif
91
92 #if USE(SOUP)
93 #include "WebSoupRequestManagerProxy.h"
94 #endif
95
96 #ifndef NDEBUG
97 #include <wtf/RefCountedLeakCounter.h>
98 #endif
99
100 using namespace WebCore;
101
102 namespace WebKit {
103
104 static const double sharedSecondaryProcessShutdownTimeout = 60;
105
106 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webContextCounter, ("WebContext"));
107
108 PassRefPtr<WebContext> WebContext::create(const String& injectedBundlePath)
109 {
110     InitializeWebKit2();
111     return adoptRef(new WebContext(injectedBundlePath));
112 }
113
114 static Vector<WebContext*>& contexts()
115 {
116     DEFINE_STATIC_LOCAL(Vector<WebContext*>, contexts, ());
117
118     return contexts;
119 }
120
121 const Vector<WebContext*>& WebContext::allContexts()
122 {
123     return contexts();
124 }
125
126 WebContext::WebContext(const String& injectedBundlePath)
127     : m_processModel(ProcessModelSharedSecondaryProcess)
128     , m_webProcessCountLimit(UINT_MAX)
129     , m_haveInitialEmptyProcess(false)
130     , m_processWithPageCache(0)
131     , m_defaultPageGroup(WebPageGroup::createNonNull())
132     , m_injectedBundlePath(injectedBundlePath)
133     , m_visitedLinkProvider(this)
134     , m_plugInAutoStartProvider(this)
135     , m_alwaysUsesComplexTextCodePath(false)
136     , m_shouldUseFontSmoothing(true)
137     , m_cacheModel(CacheModelDocumentViewer)
138     , m_memorySamplerEnabled(false)
139     , m_memorySamplerInterval(1400.0)
140     , m_storageManager(StorageManager::create())
141 #if USE(SOUP)
142     , m_initialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicyOnlyFromMainDocumentDomain)
143 #endif
144     , m_shouldUseTestingNetworkSession(false)
145     , m_processTerminationEnabled(true)
146 #if ENABLE(NETWORK_PROCESS)
147     , m_usesNetworkProcess(false)
148 #endif
149 #if PLATFORM(MAC)
150     , m_processSuppressionEnabled(true)
151 #endif
152 #if USE(SOUP)
153     , m_ignoreTLSErrors(true)
154 #endif
155 {
156     platformInitialize();
157
158     addMessageReceiver(Messages::WebContext::messageReceiverName(), this);
159     addMessageReceiver(WebContextLegacyMessages::messageReceiverName(), this);
160
161     // NOTE: These sub-objects must be initialized after m_messageReceiverMap..
162     m_iconDatabase = WebIconDatabase::create(this);
163 #if ENABLE(NETSCAPE_PLUGIN_API)
164     m_pluginSiteDataManager = WebPluginSiteDataManager::create(this);
165 #endif // ENABLE(NETSCAPE_PLUGIN_API)
166
167     addSupplement<WebApplicationCacheManagerProxy>();
168     addSupplement<WebCookieManagerProxy>();
169     addSupplement<WebGeolocationManagerProxy>();
170     addSupplement<WebKeyValueStorageManager>();
171     addSupplement<WebMediaCacheManagerProxy>();
172     addSupplement<WebNotificationManagerProxy>();
173     addSupplement<WebResourceCacheManagerProxy>();
174 #if ENABLE(SQL_DATABASE)
175     addSupplement<WebDatabaseManagerProxy>();
176 #endif
177 #if USE(SOUP)
178     addSupplement<WebSoupRequestManagerProxy>();
179 #endif
180 #if ENABLE(BATTERY_STATUS)
181     addSupplement<WebBatteryManagerProxy>();
182 #endif
183 #if ENABLE(NETWORK_INFO)
184     addSupplement<WebNetworkInfoManagerProxy>();
185 #endif
186
187     contexts().append(this);
188
189     addLanguageChangeObserver(this, languageChanged);
190
191 #if !LOG_DISABLED
192     WebCore::initializeLoggingChannelsIfNecessary();
193     WebKit::initializeLogChannelsIfNecessary();
194 #endif // !LOG_DISABLED
195
196 #if ENABLE(NETSCAPE_PLUGIN_API)
197     m_pluginInfoStore.setClient(this);
198 #endif
199
200 #ifndef NDEBUG
201     webContextCounter.increment();
202 #endif
203
204     m_storageManager->setLocalStorageDirectory(localStorageDirectory());
205 }
206
207 #if !PLATFORM(MAC)
208 void WebContext::platformInitialize()
209 {
210 }
211 #endif
212
213 WebContext::~WebContext()
214 {
215     ASSERT(contexts().find(this) != notFound);
216     contexts().remove(contexts().find(this));
217
218     removeLanguageChangeObserver(this);
219
220     m_messageReceiverMap.invalidate();
221
222     WebContextSupplementMap::const_iterator it = m_supplements.begin();
223     WebContextSupplementMap::const_iterator end = m_supplements.end();
224     for (; it != end; ++it) {
225         it->value->contextDestroyed();
226         it->value->clearContext();
227     }
228
229     m_iconDatabase->invalidate();
230     m_iconDatabase->clearContext();
231     
232 #if ENABLE(NETSCAPE_PLUGIN_API)
233     m_pluginSiteDataManager->invalidate();
234     m_pluginSiteDataManager->clearContext();
235 #endif
236
237     invalidateCallbackMap(m_dictionaryCallbacks);
238
239     platformInvalidateContext();
240
241 #if ENABLE(NETSCAPE_PLUGIN_API)
242     m_pluginInfoStore.setClient(0);
243 #endif
244
245 #ifndef NDEBUG
246     webContextCounter.decrement();
247 #endif
248 }
249
250 void WebContext::initializeClient(const WKContextClientBase* client)
251 {
252     m_client.initialize(client);
253 }
254
255 void WebContext::initializeInjectedBundleClient(const WKContextInjectedBundleClientBase* client)
256 {
257     m_injectedBundleClient.initialize(client);
258 }
259
260 void WebContext::initializeConnectionClient(const WKContextConnectionClientBase* client)
261 {
262     m_connectionClient.initialize(client);
263 }
264
265 void WebContext::initializeHistoryClient(const WKContextHistoryClientBase* client)
266 {
267     m_historyClient.initialize(client);
268
269     sendToAllProcesses(Messages::WebProcess::SetShouldTrackVisitedLinks(m_historyClient.shouldTrackVisitedLinks()));
270 }
271
272 void WebContext::initializeDownloadClient(const WKContextDownloadClientBase* client)
273 {
274     m_downloadClient.initialize(client);
275 }
276
277 void WebContext::setProcessModel(ProcessModel processModel)
278 {
279     // Guard against API misuse.
280     if (!m_processes.isEmpty())
281         CRASH();
282     if (processModel != ProcessModelSharedSecondaryProcess && !m_messagesToInjectedBundlePostedToEmptyContext.isEmpty())
283         CRASH();
284
285     m_processModel = processModel;
286 }
287
288 void WebContext::setMaximumNumberOfProcesses(unsigned maximumNumberOfProcesses)
289 {
290     // Guard against API misuse.
291     if (!m_processes.isEmpty())
292         CRASH();
293
294     if (maximumNumberOfProcesses == 0)
295         m_webProcessCountLimit = UINT_MAX;
296     else
297         m_webProcessCountLimit = maximumNumberOfProcesses;
298 }
299
300 CoreIPC::Connection* WebContext::networkingProcessConnection()
301 {
302     switch (m_processModel) {
303     case ProcessModelSharedSecondaryProcess:
304 #if ENABLE(NETWORK_PROCESS)
305         if (m_usesNetworkProcess)
306             return m_networkProcess->connection();
307 #endif
308         return m_processes[0]->connection();
309     case ProcessModelMultipleSecondaryProcesses:
310 #if ENABLE(NETWORK_PROCESS)
311         ASSERT(m_usesNetworkProcess);
312         return m_networkProcess->connection();
313 #else
314         break;
315 #endif
316     }
317     ASSERT_NOT_REACHED();
318     return 0;
319 }
320
321 void WebContext::languageChanged(void* context)
322 {
323     static_cast<WebContext*>(context)->languageChanged();
324 }
325
326 void WebContext::languageChanged()
327 {
328     sendToAllProcesses(Messages::WebProcess::UserPreferredLanguagesChanged(userPreferredLanguages()));
329 }
330
331 void WebContext::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
332 {
333     sendToAllProcesses(Messages::WebProcess::FullKeyboardAccessModeChanged(fullKeyboardAccessEnabled));
334 }
335
336 void WebContext::textCheckerStateChanged()
337 {
338     sendToAllProcesses(Messages::WebProcess::SetTextCheckerState(TextChecker::state()));
339 }
340
341 void WebContext::setUsesNetworkProcess(bool usesNetworkProcess)
342 {
343 #if ENABLE(NETWORK_PROCESS)
344     m_usesNetworkProcess = usesNetworkProcess;
345 #else
346     UNUSED_PARAM(usesNetworkProcess);
347 #endif
348 }
349
350 bool WebContext::usesNetworkProcess() const
351 {
352 #if ENABLE(NETWORK_PROCESS)
353     return m_usesNetworkProcess;
354 #else
355     return false;
356 #endif
357 }
358
359 #if ENABLE(NETWORK_PROCESS)
360 void WebContext::ensureNetworkProcess()
361 {
362     if (m_networkProcess)
363         return;
364
365     m_networkProcess = NetworkProcessProxy::create(*this);
366
367     NetworkProcessCreationParameters parameters;
368
369     parameters.privateBrowsingEnabled = WebPreferences::anyPageGroupsAreUsingPrivateBrowsing();
370
371     parameters.cacheModel = m_cacheModel;
372
373     parameters.diskCacheDirectory = diskCacheDirectory();
374     if (!parameters.diskCacheDirectory.isEmpty())
375         SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle);
376
377     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
378
379     // Add any platform specific parameters
380     platformInitializeNetworkProcess(parameters);
381
382     // Initialize the network process.
383     m_networkProcess->send(Messages::NetworkProcess::InitializeNetworkProcess(parameters), 0);
384 }
385
386 void WebContext::networkProcessCrashed(NetworkProcessProxy* networkProcessProxy)
387 {
388     ASSERT(m_networkProcess);
389     ASSERT(networkProcessProxy == m_networkProcess.get());
390
391     WebContextSupplementMap::const_iterator it = m_supplements.begin();
392     WebContextSupplementMap::const_iterator end = m_supplements.end();
393     for (; it != end; ++it)
394         it->value->processDidClose(networkProcessProxy);
395
396     m_networkProcess = nullptr;
397
398     m_client.networkProcessDidCrash(this);
399 }
400
401 void WebContext::getNetworkProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> reply)
402 {
403     ASSERT(reply);
404
405     ensureNetworkProcess();
406     ASSERT(m_networkProcess);
407
408     m_networkProcess->getNetworkProcessConnection(reply);
409 }
410 #endif
411
412 #if ENABLE(DATABASE_PROCESS)
413 void WebContext::ensureDatabaseProcess()
414 {
415     if (m_databaseProcess)
416         return;
417
418     m_databaseProcess = DatabaseProcessProxy::create(this);
419
420     DatabaseProcessCreationParameters parameters;
421
422     // Indexed databases exist in a subdirectory of the "database directory path."
423     // Currently, the top level of that directory contains entities related to WebSQL databases.
424     // We should fix this, and move WebSQL into a subdirectory (https://bugs.webkit.org/show_bug.cgi?id=124807)
425     // In the meantime, an entity name prefixed with three underscores will not conflict with any WebSQL entities.
426     parameters.indexedDatabaseDirectory = pathByAppendingComponent(databaseDirectory(), "___IndexedDB");
427
428     m_databaseProcess->send(Messages::DatabaseProcess::InitializeDatabaseProcess(parameters), 0);
429 }
430
431 void WebContext::getDatabaseProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetDatabaseProcessConnection::DelayedReply> reply)
432 {
433     ASSERT(reply);
434
435     ensureDatabaseProcess();
436
437     m_databaseProcess->getDatabaseProcessConnection(reply);
438 }
439 #endif
440
441 void WebContext::willStartUsingPrivateBrowsing()
442 {
443     const Vector<WebContext*>& contexts = allContexts();
444     for (size_t i = 0, count = contexts.size(); i < count; ++i)
445         contexts[i]->setAnyPageGroupMightHavePrivateBrowsingEnabled(true);
446 }
447
448 void WebContext::willStopUsingPrivateBrowsing()
449 {
450     const Vector<WebContext*>& contexts = allContexts();
451     for (size_t i = 0, count = contexts.size(); i < count; ++i)
452         contexts[i]->setAnyPageGroupMightHavePrivateBrowsingEnabled(false);
453 }
454
455 void WebContext::setAnyPageGroupMightHavePrivateBrowsingEnabled(bool privateBrowsingEnabled)
456 {
457     m_iconDatabase->setPrivateBrowsingEnabled(privateBrowsingEnabled);
458
459 #if ENABLE(NETWORK_PROCESS)
460     if (usesNetworkProcess() && networkProcess()) {
461         if (privateBrowsingEnabled)
462             networkProcess()->send(Messages::NetworkProcess::EnsurePrivateBrowsingSession(), 0);
463         else
464             networkProcess()->send(Messages::NetworkProcess::DestroyPrivateBrowsingSession(), 0);
465     }
466 #endif // ENABLED(NETWORK_PROCESS)
467
468     if (privateBrowsingEnabled)
469         sendToAllProcesses(Messages::WebProcess::EnsurePrivateBrowsingSession());
470     else
471         sendToAllProcesses(Messages::WebProcess::DestroyPrivateBrowsingSession());
472 }
473
474 void (*s_invalidMessageCallback)(WKStringRef messageName);
475
476 void WebContext::setInvalidMessageCallback(void (*invalidMessageCallback)(WKStringRef messageName))
477 {
478     s_invalidMessageCallback = invalidMessageCallback;
479 }
480
481 void WebContext::didReceiveInvalidMessage(const CoreIPC::StringReference& messageReceiverName, const CoreIPC::StringReference& messageName)
482 {
483     if (!s_invalidMessageCallback)
484         return;
485
486     StringBuilder messageNameStringBuilder;
487     messageNameStringBuilder.append(messageReceiverName.data(), messageReceiverName.size());
488     messageNameStringBuilder.append(".");
489     messageNameStringBuilder.append(messageName.data(), messageName.size());
490
491     s_invalidMessageCallback(toAPI(WebString::create(messageNameStringBuilder.toString()).get()));
492 }
493
494 void WebContext::processDidCachePage(WebProcessProxy* process)
495 {
496     if (m_processWithPageCache && m_processWithPageCache != process)
497         m_processWithPageCache->releasePageCache();
498     m_processWithPageCache = process;
499 }
500
501 WebProcessProxy& WebContext::ensureSharedWebProcess()
502 {
503     ASSERT(m_processModel == ProcessModelSharedSecondaryProcess);
504     if (m_processes.isEmpty())
505         createNewWebProcess();
506     return *m_processes[0];
507 }
508
509 WebProcessProxy& WebContext::createNewWebProcess()
510 {
511 #if ENABLE(NETWORK_PROCESS)
512     if (m_usesNetworkProcess)
513         ensureNetworkProcess();
514 #endif
515
516     RefPtr<WebProcessProxy> process = WebProcessProxy::create(*this);
517
518     WebProcessCreationParameters parameters;
519
520     parameters.injectedBundlePath = injectedBundlePath();
521     if (!parameters.injectedBundlePath.isEmpty())
522         SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle);
523
524     parameters.applicationCacheDirectory = applicationCacheDirectory();
525     if (!parameters.applicationCacheDirectory.isEmpty())
526         SandboxExtension::createHandleForReadWriteDirectory(parameters.applicationCacheDirectory, parameters.applicationCacheDirectoryExtensionHandle);
527
528     parameters.databaseDirectory = databaseDirectory();
529     if (!parameters.databaseDirectory.isEmpty())
530         SandboxExtension::createHandleForReadWriteDirectory(parameters.databaseDirectory, parameters.databaseDirectoryExtensionHandle);
531
532     parameters.localStorageDirectory = localStorageDirectory();
533     if (!parameters.localStorageDirectory.isEmpty())
534         SandboxExtension::createHandleForReadWriteDirectory(parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
535
536     parameters.diskCacheDirectory = diskCacheDirectory();
537     if (!parameters.diskCacheDirectory.isEmpty())
538         SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle);
539
540     parameters.cookieStorageDirectory = cookieStorageDirectory();
541     if (!parameters.cookieStorageDirectory.isEmpty())
542         SandboxExtension::createHandleForReadWriteDirectory(parameters.cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
543
544     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
545
546     parameters.shouldTrackVisitedLinks = m_historyClient.shouldTrackVisitedLinks();
547     parameters.cacheModel = m_cacheModel;
548     parameters.languages = userPreferredLanguages();
549
550     copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegistererdAsEmptyDocument);
551     copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure);
552     copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden);
553     copyToVector(m_schemesToRegisterAsLocal, parameters.urlSchemesRegisteredAsLocal);
554     copyToVector(m_schemesToRegisterAsNoAccess, parameters.urlSchemesRegisteredAsNoAccess);
555     copyToVector(m_schemesToRegisterAsDisplayIsolated, parameters.urlSchemesRegisteredAsDisplayIsolated);
556     copyToVector(m_schemesToRegisterAsCORSEnabled, parameters.urlSchemesRegisteredAsCORSEnabled);
557
558     parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath;
559     parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing;
560     
561     parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty();
562
563     parameters.terminationTimeout = (m_processModel == ProcessModelSharedSecondaryProcess) ? sharedSecondaryProcessShutdownTimeout : 0;
564
565     parameters.textCheckerState = TextChecker::state();
566
567     parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled();
568
569     parameters.defaultRequestTimeoutInterval = WebURLRequest::defaultTimeoutInterval();
570
571 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
572     // FIXME: There should be a generic way for supplements to add to the intialization parameters.
573     supplement<WebNotificationManagerProxy>()->populateCopyOfNotificationPermissions(parameters.notificationPermissions);
574 #endif
575
576 #if ENABLE(NETWORK_PROCESS)
577     parameters.usesNetworkProcess = m_usesNetworkProcess;
578 #endif
579
580     parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy();
581     copyToVector(m_plugInAutoStartProvider.autoStartOrigins(), parameters.plugInAutoStartOrigins);
582
583     // Add any platform specific parameters
584     platformInitializeWebProcess(parameters);
585
586     RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient.getInjectedBundleInitializationUserData(this);
587     if (!injectedBundleInitializationUserData)
588         injectedBundleInitializationUserData = m_injectedBundleInitializationUserData;
589     process->send(Messages::WebProcess::InitializeWebProcess(parameters, WebContextUserMessageEncoder(injectedBundleInitializationUserData.get(), *process)), 0);
590
591     if (WebPreferences::anyPageGroupsAreUsingPrivateBrowsing())
592         process->send(Messages::WebProcess::EnsurePrivateBrowsingSession(), 0);
593
594     m_processes.append(process);
595
596     if (m_processModel == ProcessModelSharedSecondaryProcess) {
597         for (size_t i = 0; i != m_messagesToInjectedBundlePostedToEmptyContext.size(); ++i) {
598             pair<String, RefPtr<API::Object>>& message = m_messagesToInjectedBundlePostedToEmptyContext[i];
599
600             CoreIPC::ArgumentEncoder messageData;
601
602             messageData.encode(message.first);
603             messageData.encode(WebContextUserMessageEncoder(message.second.get(), *process));
604             process->send(Messages::WebProcess::PostInjectedBundleMessage(CoreIPC::DataReference(messageData.buffer(), messageData.bufferSize())), 0);
605         }
606         m_messagesToInjectedBundlePostedToEmptyContext.clear();
607     } else
608         ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());
609
610     return *process;
611 }
612
613 void WebContext::warmInitialProcess()  
614 {
615     if (m_haveInitialEmptyProcess) {
616         ASSERT(!m_processes.isEmpty());
617         return;
618     }
619
620     if (m_processes.size() >= m_webProcessCountLimit)
621         return;
622
623     createNewWebProcess();
624     m_haveInitialEmptyProcess = true;
625 }
626
627 void WebContext::enableProcessTermination()
628 {
629     m_processTerminationEnabled = true;
630     Vector<RefPtr<WebProcessProxy>> processes = m_processes;
631     for (size_t i = 0; i < processes.size(); ++i) {
632         if (shouldTerminate(processes[i].get()))
633             processes[i]->terminate();
634     }
635 }
636
637 bool WebContext::shouldTerminate(WebProcessProxy* process)
638 {
639     ASSERT(m_processes.contains(process));
640
641     if (!m_processTerminationEnabled)
642         return false;
643
644     for (const auto& supplement : m_supplements.values()) {
645         if (!supplement->shouldTerminate(process))
646             return false;
647     }
648
649     return true;
650 }
651
652 void WebContext::processWillOpenConnection(WebProcessProxy* process)
653 {
654     m_storageManager->processWillOpenConnection(process);
655 }
656
657 void WebContext::processWillCloseConnection(WebProcessProxy* process)
658 {
659     m_storageManager->processWillCloseConnection(process);
660 }
661
662 void WebContext::processDidFinishLaunching(WebProcessProxy* process)
663 {
664     ASSERT(m_processes.contains(process));
665
666     m_visitedLinkProvider.processDidFinishLaunching(process);
667
668     // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching
669     // so check if it needs to be started here
670     if (m_memorySamplerEnabled) {
671         SandboxExtension::Handle sampleLogSandboxHandle;        
672         double now = WTF::currentTime();
673         String sampleLogFilePath = String::format("WebProcess%llupid%d", static_cast<unsigned long long>(now), process->processIdentifier());
674         sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
675         
676         process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
677     }
678
679     m_connectionClient.didCreateConnection(this, process->webConnection());
680 }
681
682 void WebContext::disconnectProcess(WebProcessProxy* process)
683 {
684     ASSERT(m_processes.contains(process));
685
686     m_visitedLinkProvider.processDidClose(process);
687
688     if (m_haveInitialEmptyProcess && process == m_processes.last())
689         m_haveInitialEmptyProcess = false;
690
691     // 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.
692     // Clearing everything causes assertion failures, so it's less trouble to skip that for now.
693     if (m_processModel != ProcessModelSharedSecondaryProcess) {
694         RefPtr<WebProcessProxy> protect(process);
695         if (m_processWithPageCache == process)
696             m_processWithPageCache = 0;
697
698         static_cast<WebContextSupplement*>(supplement<WebGeolocationManagerProxy>())->processDidClose(process);
699
700         m_processes.remove(m_processes.find(process));
701         return;
702     }
703
704     WebContextSupplementMap::const_iterator it = m_supplements.begin();
705     WebContextSupplementMap::const_iterator end = m_supplements.end();
706     for (; it != end; ++it)
707         it->value->processDidClose(process);
708
709     // The vector may have the last reference to process proxy, which in turn may have the last reference to the context.
710     // Since vector elements are destroyed in place, we would recurse into WebProcessProxy destructor
711     // if it were invoked from Vector::remove(). RefPtr delays destruction until it's safe.
712     RefPtr<WebProcessProxy> protect(process);
713     if (m_processWithPageCache == process)
714         m_processWithPageCache = 0;
715     m_processes.remove(m_processes.find(process));
716 }
717
718 WebProcessProxy& WebContext::createNewWebProcessRespectingProcessCountLimit()
719 {
720     if (m_processes.size() < m_webProcessCountLimit)
721         return createNewWebProcess();
722
723     // Choose a process with fewest pages, to achieve flat distribution.
724     WebProcessProxy* result = nullptr;
725     unsigned fewestPagesSeen = UINT_MAX;
726     for (unsigned i = 0; i < m_processes.size(); ++i) {
727         if (fewestPagesSeen > m_processes[i]->pages().size()) {
728             result = m_processes[i].get();
729             fewestPagesSeen = m_processes[i]->pages().size();
730         }
731     }
732     return *result;
733 }
734
735 PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient& pageClient, WebPageGroup* pageGroup, WebPageProxy* relatedPage)
736 {
737     RefPtr<WebProcessProxy> process;
738     if (m_processModel == ProcessModelSharedSecondaryProcess) {
739         process = &ensureSharedWebProcess();
740     } else {
741         if (m_haveInitialEmptyProcess) {
742             process = m_processes.last();
743             m_haveInitialEmptyProcess = false;
744         } else if (relatedPage) {
745             // Sharing processes, e.g. when creating the page via window.open().
746             process = &relatedPage->process();
747         } else
748             process = &createNewWebProcessRespectingProcessCountLimit();
749     }
750
751     return process->createWebPage(pageClient, pageGroup ? *pageGroup : m_defaultPageGroup.get());
752 }
753
754 DownloadProxy* WebContext::download(WebPageProxy* initiatingPage, const ResourceRequest& request)
755 {
756     DownloadProxy* downloadProxy = createDownloadProxy();
757     uint64_t initiatingPageID = initiatingPage ? initiatingPage->pageID() : 0;
758
759 #if ENABLE(NETWORK_PROCESS)
760     if (usesNetworkProcess() && networkProcess()) {
761         // FIXME (NetworkProcess): Replicate whatever FrameLoader::setOriginalURLForDownloadRequest does with the request here.
762         networkProcess()->connection()->send(Messages::NetworkProcess::DownloadRequest(downloadProxy->downloadID(), request), 0);
763         return downloadProxy;
764     }
765 #endif
766
767     m_processes[0]->send(Messages::WebProcess::DownloadRequest(downloadProxy->downloadID(), initiatingPageID, request), 0);
768     return downloadProxy;
769 }
770
771 void WebContext::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
772 {
773     if (m_processes.isEmpty()) {
774         if (m_processModel == ProcessModelSharedSecondaryProcess)
775             m_messagesToInjectedBundlePostedToEmptyContext.append(std::make_pair(messageName, messageBody));
776         return;
777     }
778
779     for (auto process : m_processes) {
780         // FIXME: Return early if the message body contains any references to WKPageRefs/WKFrameRefs etc. since they're local to a process.
781         CoreIPC::ArgumentEncoder messageData;
782         messageData.encode(messageName);
783         messageData.encode(WebContextUserMessageEncoder(messageBody, *process.get()));
784
785         process->send(Messages::WebProcess::PostInjectedBundleMessage(CoreIPC::DataReference(messageData.buffer(), messageData.bufferSize())), 0);
786     }
787 }
788
789 // InjectedBundle client
790
791 void WebContext::didReceiveMessageFromInjectedBundle(const String& messageName, API::Object* messageBody)
792 {
793     m_injectedBundleClient.didReceiveMessageFromInjectedBundle(this, messageName, messageBody);
794 }
795
796 void WebContext::didReceiveSynchronousMessageFromInjectedBundle(const String& messageName, API::Object* messageBody, RefPtr<API::Object>& returnData)
797 {
798     m_injectedBundleClient.didReceiveSynchronousMessageFromInjectedBundle(this, messageName, messageBody, returnData);
799 }
800
801 void WebContext::populateVisitedLinks()
802 {
803     m_historyClient.populateVisitedLinks(this);
804 }
805
806 WebContext::Statistics& WebContext::statistics()
807 {
808     static Statistics statistics = Statistics();
809
810     return statistics;
811 }
812
813 #if ENABLE(NETSCAPE_PLUGIN_API)
814 void WebContext::setAdditionalPluginsDirectory(const String& directory)
815 {
816     Vector<String> directories;
817     directories.append(directory);
818
819     m_pluginInfoStore.setAdditionalPluginsDirectories(directories);
820 }
821 #endif // ENABLE(NETSCAPE_PLUGIN_API)
822
823 void WebContext::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
824 {
825     m_alwaysUsesComplexTextCodePath = alwaysUseComplexText;
826     sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText));
827 }
828
829 void WebContext::setShouldUseFontSmoothing(bool useFontSmoothing)
830 {
831     m_shouldUseFontSmoothing = useFontSmoothing;
832     sendToAllProcesses(Messages::WebProcess::SetShouldUseFontSmoothing(useFontSmoothing));
833 }
834
835 void WebContext::registerURLSchemeAsEmptyDocument(const String& urlScheme)
836 {
837     m_schemesToRegisterAsEmptyDocument.add(urlScheme);
838     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme));
839 }
840
841 void WebContext::registerURLSchemeAsSecure(const String& urlScheme)
842 {
843     m_schemesToRegisterAsSecure.add(urlScheme);
844     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme));
845 }
846
847 void WebContext::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme)
848 {
849     m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme);
850     sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme));
851 }
852
853 void WebContext::registerURLSchemeAsLocal(const String& urlScheme)
854 {
855     m_schemesToRegisterAsLocal.add(urlScheme);
856     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsLocal(urlScheme));
857 }
858
859 void WebContext::registerURLSchemeAsNoAccess(const String& urlScheme)
860 {
861     m_schemesToRegisterAsNoAccess.add(urlScheme);
862     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsNoAccess(urlScheme));
863 }
864
865 void WebContext::registerURLSchemeAsDisplayIsolated(const String& urlScheme)
866 {
867     m_schemesToRegisterAsDisplayIsolated.add(urlScheme);
868     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
869 }
870
871 void WebContext::registerURLSchemeAsCORSEnabled(const String& urlScheme)
872 {
873     m_schemesToRegisterAsCORSEnabled.add(urlScheme);
874     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
875 }
876
877 void WebContext::setCacheModel(CacheModel cacheModel)
878 {
879     m_cacheModel = cacheModel;
880     sendToAllProcesses(Messages::WebProcess::SetCacheModel(static_cast<uint32_t>(m_cacheModel)));
881
882     // FIXME: Inform the Network Process if in use.
883 }
884
885 void WebContext::setDefaultRequestTimeoutInterval(double timeoutInterval)
886 {
887     sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
888 }
889
890 void WebContext::addVisitedLink(const String& visitedURL)
891 {
892     if (visitedURL.isEmpty())
893         return;
894
895     LinkHash linkHash = visitedLinkHash(visitedURL);
896     addVisitedLinkHash(linkHash);
897 }
898
899 void WebContext::addVisitedLinkHash(LinkHash linkHash)
900 {
901     m_visitedLinkProvider.addVisitedLink(linkHash);
902 }
903
904 DownloadProxy* WebContext::createDownloadProxy()
905 {
906 #if ENABLE(NETWORK_PROCESS)
907     if (usesNetworkProcess())
908         return m_networkProcess->createDownloadProxy();
909 #endif
910
911     return ensureSharedWebProcess().createDownloadProxy();
912 }
913
914 void WebContext::addMessageReceiver(CoreIPC::StringReference messageReceiverName, CoreIPC::MessageReceiver* messageReceiver)
915 {
916     m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
917 }
918
919 void WebContext::addMessageReceiver(CoreIPC::StringReference messageReceiverName, uint64_t destinationID, CoreIPC::MessageReceiver* messageReceiver)
920 {
921     m_messageReceiverMap.addMessageReceiver(messageReceiverName, destinationID, messageReceiver);
922 }
923
924 void WebContext::removeMessageReceiver(CoreIPC::StringReference messageReceiverName, uint64_t destinationID)
925 {
926     m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
927 }
928
929 bool WebContext::dispatchMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder)
930 {
931     return m_messageReceiverMap.dispatchMessage(connection, decoder);
932 }
933
934 bool WebContext::dispatchSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, std::unique_ptr<CoreIPC::MessageEncoder>& replyEncoder)
935 {
936     return m_messageReceiverMap.dispatchSyncMessage(connection, decoder, replyEncoder);
937 }
938
939 void WebContext::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder)
940 {
941     if (decoder.messageReceiverName() == Messages::WebContext::messageReceiverName()) {
942         didReceiveWebContextMessage(connection, decoder);
943         return;
944     }
945
946     if (decoder.messageReceiverName() == WebContextLegacyMessages::messageReceiverName()
947         && decoder.messageName() == WebContextLegacyMessages::postMessageMessageName()) {
948         String messageName;
949         RefPtr<API::Object> messageBody;
950         WebContextUserMessageDecoder messageBodyDecoder(messageBody, *WebProcessProxy::fromConnection(connection));
951         if (!decoder.decode(messageName))
952             return;
953         if (!decoder.decode(messageBodyDecoder))
954             return;
955
956         didReceiveMessageFromInjectedBundle(messageName, messageBody.get());
957         return;
958     }
959
960     ASSERT_NOT_REACHED();
961 }
962
963 void WebContext::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, std::unique_ptr<CoreIPC::MessageEncoder>& replyEncoder)
964 {
965     if (decoder.messageReceiverName() == Messages::WebContext::messageReceiverName()) {
966         didReceiveSyncWebContextMessage(connection, decoder, replyEncoder);
967         return;
968     }
969
970     if (decoder.messageReceiverName() == WebContextLegacyMessages::messageReceiverName()
971         && decoder.messageName() == WebContextLegacyMessages::postSynchronousMessageMessageName()) {
972         // FIXME: We should probably encode something in the case that the arguments do not decode correctly.
973
974         WebProcessProxy* process = WebProcessProxy::fromConnection(connection);
975
976         String messageName;
977         RefPtr<API::Object> messageBody;
978         WebContextUserMessageDecoder messageBodyDecoder(messageBody, *process);
979         if (!decoder.decode(messageName))
980             return;
981         if (!decoder.decode(messageBodyDecoder))
982             return;
983
984         RefPtr<API::Object> returnData;
985         didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody.get(), returnData);
986         replyEncoder->encode(WebContextUserMessageEncoder(returnData.get(), *process));
987         return;
988     }
989
990     ASSERT_NOT_REACHED();
991 }
992
993 void WebContext::setEnhancedAccessibility(bool flag)
994 {
995     sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag));
996 }
997     
998 void WebContext::startMemorySampler(const double interval)
999 {    
1000     // For new WebProcesses we will also want to start the Memory Sampler
1001     m_memorySamplerEnabled = true;
1002     m_memorySamplerInterval = interval;
1003     
1004     // For UIProcess
1005 #if ENABLE(MEMORY_SAMPLER)
1006     WebMemorySampler::shared()->start(interval);
1007 #endif
1008     
1009     // For WebProcess
1010     SandboxExtension::Handle sampleLogSandboxHandle;    
1011     double now = WTF::currentTime();
1012     String sampleLogFilePath = String::format("WebProcess%llu", static_cast<unsigned long long>(now));
1013     sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
1014     
1015     sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
1016 }
1017
1018 void WebContext::stopMemorySampler()
1019 {    
1020     // For WebProcess
1021     m_memorySamplerEnabled = false;
1022     
1023     // For UIProcess
1024 #if ENABLE(MEMORY_SAMPLER)
1025     WebMemorySampler::shared()->stop();
1026 #endif
1027
1028     sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
1029 }
1030
1031 String WebContext::applicationCacheDirectory() const
1032 {
1033     if (!m_overrideApplicationCacheDirectory.isEmpty())
1034         return m_overrideApplicationCacheDirectory;
1035
1036     return platformDefaultApplicationCacheDirectory();
1037 }
1038
1039 String WebContext::databaseDirectory() const
1040 {
1041     if (!m_overrideDatabaseDirectory.isEmpty())
1042         return m_overrideDatabaseDirectory;
1043
1044     return platformDefaultDatabaseDirectory();
1045 }
1046
1047 void WebContext::setIconDatabasePath(const String& path)
1048 {
1049     m_overrideIconDatabasePath = path;
1050     m_iconDatabase->setDatabasePath(path);
1051 }
1052
1053 String WebContext::iconDatabasePath() const
1054 {
1055     if (!m_overrideIconDatabasePath.isEmpty())
1056         return m_overrideIconDatabasePath;
1057
1058     return platformDefaultIconDatabasePath();
1059 }
1060
1061 void WebContext::setLocalStorageDirectory(const String& directory)
1062 {
1063     m_overrideLocalStorageDirectory = directory;
1064     m_storageManager->setLocalStorageDirectory(localStorageDirectory());
1065 }
1066
1067 String WebContext::localStorageDirectory() const
1068 {
1069     if (!m_overrideLocalStorageDirectory.isEmpty())
1070         return m_overrideLocalStorageDirectory;
1071
1072     return platformDefaultLocalStorageDirectory();
1073 }
1074
1075 String WebContext::diskCacheDirectory() const
1076 {
1077     if (!m_overrideDiskCacheDirectory.isEmpty())
1078         return m_overrideDiskCacheDirectory;
1079
1080     return platformDefaultDiskCacheDirectory();
1081 }
1082
1083 String WebContext::cookieStorageDirectory() const
1084 {
1085     if (!m_overrideCookieStorageDirectory.isEmpty())
1086         return m_overrideCookieStorageDirectory;
1087
1088     return platformDefaultCookieStorageDirectory();
1089 }
1090
1091 void WebContext::useTestingNetworkSession()
1092 {
1093     ASSERT(m_processes.isEmpty());
1094 #if ENABLE(NETWORK_PROCESS)
1095     ASSERT(!m_networkProcess);
1096
1097     if (m_networkProcess)
1098         return;
1099 #endif
1100
1101     if (!m_processes.isEmpty())
1102         return;
1103
1104     m_shouldUseTestingNetworkSession = true;
1105 }
1106
1107 void WebContext::allowSpecificHTTPSCertificateForHost(const WebCertificateInfo* certificate, const String& host)
1108 {
1109 #if ENABLE(NETWORK_PROCESS)
1110     if (m_usesNetworkProcess && m_networkProcess) {
1111         m_networkProcess->send(Messages::NetworkProcess::AllowSpecificHTTPSCertificateForHost(certificate->certificateInfo(), host), 0);
1112         return;
1113     }
1114 #else
1115 #if USE(SOUP)
1116     m_processes[0]->send(Messages::WebProcess::AllowSpecificHTTPSCertificateForHost(certificate->certificateInfo(), host), 0);
1117     return;
1118 #else
1119     UNUSED_PARAM(certificate);
1120     UNUSED_PARAM(host);
1121 #endif
1122 #endif
1123
1124 #if !PLATFORM(IOS)
1125     ASSERT_NOT_REACHED();
1126 #endif
1127 }
1128
1129 void WebContext::setHTTPPipeliningEnabled(bool enabled)
1130 {
1131 #if PLATFORM(MAC)
1132     ResourceRequest::setHTTPPipeliningEnabled(enabled);
1133 #else
1134     UNUSED_PARAM(enabled);
1135 #endif
1136 }
1137
1138 bool WebContext::httpPipeliningEnabled() const
1139 {
1140 #if PLATFORM(MAC)
1141     return ResourceRequest::httpPipeliningEnabled();
1142 #else
1143     return false;
1144 #endif
1145 }
1146
1147 void WebContext::getStatistics(uint32_t statisticsMask, PassRefPtr<DictionaryCallback> callback)
1148 {
1149     if (!statisticsMask) {
1150         callback->invalidate();
1151         return;
1152     }
1153
1154     RefPtr<StatisticsRequest> request = StatisticsRequest::create(callback);
1155
1156     if (statisticsMask & StatisticsRequestTypeWebContent)
1157         requestWebContentStatistics(request.get());
1158     
1159     if (statisticsMask & StatisticsRequestTypeNetworking)
1160         requestNetworkingStatistics(request.get());
1161 }
1162
1163 void WebContext::requestWebContentStatistics(StatisticsRequest* request)
1164 {
1165     if (m_processModel == ProcessModelSharedSecondaryProcess) {
1166         if (m_processes.isEmpty())
1167             return;
1168         
1169         uint64_t requestID = request->addOutstandingRequest();
1170         m_statisticsRequests.set(requestID, request);
1171         m_processes[0]->send(Messages::WebProcess::GetWebCoreStatistics(requestID), 0);
1172
1173     } else {
1174         // FIXME (Multi-WebProcess) <rdar://problem/13200059>: Make getting statistics from multiple WebProcesses work.
1175     }
1176 }
1177
1178 void WebContext::requestNetworkingStatistics(StatisticsRequest* request)
1179 {
1180     bool networkProcessUnavailable;
1181 #if ENABLE(NETWORK_PROCESS)
1182     networkProcessUnavailable = !m_usesNetworkProcess || !m_networkProcess;
1183 #else
1184     networkProcessUnavailable = true;
1185 #endif
1186
1187     if (networkProcessUnavailable) {
1188         LOG_ERROR("Attempt to get NetworkProcess statistics but the NetworkProcess is unavailable");
1189         return;
1190     }
1191
1192 #if ENABLE(NETWORK_PROCESS)
1193     uint64_t requestID = request->addOutstandingRequest();
1194     m_statisticsRequests.set(requestID, request);
1195     m_networkProcess->send(Messages::NetworkProcess::GetNetworkProcessStatistics(requestID), 0);
1196 #else
1197     UNUSED_PARAM(request);
1198 #endif
1199 }
1200
1201 #if !PLATFORM(MAC)
1202 void WebContext::dummy(bool&)
1203 {
1204 }
1205 #endif
1206
1207 void WebContext::didGetStatistics(const StatisticsData& statisticsData, uint64_t requestID)
1208 {
1209     RefPtr<StatisticsRequest> request = m_statisticsRequests.take(requestID);
1210     if (!request) {
1211         LOG_ERROR("Cannot report networking statistics.");
1212         return;
1213     }
1214
1215     request->completedRequest(requestID, statisticsData);
1216 }
1217     
1218 void WebContext::garbageCollectJavaScriptObjects()
1219 {
1220     sendToAllProcesses(Messages::WebProcess::GarbageCollectJavaScriptObjects());
1221 }
1222
1223 void WebContext::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1224 {
1225     sendToAllProcesses(Messages::WebProcess::SetJavaScriptGarbageCollectorTimerEnabled(flag));
1226 }
1227
1228 void WebContext::addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash)
1229 {
1230     m_plugInAutoStartProvider.addAutoStartOriginHash(pageOrigin, plugInOriginHash);
1231 }
1232
1233 void WebContext::plugInDidReceiveUserInteraction(unsigned plugInOriginHash)
1234 {
1235     m_plugInAutoStartProvider.didReceiveUserInteraction(plugInOriginHash);
1236 }
1237
1238 PassRefPtr<ImmutableDictionary> WebContext::plugInAutoStartOriginHashes() const
1239 {
1240     return m_plugInAutoStartProvider.autoStartOriginsTableCopy();
1241 }
1242
1243 void WebContext::setPlugInAutoStartOriginHashes(ImmutableDictionary& dictionary)
1244 {
1245     m_plugInAutoStartProvider.setAutoStartOriginsTable(dictionary);
1246 }
1247
1248 void WebContext::setPlugInAutoStartOrigins(API::Array& array)
1249 {
1250     m_plugInAutoStartProvider.setAutoStartOriginsArray(array);
1251 }
1252
1253 #if ENABLE(CUSTOM_PROTOCOLS)
1254 void WebContext::registerSchemeForCustomProtocol(const String& scheme)
1255 {
1256     sendToNetworkingProcess(Messages::CustomProtocolManager::RegisterScheme(scheme));
1257 }
1258
1259 void WebContext::unregisterSchemeForCustomProtocol(const String& scheme)
1260 {
1261     sendToNetworkingProcess(Messages::CustomProtocolManager::UnregisterScheme(scheme));
1262 }
1263 #endif
1264
1265 #if ENABLE(NETSCAPE_PLUGIN_API)
1266 void WebContext::pluginInfoStoreDidLoadPlugins(PluginInfoStore* store)
1267 {
1268 #ifdef NDEBUG
1269     UNUSED_PARAM(store);
1270 #endif
1271     ASSERT(store == &m_pluginInfoStore);
1272
1273     Vector<PluginModuleInfo> pluginModules = m_pluginInfoStore.plugins();
1274
1275     Vector<RefPtr<API::Object>> plugins;
1276     plugins.reserveInitialCapacity(pluginModules.size());
1277
1278     for (const auto& pluginModule : pluginModules) {
1279         ImmutableDictionary::MapType map;
1280         map.set(ASCIILiteral("path"), WebString::create(pluginModule.path));
1281         map.set(ASCIILiteral("name"), WebString::create(pluginModule.info.name));
1282         map.set(ASCIILiteral("file"), WebString::create(pluginModule.info.file));
1283         map.set(ASCIILiteral("desc"), WebString::create(pluginModule.info.desc));
1284
1285         Vector<RefPtr<API::Object>> mimeTypes;
1286         mimeTypes.reserveInitialCapacity(pluginModule.info.mimes.size());
1287         for (const auto& mimeClassInfo : pluginModule.info.mimes)
1288             mimeTypes.uncheckedAppend(WebString::create(mimeClassInfo.type));
1289         map.set(ASCIILiteral("mimes"), API::Array::create(std::move(mimeTypes)));
1290
1291 #if PLATFORM(MAC)
1292         map.set(ASCIILiteral("bundleId"), WebString::create(pluginModule.bundleIdentifier));
1293         map.set(ASCIILiteral("version"), WebString::create(pluginModule.versionString));
1294 #endif
1295
1296         plugins.uncheckedAppend(ImmutableDictionary::adopt(map));
1297     }
1298
1299     m_client.plugInInformationBecameAvailable(this, API::Array::create(std::move(plugins)).get());
1300 }
1301 #endif
1302
1303 } // namespace WebKit