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