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