4bb55852a3784b38e38e39fd2abc1327349b2b2c
[WebKit-https.git] / Source / WebKit2 / UIProcess / WebProcessProxy.cpp
1 /*
2  * Copyright (C) 2010, 2011 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 "WebProcessProxy.h"
28
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"
39 #include "UserData.h"
40 #include "WebBackForwardListItem.h"
41 #include "WebInspectorProxy.h"
42 #include "WebNavigationDataStore.h"
43 #include "WebNotificationManagerProxy.h"
44 #include "WebPageGroup.h"
45 #include "WebPageProxy.h"
46 #include "WebPasteboardProxy.h"
47 #include "WebPluginSiteDataManager.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>
55 #include <stdio.h>
56 #include <wtf/NeverDestroyed.h>
57 #include <wtf/RunLoop.h>
58 #include <wtf/text/CString.h>
59 #include <wtf/text/WTFString.h>
60
61 #if PLATFORM(COCOA)
62 #include "ObjCObjectGraph.h"
63 #include "PDFPlugin.h"
64 #endif
65
66 #if ENABLE(SEC_ITEM_SHIM)
67 #include "SecItemShimProxy.h"
68 #endif
69
70 using namespace WebCore;
71
72 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, connection())
73 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromWebProcess(url), connection())
74
75 namespace WebKit {
76
77 static uint64_t generatePageID()
78 {
79     static uint64_t uniquePageID;
80     return ++uniquePageID;
81 }
82
83 static uint64_t generateCallbackID()
84 {
85     static uint64_t callbackID;
86
87     return ++callbackID;
88 }
89
90 static WebProcessProxy::WebPageProxyMap& globalPageMap()
91 {
92     ASSERT(RunLoop::isMain());
93     static NeverDestroyed<WebProcessProxy::WebPageProxyMap> pageMap;
94     return pageMap;
95 }
96
97 Ref<WebProcessProxy> WebProcessProxy::create(WebProcessPool& processPool)
98 {
99     return adoptRef(*new WebProcessProxy(processPool));
100 }
101
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)
108     , m_throttler(std::make_unique<ProcessThrottler>(this))
109 {
110     WebPasteboardProxy::singleton().addWebProcessProxy(*this);
111
112     connect();
113 }
114
115 WebProcessProxy::~WebProcessProxy()
116 {
117     ASSERT(m_pendingFetchWebsiteDataCallbacks.isEmpty());
118     ASSERT(m_pendingDeleteWebsiteDataCallbacks.isEmpty());
119     ASSERT(m_pendingDeleteWebsiteDataForOriginsCallbacks.isEmpty());
120
121     if (m_webConnection)
122         m_webConnection->invalidate();
123
124     while (m_numberOfTimesSuddenTerminationWasDisabled-- > 0)
125         WebCore::enableSuddenTermination();
126 }
127
128 void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
129 {
130     launchOptions.processType = ProcessLauncher::WebProcess;
131     if (WebInspectorProxy::isInspectorProcessPool(m_processPool))
132         launchOptions.extraInitializationData.add(ASCIILiteral("inspector-process"), ASCIILiteral("1"));
133     platformGetLaunchOptions(launchOptions);
134 }
135
136 void WebProcessProxy::connectionWillOpen(IPC::Connection& connection)
137 {
138     ASSERT(this->connection() == &connection);
139
140 #if ENABLE(SEC_ITEM_SHIM)
141     SecItemShimProxy::singleton().initializeConnection(connection);
142 #endif
143
144     for (auto& page : m_pageMap.values())
145         page->connectionWillOpen(connection);
146 }
147
148 void WebProcessProxy::connectionDidClose(IPC::Connection& connection)
149 {
150     ASSERT(this->connection() == &connection);
151
152     for (const auto& callback : m_pendingFetchWebsiteDataCallbacks.values())
153         callback(WebsiteData());
154     m_pendingFetchWebsiteDataCallbacks.clear();
155
156     for (const auto& callback : m_pendingDeleteWebsiteDataCallbacks.values())
157         callback();
158     m_pendingDeleteWebsiteDataCallbacks.clear();
159
160     for (const auto& callback : m_pendingDeleteWebsiteDataForOriginsCallbacks.values())
161         callback();
162     m_pendingDeleteWebsiteDataForOriginsCallbacks.clear();
163
164     for (auto& page : m_pageMap.values())
165         page->connectionDidClose(connection);
166 }
167
168 void WebProcessProxy::disconnect()
169 {
170     clearConnection();
171
172     if (m_webConnection) {
173         m_webConnection->invalidate();
174         m_webConnection = nullptr;
175     }
176
177     m_responsivenessTimer.invalidate();
178     m_tokenForHoldingLockedFiles = nullptr;
179
180     Vector<RefPtr<WebFrameProxy>> frames;
181     copyValuesToVector(m_frameMap, frames);
182
183     for (size_t i = 0, size = frames.size(); i < size; ++i)
184         frames[i]->disconnect();
185     m_frameMap.clear();
186
187     if (m_downloadProxyMap)
188         m_downloadProxyMap->processDidClose();
189
190     for (VisitedLinkProvider* visitedLinkProvider : m_visitedLinkProviders)
191         visitedLinkProvider->removeProcess(*this);
192     m_visitedLinkProviders.clear();
193
194     for (WebUserContentControllerProxy* webUserContentControllerProxy : m_webUserContentControllerProxies)
195         webUserContentControllerProxy->removeProcess(*this);
196     m_webUserContentControllerProxies.clear();
197
198     m_processPool->disconnectProcess(this);
199 }
200
201 WebPageProxy* WebProcessProxy::webPage(uint64_t pageID)
202 {
203     return globalPageMap().get(pageID);
204 }
205
206 Ref<WebPageProxy> WebProcessProxy::createWebPage(PageClient& pageClient, const WebPageConfiguration& configuration)
207 {
208     uint64_t pageID = generatePageID();
209     Ref<WebPageProxy> webPage = WebPageProxy::create(pageClient, *this, pageID, configuration);
210
211     m_pageMap.set(pageID, webPage.ptr());
212     globalPageMap().set(pageID, webPage.ptr());
213
214     return webPage;
215 }
216
217 void WebProcessProxy::addExistingWebPage(WebPageProxy* webPage, uint64_t pageID)
218 {
219     ASSERT(!m_pageMap.contains(pageID));
220     ASSERT(!globalPageMap().contains(pageID));
221
222     m_pageMap.set(pageID, webPage);
223     globalPageMap().set(pageID, webPage);
224 }
225
226 void WebProcessProxy::removeWebPage(uint64_t pageID)
227 {
228     m_pageMap.remove(pageID);
229     globalPageMap().remove(pageID);
230     
231     Vector<uint64_t> itemIDsToRemove;
232     for (auto& idAndItem : m_backForwardListItemMap) {
233         if (idAndItem.value->pageID() == pageID)
234             itemIDsToRemove.append(idAndItem.key);
235     }
236     for (auto itemID : itemIDsToRemove)
237         m_backForwardListItemMap.remove(itemID);
238
239     // If this was the last WebPage open in that web process, and we have no other reason to keep it alive, let it go.
240     // We only allow this when using a network process, as otherwise the WebProcess needs to preserve its session state.
241     if (!m_processPool->usesNetworkProcess() || state() == State::Terminated || !canTerminateChildProcess())
242         return;
243
244     abortProcessLaunchIfNeeded();
245
246 #if PLATFORM(IOS)
247     if (state() == State::Running) {
248         // On iOS deploy a watchdog in the UI process, since the content may be suspended.
249         // 30s should be sufficient for any outstanding activity to complete cleanly.
250         connection()->terminateSoon(30);
251     }
252 #endif
253
254     disconnect();
255 }
256
257 void WebProcessProxy::addVisitedLinkProvider(VisitedLinkProvider& provider)
258 {
259     m_visitedLinkProviders.add(&provider);
260     provider.addProcess(*this);
261 }
262
263 void WebProcessProxy::addWebUserContentControllerProxy(WebUserContentControllerProxy& proxy)
264 {
265     m_webUserContentControllerProxies.add(&proxy);
266     proxy.addProcess(*this);
267 }
268
269 void WebProcessProxy::didDestroyVisitedLinkProvider(VisitedLinkProvider& provider)
270 {
271     ASSERT(m_visitedLinkProviders.contains(&provider));
272     m_visitedLinkProviders.remove(&provider);
273 }
274
275 void WebProcessProxy::didDestroyWebUserContentControllerProxy(WebUserContentControllerProxy& proxy)
276 {
277     ASSERT(m_webUserContentControllerProxies.contains(&proxy));
278     m_webUserContentControllerProxies.remove(&proxy);
279 }
280
281 WebBackForwardListItem* WebProcessProxy::webBackForwardItem(uint64_t itemID) const
282 {
283     return m_backForwardListItemMap.get(itemID);
284 }
285
286 void WebProcessProxy::registerNewWebBackForwardListItem(WebBackForwardListItem* item)
287 {
288     // This item was just created by the UIProcess and is being added to the map for the first time
289     // so we should not already have an item for this ID.
290     ASSERT(!m_backForwardListItemMap.contains(item->itemID()));
291
292     m_backForwardListItemMap.set(item->itemID(), item);
293 }
294
295 void WebProcessProxy::removeBackForwardItem(uint64_t itemID)
296 {
297     m_backForwardListItemMap.remove(itemID);
298 }
299
300 void WebProcessProxy::assumeReadAccessToBaseURL(const String& urlString)
301 {
302     URL url(URL(), urlString);
303     if (!url.isLocalFile())
304         return;
305
306     // There's a chance that urlString does not point to a directory.
307     // Get url's base URL to add to m_localPathsWithAssumedReadAccess.
308     URL baseURL(URL(), url.baseAsString());
309     
310     // Client loads an alternate string. This doesn't grant universal file read, but the web process is assumed
311     // to have read access to this directory already.
312     m_localPathsWithAssumedReadAccess.add(baseURL.fileSystemPath());
313 }
314
315 bool WebProcessProxy::hasAssumedReadAccessToURL(const URL& url) const
316 {
317     if (!url.isLocalFile())
318         return false;
319
320     String path = url.fileSystemPath();
321     for (const String& assumedAccessPath : m_localPathsWithAssumedReadAccess) {
322         // There are no ".." components, because URL removes those.
323         if (path.startsWith(assumedAccessPath))
324             return true;
325     }
326
327     return false;
328 }
329
330 bool WebProcessProxy::checkURLReceivedFromWebProcess(const String& urlString)
331 {
332     return checkURLReceivedFromWebProcess(URL(URL(), urlString));
333 }
334
335 bool WebProcessProxy::checkURLReceivedFromWebProcess(const URL& url)
336 {
337     // 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.
338
339     // Any other non-file URL is OK.
340     if (!url.isLocalFile())
341         return true;
342
343     // Any file URL is also OK if we've loaded a file URL through API before, granting universal read access.
344     if (m_mayHaveUniversalFileReadSandboxExtension)
345         return true;
346
347     // If we loaded a string with a file base URL before, loading resources from that subdirectory is fine.
348     if (hasAssumedReadAccessToURL(url))
349         return true;
350
351     // Items in back/forward list have been already checked.
352     // 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.
353     String path = url.fileSystemPath();
354     for (WebBackForwardListItemMap::iterator iter = m_backForwardListItemMap.begin(), end = m_backForwardListItemMap.end(); iter != end; ++iter) {
355         URL itemURL(URL(), iter->value->url());
356         if (itemURL.isLocalFile() && itemURL.fileSystemPath() == path)
357             return true;
358         URL itemOriginalURL(URL(), iter->value->originalURL());
359         if (itemOriginalURL.isLocalFile() && itemOriginalURL.fileSystemPath() == path)
360             return true;
361     }
362
363     // A Web process that was never asked to load a file URL should not ever ask us to do anything with a file URL.
364     WTFLogAlways("Received an unexpected URL from the web process: '%s'\n", url.string().utf8().data());
365     return false;
366 }
367
368 #if !PLATFORM(COCOA)
369 bool WebProcessProxy::fullKeyboardAccessEnabled()
370 {
371     return false;
372 }
373 #endif
374
375 void WebProcessProxy::addBackForwardItem(uint64_t itemID, uint64_t pageID, const PageState& pageState)
376 {
377     MESSAGE_CHECK_URL(pageState.mainFrameState.originalURLString);
378     MESSAGE_CHECK_URL(pageState.mainFrameState.urlString);
379
380     auto& backForwardListItem = m_backForwardListItemMap.add(itemID, nullptr).iterator->value;
381     if (!backForwardListItem) {
382         BackForwardListItemState backForwardListItemState;
383         backForwardListItemState.identifier = itemID;
384         backForwardListItemState.pageState = pageState;
385         backForwardListItem = WebBackForwardListItem::create(WTF::move(backForwardListItemState), pageID);
386         return;
387     }
388
389     // Update existing item.
390     backForwardListItem->setPageState(pageState);
391 }
392
393 #if ENABLE(NETSCAPE_PLUGIN_API)
394 void WebProcessProxy::getPlugins(bool refresh, Vector<PluginInfo>& plugins, Vector<PluginInfo>& applicationPlugins)
395 {
396     if (refresh)
397         m_processPool->pluginInfoStore().refresh();
398
399     Vector<PluginModuleInfo> pluginModules = m_processPool->pluginInfoStore().plugins();
400     for (size_t i = 0; i < pluginModules.size(); ++i)
401         plugins.append(pluginModules[i].info);
402
403 #if ENABLE(PDFKIT_PLUGIN)
404     // Add built-in PDF last, so that it's not used when a real plug-in is installed.
405     if (!m_processPool->omitPDFSupport()) {
406         plugins.append(PDFPlugin::pluginInfo());
407         applicationPlugins.append(PDFPlugin::pluginInfo());
408     }
409 #else
410     UNUSED_PARAM(applicationPlugins);
411 #endif
412 }
413 #endif // ENABLE(NETSCAPE_PLUGIN_API)
414
415 #if ENABLE(NETSCAPE_PLUGIN_API)
416 void WebProcessProxy::getPluginProcessConnection(uint64_t pluginProcessToken, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply)
417 {
418     PluginProcessManager::singleton().getPluginProcessConnection(pluginProcessToken, reply);
419 }
420 #endif
421
422 #if ENABLE(NETWORK_PROCESS)
423 void WebProcessProxy::getNetworkProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> reply)
424 {
425     m_processPool->getNetworkProcessConnection(reply);
426 }
427 #endif // ENABLE(NETWORK_PROCESS)
428
429 #if ENABLE(DATABASE_PROCESS)
430 void WebProcessProxy::getDatabaseProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetDatabaseProcessConnection::DelayedReply> reply)
431 {
432     m_processPool->getDatabaseProcessConnection(reply);
433 }
434 #endif // ENABLE(DATABASE_PROCESS)
435
436 void WebProcessProxy::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
437 {
438     if (dispatchMessage(connection, decoder))
439         return;
440
441     if (m_processPool->dispatchMessage(connection, decoder))
442         return;
443
444     if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
445         didReceiveWebProcessProxyMessage(connection, decoder);
446         return;
447     }
448
449     // FIXME: Add unhandled message logging.
450 }
451
452 void WebProcessProxy::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
453 {
454     if (dispatchSyncMessage(connection, decoder, replyEncoder))
455         return;
456
457     if (m_processPool->dispatchSyncMessage(connection, decoder, replyEncoder))
458         return;
459
460     if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
461         didReceiveSyncWebProcessProxyMessage(connection, decoder, replyEncoder);
462         return;
463     }
464
465     // FIXME: Add unhandled message logging.
466 }
467
468 void WebProcessProxy::didClose(IPC::Connection&)
469 {
470     // Protect ourselves, as the call to disconnect() below may otherwise cause us
471     // to be deleted before we can finish our work.
472     Ref<WebProcessProxy> protect(*this);
473
474     webConnection()->didClose();
475
476     Vector<RefPtr<WebPageProxy>> pages;
477     copyValuesToVector(m_pageMap, pages);
478
479     disconnect();
480
481     for (size_t i = 0, size = pages.size(); i < size; ++i)
482         pages[i]->processDidCrash();
483
484 }
485
486 void WebProcessProxy::didReceiveInvalidMessage(IPC::Connection& connection, IPC::StringReference messageReceiverName, IPC::StringReference messageName)
487 {
488     WTFLogAlways("Received an invalid message \"%s.%s\" from the web process.\n", messageReceiverName.toString().data(), messageName.toString().data());
489
490     WebProcessPool::didReceiveInvalidMessage(messageReceiverName, messageName);
491
492     // Terminate the WebProcess.
493     terminate();
494
495     // Since we've invalidated the connection we'll never get a IPC::Connection::Client::didClose
496     // callback so we'll explicitly call it here instead.
497     didClose(connection);
498 }
499
500 void WebProcessProxy::didBecomeUnresponsive(ResponsivenessTimer*)
501 {
502     Vector<RefPtr<WebPageProxy>> pages;
503     copyValuesToVector(m_pageMap, pages);
504     for (size_t i = 0, size = pages.size(); i < size; ++i)
505         pages[i]->processDidBecomeUnresponsive();
506 }
507
508 void WebProcessProxy::interactionOccurredWhileUnresponsive(ResponsivenessTimer*)
509 {
510     Vector<RefPtr<WebPageProxy>> pages;
511     copyValuesToVector(m_pageMap, pages);
512     for (size_t i = 0, size = pages.size(); i < size; ++i)
513         pages[i]->interactionOccurredWhileProcessUnresponsive();
514 }
515
516 void WebProcessProxy::didBecomeResponsive(ResponsivenessTimer*)
517 {
518     Vector<RefPtr<WebPageProxy>> pages;
519     copyValuesToVector(m_pageMap, pages);
520     for (size_t i = 0, size = pages.size(); i < size; ++i)
521         pages[i]->processDidBecomeResponsive();
522 }
523
524 void WebProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connection::Identifier connectionIdentifier)
525 {
526     ChildProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
527
528     for (WebPageProxy* page : m_pageMap.values()) {
529         ASSERT(this == &page->process());
530         page->processDidFinishLaunching();
531     }
532
533     m_webConnection = WebConnectionToWebProcess::create(this);
534
535     m_processPool->processDidFinishLaunching(this);
536
537 #if PLATFORM(IOS)
538     xpc_connection_t xpcConnection = connection()->xpcConnection();
539     ASSERT(xpcConnection);
540     m_throttler->didConnectToProcess(xpc_connection_get_pid(xpcConnection));
541 #endif
542
543     initializeNetworkProcessActivityToken();
544 }
545
546 WebFrameProxy* WebProcessProxy::webFrame(uint64_t frameID) const
547 {
548     if (!WebFrameProxyMap::isValidKey(frameID))
549         return 0;
550
551     return m_frameMap.get(frameID);
552 }
553
554 bool WebProcessProxy::canCreateFrame(uint64_t frameID) const
555 {
556     return WebFrameProxyMap::isValidKey(frameID) && !m_frameMap.contains(frameID);
557 }
558
559 void WebProcessProxy::frameCreated(uint64_t frameID, WebFrameProxy* frameProxy)
560 {
561     ASSERT(canCreateFrame(frameID));
562     m_frameMap.set(frameID, frameProxy);
563 }
564
565 void WebProcessProxy::didDestroyFrame(uint64_t frameID)
566 {
567     // If the page is closed before it has had the chance to send the DidCreateMainFrame message
568     // back to the UIProcess, then the frameDestroyed message will still be received because it
569     // gets sent directly to the WebProcessProxy.
570     ASSERT(WebFrameProxyMap::isValidKey(frameID));
571     m_frameMap.remove(frameID);
572 }
573
574 void WebProcessProxy::disconnectFramesFromPage(WebPageProxy* page)
575 {
576     Vector<RefPtr<WebFrameProxy>> frames;
577     copyValuesToVector(m_frameMap, frames);
578     for (size_t i = 0, size = frames.size(); i < size; ++i) {
579         if (frames[i]->page() == page)
580             frames[i]->disconnect();
581     }
582 }
583
584 size_t WebProcessProxy::frameCountInPage(WebPageProxy* page) const
585 {
586     size_t result = 0;
587     for (HashMap<uint64_t, RefPtr<WebFrameProxy>>::const_iterator iter = m_frameMap.begin(); iter != m_frameMap.end(); ++iter) {
588         if (iter->value->page() == page)
589             ++result;
590     }
591     return result;
592 }
593
594 bool WebProcessProxy::canTerminateChildProcess()
595 {
596     if (!m_pageMap.isEmpty())
597         return false;
598
599     if (m_downloadProxyMap && !m_downloadProxyMap->isEmpty())
600         return false;
601
602     if (!m_pendingDeleteWebsiteDataCallbacks.isEmpty())
603         return false;
604
605     if (!m_processPool->shouldTerminate(this))
606         return false;
607
608     return true;
609 }
610
611 void WebProcessProxy::shouldTerminate(bool& shouldTerminate)
612 {
613     shouldTerminate = canTerminateChildProcess();
614     if (shouldTerminate) {
615         // We know that the web process is going to terminate so disconnect it from the process pool.
616         disconnect();
617     }
618 }
619
620 void WebProcessProxy::didFetchWebsiteData(uint64_t callbackID, const WebsiteData& websiteData)
621 {
622     auto callback = m_pendingFetchWebsiteDataCallbacks.take(callbackID);
623     callback(websiteData);
624 }
625
626 void WebProcessProxy::didDeleteWebsiteData(uint64_t callbackID)
627 {
628     auto callback = m_pendingDeleteWebsiteDataCallbacks.take(callbackID);
629     callback();
630 }
631
632 void WebProcessProxy::didDeleteWebsiteDataForOrigins(uint64_t callbackID)
633 {
634     auto callback = m_pendingDeleteWebsiteDataForOriginsCallbacks.take(callbackID);
635     callback();
636 }
637
638 void WebProcessProxy::updateTextCheckerState()
639 {
640     if (canSendMessage())
641         send(Messages::WebProcess::SetTextCheckerState(TextChecker::state()), 0);
642 }
643
644 DownloadProxy* WebProcessProxy::createDownloadProxy(const ResourceRequest& request)
645 {
646 #if ENABLE(NETWORK_PROCESS)
647     ASSERT(!m_processPool->usesNetworkProcess());
648 #endif
649
650     if (!m_downloadProxyMap)
651         m_downloadProxyMap = std::make_unique<DownloadProxyMap>(this);
652
653     return m_downloadProxyMap->createDownloadProxy(m_processPool, request);
654 }
655
656 void WebProcessProxy::didSaveToPageCache()
657 {
658     m_processPool->processDidCachePage(this);
659 }
660
661 void WebProcessProxy::releasePageCache()
662 {
663     if (canSendMessage())
664         send(Messages::WebProcess::ReleasePageCache(), 0);
665 }
666
667 void WebProcessProxy::windowServerConnectionStateChanged()
668 {
669     for (const auto& page : m_pageMap.values())
670         page->viewStateDidChange(ViewState::IsVisuallyIdle);
671 }
672
673 void WebProcessProxy::fetchWebsiteData(SessionID sessionID, WebsiteDataTypes dataTypes, std::function<void (WebsiteData)> completionHandler)
674 {
675     ASSERT(canSendMessage());
676
677     uint64_t callbackID = generateCallbackID();
678     m_pendingFetchWebsiteDataCallbacks.add(callbackID, WTF::move(completionHandler));
679
680     send(Messages::WebProcess::FetchWebsiteData(sessionID, dataTypes, callbackID), 0);
681 }
682
683 void WebProcessProxy::deleteWebsiteData(SessionID sessionID, WebsiteDataTypes dataTypes, std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler)
684 {
685     ASSERT(canSendMessage());
686
687     uint64_t callbackID = generateCallbackID();
688
689     m_pendingDeleteWebsiteDataCallbacks.add(callbackID, WTF::move(completionHandler));
690     send(Messages::WebProcess::DeleteWebsiteData(sessionID, dataTypes, modifiedSince, callbackID), 0);
691 }
692
693 void WebProcessProxy::deleteWebsiteDataForOrigins(SessionID sessionID, WebsiteDataTypes dataTypes, const Vector<RefPtr<WebCore::SecurityOrigin>>& origins, std::function<void ()> completionHandler)
694 {
695     ASSERT(canSendMessage());
696
697     uint64_t callbackID = generateCallbackID();
698     m_pendingDeleteWebsiteDataForOriginsCallbacks.add(callbackID, WTF::move(completionHandler));
699
700     Vector<SecurityOriginData> originData;
701     for (auto& origin : origins)
702         originData.append(SecurityOriginData::fromSecurityOrigin(*origin));
703
704     send(Messages::WebProcess::DeleteWebsiteDataForOrigins(sessionID, dataTypes, originData, callbackID), 0);
705 }
706
707 void WebProcessProxy::requestTermination()
708 {
709     if (state() != State::Running)
710         return;
711
712     ChildProcessProxy::terminate();
713
714     if (webConnection())
715         webConnection()->didClose();
716
717     disconnect();
718 }
719
720 void WebProcessProxy::enableSuddenTermination()
721 {
722     if (state() != State::Running)
723         return;
724
725     ASSERT(m_numberOfTimesSuddenTerminationWasDisabled);
726     WebCore::enableSuddenTermination();
727     --m_numberOfTimesSuddenTerminationWasDisabled;
728 }
729
730 void WebProcessProxy::disableSuddenTermination()
731 {
732     if (state() != State::Running)
733         return;
734
735     WebCore::disableSuddenTermination();
736     ++m_numberOfTimesSuddenTerminationWasDisabled;
737 }
738
739 RefPtr<API::Object> WebProcessProxy::transformHandlesToObjects(API::Object* object)
740 {
741     struct Transformer final : UserData::Transformer {
742         Transformer(WebProcessProxy& webProcessProxy)
743             : m_webProcessProxy(webProcessProxy)
744         {
745         }
746
747         virtual bool shouldTransformObject(const API::Object& object) const override
748         {
749             switch (object.type()) {
750             case API::Object::Type::FrameHandle:
751                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
752
753             case API::Object::Type::PageHandle:
754                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
755
756             case API::Object::Type::PageGroupHandle:
757 #if PLATFORM(COCOA)
758             case API::Object::Type::ObjCObjectGraph:
759 #endif
760                 return true;
761
762             default:
763                 return false;
764             }
765         }
766
767         virtual RefPtr<API::Object> transformObject(API::Object& object) const override
768         {
769             switch (object.type()) {
770             case API::Object::Type::FrameHandle:
771                 ASSERT(static_cast<API::FrameHandle&>(object).isAutoconverting());
772                 return m_webProcessProxy.webFrame(static_cast<API::FrameHandle&>(object).frameID());
773
774             case API::Object::Type::PageGroupHandle:
775                 return WebPageGroup::get(static_cast<API::PageGroupHandle&>(object).webPageGroupData().pageGroupID);
776
777             case API::Object::Type::PageHandle:
778                 ASSERT(static_cast<API::PageHandle&>(object).isAutoconverting());
779                 return m_webProcessProxy.webPage(static_cast<API::PageHandle&>(object).pageID());
780
781 #if PLATFORM(COCOA)
782             case API::Object::Type::ObjCObjectGraph:
783                 return m_webProcessProxy.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));;
784 #endif
785             default:
786                 return &object;
787             }
788         }
789
790         WebProcessProxy& m_webProcessProxy;
791     };
792
793     return UserData::transform(object, Transformer(*this));
794 }
795
796 RefPtr<API::Object> WebProcessProxy::transformObjectsToHandles(API::Object* object)
797 {
798     struct Transformer final : UserData::Transformer {
799         virtual bool shouldTransformObject(const API::Object& object) const override
800         {
801             switch (object.type()) {
802             case API::Object::Type::Frame:
803             case API::Object::Type::Page:
804             case API::Object::Type::PageGroup:
805 #if PLATFORM(COCOA)
806             case API::Object::Type::ObjCObjectGraph:
807 #endif
808                 return true;
809
810             default:
811                 return false;
812             }
813         }
814
815         virtual RefPtr<API::Object> transformObject(API::Object& object) const override
816         {
817             switch (object.type()) {
818             case API::Object::Type::Frame:
819                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrameProxy&>(object).frameID());
820
821             case API::Object::Type::Page:
822                 return API::PageHandle::createAutoconverting(static_cast<const WebPageProxy&>(object).pageID());
823
824             case API::Object::Type::PageGroup:
825                 return API::PageGroupHandle::create(WebPageGroupData(static_cast<const WebPageGroup&>(object).data()));
826
827 #if PLATFORM(COCOA)
828             case API::Object::Type::ObjCObjectGraph:
829                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
830 #endif
831
832             default:
833                 return &object;
834             }
835         }
836     };
837
838     return UserData::transform(object, Transformer());
839 }
840
841 void WebProcessProxy::sendProcessWillSuspend()
842 {
843     if (canSendMessage())
844         send(Messages::WebProcess::ProcessWillSuspend(), 0);
845 }
846
847 void WebProcessProxy::sendCancelProcessWillSuspend()
848 {
849     if (canSendMessage())
850         send(Messages::WebProcess::CancelProcessWillSuspend(), 0);
851 }
852
853 void WebProcessProxy::initializeNetworkProcessActivityToken()
854 {
855 #if PLATFORM(IOS) && ENABLE(NETWORK_PROCESS)
856     if (processPool().usesNetworkProcess())
857         m_tokenForNetworkProcess = processPool().ensureNetworkProcess().throttler().foregroundActivityToken();
858 #endif
859 }
860
861 void WebProcessProxy::sendProcessDidResume()
862 {
863     initializeNetworkProcessActivityToken();
864
865     if (canSendMessage())
866         send(Messages::WebProcess::ProcessDidResume(), 0);
867 }
868     
869 void WebProcessProxy::processReadyToSuspend()
870 {
871     m_throttler->processReadyToSuspend();
872 #if PLATFORM(IOS) && ENABLE(NETWORK_PROCESS)
873     m_tokenForNetworkProcess = nullptr;
874 #endif
875 }
876
877 void WebProcessProxy::didCancelProcessSuspension()
878 {
879     m_throttler->didCancelProcessSuspension();
880 }
881
882 void WebProcessProxy::setIsHoldingLockedFiles(bool isHoldingLockedFiles)
883 {
884     if (!isHoldingLockedFiles) {
885         m_tokenForHoldingLockedFiles = nullptr;
886         return;
887     }
888     if (!m_tokenForHoldingLockedFiles)
889         m_tokenForHoldingLockedFiles = m_throttler->backgroundActivityToken();
890 }
891
892 } // namespace WebKit