2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "WebProcessProxy.h"
29 #include "APIFrameHandle.h"
30 #include "APIPageGroupHandle.h"
31 #include "APIPageHandle.h"
32 #include "CustomProtocolManagerProxyMessages.h"
33 #include "DataReference.h"
34 #include "DownloadProxyMap.h"
35 #include "PluginInfoStore.h"
36 #include "PluginProcessManager.h"
37 #include "TextChecker.h"
38 #include "TextCheckerState.h"
40 #include "WebBackForwardListItem.h"
41 #include "WebIconDatabase.h"
42 #include "WebInspectorProxy.h"
43 #include "WebNavigationDataStore.h"
44 #include "WebNotificationManagerProxy.h"
45 #include "WebPageGroup.h"
46 #include "WebPageProxy.h"
47 #include "WebPasteboardProxy.h"
48 #include "WebProcessMessages.h"
49 #include "WebProcessPool.h"
50 #include "WebProcessProxyMessages.h"
51 #include "WebUserContentControllerProxy.h"
52 #include "WebsiteData.h"
53 #include <WebCore/SuddenTermination.h>
54 #include <WebCore/URL.h>
56 #include <wtf/NeverDestroyed.h>
57 #include <wtf/RunLoop.h>
58 #include <wtf/text/CString.h>
59 #include <wtf/text/WTFString.h>
62 #include "ObjCObjectGraph.h"
63 #include "PDFPlugin.h"
66 #if ENABLE(SEC_ITEM_SHIM)
67 #include "SecItemShimProxy.h"
70 using namespace WebCore;
72 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, connection())
73 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromWebProcess(url), connection())
77 static uint64_t generatePageID()
79 static uint64_t uniquePageID;
80 return ++uniquePageID;
83 static uint64_t generateCallbackID()
85 static uint64_t callbackID;
90 static WebProcessProxy::WebPageProxyMap& globalPageMap()
92 ASSERT(RunLoop::isMain());
93 static NeverDestroyed<WebProcessProxy::WebPageProxyMap> pageMap;
97 Ref<WebProcessProxy> WebProcessProxy::create(WebProcessPool& processPool)
99 return adoptRef(*new WebProcessProxy(processPool));
102 WebProcessProxy::WebProcessProxy(WebProcessPool& processPool)
103 : m_responsivenessTimer(*this)
104 , m_processPool(processPool)
105 , m_mayHaveUniversalFileReadSandboxExtension(false)
106 , m_customProtocolManagerProxy(this, processPool)
107 , m_numberOfTimesSuddenTerminationWasDisabled(0)
110 WebPasteboardProxy::singleton().addWebProcessProxy(*this);
115 WebProcessProxy::~WebProcessProxy()
117 ASSERT(m_pendingFetchWebsiteDataCallbacks.isEmpty());
118 ASSERT(m_pendingDeleteWebsiteDataCallbacks.isEmpty());
119 ASSERT(m_pendingDeleteWebsiteDataForOriginsCallbacks.isEmpty());
120 ASSERT(m_pageURLRetainCountMap.isEmpty());
123 m_webConnection->invalidate();
125 while (m_numberOfTimesSuddenTerminationWasDisabled-- > 0)
126 WebCore::enableSuddenTermination();
129 void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
131 launchOptions.processType = ProcessLauncher::WebProcess;
133 ChildProcessProxy::getLaunchOptions(launchOptions);
135 if (WebInspectorProxy::isInspectorProcessPool(m_processPool))
136 launchOptions.extraInitializationData.add(ASCIILiteral("inspector-process"), ASCIILiteral("1"));
138 auto overrideLanguages = m_processPool->configuration().overrideLanguages();
139 if (overrideLanguages.size()) {
140 StringBuilder languageString;
141 for (size_t i = 0; i < overrideLanguages.size(); ++i) {
143 languageString.append(',');
144 languageString.append(overrideLanguages[i]);
146 launchOptions.extraInitializationData.add(ASCIILiteral("OverrideLanguages"), languageString.toString());
149 platformGetLaunchOptions(launchOptions);
152 void WebProcessProxy::connectionWillOpen(IPC::Connection& connection)
154 ASSERT(this->connection() == &connection);
156 #if ENABLE(SEC_ITEM_SHIM)
157 SecItemShimProxy::singleton().initializeConnection(connection);
160 for (auto& page : m_pageMap.values())
161 page->connectionWillOpen(connection);
164 void WebProcessProxy::processWillShutDown(IPC::Connection& connection)
166 ASSERT_UNUSED(connection, this->connection() == &connection);
168 for (const auto& callback : m_pendingFetchWebsiteDataCallbacks.values())
169 callback(WebsiteData());
170 m_pendingFetchWebsiteDataCallbacks.clear();
172 for (const auto& callback : m_pendingDeleteWebsiteDataCallbacks.values())
174 m_pendingDeleteWebsiteDataCallbacks.clear();
176 for (const auto& callback : m_pendingDeleteWebsiteDataForOriginsCallbacks.values())
178 m_pendingDeleteWebsiteDataForOriginsCallbacks.clear();
180 for (auto& page : m_pageMap.values())
181 page->webProcessWillShutDown();
183 releaseRemainingIconsForPageURLs();
186 void WebProcessProxy::shutDown()
190 if (m_webConnection) {
191 m_webConnection->invalidate();
192 m_webConnection = nullptr;
195 m_responsivenessTimer.invalidate();
196 m_tokenForHoldingLockedFiles = nullptr;
198 Vector<RefPtr<WebFrameProxy>> frames;
199 copyValuesToVector(m_frameMap, frames);
201 for (size_t i = 0, size = frames.size(); i < size; ++i)
202 frames[i]->webProcessWillShutDown();
205 if (m_downloadProxyMap)
206 m_downloadProxyMap->processDidClose();
208 for (VisitedLinkStore* visitedLinkStore : m_visitedLinkStores)
209 visitedLinkStore->removeProcess(*this);
210 m_visitedLinkStores.clear();
212 for (WebUserContentControllerProxy* webUserContentControllerProxy : m_webUserContentControllerProxies)
213 webUserContentControllerProxy->removeProcess(*this);
214 m_webUserContentControllerProxies.clear();
216 m_processPool->disconnectProcess(this);
219 WebPageProxy* WebProcessProxy::webPage(uint64_t pageID)
221 return globalPageMap().get(pageID);
224 Ref<WebPageProxy> WebProcessProxy::createWebPage(PageClient& pageClient, Ref<API::PageConfiguration>&& pageConfiguration)
226 uint64_t pageID = generatePageID();
227 Ref<WebPageProxy> webPage = WebPageProxy::create(pageClient, *this, pageID, WTF::move(pageConfiguration));
229 m_pageMap.set(pageID, webPage.ptr());
230 globalPageMap().set(pageID, webPage.ptr());
235 void WebProcessProxy::addExistingWebPage(WebPageProxy* webPage, uint64_t pageID)
237 ASSERT(!m_pageMap.contains(pageID));
238 ASSERT(!globalPageMap().contains(pageID));
240 m_pageMap.set(pageID, webPage);
241 globalPageMap().set(pageID, webPage);
244 void WebProcessProxy::removeWebPage(uint64_t pageID)
246 m_pageMap.remove(pageID);
247 globalPageMap().remove(pageID);
249 Vector<uint64_t> itemIDsToRemove;
250 for (auto& idAndItem : m_backForwardListItemMap) {
251 if (idAndItem.value->pageID() == pageID)
252 itemIDsToRemove.append(idAndItem.key);
254 for (auto itemID : itemIDsToRemove)
255 m_backForwardListItemMap.remove(itemID);
257 // If this was the last WebPage open in that web process, and we have no other reason to keep it alive, let it go.
258 // We only allow this when using a network process, as otherwise the WebProcess needs to preserve its session state.
259 if (!m_processPool->usesNetworkProcess() || state() == State::Terminated || !canTerminateChildProcess())
265 void WebProcessProxy::addVisitedLinkStore(VisitedLinkStore& store)
267 m_visitedLinkStores.add(&store);
268 store.addProcess(*this);
271 void WebProcessProxy::addWebUserContentControllerProxy(WebUserContentControllerProxy& proxy)
273 m_webUserContentControllerProxies.add(&proxy);
274 proxy.addProcess(*this);
277 void WebProcessProxy::didDestroyVisitedLinkStore(VisitedLinkStore& store)
279 ASSERT(m_visitedLinkStores.contains(&store));
280 m_visitedLinkStores.remove(&store);
283 void WebProcessProxy::didDestroyWebUserContentControllerProxy(WebUserContentControllerProxy& proxy)
285 ASSERT(m_webUserContentControllerProxies.contains(&proxy));
286 m_webUserContentControllerProxies.remove(&proxy);
289 WebBackForwardListItem* WebProcessProxy::webBackForwardItem(uint64_t itemID) const
291 return m_backForwardListItemMap.get(itemID);
294 void WebProcessProxy::registerNewWebBackForwardListItem(WebBackForwardListItem* item)
296 // This item was just created by the UIProcess and is being added to the map for the first time
297 // so we should not already have an item for this ID.
298 ASSERT(!m_backForwardListItemMap.contains(item->itemID()));
300 m_backForwardListItemMap.set(item->itemID(), item);
303 void WebProcessProxy::removeBackForwardItem(uint64_t itemID)
305 m_backForwardListItemMap.remove(itemID);
308 void WebProcessProxy::assumeReadAccessToBaseURL(const String& urlString)
310 URL url(URL(), urlString);
311 if (!url.isLocalFile())
314 // There's a chance that urlString does not point to a directory.
315 // Get url's base URL to add to m_localPathsWithAssumedReadAccess.
316 URL baseURL(URL(), url.baseAsString());
318 // Client loads an alternate string. This doesn't grant universal file read, but the web process is assumed
319 // to have read access to this directory already.
320 m_localPathsWithAssumedReadAccess.add(baseURL.fileSystemPath());
323 bool WebProcessProxy::hasAssumedReadAccessToURL(const URL& url) const
325 if (!url.isLocalFile())
328 String path = url.fileSystemPath();
329 for (const String& assumedAccessPath : m_localPathsWithAssumedReadAccess) {
330 // There are no ".." components, because URL removes those.
331 if (path.startsWith(assumedAccessPath))
338 bool WebProcessProxy::checkURLReceivedFromWebProcess(const String& urlString)
340 return checkURLReceivedFromWebProcess(URL(URL(), urlString));
343 bool WebProcessProxy::checkURLReceivedFromWebProcess(const URL& url)
345 // FIXME: Consider checking that the URL is valid. Currently, WebProcess sends invalid URLs in many cases, but it probably doesn't have good reasons to do that.
347 // Any other non-file URL is OK.
348 if (!url.isLocalFile())
351 // Any file URL is also OK if we've loaded a file URL through API before, granting universal read access.
352 if (m_mayHaveUniversalFileReadSandboxExtension)
355 // If we loaded a string with a file base URL before, loading resources from that subdirectory is fine.
356 if (hasAssumedReadAccessToURL(url))
359 // Items in back/forward list have been already checked.
360 // One case where we don't have sandbox extensions for file URLs in b/f list is if the list has been reinstated after a crash or a browser restart.
361 String path = url.fileSystemPath();
362 for (WebBackForwardListItemMap::iterator iter = m_backForwardListItemMap.begin(), end = m_backForwardListItemMap.end(); iter != end; ++iter) {
363 URL itemURL(URL(), iter->value->url());
364 if (itemURL.isLocalFile() && itemURL.fileSystemPath() == path)
366 URL itemOriginalURL(URL(), iter->value->originalURL());
367 if (itemOriginalURL.isLocalFile() && itemOriginalURL.fileSystemPath() == path)
371 // A Web process that was never asked to load a file URL should not ever ask us to do anything with a file URL.
372 WTFLogAlways("Received an unexpected URL from the web process: '%s'\n", url.string().utf8().data());
377 bool WebProcessProxy::fullKeyboardAccessEnabled()
383 void WebProcessProxy::addBackForwardItem(uint64_t itemID, uint64_t pageID, const PageState& pageState)
385 MESSAGE_CHECK_URL(pageState.mainFrameState.originalURLString);
386 MESSAGE_CHECK_URL(pageState.mainFrameState.urlString);
388 auto& backForwardListItem = m_backForwardListItemMap.add(itemID, nullptr).iterator->value;
389 if (!backForwardListItem) {
390 BackForwardListItemState backForwardListItemState;
391 backForwardListItemState.identifier = itemID;
392 backForwardListItemState.pageState = pageState;
393 backForwardListItem = WebBackForwardListItem::create(WTF::move(backForwardListItemState), pageID);
397 // Update existing item.
398 backForwardListItem->setPageState(pageState);
401 #if ENABLE(NETSCAPE_PLUGIN_API)
402 void WebProcessProxy::getPlugins(bool refresh, Vector<PluginInfo>& plugins, Vector<PluginInfo>& applicationPlugins)
405 m_processPool->pluginInfoStore().refresh();
407 Vector<PluginModuleInfo> pluginModules = m_processPool->pluginInfoStore().plugins();
408 for (size_t i = 0; i < pluginModules.size(); ++i)
409 plugins.append(pluginModules[i].info);
411 #if ENABLE(PDFKIT_PLUGIN)
412 // Add built-in PDF last, so that it's not used when a real plug-in is installed.
413 if (!m_processPool->omitPDFSupport()) {
414 plugins.append(PDFPlugin::pluginInfo());
415 applicationPlugins.append(PDFPlugin::pluginInfo());
418 UNUSED_PARAM(applicationPlugins);
421 #endif // ENABLE(NETSCAPE_PLUGIN_API)
423 #if ENABLE(NETSCAPE_PLUGIN_API)
424 void WebProcessProxy::getPluginProcessConnection(uint64_t pluginProcessToken, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply)
426 PluginProcessManager::singleton().getPluginProcessConnection(pluginProcessToken, reply);
430 void WebProcessProxy::getNetworkProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> reply)
432 m_processPool->getNetworkProcessConnection(reply);
435 #if ENABLE(DATABASE_PROCESS)
436 void WebProcessProxy::getDatabaseProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetDatabaseProcessConnection::DelayedReply> reply)
438 m_processPool->getDatabaseProcessConnection(reply);
440 #endif // ENABLE(DATABASE_PROCESS)
442 void WebProcessProxy::retainIconForPageURL(const String& pageURL)
444 WebIconDatabase* iconDatabase = processPool().iconDatabase();
445 if (!iconDatabase || pageURL.isEmpty())
448 // Track retain counts so we can release them if the WebProcess terminates early.
449 auto result = m_pageURLRetainCountMap.add(pageURL, 1);
450 if (!result.isNewEntry)
451 ++result.iterator->value;
453 iconDatabase->retainIconForPageURL(pageURL);
456 void WebProcessProxy::releaseIconForPageURL(const String& pageURL)
458 WebIconDatabase* iconDatabase = processPool().iconDatabase();
459 if (!iconDatabase || pageURL.isEmpty())
462 // Track retain counts so we can release them if the WebProcess terminates early.
463 auto result = m_pageURLRetainCountMap.find(pageURL);
464 if (result == m_pageURLRetainCountMap.end())
469 m_pageURLRetainCountMap.remove(result);
471 iconDatabase->releaseIconForPageURL(pageURL);
474 void WebProcessProxy::releaseRemainingIconsForPageURLs()
476 WebIconDatabase* iconDatabase = processPool().iconDatabase();
480 for (auto& entry : m_pageURLRetainCountMap) {
481 uint64_t count = entry.value;
482 for (uint64_t i = 0; i < count; ++i)
483 iconDatabase->releaseIconForPageURL(entry.key);
486 m_pageURLRetainCountMap.clear();
489 void WebProcessProxy::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
491 if (dispatchMessage(connection, decoder))
494 if (m_processPool->dispatchMessage(connection, decoder))
497 if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
498 didReceiveWebProcessProxyMessage(connection, decoder);
502 // FIXME: Add unhandled message logging.
505 void WebProcessProxy::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
507 if (dispatchSyncMessage(connection, decoder, replyEncoder))
510 if (m_processPool->dispatchSyncMessage(connection, decoder, replyEncoder))
513 if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
514 didReceiveSyncWebProcessProxyMessage(connection, decoder, replyEncoder);
518 // FIXME: Add unhandled message logging.
521 void WebProcessProxy::didClose(IPC::Connection&)
523 // Protect ourselves, as the call to disconnect() below may otherwise cause us
524 // to be deleted before we can finish our work.
525 Ref<WebProcessProxy> protect(*this);
527 webConnection()->didClose();
529 Vector<RefPtr<WebPageProxy>> pages;
530 copyValuesToVector(m_pageMap, pages);
534 for (size_t i = 0, size = pages.size(); i < size; ++i)
535 pages[i]->processDidCrash();
539 void WebProcessProxy::didReceiveInvalidMessage(IPC::Connection& connection, IPC::StringReference messageReceiverName, IPC::StringReference messageName)
541 WTFLogAlways("Received an invalid message \"%s.%s\" from the web process.\n", messageReceiverName.toString().data(), messageName.toString().data());
543 WebProcessPool::didReceiveInvalidMessage(messageReceiverName, messageName);
545 // Terminate the WebProcess.
548 // Since we've invalidated the connection we'll never get a IPC::Connection::Client::didClose
549 // callback so we'll explicitly call it here instead.
550 didClose(connection);
553 void WebProcessProxy::didBecomeUnresponsive()
555 Vector<RefPtr<WebPageProxy>> pages;
556 copyValuesToVector(m_pageMap, pages);
557 for (auto& page : pages)
558 page->processDidBecomeUnresponsive();
561 void WebProcessProxy::didBecomeResponsive()
563 Vector<RefPtr<WebPageProxy>> pages;
564 copyValuesToVector(m_pageMap, pages);
565 for (auto& page : pages)
566 page->processDidBecomeResponsive();
569 void WebProcessProxy::willChangeIsResponsive()
571 Vector<RefPtr<WebPageProxy>> pages;
572 copyValuesToVector(m_pageMap, pages);
573 for (auto& page : pages)
574 page->willChangeProcessIsResponsive();
577 void WebProcessProxy::didChangeIsResponsive()
579 Vector<RefPtr<WebPageProxy>> pages;
580 copyValuesToVector(m_pageMap, pages);
581 for (auto& page : pages)
582 page->didChangeProcessIsResponsive();
585 void WebProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connection::Identifier connectionIdentifier)
587 ChildProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
589 for (WebPageProxy* page : m_pageMap.values()) {
590 ASSERT(this == &page->process());
591 page->processDidFinishLaunching();
594 m_webConnection = WebConnectionToWebProcess::create(this);
596 m_processPool->processDidFinishLaunching(this);
599 xpc_connection_t xpcConnection = connection()->xpcConnection();
600 ASSERT(xpcConnection);
601 m_throttler.didConnectToProcess(xpc_connection_get_pid(xpcConnection));
605 WebFrameProxy* WebProcessProxy::webFrame(uint64_t frameID) const
607 if (!WebFrameProxyMap::isValidKey(frameID))
610 return m_frameMap.get(frameID);
613 bool WebProcessProxy::canCreateFrame(uint64_t frameID) const
615 return WebFrameProxyMap::isValidKey(frameID) && !m_frameMap.contains(frameID);
618 void WebProcessProxy::frameCreated(uint64_t frameID, WebFrameProxy* frameProxy)
620 ASSERT(canCreateFrame(frameID));
621 m_frameMap.set(frameID, frameProxy);
624 void WebProcessProxy::didDestroyFrame(uint64_t frameID)
626 // If the page is closed before it has had the chance to send the DidCreateMainFrame message
627 // back to the UIProcess, then the frameDestroyed message will still be received because it
628 // gets sent directly to the WebProcessProxy.
629 ASSERT(WebFrameProxyMap::isValidKey(frameID));
630 m_frameMap.remove(frameID);
633 void WebProcessProxy::disconnectFramesFromPage(WebPageProxy* page)
635 Vector<RefPtr<WebFrameProxy>> frames;
636 copyValuesToVector(m_frameMap, frames);
637 for (size_t i = 0, size = frames.size(); i < size; ++i) {
638 if (frames[i]->page() == page)
639 frames[i]->webProcessWillShutDown();
643 size_t WebProcessProxy::frameCountInPage(WebPageProxy* page) const
646 for (HashMap<uint64_t, RefPtr<WebFrameProxy>>::const_iterator iter = m_frameMap.begin(); iter != m_frameMap.end(); ++iter) {
647 if (iter->value->page() == page)
653 bool WebProcessProxy::canTerminateChildProcess()
655 if (!m_pageMap.isEmpty())
658 if (m_downloadProxyMap && !m_downloadProxyMap->isEmpty())
661 if (!m_pendingDeleteWebsiteDataCallbacks.isEmpty())
664 if (!m_processPool->shouldTerminate(this))
670 void WebProcessProxy::shouldTerminate(bool& shouldTerminate)
672 shouldTerminate = canTerminateChildProcess();
673 if (shouldTerminate) {
674 // We know that the web process is going to terminate so start shutting it down in the UI process.
679 void WebProcessProxy::didFetchWebsiteData(uint64_t callbackID, const WebsiteData& websiteData)
681 auto callback = m_pendingFetchWebsiteDataCallbacks.take(callbackID);
682 callback(websiteData);
685 void WebProcessProxy::didDeleteWebsiteData(uint64_t callbackID)
687 auto callback = m_pendingDeleteWebsiteDataCallbacks.take(callbackID);
691 void WebProcessProxy::didDeleteWebsiteDataForOrigins(uint64_t callbackID)
693 auto callback = m_pendingDeleteWebsiteDataForOriginsCallbacks.take(callbackID);
697 void WebProcessProxy::updateTextCheckerState()
699 if (canSendMessage())
700 send(Messages::WebProcess::SetTextCheckerState(TextChecker::state()), 0);
703 DownloadProxy* WebProcessProxy::createDownloadProxy(const ResourceRequest& request)
705 ASSERT(!m_processPool->usesNetworkProcess());
707 if (!m_downloadProxyMap)
708 m_downloadProxyMap = std::make_unique<DownloadProxyMap>(this);
710 return m_downloadProxyMap->createDownloadProxy(m_processPool, request);
713 void WebProcessProxy::didSaveToPageCache()
715 m_processPool->processDidCachePage(this);
718 void WebProcessProxy::releasePageCache()
720 if (canSendMessage())
721 send(Messages::WebProcess::ReleasePageCache(), 0);
724 void WebProcessProxy::windowServerConnectionStateChanged()
726 for (const auto& page : m_pageMap.values())
727 page->viewStateDidChange(ViewState::IsVisuallyIdle);
730 void WebProcessProxy::fetchWebsiteData(SessionID sessionID, WebsiteDataTypes dataTypes, std::function<void (WebsiteData)> completionHandler)
732 ASSERT(canSendMessage());
734 uint64_t callbackID = generateCallbackID();
735 auto token = throttler().backgroundActivityToken();
737 m_pendingFetchWebsiteDataCallbacks.add(callbackID, [token, completionHandler](WebsiteData websiteData) {
738 completionHandler(WTF::move(websiteData));
741 send(Messages::WebProcess::FetchWebsiteData(sessionID, dataTypes, callbackID), 0);
744 void WebProcessProxy::deleteWebsiteData(SessionID sessionID, WebsiteDataTypes dataTypes, std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler)
746 ASSERT(canSendMessage());
748 uint64_t callbackID = generateCallbackID();
749 auto token = throttler().backgroundActivityToken();
751 m_pendingDeleteWebsiteDataCallbacks.add(callbackID, [token, completionHandler] {
754 send(Messages::WebProcess::DeleteWebsiteData(sessionID, dataTypes, modifiedSince, callbackID), 0);
757 void WebProcessProxy::deleteWebsiteDataForOrigins(SessionID sessionID, WebsiteDataTypes dataTypes, const Vector<RefPtr<WebCore::SecurityOrigin>>& origins, std::function<void ()> completionHandler)
759 ASSERT(canSendMessage());
761 uint64_t callbackID = generateCallbackID();
762 auto token = throttler().backgroundActivityToken();
764 m_pendingDeleteWebsiteDataForOriginsCallbacks.add(callbackID, [token, completionHandler] {
768 Vector<SecurityOriginData> originData;
769 for (auto& origin : origins)
770 originData.append(SecurityOriginData::fromSecurityOrigin(*origin));
772 send(Messages::WebProcess::DeleteWebsiteDataForOrigins(sessionID, dataTypes, originData, callbackID), 0);
775 void WebProcessProxy::requestTermination()
777 if (state() != State::Running)
780 ChildProcessProxy::terminate();
783 webConnection()->didClose();
788 void WebProcessProxy::enableSuddenTermination()
790 if (state() != State::Running)
793 ASSERT(m_numberOfTimesSuddenTerminationWasDisabled);
794 WebCore::enableSuddenTermination();
795 --m_numberOfTimesSuddenTerminationWasDisabled;
798 void WebProcessProxy::disableSuddenTermination()
800 if (state() != State::Running)
803 WebCore::disableSuddenTermination();
804 ++m_numberOfTimesSuddenTerminationWasDisabled;
807 RefPtr<API::Object> WebProcessProxy::transformHandlesToObjects(API::Object* object)
809 struct Transformer final : UserData::Transformer {
810 Transformer(WebProcessProxy& webProcessProxy)
811 : m_webProcessProxy(webProcessProxy)
815 virtual bool shouldTransformObject(const API::Object& object) const override
817 switch (object.type()) {
818 case API::Object::Type::FrameHandle:
819 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
821 case API::Object::Type::PageHandle:
822 return static_cast<const API::PageHandle&>(object).isAutoconverting();
824 case API::Object::Type::PageGroupHandle:
826 case API::Object::Type::ObjCObjectGraph:
835 virtual RefPtr<API::Object> transformObject(API::Object& object) const override
837 switch (object.type()) {
838 case API::Object::Type::FrameHandle:
839 ASSERT(static_cast<API::FrameHandle&>(object).isAutoconverting());
840 return m_webProcessProxy.webFrame(static_cast<API::FrameHandle&>(object).frameID());
842 case API::Object::Type::PageGroupHandle:
843 return WebPageGroup::get(static_cast<API::PageGroupHandle&>(object).webPageGroupData().pageGroupID);
845 case API::Object::Type::PageHandle:
846 ASSERT(static_cast<API::PageHandle&>(object).isAutoconverting());
847 return m_webProcessProxy.webPage(static_cast<API::PageHandle&>(object).pageID());
850 case API::Object::Type::ObjCObjectGraph:
851 return m_webProcessProxy.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
858 WebProcessProxy& m_webProcessProxy;
861 return UserData::transform(object, Transformer(*this));
864 RefPtr<API::Object> WebProcessProxy::transformObjectsToHandles(API::Object* object)
866 struct Transformer final : UserData::Transformer {
867 virtual bool shouldTransformObject(const API::Object& object) const override
869 switch (object.type()) {
870 case API::Object::Type::Frame:
871 case API::Object::Type::Page:
872 case API::Object::Type::PageGroup:
874 case API::Object::Type::ObjCObjectGraph:
883 virtual RefPtr<API::Object> transformObject(API::Object& object) const override
885 switch (object.type()) {
886 case API::Object::Type::Frame:
887 return API::FrameHandle::createAutoconverting(static_cast<const WebFrameProxy&>(object).frameID());
889 case API::Object::Type::Page:
890 return API::PageHandle::createAutoconverting(static_cast<const WebPageProxy&>(object).pageID());
892 case API::Object::Type::PageGroup:
893 return API::PageGroupHandle::create(WebPageGroupData(static_cast<const WebPageGroup&>(object).data()));
896 case API::Object::Type::ObjCObjectGraph:
897 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
906 return UserData::transform(object, Transformer());
909 void WebProcessProxy::sendProcessWillSuspendImminently()
911 if (!canSendMessage())
914 bool handled = false;
915 sendSync(Messages::WebProcess::ProcessWillSuspendImminently(), Messages::WebProcess::ProcessWillSuspendImminently::Reply(handled), 0, std::chrono::seconds(1));
918 void WebProcessProxy::sendPrepareToSuspend()
920 if (canSendMessage())
921 send(Messages::WebProcess::PrepareToSuspend(), 0);
924 void WebProcessProxy::sendCancelPrepareToSuspend()
926 if (canSendMessage())
927 send(Messages::WebProcess::CancelPrepareToSuspend(), 0);
930 void WebProcessProxy::sendProcessDidResume()
932 if (canSendMessage())
933 send(Messages::WebProcess::ProcessDidResume(), 0);
936 void WebProcessProxy::processReadyToSuspend()
938 m_throttler.processReadyToSuspend();
941 void WebProcessProxy::didCancelProcessSuspension()
943 m_throttler.didCancelProcessSuspension();
946 void WebProcessProxy::reinstateNetworkProcessAssertionState(NetworkProcessProxy& newNetworkProcessProxy)
949 ASSERT(!m_backgroundTokenForNetworkProcess || !m_foregroundTokenForNetworkProcess);
951 // The network process crashed; take new tokens for the new network process.
952 if (m_backgroundTokenForNetworkProcess)
953 m_backgroundTokenForNetworkProcess = newNetworkProcessProxy.throttler().backgroundActivityToken();
954 else if (m_foregroundTokenForNetworkProcess)
955 m_foregroundTokenForNetworkProcess = newNetworkProcessProxy.throttler().foregroundActivityToken();
957 UNUSED_PARAM(newNetworkProcessProxy);
961 void WebProcessProxy::didSetAssertionState(AssertionState state)
964 ASSERT(!m_backgroundTokenForNetworkProcess || !m_foregroundTokenForNetworkProcess);
967 case AssertionState::Suspended:
968 m_foregroundTokenForNetworkProcess = nullptr;
969 m_backgroundTokenForNetworkProcess = nullptr;
970 for (auto& page : m_pageMap.values())
971 page->processWillBecomeSuspended();
974 case AssertionState::Background:
975 if (processPool().usesNetworkProcess())
976 m_backgroundTokenForNetworkProcess = processPool().ensureNetworkProcess().throttler().backgroundActivityToken();
977 m_foregroundTokenForNetworkProcess = nullptr;
980 case AssertionState::Foreground:
981 if (processPool().usesNetworkProcess())
982 m_foregroundTokenForNetworkProcess = processPool().ensureNetworkProcess().throttler().foregroundActivityToken();
983 m_backgroundTokenForNetworkProcess = nullptr;
984 for (auto& page : m_pageMap.values())
985 page->processWillBecomeForeground();
989 ASSERT(!m_backgroundTokenForNetworkProcess || !m_foregroundTokenForNetworkProcess);
995 void WebProcessProxy::setIsHoldingLockedFiles(bool isHoldingLockedFiles)
997 if (!isHoldingLockedFiles) {
998 m_tokenForHoldingLockedFiles = nullptr;
1001 if (!m_tokenForHoldingLockedFiles)
1002 m_tokenForHoldingLockedFiles = m_throttler.backgroundActivityToken();
1005 } // namespace WebKit