[CSSRegions] Fix offsetLeft / offsetTop for elements inside named flow
[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 "DataReference.h"
30 #include "DownloadProxyMap.h"
31 #include "PluginInfoStore.h"
32 #include "PluginProcessManager.h"
33 #include "TextChecker.h"
34 #include "TextCheckerState.h"
35 #include "WebBackForwardListItem.h"
36 #include "WebContext.h"
37 #include "WebNavigationDataStore.h"
38 #include "WebNotificationManagerProxy.h"
39 #include "WebPageProxy.h"
40 #include "WebPluginSiteDataManager.h"
41 #include "WebProcessMessages.h"
42 #include "WebProcessProxyMessages.h"
43 #include <WebCore/KURL.h>
44 #include <WebCore/SuddenTermination.h>
45 #include <stdio.h>
46 #include <wtf/MainThread.h>
47 #include <wtf/text/CString.h>
48 #include <wtf/text/WTFString.h>
49
50 #if PLATFORM(MAC)
51 #include "SimplePDFPlugin.h"
52 #if ENABLE(PDFKIT_PLUGIN)
53 #include "PDFPlugin.h"
54 #endif
55 #endif
56
57 #if ENABLE(CUSTOM_PROTOCOLS)
58 #include "CustomProtocolManagerProxyMessages.h"
59 #endif
60
61 #if USE(SECURITY_FRAMEWORK)
62 #include "SecItemShimProxy.h"
63 #endif
64
65 using namespace WebCore;
66
67 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, connection())
68 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromWebProcess(url), connection())
69
70 namespace WebKit {
71
72 static uint64_t generatePageID()
73 {
74     static uint64_t uniquePageID;
75     return ++uniquePageID;
76 }
77
78 static WebProcessProxy::WebPageProxyMap& globalPageMap()
79 {
80     ASSERT(isMainThread());
81     DEFINE_STATIC_LOCAL(WebProcessProxy::WebPageProxyMap, pageMap, ());
82     return pageMap;
83 }
84
85 PassRefPtr<WebProcessProxy> WebProcessProxy::create(PassRefPtr<WebContext> context)
86 {
87     return adoptRef(new WebProcessProxy(context));
88 }
89
90 WebProcessProxy::WebProcessProxy(PassRefPtr<WebContext> context)
91     : m_responsivenessTimer(this)
92     , m_context(context)
93     , m_mayHaveUniversalFileReadSandboxExtension(false)
94     , m_suddenTerminationCounter(0)
95 #if ENABLE(CUSTOM_PROTOCOLS)
96     , m_customProtocolManagerProxy(this)
97 #endif
98 #if PLATFORM(MAC)
99     , m_processSuppressionEnabled(false)
100 #endif
101 {
102     connect();
103 }
104
105 WebProcessProxy::~WebProcessProxy()
106 {
107     if (m_webConnection)
108         m_webConnection->invalidate();
109 }
110
111 void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
112 {
113     launchOptions.processType = ProcessLauncher::WebProcess;
114     platformGetLaunchOptions(launchOptions);
115 }
116
117 void WebProcessProxy::connectionWillOpen(CoreIPC::Connection* connection)
118 {
119     ASSERT(this->connection() == connection);
120
121 #if USE(SECURITY_FRAMEWORK)
122     SecItemShimProxy::shared().initializeConnection(connection);
123 #endif
124
125     for (WebPageProxyMap::iterator it = m_pageMap.begin(), end = m_pageMap.end(); it != end; ++it)
126         it->value->connectionWillOpen(connection);
127
128     m_context->processWillOpenConnection(this);
129 }
130
131 void WebProcessProxy::connectionWillClose(CoreIPC::Connection* connection)
132 {
133     ASSERT(this->connection() == connection);
134
135     for (WebPageProxyMap::iterator it = m_pageMap.begin(), end = m_pageMap.end(); it != end; ++it)
136         it->value->connectionWillClose(connection);
137
138     m_context->processWillCloseConnection(this);
139 }
140
141 void WebProcessProxy::disconnect()
142 {
143     clearConnection();
144
145     if (m_webConnection) {
146         m_webConnection->invalidate();
147         m_webConnection = nullptr;
148     }
149
150     m_responsivenessTimer.stop();
151
152     Vector<RefPtr<WebFrameProxy>> frames;
153     copyValuesToVector(m_frameMap, frames);
154
155     for (size_t i = 0, size = frames.size(); i < size; ++i)
156         frames[i]->disconnect();
157     m_frameMap.clear();
158
159     if (m_downloadProxyMap)
160         m_downloadProxyMap->processDidClose();
161
162     m_context->disconnectProcess(this);
163 }
164
165 WebPageProxy* WebProcessProxy::webPage(uint64_t pageID)
166 {
167     return globalPageMap().get(pageID);
168 }
169
170 PassRefPtr<WebPageProxy> WebProcessProxy::createWebPage(PageClient* pageClient, WebContext*, WebPageGroup* pageGroup)
171 {
172     uint64_t pageID = generatePageID();
173     RefPtr<WebPageProxy> webPage = WebPageProxy::create(pageClient, this, pageGroup, pageID);
174     m_pageMap.set(pageID, webPage.get());
175     globalPageMap().set(pageID, webPage.get());
176 #if PLATFORM(MAC)
177     if (pageIsProcessSuppressible(webPage.get()))
178         m_processSuppressiblePages.add(pageID);
179     updateProcessSuppressionState();
180 #endif
181     return webPage.release();
182 }
183
184 void WebProcessProxy::addExistingWebPage(WebPageProxy* webPage, uint64_t pageID)
185 {
186     m_pageMap.set(pageID, webPage);
187     globalPageMap().set(pageID, webPage);
188 #if PLATFORM(MAC)
189     if (pageIsProcessSuppressible(webPage))
190         m_processSuppressiblePages.add(pageID);
191     updateProcessSuppressionState();
192 #endif
193 }
194
195 void WebProcessProxy::removeWebPage(uint64_t pageID)
196 {
197     m_pageMap.remove(pageID);
198     globalPageMap().remove(pageID);
199 #if PLATFORM(MAC)
200     m_processSuppressiblePages.remove(pageID);
201     updateProcessSuppressionState();
202 #endif
203
204 #if ENABLE(NETWORK_PROCESS)
205     // Terminate the web process immediately if we have enough information to confidently do so.
206     // This only works if we're using a network process. Otherwise we have to wait for the web process to clean up.
207     if (!m_suddenTerminationCounter && canTerminateChildProcess() && m_context->usesNetworkProcess())
208         requestTermination();
209 #endif
210 }
211
212 Vector<WebPageProxy*> WebProcessProxy::pages() const
213 {
214     Vector<WebPageProxy*> result;
215     copyValuesToVector(m_pageMap, result);
216     return result;
217 }
218
219 WebBackForwardListItem* WebProcessProxy::webBackForwardItem(uint64_t itemID) const
220 {
221     return m_backForwardListItemMap.get(itemID);
222 }
223
224 void WebProcessProxy::registerNewWebBackForwardListItem(WebBackForwardListItem* item)
225 {
226     // This item was just created by the UIProcess and is being added to the map for the first time
227     // so we should not already have an item for this ID.
228     ASSERT(!m_backForwardListItemMap.contains(item->itemID()));
229
230     m_backForwardListItemMap.set(item->itemID(), item);
231 }
232
233 void WebProcessProxy::assumeReadAccessToBaseURL(const String& urlString)
234 {
235     KURL url(KURL(), urlString);
236     if (!url.isLocalFile())
237         return;
238
239     // There's a chance that urlString does not point to a directory.
240     // Get url's base URL to add to m_localPathsWithAssumedReadAccess.
241     KURL baseURL(KURL(), url.baseAsString());
242     
243     // Client loads an alternate string. This doesn't grant universal file read, but the web process is assumed
244     // to have read access to this directory already.
245     m_localPathsWithAssumedReadAccess.add(baseURL.fileSystemPath());
246 }
247
248 bool WebProcessProxy::checkURLReceivedFromWebProcess(const String& urlString)
249 {
250     return checkURLReceivedFromWebProcess(KURL(KURL(), urlString));
251 }
252
253 bool WebProcessProxy::checkURLReceivedFromWebProcess(const KURL& url)
254 {
255     // 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.
256
257     // Any other non-file URL is OK.
258     if (!url.isLocalFile())
259         return true;
260
261     // Any file URL is also OK if we've loaded a file URL through API before, granting universal read access.
262     if (m_mayHaveUniversalFileReadSandboxExtension)
263         return true;
264
265     // If we loaded a string with a file base URL before, loading resources from that subdirectory is fine.
266     // There are no ".." components, because all URLs received from WebProcess are parsed with KURL, which removes those.
267     String path = url.fileSystemPath();
268     for (HashSet<String>::const_iterator iter = m_localPathsWithAssumedReadAccess.begin(); iter != m_localPathsWithAssumedReadAccess.end(); ++iter) {
269         if (path.startsWith(*iter))
270             return true;
271     }
272
273     // Items in back/forward list have been already checked.
274     // 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.
275     for (WebBackForwardListItemMap::iterator iter = m_backForwardListItemMap.begin(), end = m_backForwardListItemMap.end(); iter != end; ++iter) {
276         if (KURL(KURL(), iter->value->url()).fileSystemPath() == path)
277             return true;
278         if (KURL(KURL(), iter->value->originalURL()).fileSystemPath() == path)
279             return true;
280     }
281
282     // A Web process that was never asked to load a file URL should not ever ask us to do anything with a file URL.
283     WTFLogAlways("Received an unexpected URL from the web process: '%s'\n", url.string().utf8().data());
284     return false;
285 }
286
287 #if !PLATFORM(MAC)
288 bool WebProcessProxy::fullKeyboardAccessEnabled()
289 {
290     return false;
291 }
292 #endif
293
294 void WebProcessProxy::addBackForwardItem(uint64_t itemID, const String& originalURL, const String& url, const String& title, const CoreIPC::DataReference& backForwardData)
295 {
296     MESSAGE_CHECK_URL(originalURL);
297     MESSAGE_CHECK_URL(url);
298
299     WebBackForwardListItemMap::AddResult result = m_backForwardListItemMap.add(itemID, 0);
300     if (result.isNewEntry) {
301         result.iterator->value = WebBackForwardListItem::create(originalURL, url, title, backForwardData.data(), backForwardData.size(), itemID);
302         return;
303     }
304
305     // Update existing item.
306     result.iterator->value->setOriginalURL(originalURL);
307     result.iterator->value->setURL(url);
308     result.iterator->value->setTitle(title);
309     result.iterator->value->setBackForwardData(backForwardData.data(), backForwardData.size());
310 }
311
312 #if ENABLE(NETSCAPE_PLUGIN_API)
313 void WebProcessProxy::getPlugins(bool refresh, Vector<PluginInfo>& plugins)
314 {
315     if (refresh)
316         m_context->pluginInfoStore().refresh();
317
318     Vector<PluginModuleInfo> pluginModules = m_context->pluginInfoStore().plugins();
319     for (size_t i = 0; i < pluginModules.size(); ++i)
320         plugins.append(pluginModules[i].info);
321
322 #if PLATFORM(MAC)
323     // Add built-in PDF last, so that it's not used when a real plug-in is installed.
324     if (!m_context->omitPDFSupport()) {
325 #if ENABLE(PDFKIT_PLUGIN)
326         plugins.append(PDFPlugin::pluginInfo());
327 #endif
328         plugins.append(SimplePDFPlugin::pluginInfo());
329     }
330 #endif
331 }
332 #endif // ENABLE(NETSCAPE_PLUGIN_API)
333
334 #if ENABLE(PLUGIN_PROCESS)
335 void WebProcessProxy::getPluginProcessConnection(const String& pluginPath, uint32_t processType, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply)
336 {
337     PluginProcessManager::shared().getPluginProcessConnection(m_context->pluginInfoStore(), pluginPath, static_cast<PluginProcess::Type>(processType), reply);
338 }
339
340 #elif ENABLE(NETSCAPE_PLUGIN_API)
341
342 void WebProcessProxy::didGetSitesWithPluginData(const Vector<String>& sites, uint64_t callbackID)
343 {
344     m_context->pluginSiteDataManager()->didGetSitesWithData(sites, callbackID);
345 }
346
347 void WebProcessProxy::didClearPluginSiteData(uint64_t callbackID)
348 {
349     m_context->pluginSiteDataManager()->didClearSiteData(callbackID);
350 }
351
352 #endif
353
354 #if ENABLE(SHARED_WORKER_PROCESS)
355 void WebProcessProxy::getSharedWorkerProcessConnection(const String& /* url */, const String& /* name */, PassRefPtr<Messages::WebProcessProxy::GetSharedWorkerProcessConnection::DelayedReply>)
356 {
357     // FIXME: Implement
358 }
359 #endif // ENABLE(SHARED_WORKER_PROCESS)
360
361 #if ENABLE(NETWORK_PROCESS)
362 void WebProcessProxy::getNetworkProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> reply)
363 {
364     m_context->getNetworkProcessConnection(reply);
365 }
366 #endif // ENABLE(NETWORK_PROCESS)
367
368 void WebProcessProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder)
369 {
370     if (dispatchMessage(connection, decoder))
371         return;
372
373     if (m_context->dispatchMessage(connection, decoder))
374         return;
375
376     if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
377         didReceiveWebProcessProxyMessage(connection, decoder);
378         return;
379     }
380
381     // FIXME: Add unhandled message logging.
382 }
383
384 void WebProcessProxy::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder)
385 {
386     if (dispatchSyncMessage(connection, decoder, replyEncoder))
387         return;
388
389     if (m_context->dispatchSyncMessage(connection, decoder, replyEncoder))
390         return;
391
392     if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
393         didReceiveSyncWebProcessProxyMessage(connection, decoder, replyEncoder);
394         return;
395     }
396
397     // FIXME: Add unhandled message logging.
398 }
399
400 void WebProcessProxy::didClose(CoreIPC::Connection*)
401 {
402     // Protect ourselves, as the call to disconnect() below may otherwise cause us
403     // to be deleted before we can finish our work.
404     RefPtr<WebProcessProxy> protect(this);
405
406     webConnection()->didClose();
407
408     Vector<RefPtr<WebPageProxy>> pages;
409     copyValuesToVector(m_pageMap, pages);
410
411     disconnect();
412
413     for (size_t i = 0, size = pages.size(); i < size; ++i)
414         pages[i]->processDidCrash();
415
416 }
417
418 void WebProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection* connection, CoreIPC::StringReference messageReceiverName, CoreIPC::StringReference messageName)
419 {
420     WTFLogAlways("Received an invalid message \"%s.%s\" from the web process.\n", messageReceiverName.toString().data(), messageName.toString().data());
421
422     WebContext::didReceiveInvalidMessage(messageReceiverName, messageName);
423
424     // Terminate the WebProcess.
425     terminate();
426
427     // Since we've invalidated the connection we'll never get a CoreIPC::Connection::Client::didClose
428     // callback so we'll explicitly call it here instead.
429     didClose(connection);
430 }
431
432 void WebProcessProxy::didBecomeUnresponsive(ResponsivenessTimer*)
433 {
434     Vector<RefPtr<WebPageProxy>> pages;
435     copyValuesToVector(m_pageMap, pages);
436     for (size_t i = 0, size = pages.size(); i < size; ++i)
437         pages[i]->processDidBecomeUnresponsive();
438 }
439
440 void WebProcessProxy::interactionOccurredWhileUnresponsive(ResponsivenessTimer*)
441 {
442     Vector<RefPtr<WebPageProxy>> pages;
443     copyValuesToVector(m_pageMap, pages);
444     for (size_t i = 0, size = pages.size(); i < size; ++i)
445         pages[i]->interactionOccurredWhileProcessUnresponsive();
446 }
447
448 void WebProcessProxy::didBecomeResponsive(ResponsivenessTimer*)
449 {
450     Vector<RefPtr<WebPageProxy>> pages;
451     copyValuesToVector(m_pageMap, pages);
452     for (size_t i = 0, size = pages.size(); i < size; ++i)
453         pages[i]->processDidBecomeResponsive();
454 }
455
456 void WebProcessProxy::didFinishLaunching(ProcessLauncher* launcher, CoreIPC::Connection::Identifier connectionIdentifier)
457 {
458     ChildProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
459
460     m_webConnection = WebConnectionToWebProcess::create(this);
461
462     m_context->processDidFinishLaunching(this);
463
464 #if PLATFORM(MAC)
465     updateProcessSuppressionState();
466 #endif
467 }
468
469 WebFrameProxy* WebProcessProxy::webFrame(uint64_t frameID) const
470 {
471     if (!WebFrameProxyMap::isValidKey(frameID))
472         return 0;
473
474     return m_frameMap.get(frameID);
475 }
476
477 bool WebProcessProxy::canCreateFrame(uint64_t frameID) const
478 {
479     return WebFrameProxyMap::isValidKey(frameID) && !m_frameMap.contains(frameID);
480 }
481
482 void WebProcessProxy::frameCreated(uint64_t frameID, WebFrameProxy* frameProxy)
483 {
484     ASSERT(canCreateFrame(frameID));
485     m_frameMap.set(frameID, frameProxy);
486 }
487
488 void WebProcessProxy::didDestroyFrame(uint64_t frameID)
489 {
490     // If the page is closed before it has had the chance to send the DidCreateMainFrame message
491     // back to the UIProcess, then the frameDestroyed message will still be received because it
492     // gets sent directly to the WebProcessProxy.
493     ASSERT(WebFrameProxyMap::isValidKey(frameID));
494     m_frameMap.remove(frameID);
495 }
496
497 void WebProcessProxy::disconnectFramesFromPage(WebPageProxy* page)
498 {
499     Vector<RefPtr<WebFrameProxy>> frames;
500     copyValuesToVector(m_frameMap, frames);
501     for (size_t i = 0, size = frames.size(); i < size; ++i) {
502         if (frames[i]->page() == page)
503             frames[i]->disconnect();
504     }
505 }
506
507 size_t WebProcessProxy::frameCountInPage(WebPageProxy* page) const
508 {
509     size_t result = 0;
510     for (HashMap<uint64_t, RefPtr<WebFrameProxy>>::const_iterator iter = m_frameMap.begin(); iter != m_frameMap.end(); ++iter) {
511         if (iter->value->page() == page)
512             ++result;
513     }
514     return result;
515 }
516
517 bool WebProcessProxy::canTerminateChildProcess()
518 {
519     if (!m_pageMap.isEmpty())
520         return false;
521
522     if (m_downloadProxyMap && !m_downloadProxyMap->isEmpty())
523         return false;
524
525     if (!m_context->shouldTerminate(this))
526         return false;
527
528     return true;
529 }
530
531 void WebProcessProxy::shouldTerminate(bool& shouldTerminate)
532 {
533     shouldTerminate = canTerminateChildProcess();
534     if (shouldTerminate) {
535         // We know that the web process is going to terminate so disconnect it from the context.
536         disconnect();
537     }
538 }
539
540 void WebProcessProxy::updateTextCheckerState()
541 {
542     if (canSendMessage())
543         send(Messages::WebProcess::SetTextCheckerState(TextChecker::state()), 0);
544 }
545
546 DownloadProxy* WebProcessProxy::createDownloadProxy()
547 {
548 #if ENABLE(NETWORK_PROCESS)
549     ASSERT(!m_context->usesNetworkProcess());
550 #endif
551
552     if (!m_downloadProxyMap)
553         m_downloadProxyMap = adoptPtr(new DownloadProxyMap(this));
554
555     return m_downloadProxyMap->createDownloadProxy(m_context.get());
556 }
557
558 void WebProcessProxy::didNavigateWithNavigationData(uint64_t pageID, const WebNavigationDataStore& store, uint64_t frameID) 
559 {
560     WebPageProxy* page = webPage(pageID);
561     if (!page)
562         return;
563     
564     WebFrameProxy* frame = webFrame(frameID);
565     MESSAGE_CHECK(frame);
566     MESSAGE_CHECK(frame->page() == page);
567     
568     m_context->historyClient().didNavigateWithNavigationData(m_context.get(), page, store, frame);
569 }
570
571 void WebProcessProxy::didPerformClientRedirect(uint64_t pageID, const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
572 {
573     WebPageProxy* page = webPage(pageID);
574     if (!page)
575         return;
576
577     if (sourceURLString.isEmpty() || destinationURLString.isEmpty())
578         return;
579     
580     WebFrameProxy* frame = webFrame(frameID);
581     MESSAGE_CHECK(frame);
582     MESSAGE_CHECK(frame->page() == page);
583     MESSAGE_CHECK_URL(sourceURLString);
584     MESSAGE_CHECK_URL(destinationURLString);
585
586     m_context->historyClient().didPerformClientRedirect(m_context.get(), page, sourceURLString, destinationURLString, frame);
587 }
588
589 void WebProcessProxy::didPerformServerRedirect(uint64_t pageID, const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
590 {
591     WebPageProxy* page = webPage(pageID);
592     if (!page)
593         return;
594     
595     if (sourceURLString.isEmpty() || destinationURLString.isEmpty())
596         return;
597     
598     WebFrameProxy* frame = webFrame(frameID);
599     MESSAGE_CHECK(frame);
600     MESSAGE_CHECK(frame->page() == page);
601     MESSAGE_CHECK_URL(sourceURLString);
602     MESSAGE_CHECK_URL(destinationURLString);
603
604     m_context->historyClient().didPerformServerRedirect(m_context.get(), page, sourceURLString, destinationURLString, frame);
605 }
606
607 void WebProcessProxy::didUpdateHistoryTitle(uint64_t pageID, const String& title, const String& url, uint64_t frameID)
608 {
609     WebPageProxy* page = webPage(pageID);
610     if (!page)
611         return;
612
613     WebFrameProxy* frame = webFrame(frameID);
614     MESSAGE_CHECK(frame);
615     MESSAGE_CHECK(frame->page() == page);
616     MESSAGE_CHECK_URL(url);
617
618     m_context->historyClient().didUpdateHistoryTitle(m_context.get(), page, title, url, frame);
619 }
620
621 void WebProcessProxy::pageVisibilityChanged(WebKit::WebPageProxy *page)
622 {
623 #if PLATFORM(MAC)
624     if (pageIsProcessSuppressible(page))
625         m_processSuppressiblePages.add(page->pageID());
626     else
627         m_processSuppressiblePages.remove(page->pageID());
628     updateProcessSuppressionState();
629 #else
630     UNUSED_PARAM(page);
631 #endif
632 }
633
634 void WebProcessProxy::pagePreferencesChanged(WebKit::WebPageProxy *page)
635 {
636 #if PLATFORM(MAC)
637     if (pageIsProcessSuppressible(page))
638         m_processSuppressiblePages.add(page->pageID());
639     else
640         m_processSuppressiblePages.remove(page->pageID());
641     updateProcessSuppressionState();
642 #else
643     UNUSED_PARAM(page);
644 #endif
645 }
646
647 void WebProcessProxy::didSaveToPageCache()
648 {
649     m_context->processDidCachePage(this);
650 }
651
652 void WebProcessProxy::releasePageCache()
653 {
654     if (canSendMessage())
655         send(Messages::WebProcess::ReleasePageCache(), 0);
656 }
657
658
659 void WebProcessProxy::requestTermination()
660 {
661     ChildProcessProxy::terminate();
662
663     if (webConnection())
664         webConnection()->didClose();
665
666     disconnect();
667 }
668
669
670 void WebProcessProxy::enableSuddenTermination()
671 {
672     if (!isValid())
673         return;
674
675     WebCore::enableSuddenTermination();
676     m_suddenTerminationCounter--;
677 }
678
679 void WebProcessProxy::disableSuddenTermination()
680 {
681     if (!isValid())
682         return;
683
684     WebCore::disableSuddenTermination();
685     m_suddenTerminationCounter++;
686 }
687
688 } // namespace WebKit