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