1/* 2 * Copyright (C) 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 3 * Copyright (C) 2012 Intel Corporation. All rights reserved. 4 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 17 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 25 * THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "config.h" 29#include "WebPage.h" 30 31#include "Arguments.h" 32#include "DataReference.h" 33#include "DragControllerAction.h" 34#include "DrawingArea.h" 35#include "DrawingAreaMessages.h" 36#include "EditingRange.h" 37#include "EditorState.h" 38#include "EventDispatcher.h" 39#include "InjectedBundle.h" 40#include "InjectedBundleBackForwardList.h" 41#include "InjectedBundleUserMessageCoders.h" 42#include "LayerTreeHost.h" 43#include "Logging.h" 44#include "NetscapePlugin.h" 45#include "NotificationPermissionRequestManager.h" 46#include "PageBanner.h" 47#include "PluginProcessAttributes.h" 48#include "PluginProxy.h" 49#include "PluginView.h" 50#include "PrintInfo.h" 51#include "ServicesOverlayController.h" 52#include "SessionState.h" 53#include "SessionStateConversion.h" 54#include "SessionTracker.h" 55#include "ShareableBitmap.h" 56#include "VisitedLinkTableController.h" 57#include "WKBundleAPICast.h" 58#include "WKRetainPtr.h" 59#include "WKSharedAPICast.h" 60#include "WebAlternativeTextClient.h" 61#include "WebBackForwardListItem.h" 62#include "WebBackForwardListProxy.h" 63#include "WebChromeClient.h" 64#include "WebColorChooser.h" 65#include "WebContextMenu.h" 66#include "WebContextMenuClient.h" 67#include "WebContextMessages.h" 68#include "WebCoreArgumentCoders.h" 69#include "WebDocumentLoader.h" 70#include "WebDragClient.h" 71#include "WebEditorClient.h" 72#include "WebEvent.h" 73#include "WebEventConversion.h" 74#include "WebFrame.h" 75#include "WebFrameLoaderClient.h" 76#include "WebFullScreenManager.h" 77#include "WebFullScreenManagerMessages.h" 78#include "WebGeolocationClient.h" 79#include "WebImage.h" 80#include "WebInspector.h" 81#include "WebInspectorClient.h" 82#include "WebInspectorMessages.h" 83#include "WebNotificationClient.h" 84#include "WebOpenPanelResultListener.h" 85#include "WebPageCreationParameters.h" 86#include "WebPageGroupProxy.h" 87#include "WebPageMessages.h" 88#include "WebPageProxyMessages.h" 89#include "WebPlugInClient.h" 90#include "WebPopupMenu.h" 91#include "WebPreferencesDefinitions.h" 92#include "WebPreferencesKeys.h" 93#include "WebPreferencesStore.h" 94#include "WebProcess.h" 95#include "WebProcessProxyMessages.h" 96#include "WebProgressTrackerClient.h" 97#include "WebUndoStep.h" 98#include "WebUserContentController.h" 99#include <JavaScriptCore/APICast.h> 100#include <WebCore/ArchiveResource.h> 101#include <WebCore/Chrome.h> 102#include <WebCore/ContextMenuController.h> 103#include <WebCore/DatabaseManager.h> 104#include <WebCore/DocumentFragment.h> 105#include <WebCore/DocumentLoader.h> 106#include <WebCore/DocumentMarkerController.h> 107#include <WebCore/DragController.h> 108#include <WebCore/DragData.h> 109#include <WebCore/ElementIterator.h> 110#include <WebCore/EventHandler.h> 111#include <WebCore/FocusController.h> 112#include <WebCore/FormState.h> 113#include <WebCore/FrameLoadRequest.h> 114#include <WebCore/FrameLoaderTypes.h> 115#include <WebCore/FrameView.h> 116#include <WebCore/HTMLFormElement.h> 117#include <WebCore/HTMLInputElement.h> 118#include <WebCore/HTMLPlugInElement.h> 119#include <WebCore/HTMLPlugInImageElement.h> 120#include <WebCore/HistoryController.h> 121#include <WebCore/HistoryItem.h> 122#include <WebCore/HitTestResult.h> 123#include <WebCore/JSDOMWindow.h> 124#include <WebCore/KeyboardEvent.h> 125#include <WebCore/MIMETypeRegistry.h> 126#include <WebCore/MainFrame.h> 127#include <WebCore/MouseEvent.h> 128#include <WebCore/Page.h> 129#include <WebCore/PageThrottler.h> 130#include <WebCore/PlatformKeyboardEvent.h> 131#include <WebCore/PluginDocument.h> 132#include <WebCore/PrintContext.h> 133#include <WebCore/Range.h> 134#include <WebCore/RenderLayer.h> 135#include <WebCore/RenderTreeAsText.h> 136#include <WebCore/RenderView.h> 137#include <WebCore/ResourceBuffer.h> 138#include <WebCore/ResourceRequest.h> 139#include <WebCore/ResourceResponse.h> 140#include <WebCore/RuntimeEnabledFeatures.h> 141#include <WebCore/SchemeRegistry.h> 142#include <WebCore/ScriptController.h> 143#include <WebCore/SerializedScriptValue.h> 144#include <WebCore/SessionID.h> 145#include <WebCore/Settings.h> 146#include <WebCore/ShadowRoot.h> 147#include <WebCore/SharedBuffer.h> 148#include <WebCore/SubframeLoader.h> 149#include <WebCore/SubstituteData.h> 150#include <WebCore/TextIterator.h> 151#include <WebCore/UserInputBridge.h> 152#include <WebCore/VisiblePosition.h> 153#include <WebCore/VisibleUnits.h> 154#include <WebCore/markup.h> 155#include <bindings/ScriptValue.h> 156#include <profiler/ProfilerDatabase.h> 157#include <runtime/JSCInlines.h> 158#include <runtime/JSCJSValue.h> 159#include <runtime/JSLock.h> 160#include <wtf/RunLoop.h> 161 162#if ENABLE(MHTML) 163#include <WebCore/MHTMLArchive.h> 164#endif 165 166#if ENABLE(BATTERY_STATUS) 167#include "WebBatteryClient.h" 168#endif 169 170#if ENABLE(VIBRATION) 171#include "WebVibrationClient.h" 172#endif 173 174#if ENABLE(PROXIMITY_EVENTS) 175#include "WebDeviceProximityClient.h" 176#endif 177 178#if PLATFORM(COCOA) 179#include "PDFPlugin.h" 180#include "RemoteLayerTreeTransaction.h" 181#include "WKStringCF.h" 182#include <WebCore/LegacyWebArchive.h> 183#endif 184 185#if PLATFORM(GTK) 186#include <gtk/gtk.h> 187#include "DataObjectGtk.h" 188#include "WebPrintOperationGtk.h" 189#endif 190 191#if PLATFORM(IOS) 192#include "RemoteLayerTreeDrawingArea.h" 193#include "WebVideoFullscreenManager.h" 194#include <CoreGraphics/CoreGraphics.h> 195#include <CoreText/CTFontDescriptorPriv.h> 196#include <CoreText/CTFontPriv.h> 197#include <WebCore/Icon.h> 198#endif 199 200#ifndef NDEBUG 201#include <wtf/RefCountedLeakCounter.h> 202#endif 203 204#if USE(COORDINATED_GRAPHICS) 205#include "CoordinatedLayerTreeHostMessages.h" 206#endif 207 208using namespace JSC; 209using namespace WebCore; 210 211namespace WebKit { 212 213class SendStopResponsivenessTimer { 214public: 215 SendStopResponsivenessTimer(WebPage* page) 216 : m_page(page) 217 { 218 } 219 220 ~SendStopResponsivenessTimer() 221 { 222 m_page->send(Messages::WebPageProxy::StopResponsivenessTimer()); 223 } 224 225private: 226 WebPage* m_page; 227}; 228 229DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageCounter, ("WebPage")); 230 231PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters) 232{ 233 RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters)); 234 235 if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle()) 236 WebProcess::shared().injectedBundle()->didCreatePage(page.get()); 237 238 return page.release(); 239} 240 241WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters) 242 : m_pageID(pageID) 243 , m_viewSize(parameters.viewSize) 244 , m_hasSeenPlugin(false) 245 , m_useFixedLayout(false) 246 , m_drawsBackground(true) 247 , m_drawsTransparentBackground(false) 248 , m_isInRedo(false) 249 , m_isClosed(false) 250 , m_tabToLinks(false) 251 , m_asynchronousPluginInitializationEnabled(false) 252 , m_asynchronousPluginInitializationEnabledForAllPlugins(false) 253 , m_artificialPluginInitializationDelayEnabled(false) 254 , m_scrollingPerformanceLoggingEnabled(false) 255 , m_mainFrameIsScrollable(true) 256#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 257 , m_readyToFindPrimarySnapshottedPlugin(false) 258 , m_didFindPrimarySnapshottedPlugin(false) 259 , m_numberOfPrimarySnapshotDetectionAttempts(0) 260 , m_determinePrimarySnapshottedPlugInTimer(RunLoop::main(), this, &WebPage::determinePrimarySnapshottedPlugInTimerFired) 261#endif 262#if ENABLE(SERVICE_CONTROLS) 263 , m_serviceControlsEnabled(false) 264#endif 265 , m_layerHostingMode(parameters.layerHostingMode) 266#if PLATFORM(COCOA) 267 , m_pdfPluginEnabled(false) 268 , m_hasCachedWindowFrame(false) 269 , m_viewGestureGeometryCollector(*this) 270#elif PLATFORM(GTK) && HAVE(ACCESSIBILITY) 271 , m_accessibilityObject(0) 272#endif 273 , m_setCanStartMediaTimer(RunLoop::main(), this, &WebPage::setCanStartMediaTimerFired) 274 , m_formClient(std::make_unique<API::InjectedBundle::FormClient>()) 275 , m_uiClient(std::make_unique<API::InjectedBundle::PageUIClient>()) 276 , m_findController(this) 277#if ENABLE(INPUT_TYPE_COLOR) 278 , m_activeColorChooser(0) 279#endif 280 , m_userContentController(parameters.userContentControllerID ? WebUserContentController::getOrCreate(parameters.userContentControllerID) : nullptr) 281#if ENABLE(GEOLOCATION) 282 , m_geolocationPermissionRequestManager(this) 283#endif 284 , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel) 285 , m_canRunModal(parameters.canRunModal) 286 , m_isRunningModal(false) 287 , m_cachedMainFrameIsPinnedToLeftSide(true) 288 , m_cachedMainFrameIsPinnedToRightSide(true) 289 , m_cachedMainFrameIsPinnedToTopSide(true) 290 , m_cachedMainFrameIsPinnedToBottomSide(true) 291 , m_canShortCircuitHorizontalWheelEvents(false) 292 , m_numWheelEventHandlers(0) 293 , m_cachedPageCount(0) 294 , m_autoSizingShouldExpandToViewHeight(false) 295#if ENABLE(CONTEXT_MENUS) 296 , m_isShowingContextMenu(false) 297#endif 298#if PLATFORM(IOS) 299 , m_firstLayerTreeTransactionIDAfterDidCommitLoad(0) 300 , m_hasReceivedVisibleContentRectsAfterDidCommitLoad(false) 301 , m_scaleWasSetByUIProcess(false) 302 , m_userHasChangedPageScaleFactor(false) 303 , m_hasStablePageScaleFactor(true) 304 , m_userIsInteracting(false) 305 , m_hasPendingBlurNotification(false) 306 , m_useTestingViewportConfiguration(false) 307 , m_isInStableState(true) 308 , m_oldestNonStableUpdateVisibleContentRectsTimestamp(std::chrono::milliseconds::zero()) 309 , m_estimatedLatency(std::chrono::milliseconds::zero()) 310 , m_screenSize(parameters.screenSize) 311 , m_availableScreenSize(parameters.availableScreenSize) 312 , m_deviceOrientation(0) 313 , m_inDynamicSizeUpdate(false) 314#endif 315 , m_inspectorClient(0) 316 , m_backgroundColor(Color::white) 317 , m_maximumRenderingSuppressionToken(0) 318 , m_scrollPinningBehavior(DoNotPin) 319 , m_useAsyncScrolling(false) 320 , m_viewState(parameters.viewState) 321 , m_processSuppressionDisabledByWebPreference("Process suppression is disabled.") 322 , m_pendingNavigationID(0) 323#if ENABLE(WEBGL) 324 , m_systemWebGLPolicy(WebGLAllowCreation) 325#endif 326 , m_pageOverlayController(*this) 327{ 328 ASSERT(m_pageID); 329 // FIXME: This is a non-ideal location for this Setting and 330 // 4ms should be adopted project-wide now, https://bugs.webkit.org/show_bug.cgi?id=61214 331 Settings::setDefaultMinDOMTimerInterval(0.004); 332 333#if PLATFORM(IOS) 334 Settings::setShouldManageAudioSessionCategory(true); 335#endif 336 337 Page::PageClients pageClients; 338 pageClients.chromeClient = new WebChromeClient(this); 339#if ENABLE(CONTEXT_MENUS) 340 pageClients.contextMenuClient = new WebContextMenuClient(this); 341#endif 342 pageClients.editorClient = new WebEditorClient(this); 343#if ENABLE(DRAG_SUPPORT) 344 pageClients.dragClient = new WebDragClient(this); 345#endif 346 pageClients.backForwardClient = WebBackForwardListProxy::create(this); 347#if ENABLE(INSPECTOR) 348 m_inspectorClient = new WebInspectorClient(this); 349 pageClients.inspectorClient = m_inspectorClient; 350#endif 351#if USE(AUTOCORRECTION_PANEL) 352 pageClients.alternativeTextClient = new WebAlternativeTextClient(this); 353#endif 354 pageClients.plugInClient = new WebPlugInClient(this); 355 pageClients.loaderClientForMainFrame = new WebFrameLoaderClient; 356 pageClients.progressTrackerClient = new WebProgressTrackerClient(*this); 357 358 pageClients.userContentController = m_userContentController ? &m_userContentController->userContentController() : nullptr; 359 pageClients.visitedLinkStore = VisitedLinkTableController::getOrCreate(parameters.visitedLinkTableID); 360 361 m_page = std::make_unique<Page>(pageClients); 362 363 m_drawingArea = DrawingArea::create(*this, parameters); 364 m_drawingArea->setPaintingEnabled(false); 365 m_pageOverlayController.initialize(); 366 367#if ENABLE(ASYNC_SCROLLING) 368 m_useAsyncScrolling = parameters.store.getBoolValueForKey(WebPreferencesKey::threadedScrollingEnabledKey()); 369 if (!m_drawingArea->supportsAsyncScrolling()) 370 m_useAsyncScrolling = false; 371 m_page->settings().setScrollingCoordinatorEnabled(m_useAsyncScrolling); 372#endif 373 374 m_mainFrame = WebFrame::createWithCoreMainFrame(this, &m_page->mainFrame()); 375 376#if ENABLE(BATTERY_STATUS) 377 WebCore::provideBatteryTo(m_page.get(), new WebBatteryClient(this)); 378#endif 379#if ENABLE(GEOLOCATION) 380 WebCore::provideGeolocationTo(m_page.get(), new WebGeolocationClient(this)); 381#endif 382#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 383 WebCore::provideNotification(m_page.get(), new WebNotificationClient(this)); 384#endif 385#if ENABLE(VIBRATION) 386 WebCore::provideVibrationTo(m_page.get(), new WebVibrationClient(this)); 387#endif 388#if ENABLE(PROXIMITY_EVENTS) 389 WebCore::provideDeviceProximityTo(m_page.get(), new WebDeviceProximityClient(this)); 390#endif 391 392#if ENABLE(REMOTE_INSPECTOR) 393 m_page->setRemoteInspectionAllowed(true); 394#endif 395 396 m_page->setCanStartMedia(false); 397 m_mayStartMediaWhenInWindow = parameters.mayStartMediaWhenInWindow; 398 399 m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData); 400 m_page->setGroupName(m_pageGroup->identifier()); 401 m_page->setDeviceScaleFactor(parameters.deviceScaleFactor); 402#if PLATFORM(IOS) 403 m_page->setTextAutosizingWidth(parameters.textAutosizingWidth); 404#endif 405 406 updatePreferences(parameters.store); 407 platformInitialize(); 408 409 setUseFixedLayout(parameters.useFixedLayout); 410 411 setDrawsBackground(parameters.drawsBackground); 412 setDrawsTransparentBackground(parameters.drawsTransparentBackground); 413 414 setUnderlayColor(parameters.underlayColor); 415 416 setPaginationMode(parameters.paginationMode); 417 setPaginationBehavesLikeColumns(parameters.paginationBehavesLikeColumns); 418 setPageLength(parameters.pageLength); 419 setGapBetweenPages(parameters.gapBetweenPages); 420 421 // If the page is created off-screen, its visibilityState should be prerender. 422 m_page->setViewState(m_viewState); 423 if (!isVisible()) 424 m_page->setIsPrerender(); 425 m_page->createPageThrottler(); 426 427 updateIsInWindow(true); 428 429 setMinimumLayoutSize(parameters.minimumLayoutSize); 430 setAutoSizingShouldExpandToViewHeight(parameters.autoSizingShouldExpandToViewHeight); 431 432 setScrollPinningBehavior(parameters.scrollPinningBehavior); 433 setBackgroundExtendsBeyondPage(parameters.backgroundExtendsBeyondPage); 434 435 setTopContentInset(parameters.topContentInset); 436 437 m_userAgent = parameters.userAgent; 438 439 WebBackForwardListProxy::setHighestItemIDFromUIProcess(parameters.highestUsedBackForwardItemID); 440 441 if (!parameters.itemStates.isEmpty()) 442 restoreSession(parameters.itemStates); 443 444 if (parameters.sessionID.isValid()) 445 setSessionID(parameters.sessionID); 446 447 m_drawingArea->setPaintingEnabled(true); 448 449 setMediaVolume(parameters.mediaVolume); 450 451 // We use the DidFirstVisuallyNonEmptyLayout milestone to determine when to unfreeze the layer tree. 452 m_page->addLayoutMilestones(DidFirstLayout | DidFirstVisuallyNonEmptyLayout); 453 454 WebProcess::shared().addMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID, *this); 455 456 // FIXME: This should be done in the object constructors, and the objects themselves should be message receivers. 457 WebProcess::shared().addMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_pageID, *this); 458#if USE(COORDINATED_GRAPHICS) 459 WebProcess::shared().addMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID, *this); 460#endif 461#if ENABLE(INSPECTOR) 462 WebProcess::shared().addMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID, *this); 463#endif 464#if ENABLE(FULLSCREEN_API) 465 WebProcess::shared().addMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID, *this); 466#endif 467 468#ifndef NDEBUG 469 webPageCounter.increment(); 470#endif 471 472#if ENABLE(ASYNC_SCROLLING) 473 if (m_useAsyncScrolling) 474 WebProcess::shared().eventDispatcher().addScrollingTreeForPage(this); 475#endif 476 477 for (auto& mimeType : parameters.mimeTypesWithCustomContentProviders) 478 m_mimeTypesWithCustomContentProviders.add(mimeType); 479} 480 481void WebPage::reinitializeWebPage(const WebPageCreationParameters& parameters) 482{ 483 if (m_viewState != parameters.viewState) 484 setViewState(parameters.viewState); 485 if (m_layerHostingMode != parameters.layerHostingMode) 486 setLayerHostingMode(static_cast<unsigned>(parameters.layerHostingMode)); 487} 488 489WebPage::~WebPage() 490{ 491 if (m_backForwardList) 492 m_backForwardList->detach(); 493 494 ASSERT(!m_page); 495 496#if ENABLE(ASYNC_SCROLLING) 497 if (m_useAsyncScrolling) 498 WebProcess::shared().eventDispatcher().removeScrollingTreeForPage(this); 499#endif 500 501 m_sandboxExtensionTracker.invalidate(); 502 503 for (auto* pluginView : m_pluginViews) 504 pluginView->webPageDestroyed(); 505 506#if !PLATFORM(IOS) 507 if (m_headerBanner) 508 m_headerBanner->detachFromPage(); 509 if (m_footerBanner) 510 m_footerBanner->detachFromPage(); 511#endif // !PLATFORM(IOS) 512 513 WebProcess::shared().removeMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID); 514 515 // FIXME: This should be done in the object destructors, and the objects themselves should be message receivers. 516 WebProcess::shared().removeMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_pageID); 517#if USE(COORDINATED_GRAPHICS) 518 WebProcess::shared().removeMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID); 519#endif 520#if ENABLE(INSPECTOR) 521 WebProcess::shared().removeMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID); 522#endif 523#if ENABLE(FULLSCREEN_API) 524 WebProcess::shared().removeMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID); 525#endif 526 527#ifndef NDEBUG 528 webPageCounter.decrement(); 529#endif 530} 531 532void WebPage::dummy(bool&) 533{ 534} 535 536IPC::Connection* WebPage::messageSenderConnection() 537{ 538 return WebProcess::shared().parentProcessConnection(); 539} 540 541uint64_t WebPage::messageSenderDestinationID() 542{ 543 return pageID(); 544} 545 546#if ENABLE(CONTEXT_MENUS) 547void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClientBase* client) 548{ 549 m_contextMenuClient.initialize(client); 550} 551#endif 552 553void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClientBase* client) 554{ 555 m_editorClient.initialize(client); 556} 557 558void WebPage::setInjectedBundleFormClient(std::unique_ptr<API::InjectedBundle::FormClient> formClient) 559{ 560 if (!formClient) { 561 m_formClient = std::make_unique<API::InjectedBundle::FormClient>(); 562 return; 563 } 564 565 m_formClient = WTF::move(formClient); 566} 567 568void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClientBase* client) 569{ 570 m_loaderClient.initialize(client); 571 572 // It would be nice to get rid of this code and transition all clients to using didLayout instead of 573 // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required 574 // for backwards compatibility. 575 LayoutMilestones milestones = 0; 576 if (client) { 577 if (m_loaderClient.client().didFirstLayoutForFrame) 578 milestones |= WebCore::DidFirstLayout; 579 if (m_loaderClient.client().didFirstVisuallyNonEmptyLayoutForFrame) 580 milestones |= WebCore::DidFirstVisuallyNonEmptyLayout; 581 } 582 583 if (milestones) 584 listenForLayoutMilestones(milestones); 585} 586 587void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClientBase* client) 588{ 589 m_policyClient.initialize(client); 590} 591 592void WebPage::initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClientBase* client) 593{ 594 m_resourceLoadClient.initialize(client); 595} 596 597void WebPage::setInjectedBundleUIClient(std::unique_ptr<API::InjectedBundle::PageUIClient> uiClient) 598{ 599 if (!uiClient) { 600 m_uiClient = std::make_unique<API::InjectedBundle::PageUIClient>(); 601 return; 602 } 603 604 m_uiClient = WTF::move(uiClient); 605} 606 607#if ENABLE(FULLSCREEN_API) 608void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClientBase* client) 609{ 610 m_fullScreenClient.initialize(client); 611} 612#endif 613 614void WebPage::initializeInjectedBundleDiagnosticLoggingClient(WKBundlePageDiagnosticLoggingClientBase* client) 615{ 616 m_logDiagnosticMessageClient.initialize(client); 617} 618 619#if ENABLE(NETSCAPE_PLUGIN_API) 620PassRefPtr<Plugin> WebPage::createPlugin(WebFrame* frame, HTMLPlugInElement* pluginElement, const Plugin::Parameters& parameters, String& newMIMEType) 621{ 622 String frameURLString = frame->coreFrame()->loader().documentLoader()->responseURL().string(); 623 String pageURLString = m_page->mainFrame().loader().documentLoader()->responseURL().string(); 624 625#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 626 HTMLPlugInImageElement& pluginImageElement = toHTMLPlugInImageElement(*pluginElement); 627 unsigned pluginArea = 0; 628 PluginProcessType processType = pluginElement->displayState() == HTMLPlugInElement::WaitingForSnapshot && !(plugInIsPrimarySize(pluginImageElement, pluginArea) && !plugInIntersectsSearchRect(pluginImageElement)) ? PluginProcessTypeSnapshot : PluginProcessTypeNormal; 629#else 630 PluginProcessType processType = pluginElement->displayState() == HTMLPlugInElement::WaitingForSnapshot ? PluginProcessTypeSnapshot : PluginProcessTypeNormal; 631#endif 632 633 bool allowOnlyApplicationPlugins = !frame->coreFrame()->loader().subframeLoader().allowPlugins(NotAboutToInstantiatePlugin); 634 635 uint64_t pluginProcessToken; 636 uint32_t pluginLoadPolicy; 637 String unavailabilityDescription; 638 if (!sendSync(Messages::WebPageProxy::FindPlugin(parameters.mimeType, static_cast<uint32_t>(processType), parameters.url.string(), frameURLString, pageURLString, allowOnlyApplicationPlugins), Messages::WebPageProxy::FindPlugin::Reply(pluginProcessToken, newMIMEType, pluginLoadPolicy, unavailabilityDescription))) 639 return nullptr; 640 641 bool isBlockedPlugin = static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy) == PluginModuleBlocked; 642 643 if (isBlockedPlugin || !pluginProcessToken) { 644#if ENABLE(PDFKIT_PLUGIN) 645 String path = parameters.url.path(); 646 if (shouldUsePDFPlugin() && (MIMETypeRegistry::isPDFOrPostScriptMIMEType(parameters.mimeType) || (parameters.mimeType.isEmpty() && (path.endsWith(".pdf", false) || path.endsWith(".ps", false))))) { 647 RefPtr<PDFPlugin> pdfPlugin = PDFPlugin::create(frame); 648 return pdfPlugin.release(); 649 } 650#else 651 UNUSED_PARAM(frame); 652#endif 653 } 654 655 if (isBlockedPlugin) { 656 bool replacementObscured = false; 657 if (pluginElement->renderer()->isEmbeddedObject()) { 658 RenderEmbeddedObject* renderObject = toRenderEmbeddedObject(pluginElement->renderer()); 659 renderObject->setPluginUnavailabilityReasonWithDescription(RenderEmbeddedObject::InsecurePluginVersion, unavailabilityDescription); 660 replacementObscured = renderObject->isReplacementObscured(); 661 renderObject->setUnavailablePluginIndicatorIsHidden(replacementObscured); 662 } 663 664 send(Messages::WebPageProxy::DidBlockInsecurePluginVersion(parameters.mimeType, parameters.url.string(), frameURLString, pageURLString, replacementObscured)); 665 return nullptr; 666 } 667 668 if (!pluginProcessToken) 669 return nullptr; 670 671 bool isRestartedProcess = (pluginElement->displayState() == HTMLPlugInElement::Restarting || pluginElement->displayState() == HTMLPlugInElement::RestartingWithPendingMouseClick); 672 return PluginProxy::create(pluginProcessToken, isRestartedProcess); 673} 674 675#endif // ENABLE(NETSCAPE_PLUGIN_API) 676 677#if ENABLE(WEBGL) && !PLATFORM(COCOA) 678WebCore::WebGLLoadPolicy WebPage::webGLPolicyForURL(WebFrame*, const String& /* url */) 679{ 680 return WebGLAllowCreation; 681} 682 683WebCore::WebGLLoadPolicy WebPage::resolveWebGLPolicyForURL(WebFrame*, const String& /* url */) 684{ 685 return WebGLAllowCreation; 686} 687#endif 688 689EditorState WebPage::editorState() const 690{ 691 Frame& frame = m_page->focusController().focusedOrMainFrame(); 692 693 EditorState result; 694 695 if (PluginView* pluginView = focusedPluginViewForFrame(frame)) { 696 if (!pluginView->getSelectionString().isNull()) { 697 result.selectionIsNone = false; 698 result.selectionIsRange = true; 699 result.isInPlugin = true; 700 return result; 701 } 702 } 703 704 const VisibleSelection& selection = frame.selection().selection(); 705 706 result.selectionIsNone = selection.isNone(); 707 result.selectionIsRange = selection.isRange(); 708 result.isContentEditable = selection.isContentEditable(); 709 result.isContentRichlyEditable = selection.isContentRichlyEditable(); 710 result.isInPasswordField = selection.isInPasswordField(); 711 result.hasComposition = frame.editor().hasComposition(); 712 result.shouldIgnoreCompositionSelectionChange = frame.editor().ignoreCompositionSelectionChange(); 713 714#if PLATFORM(IOS) 715 if (frame.editor().hasComposition()) { 716 RefPtr<Range> compositionRange = frame.editor().compositionRange(); 717 Vector<WebCore::SelectionRect> compositionRects; 718 compositionRange->collectSelectionRects(compositionRects); 719 if (compositionRects.size()) 720 result.firstMarkedRect = compositionRects[0].rect(); 721 if (compositionRects.size() > 1) 722 result.lastMarkedRect = compositionRects.last().rect(); 723 else 724 result.lastMarkedRect = result.firstMarkedRect; 725 result.markedText = plainTextReplacingNoBreakSpace(compositionRange.get()); 726 } 727 FrameView* view = frame.view(); 728 if (selection.isCaret()) { 729 result.caretRectAtStart = view->contentsToRootView(frame.selection().absoluteCaretBounds()); 730 result.caretRectAtEnd = result.caretRectAtStart; 731 // FIXME: The following check should take into account writing direction. 732 result.isReplaceAllowed = result.isContentEditable && atBoundaryOfGranularity(selection.start(), WordGranularity, DirectionForward); 733 result.wordAtSelection = plainTextReplacingNoBreakSpace(wordRangeFromPosition(selection.start()).get()); 734 if (selection.isContentEditable()) { 735 charactersAroundPosition(selection.start(), result.characterAfterSelection, result.characterBeforeSelection, result.twoCharacterBeforeSelection); 736 Node* root = selection.rootEditableElement(); 737 result.hasContent = root && root->hasChildNodes() && !isEndOfEditableOrNonEditableContent(firstPositionInNode(root)); 738 } 739 } else if (selection.isRange()) { 740 result.caretRectAtStart = view->contentsToRootView(VisiblePosition(selection.start()).absoluteCaretBounds()); 741 result.caretRectAtEnd = view->contentsToRootView(VisiblePosition(selection.end()).absoluteCaretBounds()); 742 RefPtr<Range> selectedRange = selection.toNormalizedRange(); 743 selectedRange->collectSelectionRects(result.selectionRects); 744 convertSelectionRectsToRootView(view, result.selectionRects); 745 String selectedText = plainTextReplacingNoBreakSpace(selectedRange.get(), TextIteratorDefaultBehavior, true); 746 // FIXME: We should disallow replace when the string contains only CJ characters. 747 result.isReplaceAllowed = result.isContentEditable && !result.isInPasswordField && !selectedText.containsOnlyWhitespace(); 748 result.selectedTextLength = selectedText.length(); 749 const int maxSelectedTextLength = 200; 750 if (selectedText.length() <= maxSelectedTextLength) 751 result.wordAtSelection = selectedText; 752 } 753 if (!selection.isNone()) { 754 Node* nodeToRemove; 755 if (RenderStyle* style = Editor::styleForSelectionStart(&frame, nodeToRemove)) { 756 CTFontRef font = style->font().primaryFont()->getCTFont(); 757 CTFontSymbolicTraits traits = font ? CTFontGetSymbolicTraits(font) : 0; 758 759 if (traits & kCTFontTraitBold) 760 result.typingAttributes |= AttributeBold; 761 if (traits & kCTFontTraitItalic) 762 result.typingAttributes |= AttributeItalics; 763 764 if (style->textDecorationsInEffect() & TextDecorationUnderline) 765 result.typingAttributes |= AttributeUnderline; 766 767 if (nodeToRemove) 768 nodeToRemove->remove(ASSERT_NO_EXCEPTION); 769 } 770 } 771#endif 772 773#if PLATFORM(GTK) 774 result.cursorRect = frame.selection().absoluteCaretBounds(); 775#endif 776 777 return result; 778} 779 780String WebPage::renderTreeExternalRepresentation() const 781{ 782 return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal); 783} 784 785String WebPage::renderTreeExternalRepresentationForPrinting() const 786{ 787 return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextPrintingMode); 788} 789 790uint64_t WebPage::renderTreeSize() const 791{ 792 if (!m_page) 793 return 0; 794 return m_page->renderTreeSize(); 795} 796 797void WebPage::setTracksRepaints(bool trackRepaints) 798{ 799 if (FrameView* view = mainFrameView()) 800 view->setTracksRepaints(trackRepaints); 801} 802 803bool WebPage::isTrackingRepaints() const 804{ 805 if (FrameView* view = mainFrameView()) 806 return view->isTrackingRepaints(); 807 808 return false; 809} 810 811void WebPage::resetTrackedRepaints() 812{ 813 if (FrameView* view = mainFrameView()) 814 view->resetTrackedRepaints(); 815} 816 817PassRefPtr<API::Array> WebPage::trackedRepaintRects() 818{ 819 FrameView* view = mainFrameView(); 820 if (!view) 821 return API::Array::create(); 822 823 Vector<RefPtr<API::Object>> repaintRects; 824 repaintRects.reserveInitialCapacity(view->trackedRepaintRects().size()); 825 826 for (const auto& repaintRect : view->trackedRepaintRects()) 827 repaintRects.uncheckedAppend(API::Rect::create(toAPI(repaintRect))); 828 829 return API::Array::create(WTF::move(repaintRects)); 830} 831 832PluginView* WebPage::focusedPluginViewForFrame(Frame& frame) 833{ 834 if (!frame.document()->isPluginDocument()) 835 return 0; 836 837 PluginDocument* pluginDocument = static_cast<PluginDocument*>(frame.document()); 838 839 if (pluginDocument->focusedElement() != pluginDocument->pluginElement()) 840 return 0; 841 842 PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget()); 843 return pluginView; 844} 845 846PluginView* WebPage::pluginViewForFrame(Frame* frame) 847{ 848 if (!frame->document()->isPluginDocument()) 849 return 0; 850 851 PluginDocument* pluginDocument = static_cast<PluginDocument*>(frame->document()); 852 PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget()); 853 return pluginView; 854} 855 856void WebPage::executeEditingCommand(const String& commandName, const String& argument) 857{ 858 Frame& frame = m_page->focusController().focusedOrMainFrame(); 859 860 if (PluginView* pluginView = focusedPluginViewForFrame(frame)) { 861 pluginView->handleEditingCommand(commandName, argument); 862 return; 863 } 864 865 frame.editor().command(commandName).execute(argument); 866} 867 868bool WebPage::isEditingCommandEnabled(const String& commandName) 869{ 870 Frame& frame = m_page->focusController().focusedOrMainFrame(); 871 872 if (PluginView* pluginView = focusedPluginViewForFrame(frame)) 873 return pluginView->isEditingCommandEnabled(commandName); 874 875 Editor::Command command = frame.editor().command(commandName); 876 return command.isSupported() && command.isEnabled(); 877} 878 879void WebPage::clearMainFrameName() 880{ 881 if (Frame* frame = mainFrame()) 882 frame->tree().clearName(); 883} 884 885void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer) 886{ 887 m_drawingArea->setRootCompositingLayer(layer); 888} 889 890void WebPage::exitAcceleratedCompositingMode() 891{ 892 m_drawingArea->setRootCompositingLayer(0); 893} 894 895void WebPage::close() 896{ 897 if (m_isClosed) 898 return; 899 900 m_isClosed = true; 901 902 // If there is still no URL, then we never loaded anything in this page, so nothing to report. 903 if (!mainWebFrame()->url().isEmpty()) 904 reportUsedFeatures(); 905 906 if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle()) 907 WebProcess::shared().injectedBundle()->willDestroyPage(this); 908 909#if ENABLE(INSPECTOR) 910 m_inspector = 0; 911#endif 912#if ENABLE(FULLSCREEN_API) 913 m_fullScreenManager = 0; 914#endif 915 916 if (m_activePopupMenu) { 917 m_activePopupMenu->disconnectFromPage(); 918 m_activePopupMenu = 0; 919 } 920 921 if (m_activeOpenPanelResultListener) { 922 m_activeOpenPanelResultListener->disconnectFromPage(); 923 m_activeOpenPanelResultListener = 0; 924 } 925 926#if ENABLE(INPUT_TYPE_COLOR) 927 if (m_activeColorChooser) { 928 m_activeColorChooser->disconnectFromPage(); 929 m_activeColorChooser = 0; 930 } 931#endif 932 933#if PLATFORM(GTK) 934 if (m_printOperation) { 935 m_printOperation->disconnectFromPage(); 936 m_printOperation = nullptr; 937 } 938#endif 939 940 m_sandboxExtensionTracker.invalidate(); 941 942#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 943 m_determinePrimarySnapshottedPlugInTimer.stop(); 944#endif 945 946#if ENABLE(CONTEXT_MENUS) 947 m_contextMenuClient.initialize(0); 948#endif 949 m_editorClient.initialize(0); 950 m_formClient = std::make_unique<API::InjectedBundle::FormClient>(); 951 m_loaderClient.initialize(0); 952 m_policyClient.initialize(0); 953 m_resourceLoadClient.initialize(0); 954 m_uiClient = std::make_unique<API::InjectedBundle::PageUIClient>(); 955#if ENABLE(FULLSCREEN_API) 956 m_fullScreenClient.initialize(0); 957#endif 958 m_logDiagnosticMessageClient.initialize(0); 959 960 m_printContext = nullptr; 961 m_mainFrame->coreFrame()->loader().detachFromParent(); 962 m_page = nullptr; 963 m_drawingArea = nullptr; 964 965 bool isRunningModal = m_isRunningModal; 966 m_isRunningModal = false; 967 968 // The WebPage can be destroyed by this call. 969 WebProcess::shared().removeWebPage(m_pageID); 970 971 if (isRunningModal) 972 RunLoop::main().stop(); 973} 974 975void WebPage::tryClose() 976{ 977 SendStopResponsivenessTimer stopper(this); 978 979 if (!corePage()->userInputBridge().tryClosePage()) { 980 send(Messages::WebPageProxy::StopResponsivenessTimer()); 981 return; 982 } 983 984 send(Messages::WebPageProxy::ClosePage(true)); 985} 986 987void WebPage::sendClose() 988{ 989 send(Messages::WebPageProxy::ClosePage(false)); 990} 991 992void WebPage::loadURLInFrame(const String& url, uint64_t frameID) 993{ 994 WebFrame* frame = WebProcess::shared().webFrame(frameID); 995 if (!frame) 996 return; 997 998 frame->coreFrame()->loader().load(FrameLoadRequest(frame->coreFrame(), ResourceRequest(URL(URL(), url)))); 999} 1000 1001void WebPage::loadRequest(uint64_t navigationID, const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle, IPC::MessageDecoder& decoder) 1002{ 1003 SendStopResponsivenessTimer stopper(this); 1004 1005 RefPtr<API::Object> userData; 1006 InjectedBundleUserMessageDecoder userMessageDecoder(userData); 1007 if (!decoder.decode(userMessageDecoder)) 1008 return; 1009 1010 m_pendingNavigationID = navigationID; 1011 1012 m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle); 1013 1014 // Let the InjectedBundle know we are about to start the load, passing the user data from the UIProcess 1015 // to all the client to set up any needed state. 1016 m_loaderClient.willLoadURLRequest(this, request, userData.get()); 1017 1018 // Initate the load in WebCore. 1019 corePage()->userInputBridge().loadRequest(FrameLoadRequest(m_mainFrame->coreFrame(), request)); 1020 1021 ASSERT(!m_pendingNavigationID); 1022} 1023 1024void WebPage::loadDataImpl(uint64_t navigationID, PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const URL& baseURL, const URL& unreachableURL, IPC::MessageDecoder& decoder) 1025{ 1026 SendStopResponsivenessTimer stopper(this); 1027 1028 RefPtr<API::Object> userData; 1029 InjectedBundleUserMessageDecoder userMessageDecoder(userData); 1030 if (!decoder.decode(userMessageDecoder)) 1031 return; 1032 1033 m_pendingNavigationID = navigationID; 1034 1035 ResourceRequest request(baseURL); 1036 SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL); 1037 1038 // Let the InjectedBundle know we are about to start the load, passing the user data from the UIProcess 1039 // to all the client to set up any needed state. 1040 m_loaderClient.willLoadDataRequest(this, request, const_cast<SharedBuffer*>(substituteData.content()), substituteData.mimeType(), substituteData.textEncoding(), substituteData.failingURL(), userData.get()); 1041 1042 // Initate the load in WebCore. 1043 m_mainFrame->coreFrame()->loader().load(FrameLoadRequest(m_mainFrame->coreFrame(), request, substituteData)); 1044} 1045 1046void WebPage::loadString(uint64_t navigationID, const String& htmlString, const String& MIMEType, const URL& baseURL, const URL& unreachableURL, IPC::MessageDecoder& decoder) 1047{ 1048 if (!htmlString.isNull() && htmlString.is8Bit()) { 1049 RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters8()), htmlString.length() * sizeof(LChar)); 1050 loadDataImpl(navigationID, sharedBuffer, MIMEType, ASCIILiteral("latin1"), baseURL, unreachableURL, decoder); 1051 } else { 1052 RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters16()), htmlString.length() * sizeof(UChar)); 1053 loadDataImpl(navigationID, sharedBuffer, MIMEType, ASCIILiteral("utf-16"), baseURL, unreachableURL, decoder); 1054 } 1055} 1056 1057void WebPage::loadData(const IPC::DataReference& data, const String& MIMEType, const String& encodingName, const String& baseURLString, IPC::MessageDecoder& decoder) 1058{ 1059 RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(data.data()), data.size()); 1060 URL baseURL = baseURLString.isEmpty() ? blankURL() : URL(URL(), baseURLString); 1061 loadDataImpl(0, sharedBuffer, MIMEType, encodingName, baseURL, URL(), decoder); 1062} 1063 1064void WebPage::loadHTMLString(uint64_t navigationID, const String& htmlString, const String& baseURLString, IPC::MessageDecoder& decoder) 1065{ 1066 URL baseURL = baseURLString.isEmpty() ? blankURL() : URL(URL(), baseURLString); 1067 loadString(navigationID, htmlString, ASCIILiteral("text/html"), baseURL, URL(), decoder); 1068} 1069 1070void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString, IPC::MessageDecoder& decoder) 1071{ 1072 URL baseURL = baseURLString.isEmpty() ? blankURL() : URL(URL(), baseURLString); 1073 URL unreachableURL = unreachableURLString.isEmpty() ? URL() : URL(URL(), unreachableURLString); 1074 loadString(0, htmlString, ASCIILiteral("text/html"), baseURL, unreachableURL, decoder); 1075} 1076 1077void WebPage::loadPlainTextString(const String& string, IPC::MessageDecoder& decoder) 1078{ 1079 loadString(0, string, ASCIILiteral("text/plain"), blankURL(), URL(), decoder); 1080} 1081 1082void WebPage::loadWebArchiveData(const IPC::DataReference& webArchiveData, IPC::MessageDecoder& decoder) 1083{ 1084 RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(webArchiveData.data()), webArchiveData.size() * sizeof(uint8_t)); 1085 loadDataImpl(0, sharedBuffer, ASCIILiteral("application/x-webarchive"), ASCIILiteral("utf-16"), blankURL(), URL(), decoder); 1086} 1087 1088void WebPage::stopLoadingFrame(uint64_t frameID) 1089{ 1090 WebFrame* frame = WebProcess::shared().webFrame(frameID); 1091 if (!frame) 1092 return; 1093 1094 corePage()->userInputBridge().stopLoadingFrame(frame->coreFrame()); 1095} 1096 1097void WebPage::stopLoading() 1098{ 1099 SendStopResponsivenessTimer stopper(this); 1100 1101 corePage()->userInputBridge().stopLoadingFrame(m_mainFrame->coreFrame()); 1102} 1103 1104bool WebPage::defersLoading() const 1105{ 1106 return m_page->defersLoading(); 1107} 1108 1109void WebPage::setDefersLoading(bool defersLoading) 1110{ 1111 m_page->setDefersLoading(defersLoading); 1112} 1113 1114void WebPage::reload(uint64_t navigationID, bool reloadFromOrigin, const SandboxExtension::Handle& sandboxExtensionHandle) 1115{ 1116 SendStopResponsivenessTimer stopper(this); 1117 1118 ASSERT(!m_pendingNavigationID); 1119 m_pendingNavigationID = navigationID; 1120 1121 m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle); 1122 corePage()->userInputBridge().reloadFrame(m_mainFrame->coreFrame(), reloadFromOrigin); 1123} 1124 1125void WebPage::goForward(uint64_t navigationID, uint64_t backForwardItemID) 1126{ 1127 SendStopResponsivenessTimer stopper(this); 1128 1129 HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID); 1130 ASSERT(item); 1131 if (!item) 1132 return; 1133 1134 ASSERT(!m_pendingNavigationID); 1135 if (!item->isInPageCache()) 1136 m_pendingNavigationID = navigationID; 1137 1138 m_page->goToItem(item, FrameLoadType::Forward); 1139} 1140 1141void WebPage::goBack(uint64_t navigationID, uint64_t backForwardItemID) 1142{ 1143 SendStopResponsivenessTimer stopper(this); 1144 1145 HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID); 1146 ASSERT(item); 1147 if (!item) 1148 return; 1149 1150 ASSERT(!m_pendingNavigationID); 1151 if (!item->isInPageCache()) 1152 m_pendingNavigationID = navigationID; 1153 1154 m_page->goToItem(item, FrameLoadType::Back); 1155} 1156 1157void WebPage::goToBackForwardItem(uint64_t navigationID, uint64_t backForwardItemID) 1158{ 1159 SendStopResponsivenessTimer stopper(this); 1160 1161 HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID); 1162 ASSERT(item); 1163 if (!item) 1164 return; 1165 1166 ASSERT(!m_pendingNavigationID); 1167 if (!item->isInPageCache()) 1168 m_pendingNavigationID = navigationID; 1169 1170 m_page->goToItem(item, FrameLoadType::IndexedBackForward); 1171} 1172 1173void WebPage::tryRestoreScrollPosition() 1174{ 1175 m_page->mainFrame().loader().history().restoreScrollPositionAndViewState(); 1176} 1177 1178void WebPage::layoutIfNeeded() 1179{ 1180 if (m_mainFrame->coreFrame()->view()) 1181 m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive(); 1182} 1183 1184WebPage* WebPage::fromCorePage(Page* page) 1185{ 1186 return static_cast<WebChromeClient&>(page->chrome().client()).page(); 1187} 1188 1189void WebPage::setSize(const WebCore::IntSize& viewSize) 1190{ 1191 if (m_viewSize == viewSize) 1192 return; 1193 1194 FrameView* view = m_page->mainFrame().view(); 1195 view->resize(viewSize); 1196 m_drawingArea->setNeedsDisplay(); 1197 1198 m_viewSize = viewSize; 1199 1200#if USE(TILED_BACKING_STORE) 1201 if (view->useFixedLayout()) 1202 sendViewportAttributesChanged(); 1203#endif 1204 1205 m_pageOverlayController.didChangeViewSize(); 1206} 1207 1208#if USE(TILED_BACKING_STORE) 1209void WebPage::setFixedVisibleContentRect(const IntRect& rect) 1210{ 1211 ASSERT(m_useFixedLayout); 1212 1213 m_page->mainFrame().view()->setFixedVisibleContentRect(rect); 1214} 1215 1216void WebPage::sendViewportAttributesChanged() 1217{ 1218 ASSERT(m_useFixedLayout); 1219 1220 // Viewport properties have no impact on zero sized fixed viewports. 1221 if (m_viewSize.isEmpty()) 1222 return; 1223 1224 // Recalculate the recommended layout size, when the available size (device pixel) changes. 1225 Settings& settings = m_page->settings(); 1226 1227 int minimumLayoutFallbackWidth = std::max(settings.layoutFallbackWidth(), m_viewSize.width()); 1228 1229 // If unset we use the viewport dimensions. This fits with the behavior of desktop browsers. 1230 int deviceWidth = (settings.deviceWidth() > 0) ? settings.deviceWidth() : m_viewSize.width(); 1231 int deviceHeight = (settings.deviceHeight() > 0) ? settings.deviceHeight() : m_viewSize.height(); 1232 1233 ViewportAttributes attr = computeViewportAttributes(m_page->viewportArguments(), minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewSize); 1234 1235 FrameView* view = m_page->mainFrame().view(); 1236 1237 // If no layout was done yet set contentFixedOrigin to (0,0). 1238 IntPoint contentFixedOrigin = view->didFirstLayout() ? view->fixedVisibleContentRect().location() : IntPoint(); 1239 1240 // Put the width and height to the viewport width and height. In css units however. 1241 // Use FloatSize to avoid truncated values during scale. 1242 FloatSize contentFixedSize = m_viewSize; 1243 1244#if ENABLE(CSS_DEVICE_ADAPTATION) 1245 // CSS viewport descriptors might be applied to already affected viewport size 1246 // if the page enables/disables stylesheets, so need to keep initial viewport size. 1247 view->setInitialViewportSize(roundedIntSize(contentFixedSize)); 1248#endif 1249 1250 contentFixedSize.scale(1 / attr.initialScale); 1251 setFixedVisibleContentRect(IntRect(contentFixedOrigin, roundedIntSize(contentFixedSize))); 1252 1253 attr.initialScale = m_page->viewportArguments().zoom; // Resets auto (-1) if no value was set by user. 1254 1255 // This also takes care of the relayout. 1256 setFixedLayoutSize(roundedIntSize(attr.layoutSize)); 1257 1258 send(Messages::WebPageProxy::DidChangeViewportProperties(attr)); 1259} 1260#endif 1261 1262void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset) 1263{ 1264 FrameView* frameView = m_page->mainFrame().view(); 1265 1266 IntPoint scrollPosition = frameView->scrollPosition(); 1267 IntPoint maximumScrollPosition = frameView->maximumScrollPosition(); 1268 1269 // If the current scroll position in a direction is the max scroll position 1270 // we don't want to scroll at all. 1271 IntSize newScrollOffset; 1272 if (scrollPosition.x() < maximumScrollPosition.x()) 1273 newScrollOffset.setWidth(scrollOffset.width()); 1274 if (scrollPosition.y() < maximumScrollPosition.y()) 1275 newScrollOffset.setHeight(scrollOffset.height()); 1276 1277 if (newScrollOffset.isZero()) 1278 return; 1279 1280 frameView->setScrollPosition(frameView->scrollPosition() + newScrollOffset); 1281} 1282 1283void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect) 1284{ 1285 GraphicsContextStateSaver stateSaver(graphicsContext); 1286 graphicsContext.clip(rect); 1287 1288 m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect); 1289} 1290 1291double WebPage::textZoomFactor() const 1292{ 1293 Frame* frame = m_mainFrame->coreFrame(); 1294 if (!frame) 1295 return 1; 1296 return frame->textZoomFactor(); 1297} 1298 1299void WebPage::setTextZoomFactor(double zoomFactor) 1300{ 1301 PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); 1302 if (pluginView && pluginView->handlesPageScaleFactor()) 1303 return; 1304 1305 Frame* frame = m_mainFrame->coreFrame(); 1306 if (!frame) 1307 return; 1308 frame->setTextZoomFactor(static_cast<float>(zoomFactor)); 1309} 1310 1311double WebPage::pageZoomFactor() const 1312{ 1313 PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); 1314 if (pluginView && pluginView->handlesPageScaleFactor()) 1315 return pluginView->pageScaleFactor(); 1316 1317 Frame* frame = m_mainFrame->coreFrame(); 1318 if (!frame) 1319 return 1; 1320 return frame->pageZoomFactor(); 1321} 1322 1323void WebPage::setPageZoomFactor(double zoomFactor) 1324{ 1325 PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); 1326 if (pluginView && pluginView->handlesPageScaleFactor()) { 1327 pluginView->setPageScaleFactor(zoomFactor, IntPoint()); 1328 return; 1329 } 1330 1331 Frame* frame = m_mainFrame->coreFrame(); 1332 if (!frame) 1333 return; 1334 frame->setPageZoomFactor(static_cast<float>(zoomFactor)); 1335} 1336 1337void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor) 1338{ 1339 PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); 1340 if (pluginView && pluginView->handlesPageScaleFactor()) { 1341 pluginView->setPageScaleFactor(pageZoomFactor, IntPoint()); 1342 return; 1343 } 1344 1345 Frame* frame = m_mainFrame->coreFrame(); 1346 if (!frame) 1347 return; 1348 return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor)); 1349} 1350 1351void WebPage::windowScreenDidChange(uint64_t displayID) 1352{ 1353 m_page->chrome().windowScreenDidChange(static_cast<PlatformDisplayID>(displayID)); 1354} 1355 1356void WebPage::scalePage(double scale, const IntPoint& origin) 1357{ 1358 bool willChangeScaleFactor = scale != pageScaleFactor(); 1359 1360#if PLATFORM(IOS) 1361 if (willChangeScaleFactor) { 1362 if (!m_inDynamicSizeUpdate) 1363 m_dynamicSizeUpdateHistory.clear(); 1364 m_scaleWasSetByUIProcess = false; 1365 } 1366#endif 1367 PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); 1368 if (pluginView && pluginView->handlesPageScaleFactor()) { 1369 pluginView->setPageScaleFactor(scale, origin); 1370 return; 1371 } 1372 1373 m_page->setPageScaleFactor(scale, origin); 1374 1375 // We can't early return before setPageScaleFactor because the origin might be different. 1376 if (!willChangeScaleFactor) 1377 return; 1378 1379 for (auto* pluginView : m_pluginViews) 1380 pluginView->pageScaleFactorDidChange(); 1381 1382 if (m_drawingArea->layerTreeHost()) 1383 m_drawingArea->layerTreeHost()->deviceOrPageScaleFactorChanged(); 1384 1385 send(Messages::WebPageProxy::PageScaleFactorDidChange(scale)); 1386} 1387 1388void WebPage::scalePageInViewCoordinates(double scale, IntPoint centerInViewCoordinates) 1389{ 1390 if (scale == pageScaleFactor()) 1391 return; 1392 1393 IntPoint scrollPositionAtNewScale = mainFrameView()->rootViewToContents(-centerInViewCoordinates); 1394 double scaleRatio = scale / pageScaleFactor(); 1395 scrollPositionAtNewScale.scale(scaleRatio, scaleRatio); 1396 scalePage(scale, scrollPositionAtNewScale); 1397} 1398 1399double WebPage::pageScaleFactor() const 1400{ 1401 PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); 1402 if (pluginView && pluginView->handlesPageScaleFactor()) 1403 return pluginView->pageScaleFactor(); 1404 1405 return m_page->pageScaleFactor(); 1406} 1407 1408void WebPage::setDeviceScaleFactor(float scaleFactor) 1409{ 1410 if (scaleFactor == m_page->deviceScaleFactor()) 1411 return; 1412 1413 m_page->setDeviceScaleFactor(scaleFactor); 1414 1415 // Tell all our plug-in views that the device scale factor changed. 1416#if PLATFORM(MAC) 1417 for (auto* pluginView : m_pluginViews) 1418 pluginView->setDeviceScaleFactor(scaleFactor); 1419 1420 updateHeaderAndFooterLayersForDeviceScaleChange(scaleFactor); 1421#endif 1422 1423 if (m_findController.isShowingOverlay()) { 1424 // We must have updated layout to get the selection rects right. 1425 layoutIfNeeded(); 1426 m_findController.deviceScaleFactorDidChange(); 1427 } 1428 1429 if (m_drawingArea->layerTreeHost()) 1430 m_drawingArea->layerTreeHost()->deviceOrPageScaleFactorChanged(); 1431 1432 m_pageOverlayController.didChangeDeviceScaleFactor(); 1433} 1434 1435float WebPage::deviceScaleFactor() const 1436{ 1437 return m_page->deviceScaleFactor(); 1438} 1439 1440void WebPage::setUseFixedLayout(bool fixed) 1441{ 1442 // Do not overwrite current settings if initially setting it to false. 1443 if (m_useFixedLayout == fixed) 1444 return; 1445 m_useFixedLayout = fixed; 1446 1447#if !PLATFORM(IOS) 1448 m_page->settings().setFixedElementsLayoutRelativeToFrame(fixed); 1449#endif 1450#if USE(COORDINATED_GRAPHICS) 1451 m_page->settings().setAcceleratedCompositingForFixedPositionEnabled(fixed); 1452 m_page->settings().setFixedPositionCreatesStackingContext(fixed); 1453 m_page->settings().setDelegatesPageScaling(fixed); 1454 m_page->settings().setScrollingCoordinatorEnabled(fixed); 1455#endif 1456 1457#if USE(TILED_BACKING_STORE) && ENABLE(SMOOTH_SCROLLING) 1458 // Delegated scrolling will be enabled when the FrameView is created if fixed layout is enabled. 1459 // Ensure we don't do animated scrolling in the WebProcess in that case. 1460 m_page->settings().setScrollAnimatorEnabled(!fixed); 1461#endif 1462 1463 FrameView* view = mainFrameView(); 1464 if (!view) 1465 return; 1466 1467#if USE(TILED_BACKING_STORE) 1468 view->setDelegatesScrolling(fixed); 1469 view->setPaintsEntireContents(fixed); 1470#endif 1471 view->setUseFixedLayout(fixed); 1472 if (!fixed) 1473 setFixedLayoutSize(IntSize()); 1474} 1475 1476void WebPage::setFixedLayoutSize(const IntSize& size) 1477{ 1478 FrameView* view = mainFrameView(); 1479 if (!view || view->fixedLayoutSize() == size) 1480 return; 1481 1482 view->setFixedLayoutSize(size); 1483} 1484 1485void WebPage::listenForLayoutMilestones(uint32_t milestones) 1486{ 1487 if (!m_page) 1488 return; 1489 m_page->addLayoutMilestones(static_cast<LayoutMilestones>(milestones)); 1490} 1491 1492void WebPage::setSuppressScrollbarAnimations(bool suppressAnimations) 1493{ 1494 m_page->setShouldSuppressScrollbarAnimations(suppressAnimations); 1495} 1496 1497void WebPage::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding) 1498{ 1499 m_page->setVerticalScrollElasticity(enableVerticalRubberBanding ? ScrollElasticityAllowed : ScrollElasticityNone); 1500} 1501 1502void WebPage::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding) 1503{ 1504 m_page->setHorizontalScrollElasticity(enableHorizontalRubberBanding ? ScrollElasticityAllowed : ScrollElasticityNone); 1505} 1506 1507void WebPage::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage) 1508{ 1509 if (m_page->settings().backgroundShouldExtendBeyondPage() != backgroundExtendsBeyondPage) 1510 m_page->settings().setBackgroundShouldExtendBeyondPage(backgroundExtendsBeyondPage); 1511} 1512 1513void WebPage::setPaginationMode(uint32_t mode) 1514{ 1515 Pagination pagination = m_page->pagination(); 1516 pagination.mode = static_cast<Pagination::Mode>(mode); 1517 m_page->setPagination(pagination); 1518} 1519 1520void WebPage::setPaginationBehavesLikeColumns(bool behavesLikeColumns) 1521{ 1522 Pagination pagination = m_page->pagination(); 1523 pagination.behavesLikeColumns = behavesLikeColumns; 1524 m_page->setPagination(pagination); 1525} 1526 1527void WebPage::setPageLength(double pageLength) 1528{ 1529 Pagination pagination = m_page->pagination(); 1530 pagination.pageLength = pageLength; 1531 m_page->setPagination(pagination); 1532} 1533 1534void WebPage::setGapBetweenPages(double gap) 1535{ 1536 Pagination pagination = m_page->pagination(); 1537 pagination.gap = gap; 1538 m_page->setPagination(pagination); 1539} 1540 1541void WebPage::postInjectedBundleMessage(const String& messageName, IPC::MessageDecoder& decoder) 1542{ 1543 InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle(); 1544 if (!injectedBundle) 1545 return; 1546 1547 RefPtr<API::Object> messageBody; 1548 InjectedBundleUserMessageDecoder messageBodyDecoder(messageBody); 1549 if (!decoder.decode(messageBodyDecoder)) 1550 return; 1551 1552 injectedBundle->didReceiveMessageToPage(this, messageName, messageBody.get()); 1553} 1554 1555void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay, PageOverlay::FadeMode fadeMode) 1556{ 1557 m_pageOverlayController.installPageOverlay(pageOverlay, fadeMode); 1558} 1559 1560void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay, PageOverlay::FadeMode fadeMode) 1561{ 1562 m_pageOverlayController.uninstallPageOverlay(pageOverlay, fadeMode); 1563} 1564 1565#if !PLATFORM(IOS) 1566void WebPage::setHeaderPageBanner(PassRefPtr<PageBanner> pageBanner) 1567{ 1568 if (m_headerBanner) 1569 m_headerBanner->detachFromPage(); 1570 1571 m_headerBanner = pageBanner; 1572 1573 if (m_headerBanner) 1574 m_headerBanner->addToPage(PageBanner::Header, this); 1575} 1576 1577PageBanner* WebPage::headerPageBanner() 1578{ 1579 return m_headerBanner.get(); 1580} 1581 1582void WebPage::setFooterPageBanner(PassRefPtr<PageBanner> pageBanner) 1583{ 1584 if (m_footerBanner) 1585 m_footerBanner->detachFromPage(); 1586 1587 m_footerBanner = pageBanner; 1588 1589 if (m_footerBanner) 1590 m_footerBanner->addToPage(PageBanner::Footer, this); 1591} 1592 1593PageBanner* WebPage::footerPageBanner() 1594{ 1595 return m_footerBanner.get(); 1596} 1597 1598void WebPage::hidePageBanners() 1599{ 1600 if (m_headerBanner) 1601 m_headerBanner->hide(); 1602 if (m_footerBanner) 1603 m_footerBanner->hide(); 1604} 1605 1606void WebPage::showPageBanners() 1607{ 1608 if (m_headerBanner) 1609 m_headerBanner->showIfHidden(); 1610 if (m_footerBanner) 1611 m_footerBanner->showIfHidden(); 1612} 1613#endif // !PLATFORM(IOS) 1614 1615void WebPage::takeSnapshot(IntRect snapshotRect, IntSize bitmapSize, uint32_t options, uint64_t callbackID) 1616{ 1617 SnapshotOptions snapshotOptions = static_cast<SnapshotOptions>(options); 1618 snapshotOptions |= SnapshotOptionsShareable; 1619 1620 RefPtr<WebImage> image = snapshotAtSize(snapshotRect, bitmapSize, snapshotOptions); 1621 1622 ShareableBitmap::Handle handle; 1623 if (image) 1624 image->bitmap()->createHandle(handle, SharedMemory::ReadOnly); 1625 1626 send(Messages::WebPageProxy::ImageCallback(handle, callbackID)); 1627} 1628 1629PassRefPtr<WebImage> WebPage::scaledSnapshotWithOptions(const IntRect& rect, double additionalScaleFactor, SnapshotOptions options) 1630{ 1631 IntRect snapshotRect = rect; 1632 IntSize bitmapSize = snapshotRect.size(); 1633 double scaleFactor = additionalScaleFactor; 1634 if (!(options & SnapshotOptionsExcludeDeviceScaleFactor)) 1635 scaleFactor *= corePage()->deviceScaleFactor(); 1636 bitmapSize.scale(scaleFactor); 1637 1638 return snapshotAtSize(rect, bitmapSize, options); 1639} 1640 1641PassRefPtr<WebImage> WebPage::snapshotAtSize(const IntRect& rect, const IntSize& bitmapSize, SnapshotOptions options) 1642{ 1643 Frame* coreFrame = m_mainFrame->coreFrame(); 1644 if (!coreFrame) 1645 return nullptr; 1646 1647 FrameView* frameView = coreFrame->view(); 1648 if (!frameView) 1649 return nullptr; 1650 1651 IntRect snapshotRect = rect; 1652 float horizontalScaleFactor = static_cast<float>(bitmapSize.width()) / rect.width(); 1653 float verticalScaleFactor = static_cast<float>(bitmapSize.height()) / rect.height(); 1654 float scaleFactor = std::max(horizontalScaleFactor, verticalScaleFactor); 1655 1656 RefPtr<WebImage> snapshot = WebImage::create(bitmapSize, snapshotOptionsToImageOptions(options)); 1657 if (!snapshot->bitmap()) 1658 return nullptr; 1659 1660 auto graphicsContext = snapshot->bitmap()->createGraphicsContext(); 1661 1662 graphicsContext->fillRect(IntRect(IntPoint(), bitmapSize), frameView->baseBackgroundColor(), ColorSpaceDeviceRGB); 1663 1664 if (!(options & SnapshotOptionsExcludeDeviceScaleFactor)) { 1665 double deviceScaleFactor = corePage()->deviceScaleFactor(); 1666 graphicsContext->applyDeviceScaleFactor(deviceScaleFactor); 1667 scaleFactor /= deviceScaleFactor; 1668 } 1669 1670 graphicsContext->scale(FloatSize(scaleFactor, scaleFactor)); 1671 graphicsContext->translate(-snapshotRect.x(), -snapshotRect.y()); 1672 1673 FrameView::SelectionInSnapshot shouldPaintSelection = FrameView::IncludeSelection; 1674 if (options & SnapshotOptionsExcludeSelectionHighlighting) 1675 shouldPaintSelection = FrameView::ExcludeSelection; 1676 1677 FrameView::CoordinateSpaceForSnapshot coordinateSpace = FrameView::DocumentCoordinates; 1678 if (options & SnapshotOptionsInViewCoordinates) 1679 coordinateSpace = FrameView::ViewCoordinates; 1680 1681 frameView->paintContentsForSnapshot(graphicsContext.get(), snapshotRect, shouldPaintSelection, coordinateSpace); 1682 1683 if (options & SnapshotOptionsPaintSelectionRectangle) { 1684 FloatRect selectionRectangle = m_mainFrame->coreFrame()->selection().selectionBounds(); 1685 graphicsContext->setStrokeColor(Color(0xFF, 0, 0), ColorSpaceDeviceRGB); 1686 graphicsContext->strokeRect(selectionRectangle, 1); 1687 } 1688 1689 return snapshot.release(); 1690} 1691 1692PassRefPtr<WebImage> WebPage::snapshotNode(WebCore::Node& node, SnapshotOptions options, unsigned maximumPixelCount) 1693{ 1694 Frame* coreFrame = m_mainFrame->coreFrame(); 1695 if (!coreFrame) 1696 return nullptr; 1697 1698 FrameView* frameView = coreFrame->view(); 1699 if (!frameView) 1700 return nullptr; 1701 1702 if (!node.renderer()) 1703 return nullptr; 1704 1705 LayoutRect topLevelRect; 1706 IntRect snapshotRect = pixelSnappedIntRect(node.renderer()->paintingRootRect(topLevelRect)); 1707 1708 double scaleFactor = 1; 1709 IntSize snapshotSize = snapshotRect.size(); 1710 unsigned maximumHeight = maximumPixelCount / snapshotSize.width(); 1711 if (maximumHeight < static_cast<unsigned>(snapshotSize.height())) { 1712 scaleFactor = static_cast<double>(maximumHeight) / snapshotSize.height(); 1713 snapshotSize = IntSize(snapshotSize.width() * scaleFactor, maximumHeight); 1714 } 1715 1716 RefPtr<WebImage> snapshot = WebImage::create(snapshotSize, snapshotOptionsToImageOptions(options)); 1717 if (!snapshot->bitmap()) 1718 return nullptr; 1719 1720 auto graphicsContext = snapshot->bitmap()->createGraphicsContext(); 1721 1722 if (!(options & SnapshotOptionsExcludeDeviceScaleFactor)) { 1723 double deviceScaleFactor = corePage()->deviceScaleFactor(); 1724 graphicsContext->applyDeviceScaleFactor(deviceScaleFactor); 1725 scaleFactor /= deviceScaleFactor; 1726 } 1727 1728 graphicsContext->scale(FloatSize(scaleFactor, scaleFactor)); 1729 graphicsContext->translate(-snapshotRect.x(), -snapshotRect.y()); 1730 1731 Color savedBackgroundColor = frameView->baseBackgroundColor(); 1732 frameView->setBaseBackgroundColor(Color::transparent); 1733 frameView->setNodeToDraw(&node); 1734 1735 frameView->paintContentsForSnapshot(graphicsContext.get(), snapshotRect, FrameView::ExcludeSelection, FrameView::DocumentCoordinates); 1736 1737 frameView->setBaseBackgroundColor(savedBackgroundColor); 1738 frameView->setNodeToDraw(nullptr); 1739 1740 return snapshot.release(); 1741} 1742 1743void WebPage::pageDidScroll() 1744{ 1745#if PLATFORM(IOS) 1746 if (!m_inDynamicSizeUpdate) 1747 m_dynamicSizeUpdateHistory.clear(); 1748#endif 1749 m_uiClient->pageDidScroll(this); 1750 1751 send(Messages::WebPageProxy::PageDidScroll()); 1752} 1753 1754#if USE(TILED_BACKING_STORE) 1755void WebPage::pageDidRequestScroll(const IntPoint& point) 1756{ 1757 send(Messages::WebPageProxy::PageDidRequestScroll(point)); 1758} 1759#endif 1760 1761#if ENABLE(CONTEXT_MENUS) 1762WebContextMenu* WebPage::contextMenu() 1763{ 1764 if (!m_contextMenu) 1765 m_contextMenu = WebContextMenu::create(this); 1766 return m_contextMenu.get(); 1767} 1768 1769WebContextMenu* WebPage::contextMenuAtPointInWindow(const IntPoint& point) 1770{ 1771 corePage()->contextMenuController().clearContextMenu(); 1772 1773 // Simulate a mouse click to generate the correct menu. 1774 PlatformMouseEvent mouseEvent(point, point, RightButton, PlatformEvent::MousePressed, 1, false, false, false, false, currentTime()); 1775 bool handled = corePage()->userInputBridge().handleContextMenuEvent(mouseEvent, &corePage()->mainFrame()); 1776 if (!handled) 1777 return 0; 1778 1779 return contextMenu(); 1780} 1781#endif 1782 1783// Events 1784 1785static const WebEvent* g_currentEvent = 0; 1786 1787// FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to 1788// WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct 1789// platform events passed to the event handler code. 1790const WebEvent* WebPage::currentEvent() 1791{ 1792 return g_currentEvent; 1793} 1794 1795class CurrentEvent { 1796public: 1797 explicit CurrentEvent(const WebEvent& event) 1798 : m_previousCurrentEvent(g_currentEvent) 1799 { 1800 g_currentEvent = &event; 1801 } 1802 1803 ~CurrentEvent() 1804 { 1805 g_currentEvent = m_previousCurrentEvent; 1806 } 1807 1808private: 1809 const WebEvent* m_previousCurrentEvent; 1810}; 1811 1812#if ENABLE(CONTEXT_MENUS) 1813static bool isContextClick(const PlatformMouseEvent& event) 1814{ 1815 if (event.button() == WebCore::RightButton) 1816 return true; 1817 1818#if PLATFORM(COCOA) 1819 // FIXME: this really should be about OSX-style UI, not about the Mac port 1820 if (event.button() == WebCore::LeftButton && event.ctrlKey()) 1821 return true; 1822#endif 1823 1824 return false; 1825} 1826 1827static bool handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent, WebPage* page) 1828{ 1829 IntPoint point = page->corePage()->mainFrame().view()->windowToContents(platformMouseEvent.position()); 1830 HitTestResult result = page->corePage()->mainFrame().eventHandler().hitTestResultAtPoint(point); 1831 1832 Frame* frame = &page->corePage()->mainFrame(); 1833 if (result.innerNonSharedNode()) 1834 frame = result.innerNonSharedNode()->document().frame(); 1835 1836 bool handled = page->corePage()->userInputBridge().handleContextMenuEvent(platformMouseEvent, frame); 1837 if (handled) 1838 page->contextMenu()->show(); 1839 1840 return handled; 1841} 1842#endif 1843 1844static bool handleMouseEvent(const WebMouseEvent& mouseEvent, WebPage* page, bool onlyUpdateScrollbars) 1845{ 1846 Frame& frame = page->corePage()->mainFrame(); 1847 if (!frame.view()) 1848 return false; 1849 1850 PlatformMouseEvent platformMouseEvent = platform(mouseEvent); 1851 1852 switch (platformMouseEvent.type()) { 1853 case PlatformEvent::MousePressed: { 1854#if ENABLE(CONTEXT_MENUS) 1855 if (isContextClick(platformMouseEvent)) 1856 page->corePage()->contextMenuController().clearContextMenu(); 1857#endif 1858 1859 bool handled = page->corePage()->userInputBridge().handleMousePressEvent(platformMouseEvent); 1860#if ENABLE(CONTEXT_MENUS) 1861 if (isContextClick(platformMouseEvent)) 1862 handled = handleContextMenuEvent(platformMouseEvent, page); 1863#endif 1864 return handled; 1865 } 1866 case PlatformEvent::MouseReleased: 1867 return page->corePage()->userInputBridge().handleMouseReleaseEvent(platformMouseEvent); 1868 1869 case PlatformEvent::MouseMoved: 1870 if (onlyUpdateScrollbars) 1871 return page->corePage()->userInputBridge().handleMouseMoveOnScrollbarEvent(platformMouseEvent); 1872 return page->corePage()->userInputBridge().handleMouseMoveEvent(platformMouseEvent); 1873 default: 1874 ASSERT_NOT_REACHED(); 1875 return false; 1876 } 1877} 1878 1879void WebPage::mouseEvent(const WebMouseEvent& mouseEvent) 1880{ 1881 ASSERT(m_page->pageThrottler()); 1882 m_page->pageThrottler()->didReceiveUserInput(); 1883 1884#if ENABLE(CONTEXT_MENUS) 1885 // Don't try to handle any pending mouse events if a context menu is showing. 1886 if (m_isShowingContextMenu) { 1887 send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), false)); 1888 return; 1889 } 1890#endif 1891 bool handled = m_pageOverlayController.handleMouseEvent(mouseEvent); 1892 1893#if !PLATFORM(IOS) 1894 if (!handled && m_headerBanner) 1895 handled = m_headerBanner->mouseEvent(mouseEvent); 1896 if (!handled && m_footerBanner) 1897 handled = m_footerBanner->mouseEvent(mouseEvent); 1898#endif // !PLATFORM(IOS) 1899 1900 if (!handled && canHandleUserEvents()) { 1901 CurrentEvent currentEvent(mouseEvent); 1902 1903 // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse 1904 // button is currently pressed. It is possible that neither of those things will be true since on 1905 // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one 1906 // of those cases where the page is not active and the mouse is not pressed, then we can fire a more 1907 // efficient scrollbars-only version of the event. 1908 bool onlyUpdateScrollbars = !(m_page->focusController().isActive() || (mouseEvent.button() != WebMouseEvent::NoButton)); 1909 handled = handleMouseEvent(mouseEvent, this, onlyUpdateScrollbars); 1910 } 1911 1912 send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled)); 1913} 1914 1915void WebPage::mouseEventSyncForTesting(const WebMouseEvent& mouseEvent, bool& handled) 1916{ 1917 handled = m_pageOverlayController.handleMouseEvent(mouseEvent); 1918#if !PLATFORM(IOS) 1919 if (!handled && m_headerBanner) 1920 handled = m_headerBanner->mouseEvent(mouseEvent); 1921 if (!handled && m_footerBanner) 1922 handled = m_footerBanner->mouseEvent(mouseEvent); 1923#endif // !PLATFORM(IOS) 1924 1925 if (!handled) { 1926 CurrentEvent currentEvent(mouseEvent); 1927 1928 // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse 1929 // button is currently pressed. It is possible that neither of those things will be true since on 1930 // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one 1931 // of those cases where the page is not active and the mouse is not pressed, then we can fire a more 1932 // efficient scrollbars-only version of the event. 1933 bool onlyUpdateScrollbars = !(m_page->focusController().isActive() || (mouseEvent.button() != WebMouseEvent::NoButton)); 1934 handled = handleMouseEvent(mouseEvent, this, onlyUpdateScrollbars); 1935 } 1936} 1937 1938static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page) 1939{ 1940 Frame& frame = page->mainFrame(); 1941 if (!frame.view()) 1942 return false; 1943 1944 PlatformWheelEvent platformWheelEvent = platform(wheelEvent); 1945 return page->userInputBridge().handleWheelEvent(platformWheelEvent); 1946} 1947 1948void WebPage::wheelEvent(const WebWheelEvent& wheelEvent) 1949{ 1950 ASSERT(m_page->pageThrottler()); 1951 m_page->pageThrottler()->didReceiveUserInput(); 1952 1953 bool handled = false; 1954 1955 if (canHandleUserEvents()) { 1956 CurrentEvent currentEvent(wheelEvent); 1957 1958 handled = handleWheelEvent(wheelEvent, m_page.get()); 1959 } 1960 send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled)); 1961} 1962 1963void WebPage::wheelEventSyncForTesting(const WebWheelEvent& wheelEvent, bool& handled) 1964{ 1965 CurrentEvent currentEvent(wheelEvent); 1966 1967 if (ScrollingCoordinator* scrollingCoordinator = m_page->scrollingCoordinator()) 1968 scrollingCoordinator->commitTreeStateIfNeeded(); 1969 1970 handled = handleWheelEvent(wheelEvent, m_page.get()); 1971} 1972 1973static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page) 1974{ 1975 if (!page->mainFrame().view()) 1976 return false; 1977 1978 if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey()) 1979 return page->userInputBridge().handleAccessKeyEvent(platform(keyboardEvent)); 1980 return page->userInputBridge().handleKeyEvent(platform(keyboardEvent)); 1981} 1982 1983void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent) 1984{ 1985 ASSERT(m_page->pageThrottler()); 1986 m_page->pageThrottler()->didReceiveUserInput(); 1987 1988 bool handled = false; 1989 1990 if (canHandleUserEvents()) { 1991 CurrentEvent currentEvent(keyboardEvent); 1992 1993 handled = handleKeyEvent(keyboardEvent, m_page.get()); 1994 // FIXME: Platform default behaviors should be performed during normal DOM event dispatch (in most cases, in default keydown event handler). 1995 if (!handled) 1996 handled = performDefaultBehaviorForKeyEvent(keyboardEvent); 1997 } 1998 send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled)); 1999} 2000 2001void WebPage::keyEventSyncForTesting(const WebKeyboardEvent& keyboardEvent, bool& handled) 2002{ 2003 CurrentEvent currentEvent(keyboardEvent); 2004 2005 Frame& frame = m_page->focusController().focusedOrMainFrame(); 2006 frame.document()->updateStyleIfNeeded(); 2007 2008 handled = handleKeyEvent(keyboardEvent, m_page.get()); 2009 if (!handled) 2010 handled = performDefaultBehaviorForKeyEvent(keyboardEvent); 2011} 2012 2013void WebPage::validateCommand(const String& commandName, uint64_t callbackID) 2014{ 2015 bool isEnabled = false; 2016 int32_t state = 0; 2017 Frame& frame = m_page->focusController().focusedOrMainFrame(); 2018 if (PluginView* pluginView = focusedPluginViewForFrame(frame)) 2019 isEnabled = pluginView->isEditingCommandEnabled(commandName); 2020 else { 2021 Editor::Command command = frame.editor().command(commandName); 2022 state = command.state(); 2023 isEnabled = command.isSupported() && command.isEnabled(); 2024 } 2025 2026 send(Messages::WebPageProxy::ValidateCommandCallback(commandName, isEnabled, state, callbackID)); 2027} 2028 2029void WebPage::executeEditCommand(const String& commandName) 2030{ 2031 executeEditingCommand(commandName, String()); 2032} 2033 2034void WebPage::restoreSession(const Vector<BackForwardListItemState>& itemStates) 2035{ 2036 for (const auto& itemState : itemStates) 2037 WebBackForwardListProxy::addItemFromUIProcess(itemState.identifier, toHistoryItem(itemState.pageState), m_pageID); 2038} 2039 2040#if ENABLE(TOUCH_EVENTS) 2041static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page) 2042{ 2043 if (!page->mainFrame().view()) 2044 return false; 2045 2046 return page->mainFrame().eventHandler().handleTouchEvent(platform(touchEvent)); 2047} 2048#endif 2049 2050#if ENABLE(IOS_TOUCH_EVENTS) 2051void WebPage::dispatchTouchEvent(const WebTouchEvent& touchEvent, bool& handled) 2052{ 2053 RefPtr<Frame> oldFocusedFrame = m_page->focusController().focusedFrame(); 2054 RefPtr<Element> oldFocusedElement = oldFocusedFrame ? oldFocusedFrame->document()->focusedElement() : nullptr; 2055 m_userIsInteracting = true; 2056 2057 m_lastInteractionLocation = touchEvent.position(); 2058 CurrentEvent currentEvent(touchEvent); 2059 handled = handleTouchEvent(touchEvent, m_page.get()); 2060 2061 RefPtr<Frame> newFocusedFrame = m_page->focusController().focusedFrame(); 2062 RefPtr<Element> newFocusedElement = newFocusedFrame ? newFocusedFrame->document()->focusedElement() : nullptr; 2063 2064 // If the focus has not changed, we need to notify the client anyway, since it might be 2065 // necessary to start assisting the node. 2066 // If the node has been focused by JavaScript without user interaction, the 2067 // keyboard is not on screen. 2068 if (newFocusedElement && newFocusedElement == oldFocusedElement) 2069 elementDidFocus(newFocusedElement.get()); 2070 2071 m_userIsInteracting = false; 2072} 2073 2074void WebPage::touchEventSync(const WebTouchEvent& touchEvent, bool& handled) 2075{ 2076 EventDispatcher::TouchEventQueue queuedEvents; 2077 WebProcess::shared().eventDispatcher().getQueuedTouchEventsForPage(*this, queuedEvents); 2078 dispatchAsynchronousTouchEvents(queuedEvents); 2079 2080 dispatchTouchEvent(touchEvent, handled); 2081} 2082#elif ENABLE(TOUCH_EVENTS) 2083void WebPage::touchEvent(const WebTouchEvent& touchEvent) 2084{ 2085 2086 bool handled = false; 2087 if (canHandleUserEvents()) { 2088 CurrentEvent currentEvent(touchEvent); 2089 2090 handled = handleTouchEvent(touchEvent, m_page.get()); 2091 } 2092 send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled)); 2093} 2094 2095void WebPage::touchEventSyncForTesting(const WebTouchEvent& touchEvent, bool& handled) 2096{ 2097 CurrentEvent currentEvent(touchEvent); 2098 handled = handleTouchEvent(touchEvent, m_page.get()); 2099} 2100#endif 2101 2102bool WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity) 2103{ 2104 return page->userInputBridge().scrollRecursively(direction, granularity); 2105} 2106 2107bool WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity) 2108{ 2109 return page->userInputBridge().logicalScrollRecursively(direction, granularity); 2110} 2111 2112bool WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity) 2113{ 2114 return scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity)); 2115} 2116 2117void WebPage::centerSelectionInVisibleArea() 2118{ 2119 Frame& frame = m_page->focusController().focusedOrMainFrame(); 2120 frame.selection().revealSelection(ScrollAlignment::alignCenterAlways); 2121 m_findController.showFindIndicatorInSelection(); 2122} 2123 2124#if ENABLE(REMOTE_INSPECTOR) 2125void WebPage::setAllowsRemoteInspection(bool allow) 2126{ 2127 m_page->setRemoteInspectionAllowed(allow); 2128} 2129#endif 2130 2131void WebPage::setDrawsBackground(bool drawsBackground) 2132{ 2133 if (m_drawsBackground == drawsBackground) 2134 return; 2135 2136 m_drawsBackground = drawsBackground; 2137 2138 for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree().traverseNext()) { 2139 if (FrameView* view = coreFrame->view()) 2140 view->setTransparent(!drawsBackground); 2141 } 2142 2143 m_drawingArea->pageBackgroundTransparencyChanged(); 2144 m_drawingArea->setNeedsDisplay(); 2145} 2146 2147void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground) 2148{ 2149 if (m_drawsTransparentBackground == drawsTransparentBackground) 2150 return; 2151 2152 m_drawsTransparentBackground = drawsTransparentBackground; 2153 2154 Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white; 2155 for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree().traverseNext()) { 2156 if (FrameView* view = coreFrame->view()) 2157 view->setBaseBackgroundColor(backgroundColor); 2158 } 2159 2160 m_drawingArea->pageBackgroundTransparencyChanged(); 2161 m_drawingArea->setNeedsDisplay(); 2162} 2163 2164void WebPage::setTopContentInset(float contentInset) 2165{ 2166 if (contentInset == m_page->topContentInset()) 2167 return; 2168 2169 m_page->setTopContentInset(contentInset); 2170 2171 for (auto* pluginView : m_pluginViews) 2172 pluginView->topContentInsetDidChange(); 2173} 2174 2175void WebPage::viewWillStartLiveResize() 2176{ 2177 if (!m_page) 2178 return; 2179 2180 // FIXME: This should propagate to all ScrollableAreas. 2181 Frame& frame = m_page->focusController().focusedOrMainFrame(); 2182 if (FrameView* view = frame.view()) 2183 view->willStartLiveResize(); 2184} 2185 2186void WebPage::viewWillEndLiveResize() 2187{ 2188 if (!m_page) 2189 return; 2190 2191 // FIXME: This should propagate to all ScrollableAreas. 2192 Frame& frame = m_page->focusController().focusedOrMainFrame(); 2193 if (FrameView* view = frame.view()) 2194 view->willEndLiveResize(); 2195} 2196 2197void WebPage::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& event) 2198{ 2199 if (!m_page) 2200 return; 2201 2202 Frame& frame = m_page->focusController().focusedOrMainFrame(); 2203 frame.document()->setFocusedElement(0); 2204 2205 if (isKeyboardEventValid && event.type() == WebEvent::KeyDown) { 2206 PlatformKeyboardEvent platformEvent(platform(event)); 2207 platformEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown); 2208 m_page->focusController().setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, KeyboardEvent::create(platformEvent, frame.document()->defaultView()).get()); 2209 return; 2210 } 2211 2212 m_page->focusController().setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0); 2213} 2214 2215void WebPage::setWindowResizerSize(const IntSize& windowResizerSize) 2216{ 2217 if (m_windowResizerSize == windowResizerSize) 2218 return; 2219 2220 m_windowResizerSize = windowResizerSize; 2221 2222 for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree().traverseNext()) { 2223 FrameView* view = coreFrame->view(); 2224 if (view) 2225 view->windowResizerRectChanged(); 2226 } 2227} 2228 2229void WebPage::setCanStartMediaTimerFired() 2230{ 2231 if (m_page) 2232 m_page->setCanStartMedia(true); 2233} 2234 2235inline bool WebPage::canHandleUserEvents() const 2236{ 2237#if USE(TILED_BACKING_STORE) 2238 // Should apply only if the area was frozen by didStartPageTransition(). 2239 return !m_drawingArea->layerTreeStateIsFrozen(); 2240#endif 2241 return true; 2242} 2243 2244void WebPage::updateIsInWindow(bool isInitialState) 2245{ 2246 bool isInWindow = m_viewState & WebCore::ViewState::IsInWindow; 2247 2248 if (!isInWindow) { 2249 m_setCanStartMediaTimer.stop(); 2250 m_page->setCanStartMedia(false); 2251 2252 // The WebProcess does not yet know about this page; no need to tell it we're leaving the window. 2253 if (!isInitialState) 2254 WebProcess::shared().pageWillLeaveWindow(m_pageID); 2255 } else { 2256 // Defer the call to Page::setCanStartMedia() since it ends up sending a synchronous message to the UI process 2257 // in order to get plug-in connections, and the UI process will be waiting for the Web process to update the backing 2258 // store after moving the view into a window, until it times out and paints white. See <rdar://problem/9242771>. 2259 if (m_mayStartMediaWhenInWindow) 2260 m_setCanStartMediaTimer.startOneShot(0); 2261 2262 WebProcess::shared().pageDidEnterWindow(m_pageID); 2263 } 2264 2265 if (isInWindow) 2266 layoutIfNeeded(); 2267} 2268 2269void WebPage::setViewState(ViewState::Flags viewState, bool wantsDidUpdateViewState) 2270{ 2271 ViewState::Flags changed = m_viewState ^ viewState; 2272 m_viewState = viewState; 2273 2274 m_page->setViewState(viewState); 2275 for (auto* pluginView : m_pluginViews) 2276 pluginView->viewStateDidChange(changed); 2277 2278 m_drawingArea->viewStateDidChange(changed, wantsDidUpdateViewState); 2279 2280 if (changed & ViewState::IsInWindow) 2281 updateIsInWindow(); 2282} 2283 2284void WebPage::setLayerHostingMode(unsigned layerHostingMode) 2285{ 2286 m_layerHostingMode = static_cast<LayerHostingMode>(layerHostingMode); 2287 2288 m_drawingArea->setLayerHostingMode(m_layerHostingMode); 2289 2290 for (auto* pluginView : m_pluginViews) 2291 pluginView->setLayerHostingMode(m_layerHostingMode); 2292} 2293 2294void WebPage::setSessionID(SessionID sessionID) 2295{ 2296 if (sessionID.isEphemeral()) 2297 WebProcess::shared().ensurePrivateBrowsingSession(sessionID); 2298 m_page->setSessionID(sessionID); 2299} 2300 2301void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t navigationID, uint64_t downloadID) 2302{ 2303 WebFrame* frame = WebProcess::shared().webFrame(frameID); 2304 if (!frame) 2305 return; 2306 frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), navigationID, downloadID); 2307} 2308 2309void WebPage::didStartPageTransition() 2310{ 2311 m_drawingArea->setLayerTreeStateIsFrozen(true); 2312} 2313 2314void WebPage::didCompletePageTransition() 2315{ 2316#if USE(TILED_BACKING_STORE) 2317 // m_mainFrame can be null since r170163. 2318 if (m_mainFrame && m_mainFrame->coreFrame()->view()->delegatesScrolling()) { 2319 // Wait until the UI process sent us the visible rect it wants rendered. 2320 send(Messages::WebPageProxy::PageTransitionViewportReady()); 2321 } else 2322#endif 2323 2324 m_drawingArea->setLayerTreeStateIsFrozen(false); 2325} 2326 2327void WebPage::show() 2328{ 2329 send(Messages::WebPageProxy::ShowPage()); 2330} 2331 2332String WebPage::userAgent(const URL& webCoreURL) const 2333{ 2334 return userAgent(nullptr, webCoreURL); 2335} 2336 2337String WebPage::userAgent(WebFrame* frame, const URL& webcoreURL) const 2338{ 2339 if (frame && m_loaderClient.client().userAgentForURL) { 2340 RefPtr<API::URL> url = API::URL::create(webcoreURL); 2341 2342 API::String* apiString = m_loaderClient.userAgentForURL(frame, url.get()); 2343 if (apiString) 2344 return apiString->string(); 2345 } 2346 2347 String userAgent = platformUserAgent(webcoreURL); 2348 if (!userAgent.isEmpty()) 2349 return userAgent; 2350 return m_userAgent; 2351} 2352 2353void WebPage::setUserAgent(const String& userAgent) 2354{ 2355 m_userAgent = userAgent; 2356} 2357 2358void WebPage::suspendActiveDOMObjectsAndAnimations() 2359{ 2360 m_page->suspendActiveDOMObjectsAndAnimations(); 2361} 2362 2363void WebPage::resumeActiveDOMObjectsAndAnimations() 2364{ 2365 m_page->resumeActiveDOMObjectsAndAnimations(); 2366} 2367 2368IntPoint WebPage::screenToRootView(const IntPoint& point) 2369{ 2370 IntPoint windowPoint; 2371 sendSync(Messages::WebPageProxy::ScreenToRootView(point), Messages::WebPageProxy::ScreenToRootView::Reply(windowPoint)); 2372 return windowPoint; 2373} 2374 2375IntRect WebPage::rootViewToScreen(const IntRect& rect) 2376{ 2377 IntRect screenRect; 2378 sendSync(Messages::WebPageProxy::RootViewToScreen(rect), Messages::WebPageProxy::RootViewToScreen::Reply(screenRect)); 2379 return screenRect; 2380} 2381 2382#if PLATFORM(IOS) 2383IntPoint WebPage::accessibilityScreenToRootView(const IntPoint& point) 2384{ 2385 IntPoint windowPoint; 2386 sendSync(Messages::WebPageProxy::AccessibilityScreenToRootView(point), Messages::WebPageProxy::AccessibilityScreenToRootView::Reply(windowPoint)); 2387 return windowPoint; 2388} 2389 2390IntRect WebPage::rootViewToAccessibilityScreen(const IntRect& rect) 2391{ 2392 IntRect screenRect; 2393 sendSync(Messages::WebPageProxy::RootViewToAccessibilityScreen(rect), Messages::WebPageProxy::RootViewToAccessibilityScreen::Reply(screenRect)); 2394 return screenRect; 2395} 2396#endif 2397 2398IntRect WebPage::windowResizerRect() const 2399{ 2400 if (m_windowResizerSize.isEmpty()) 2401 return IntRect(); 2402 2403 IntSize frameViewSize; 2404 if (Frame* coreFrame = m_mainFrame->coreFrame()) { 2405 if (FrameView* view = coreFrame->view()) 2406 frameViewSize = view->size(); 2407 } 2408 2409 return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), 2410 m_windowResizerSize.width(), m_windowResizerSize.height()); 2411} 2412 2413KeyboardUIMode WebPage::keyboardUIMode() 2414{ 2415 bool fullKeyboardAccessEnabled = WebProcess::shared().fullKeyboardAccessEnabled(); 2416 return static_cast<KeyboardUIMode>((fullKeyboardAccessEnabled ? KeyboardAccessFull : KeyboardAccessDefault) | (m_tabToLinks ? KeyboardAccessTabsToLinks : 0)); 2417} 2418 2419void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID) 2420{ 2421 // NOTE: We need to be careful when running scripts that the objects we depend on don't 2422 // disappear during script execution. 2423 2424 // Retain the SerializedScriptValue at this level so it (and the internal data) lives 2425 // long enough for the DataReference to be encoded by the sent message. 2426 RefPtr<SerializedScriptValue> serializedResultValue; 2427 IPC::DataReference dataReference; 2428 2429 JSLockHolder lock(JSDOMWindow::commonVM()); 2430 if (JSValue resultValue = m_mainFrame->coreFrame()->script().executeScript(script, true).jsValue()) { 2431 if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(), toRef(m_mainFrame->coreFrame()->script().globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0))) 2432 dataReference = serializedResultValue->data(); 2433 } 2434 2435 send(Messages::WebPageProxy::ScriptValueCallback(dataReference, callbackID)); 2436} 2437 2438void WebPage::getContentsAsString(uint64_t callbackID) 2439{ 2440 String resultString = m_mainFrame->contentsAsString(); 2441 send(Messages::WebPageProxy::StringCallback(resultString, callbackID)); 2442} 2443 2444#if ENABLE(MHTML) 2445void WebPage::getContentsAsMHTMLData(uint64_t callbackID, bool useBinaryEncoding) 2446{ 2447 IPC::DataReference dataReference; 2448 2449 RefPtr<SharedBuffer> buffer = useBinaryEncoding 2450 ? MHTMLArchive::generateMHTMLDataUsingBinaryEncoding(m_page.get()) 2451 : MHTMLArchive::generateMHTMLData(m_page.get()); 2452 2453 if (buffer) 2454 dataReference = IPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); 2455 2456 send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); 2457} 2458#endif 2459 2460void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID) 2461{ 2462 String resultString = renderTreeExternalRepresentation(); 2463 send(Messages::WebPageProxy::StringCallback(resultString, callbackID)); 2464} 2465 2466static Frame* frameWithSelection(Page* page) 2467{ 2468 for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) { 2469 if (frame->selection().isRange()) 2470 return frame; 2471 } 2472 2473 return 0; 2474} 2475 2476void WebPage::getSelectionAsWebArchiveData(uint64_t callbackID) 2477{ 2478 IPC::DataReference dataReference; 2479 2480#if PLATFORM(COCOA) 2481 RefPtr<LegacyWebArchive> archive; 2482 RetainPtr<CFDataRef> data; 2483 2484 Frame* frame = frameWithSelection(m_page.get()); 2485 if (frame) { 2486 archive = LegacyWebArchive::createFromSelection(frame); 2487 data = archive->rawDataRepresentation(); 2488 dataReference = IPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get())); 2489 } 2490#endif 2491 2492 send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); 2493} 2494 2495void WebPage::getSelectionOrContentsAsString(uint64_t callbackID) 2496{ 2497 String resultString = m_mainFrame->selectionAsString(); 2498 if (resultString.isEmpty()) 2499 resultString = m_mainFrame->contentsAsString(); 2500 send(Messages::WebPageProxy::StringCallback(resultString, callbackID)); 2501} 2502 2503void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID) 2504{ 2505 String resultString; 2506 if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) 2507 resultString = frame->source(); 2508 2509 send(Messages::WebPageProxy::StringCallback(resultString, callbackID)); 2510} 2511 2512void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID) 2513{ 2514 IPC::DataReference dataReference; 2515 2516 RefPtr<ResourceBuffer> buffer; 2517 RefPtr<SharedBuffer> pdfResource; 2518 if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) { 2519 if (PluginView* pluginView = pluginViewForFrame(frame->coreFrame())) { 2520 if ((pdfResource = pluginView->liveResourceData())) 2521 dataReference = IPC::DataReference(reinterpret_cast<const uint8_t*>(pdfResource->data()), pdfResource->size()); 2522 } 2523 2524 if (dataReference.isEmpty()) { 2525 if (DocumentLoader* loader = frame->coreFrame()->loader().documentLoader()) { 2526 if ((buffer = loader->mainResourceData())) 2527 dataReference = IPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); 2528 } 2529 } 2530 } 2531 2532 send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); 2533} 2534 2535static PassRefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const URL& resourceURL) 2536{ 2537 DocumentLoader* loader = frame->loader().documentLoader(); 2538 if (!loader) 2539 return 0; 2540 2541 RefPtr<ArchiveResource> subresource = loader->subresource(resourceURL); 2542 if (!subresource) 2543 return 0; 2544 2545 return subresource->data(); 2546} 2547 2548void WebPage::getResourceDataFromFrame(uint64_t frameID, const String& resourceURLString, uint64_t callbackID) 2549{ 2550 IPC::DataReference dataReference; 2551 URL resourceURL(URL(), resourceURLString); 2552 2553 RefPtr<SharedBuffer> buffer; 2554 if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) { 2555 buffer = resourceDataForFrame(frame->coreFrame(), resourceURL); 2556 if (!buffer) { 2557 // Try to get the resource data from the cache. 2558 buffer = cachedResponseDataForURL(resourceURL); 2559 } 2560 2561 if (buffer) 2562 dataReference = IPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); 2563 } 2564 2565 send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); 2566} 2567 2568void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID) 2569{ 2570 IPC::DataReference dataReference; 2571 2572#if PLATFORM(COCOA) 2573 RetainPtr<CFDataRef> data; 2574 if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) { 2575 if ((data = frame->webArchiveData(0, 0))) 2576 dataReference = IPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get())); 2577 } 2578#else 2579 UNUSED_PARAM(frameID); 2580#endif 2581 2582 send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); 2583} 2584 2585void WebPage::forceRepaintWithoutCallback() 2586{ 2587 m_drawingArea->forceRepaint(); 2588} 2589 2590void WebPage::forceRepaint(uint64_t callbackID) 2591{ 2592 if (m_drawingArea->forceRepaintAsync(callbackID)) 2593 return; 2594 2595 forceRepaintWithoutCallback(); 2596 send(Messages::WebPageProxy::VoidCallback(callbackID)); 2597} 2598 2599void WebPage::preferencesDidChange(const WebPreferencesStore& store) 2600{ 2601 WebPreferencesStore::removeTestRunnerOverrides(); 2602 updatePreferences(store); 2603} 2604 2605void WebPage::updatePreferences(const WebPreferencesStore& store) 2606{ 2607 Settings& settings = m_page->settings(); 2608 2609 m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey()); 2610 m_asynchronousPluginInitializationEnabled = store.getBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledKey()); 2611 m_asynchronousPluginInitializationEnabledForAllPlugins = store.getBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledForAllPluginsKey()); 2612 m_artificialPluginInitializationDelayEnabled = store.getBoolValueForKey(WebPreferencesKey::artificialPluginInitializationDelayEnabledKey()); 2613 2614 m_scrollingPerformanceLoggingEnabled = store.getBoolValueForKey(WebPreferencesKey::scrollingPerformanceLoggingEnabledKey()); 2615 2616#if PLATFORM(COCOA) 2617 m_pdfPluginEnabled = store.getBoolValueForKey(WebPreferencesKey::pdfPluginEnabledKey()); 2618#endif 2619 2620#if ENABLE(SERVICE_CONTROLS) 2621 m_serviceControlsEnabled = store.getBoolValueForKey(WebPreferencesKey::serviceControlsEnabledKey()); 2622#endif 2623 2624 // FIXME: This should be generated from macro expansion for all preferences, 2625 // but we currently don't match the naming of WebCore exactly so we are 2626 // handrolling the boolean and integer preferences until that is fixed. 2627 2628#define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings.set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key())); 2629 2630 FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS) 2631 2632#undef INITIALIZE_SETTINGS 2633 2634 settings.setScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey())); 2635 settings.setScriptMarkupEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptMarkupEnabledKey())); 2636 settings.setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey())); 2637 settings.setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey())); 2638 settings.setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey())); 2639 settings.setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey())); 2640 settings.setJavaEnabledForLocalFiles(store.getBoolValueForKey(WebPreferencesKey::javaEnabledForLocalFilesKey())); 2641 settings.setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey())); 2642 settings.setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey())); 2643 settings.setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey())); 2644 settings.setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey())); 2645 if (store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()) && !usesEphemeralSession()) 2646 setSessionID(SessionID::legacyPrivateSessionID()); 2647 else if (!store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()) && sessionID() == SessionID::legacyPrivateSessionID()) 2648 setSessionID(SessionID::defaultSessionID()); 2649 settings.setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey())); 2650 settings.setJavaScriptExperimentsEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptExperimentsEnabledKey())); 2651 settings.setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey())); 2652 settings.setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey())); 2653 settings.setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey())); 2654 settings.setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey())); 2655 settings.setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey())); 2656#if ENABLE(WEB_ARCHIVE) 2657 settings.setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey())); 2658#endif 2659 settings.setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey())); 2660 settings.setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey())); 2661 settings.setPageCacheSupportsPlugins(store.getBoolValueForKey(WebPreferencesKey::pageCacheSupportsPluginsKey())); 2662 settings.setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey())); 2663 settings.setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey())); 2664 settings.setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey())); 2665 settings.setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey())); 2666 settings.setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey())); 2667 settings.setWebSecurityEnabled(store.getBoolValueForKey(WebPreferencesKey::webSecurityEnabledKey())); 2668 settings.setAllowUniversalAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowUniversalAccessFromFileURLsKey())); 2669 settings.setAllowFileAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowFileAccessFromFileURLsKey())); 2670 2671 settings.setMinimumFontSize(store.getDoubleValueForKey(WebPreferencesKey::minimumFontSizeKey())); 2672 settings.setMinimumLogicalFontSize(store.getDoubleValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey())); 2673 settings.setDefaultFontSize(store.getDoubleValueForKey(WebPreferencesKey::defaultFontSizeKey())); 2674 settings.setDefaultFixedFontSize(store.getDoubleValueForKey(WebPreferencesKey::defaultFixedFontSizeKey())); 2675 settings.setScreenFontSubstitutionEnabled(store.getBoolValueForKey(WebPreferencesKey::screenFontSubstitutionEnabledKey()) 2676#if PLATFORM(COCOA) 2677 || WebProcess::shared().shouldForceScreenFontSubstitution() 2678#endif 2679 ); 2680 settings.setLayoutFallbackWidth(store.getUInt32ValueForKey(WebPreferencesKey::layoutFallbackWidthKey())); 2681 settings.setDeviceWidth(store.getUInt32ValueForKey(WebPreferencesKey::deviceWidthKey())); 2682 settings.setDeviceHeight(store.getUInt32ValueForKey(WebPreferencesKey::deviceHeightKey())); 2683 settings.setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey()))); 2684 settings.setShowsToolTipOverTruncatedText(store.getBoolValueForKey(WebPreferencesKey::showsToolTipOverTruncatedTextKey())); 2685 2686 settings.setAcceleratedCompositingForOverflowScrollEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingForOverflowScrollEnabledKey())); 2687 settings.setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey())); 2688 settings.setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey())); 2689 settings.setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey())); 2690 settings.setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey())); 2691 settings.setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey())); 2692 settings.setShowTiledScrollingIndicator(store.getBoolValueForKey(WebPreferencesKey::tiledScrollingIndicatorVisibleKey())); 2693 settings.setAggressiveTileRetentionEnabled(store.getBoolValueForKey(WebPreferencesKey::aggressiveTileRetentionEnabledKey())); 2694 settings.setTemporaryTileCohortRetentionEnabled(store.getBoolValueForKey(WebPreferencesKey::temporaryTileCohortRetentionEnabledKey())); 2695 RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled(store.getBoolValueForKey(WebPreferencesKey::cssRegionsEnabledKey())); 2696 RuntimeEnabledFeatures::sharedFeatures().setCSSCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::cssCompositingEnabledKey())); 2697 settings.setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey())); 2698 settings.setMultithreadedWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::multithreadedWebGLEnabledKey())); 2699 settings.setForceSoftwareWebGLRendering(store.getBoolValueForKey(WebPreferencesKey::forceSoftwareWebGLRenderingKey())); 2700 settings.setAccelerated2dCanvasEnabled(store.getBoolValueForKey(WebPreferencesKey::accelerated2dCanvasEnabledKey())); 2701 settings.setMediaPlaybackRequiresUserGesture(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackRequiresUserGestureKey())); 2702 settings.setMediaPlaybackAllowsInline(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackAllowsInlineKey())); 2703 settings.setMockScrollbarsEnabled(store.getBoolValueForKey(WebPreferencesKey::mockScrollbarsEnabledKey())); 2704 settings.setHyperlinkAuditingEnabled(store.getBoolValueForKey(WebPreferencesKey::hyperlinkAuditingEnabledKey())); 2705 settings.setRequestAnimationFrameEnabled(store.getBoolValueForKey(WebPreferencesKey::requestAnimationFrameEnabledKey())); 2706#if ENABLE(SMOOTH_SCROLLING) 2707 settings.setScrollAnimatorEnabled(store.getBoolValueForKey(WebPreferencesKey::scrollAnimatorEnabledKey())); 2708#endif 2709 settings.setForceUpdateScrollbarsOnMainThreadForPerformanceTesting(store.getBoolValueForKey(WebPreferencesKey::forceUpdateScrollbarsOnMainThreadForPerformanceTestingKey())); 2710 settings.setInteractiveFormValidationEnabled(store.getBoolValueForKey(WebPreferencesKey::interactiveFormValidationEnabledKey())); 2711 settings.setSpatialNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::spatialNavigationEnabledKey())); 2712 2713#if ENABLE(SQL_DATABASE) 2714 DatabaseManager::manager().setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey())); 2715#endif 2716 2717#if ENABLE(FULLSCREEN_API) 2718 settings.setFullScreenEnabled(store.getBoolValueForKey(WebPreferencesKey::fullScreenEnabledKey())); 2719#endif 2720 2721#if USE(AVFOUNDATION) 2722 settings.setAVFoundationEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationEnabledKey())); 2723#endif 2724 2725#if PLATFORM(COCOA) 2726 settings.setQTKitEnabled(store.getBoolValueForKey(WebPreferencesKey::isQTKitEnabledKey())); 2727#endif 2728 2729#if PLATFORM(IOS) 2730 settings.setAVKitEnabled(true); 2731#endif 2732 2733#if ENABLE(IOS_TEXT_AUTOSIZING) 2734 settings.setMinimumZoomFontSize(store.getDoubleValueForKey(WebPreferencesKey::minimumZoomFontSizeKey())); 2735#endif 2736 2737#if ENABLE(WEB_AUDIO) 2738 settings.setWebAudioEnabled(store.getBoolValueForKey(WebPreferencesKey::webAudioEnabledKey())); 2739#endif 2740 2741#if ENABLE(MEDIA_STREAM) 2742 settings.setMediaStreamEnabled(store.getBoolValueForKey(WebPreferencesKey::mediaStreamEnabledKey())); 2743#endif 2744 2745#if ENABLE(SERVICE_CONTROLS) 2746 settings.setImageControlsEnabled(store.getBoolValueForKey(WebPreferencesKey::imageControlsEnabledKey())); 2747#endif 2748 2749#if ENABLE(IOS_AIRPLAY) 2750 settings.setMediaPlaybackAllowsAirPlay(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackAllowsAirPlayKey())); 2751#endif 2752 2753 settings.setApplicationChromeMode(store.getBoolValueForKey(WebPreferencesKey::applicationChromeModeKey())); 2754 settings.setSuppressesIncrementalRendering(store.getBoolValueForKey(WebPreferencesKey::suppressesIncrementalRenderingKey())); 2755 settings.setIncrementalRenderingSuppressionTimeoutInSeconds(store.getDoubleValueForKey(WebPreferencesKey::incrementalRenderingSuppressionTimeoutKey())); 2756 settings.setBackspaceKeyNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::backspaceKeyNavigationEnabledKey())); 2757 settings.setWantsBalancedSetDefersLoadingBehavior(store.getBoolValueForKey(WebPreferencesKey::wantsBalancedSetDefersLoadingBehaviorKey())); 2758 settings.setCaretBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::caretBrowsingEnabledKey())); 2759 2760#if ENABLE(VIDEO_TRACK) 2761 settings.setShouldDisplaySubtitles(store.getBoolValueForKey(WebPreferencesKey::shouldDisplaySubtitlesKey())); 2762 settings.setShouldDisplayCaptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayCaptionsKey())); 2763 settings.setShouldDisplayTextDescriptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayTextDescriptionsKey())); 2764#endif 2765 2766#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 2767 settings.setNotificationsEnabled(store.getBoolValueForKey(WebPreferencesKey::notificationsEnabledKey())); 2768#endif 2769 2770 settings.setShouldRespectImageOrientation(store.getBoolValueForKey(WebPreferencesKey::shouldRespectImageOrientationKey())); 2771 settings.setStorageBlockingPolicy(static_cast<SecurityOrigin::StorageBlockingPolicy>(store.getUInt32ValueForKey(WebPreferencesKey::storageBlockingPolicyKey()))); 2772 settings.setCookieEnabled(store.getBoolValueForKey(WebPreferencesKey::cookieEnabledKey())); 2773 2774 settings.setDiagnosticLoggingEnabled(store.getBoolValueForKey(WebPreferencesKey::diagnosticLoggingEnabledKey())); 2775 2776 settings.setScrollingPerformanceLoggingEnabled(m_scrollingPerformanceLoggingEnabled); 2777 2778 settings.setPlugInSnapshottingEnabled(store.getBoolValueForKey(WebPreferencesKey::plugInSnapshottingEnabledKey())); 2779 settings.setSnapshotAllPlugIns(store.getBoolValueForKey(WebPreferencesKey::snapshotAllPlugInsKey())); 2780 settings.setAutostartOriginPlugInSnapshottingEnabled(store.getBoolValueForKey(WebPreferencesKey::autostartOriginPlugInSnapshottingEnabledKey())); 2781 settings.setPrimaryPlugInSnapshotDetectionEnabled(store.getBoolValueForKey(WebPreferencesKey::primaryPlugInSnapshotDetectionEnabledKey())); 2782 settings.setUsesEncodingDetector(store.getBoolValueForKey(WebPreferencesKey::usesEncodingDetectorKey())); 2783 2784#if ENABLE(TEXT_AUTOSIZING) 2785 settings.setTextAutosizingEnabled(store.getBoolValueForKey(WebPreferencesKey::textAutosizingEnabledKey())); 2786#endif 2787 2788 settings.setLogsPageMessagesToSystemConsoleEnabled(store.getBoolValueForKey(WebPreferencesKey::logsPageMessagesToSystemConsoleEnabledKey())); 2789 settings.setAsynchronousSpellCheckingEnabled(store.getBoolValueForKey(WebPreferencesKey::asynchronousSpellCheckingEnabledKey())); 2790 2791 settings.setSmartInsertDeleteEnabled(store.getBoolValueForKey(WebPreferencesKey::smartInsertDeleteEnabledKey())); 2792 settings.setSelectTrailingWhitespaceEnabled(store.getBoolValueForKey(WebPreferencesKey::selectTrailingWhitespaceEnabledKey())); 2793 settings.setShowsURLsInToolTips(store.getBoolValueForKey(WebPreferencesKey::showsURLsInToolTipsEnabledKey())); 2794 2795#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING) 2796 settings.setHiddenPageDOMTimerThrottlingEnabled(store.getBoolValueForKey(WebPreferencesKey::hiddenPageDOMTimerThrottlingEnabledKey())); 2797#endif 2798 2799 settings.setHiddenPageCSSAnimationSuspensionEnabled(store.getBoolValueForKey(WebPreferencesKey::hiddenPageCSSAnimationSuspensionEnabledKey())); 2800 settings.setLowPowerVideoAudioBufferSizeEnabled(store.getBoolValueForKey(WebPreferencesKey::lowPowerVideoAudioBufferSizeEnabledKey())); 2801 settings.setSimpleLineLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::simpleLineLayoutEnabledKey())); 2802 settings.setSimpleLineLayoutDebugBordersEnabled(store.getBoolValueForKey(WebPreferencesKey::simpleLineLayoutDebugBordersEnabledKey())); 2803 2804 settings.setSubpixelCSSOMElementMetricsEnabled(store.getBoolValueForKey(WebPreferencesKey::subpixelCSSOMElementMetricsEnabledKey())); 2805 2806 settings.setUseLegacyTextAlignPositionedElementBehavior(store.getBoolValueForKey(WebPreferencesKey::useLegacyTextAlignPositionedElementBehaviorKey())); 2807 2808#if ENABLE(MEDIA_SOURCE) 2809 settings.setMediaSourceEnabled(store.getBoolValueForKey(WebPreferencesKey::mediaSourceEnabledKey())); 2810#endif 2811 2812 settings.setShouldConvertPositionStyleOnCopy(store.getBoolValueForKey(WebPreferencesKey::shouldConvertPositionStyleOnCopyKey())); 2813 2814 settings.setStandalone(store.getBoolValueForKey(WebPreferencesKey::standaloneKey())); 2815 settings.setTelephoneNumberParsingEnabled(store.getBoolValueForKey(WebPreferencesKey::telephoneNumberParsingEnabledKey())); 2816 settings.setAlwaysUseBaselineOfPrimaryFont(store.getBoolValueForKey(WebPreferencesKey::alwaysUseBaselineOfPrimaryFontKey())); 2817 settings.setAllowMultiElementImplicitSubmission(store.getBoolValueForKey(WebPreferencesKey::allowMultiElementImplicitSubmissionKey())); 2818 settings.setAlwaysUseAcceleratedOverflowScroll(store.getBoolValueForKey(WebPreferencesKey::alwaysUseAcceleratedOverflowScrollKey())); 2819 2820 settings.setPasswordEchoEnabled(store.getBoolValueForKey(WebPreferencesKey::passwordEchoEnabledKey())); 2821 settings.setPasswordEchoDurationInSeconds(store.getDoubleValueForKey(WebPreferencesKey::passwordEchoDurationKey())); 2822 2823 settings.setLayoutInterval(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::duration<double>(store.getDoubleValueForKey(WebPreferencesKey::layoutIntervalKey())))); 2824 settings.setMaxParseDuration(store.getDoubleValueForKey(WebPreferencesKey::maxParseDurationKey())); 2825 2826 settings.setEnableInheritURIQueryComponent(store.getBoolValueForKey(WebPreferencesKey::enableInheritURIQueryComponentKey())); 2827 2828 settings.setShouldDispatchJavaScriptWindowOnErrorEvents(true); 2829 2830#if PLATFORM(IOS) 2831 settings.setUseImageDocumentForSubframePDF(true); 2832#endif 2833 2834#if ENABLE(GAMEPAD) 2835 RuntimeEnabledFeatures::sharedFeatures().setGamepadsEnabled(store.getBoolValueForKey(WebPreferencesKey::gamepadsEnabledKey())); 2836#endif 2837 2838 if (store.getBoolValueForKey(WebPreferencesKey::pageVisibilityBasedProcessSuppressionEnabledKey())) 2839 m_processSuppressionDisabledByWebPreference.stop(); 2840 else 2841 m_processSuppressionDisabledByWebPreference.start(); 2842 2843 platformPreferencesDidChange(store); 2844 2845 if (m_drawingArea) 2846 m_drawingArea->updatePreferences(store); 2847 2848 m_pageOverlayController.didChangePreferences(); 2849} 2850 2851#if PLATFORM(COCOA) 2852void WebPage::willCommitLayerTree(RemoteLayerTreeTransaction& layerTransaction) 2853{ 2854 layerTransaction.setContentsSize(corePage()->mainFrame().view()->contentsSize()); 2855 layerTransaction.setPageScaleFactor(corePage()->pageScaleFactor()); 2856 layerTransaction.setRenderTreeSize(corePage()->renderTreeSize()); 2857 layerTransaction.setPageExtendedBackgroundColor(corePage()->pageExtendedBackgroundColor()); 2858#if PLATFORM(IOS) 2859 layerTransaction.setScaleWasSetByUIProcess(scaleWasSetByUIProcess()); 2860 layerTransaction.setMinimumScaleFactor(m_viewportConfiguration.minimumScale()); 2861 layerTransaction.setMaximumScaleFactor(m_viewportConfiguration.maximumScale()); 2862 layerTransaction.setAllowsUserScaling(allowsUserScaling()); 2863#endif 2864} 2865 2866void WebPage::didFlushLayerTreeAtTime(std::chrono::milliseconds timestamp) 2867{ 2868#if PLATFORM(IOS) 2869 if (m_oldestNonStableUpdateVisibleContentRectsTimestamp != std::chrono::milliseconds::zero()) { 2870 std::chrono::milliseconds elapsed = timestamp - m_oldestNonStableUpdateVisibleContentRectsTimestamp; 2871 m_oldestNonStableUpdateVisibleContentRectsTimestamp = std::chrono::milliseconds::zero(); 2872 2873 m_estimatedLatency = std::chrono::milliseconds(static_cast<std::chrono::milliseconds::rep>(m_estimatedLatency.count() * 0.80 + elapsed.count() * 0.20)); 2874 } 2875#else 2876 UNUSED_PARAM(timestamp); 2877#endif 2878} 2879#endif 2880 2881 2882#if ENABLE(INSPECTOR) 2883WebInspector* WebPage::inspector() 2884{ 2885 if (m_isClosed) 2886 return 0; 2887 if (!m_inspector) 2888 m_inspector = WebInspector::create(this, m_inspectorClient); 2889 return m_inspector.get(); 2890} 2891#endif 2892 2893#if PLATFORM(IOS) 2894WebVideoFullscreenManager* WebPage::videoFullscreenManager() 2895{ 2896 if (!m_videoFullscreenManager) 2897 m_videoFullscreenManager = WebVideoFullscreenManager::create(this); 2898 return m_videoFullscreenManager.get(); 2899} 2900#endif 2901 2902#if ENABLE(FULLSCREEN_API) 2903WebFullScreenManager* WebPage::fullScreenManager() 2904{ 2905 if (!m_fullScreenManager) 2906 m_fullScreenManager = WebFullScreenManager::create(this); 2907 return m_fullScreenManager.get(); 2908} 2909#endif 2910 2911NotificationPermissionRequestManager* WebPage::notificationPermissionRequestManager() 2912{ 2913 if (m_notificationPermissionRequestManager) 2914 return m_notificationPermissionRequestManager.get(); 2915 2916 m_notificationPermissionRequestManager = NotificationPermissionRequestManager::create(this); 2917 return m_notificationPermissionRequestManager.get(); 2918} 2919 2920#if !PLATFORM(GTK) && !PLATFORM(COCOA) 2921bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt) 2922{ 2923 Node* node = evt->target()->toNode(); 2924 ASSERT(node); 2925 Frame* frame = node->document().frame(); 2926 ASSERT(frame); 2927 2928 const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); 2929 if (!keyEvent) 2930 return false; 2931 2932 Editor::Command command = frame->editor().command(interpretKeyEvent(evt)); 2933 2934 if (keyEvent->type() == PlatformEvent::RawKeyDown) { 2935 // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated, 2936 // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated 2937 // (e.g. Tab that inserts a Tab character, or Enter). 2938 return !command.isTextInsertion() && command.execute(evt); 2939 } 2940 2941 if (command.execute(evt)) 2942 return true; 2943 2944 // Don't allow text insertion for nodes that cannot edit. 2945 if (!frame->editor().canEdit()) 2946 return false; 2947 2948 // Don't insert null or control characters as they can result in unexpected behaviour 2949 if (evt->charCode() < ' ') 2950 return false; 2951 2952 return frame->editor().insertText(evt->keyEvent()->text(), evt); 2953} 2954#endif 2955 2956#if ENABLE(DRAG_SUPPORT) 2957 2958#if PLATFORM(GTK) 2959void WebPage::performDragControllerAction(uint64_t action, WebCore::DragData dragData) 2960{ 2961 if (!m_page) { 2962 send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone, false, 0)); 2963 DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData()); 2964 data->deref(); 2965 return; 2966 } 2967 2968 switch (action) { 2969 case DragControllerActionEntered: { 2970 DragOperation resolvedDragOperation = m_page->dragController().dragEntered(dragData); 2971 send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted())); 2972 break; 2973 } 2974 case DragControllerActionUpdated: { 2975 DragOperation resolvedDragOperation = m_page->dragController().dragEntered(dragData); 2976 send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted())); 2977 break; 2978 } 2979 case DragControllerActionExited: 2980 m_page->dragController().dragExited(dragData); 2981 break; 2982 2983 case DragControllerActionPerformDragOperation: { 2984 m_page->dragController().performDragOperation(dragData); 2985 break; 2986 } 2987 2988 default: 2989 ASSERT_NOT_REACHED(); 2990 } 2991 // DragData does not delete its platformData so we need to do that here. 2992 DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData()); 2993 data->deref(); 2994} 2995 2996#else 2997void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsHandleArray) 2998{ 2999 if (!m_page) { 3000 send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone, false, 0)); 3001 return; 3002 } 3003 3004 DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags)); 3005 switch (action) { 3006 case DragControllerActionEntered: { 3007 DragOperation resolvedDragOperation = m_page->dragController().dragEntered(dragData); 3008 send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted())); 3009 break; 3010 3011 } 3012 case DragControllerActionUpdated: { 3013 DragOperation resolvedDragOperation = m_page->dragController().dragUpdated(dragData); 3014 send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted())); 3015 break; 3016 } 3017 case DragControllerActionExited: 3018 m_page->dragController().dragExited(dragData); 3019 break; 3020 3021 case DragControllerActionPerformDragOperation: { 3022 ASSERT(!m_pendingDropSandboxExtension); 3023 3024 m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle); 3025 for (size_t i = 0; i < sandboxExtensionsHandleArray.size(); i++) { 3026 if (RefPtr<SandboxExtension> extension = SandboxExtension::create(sandboxExtensionsHandleArray[i])) 3027 m_pendingDropExtensionsForFileUpload.append(extension); 3028 } 3029 3030 m_page->dragController().performDragOperation(dragData); 3031 3032 // If we started loading a local file, the sandbox extension tracker would have adopted this 3033 // pending drop sandbox extension. If not, we'll play it safe and clear it. 3034 m_pendingDropSandboxExtension = nullptr; 3035 3036 m_pendingDropExtensionsForFileUpload.clear(); 3037 break; 3038 } 3039 3040 default: 3041 ASSERT_NOT_REACHED(); 3042 } 3043} 3044#endif 3045 3046void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation) 3047{ 3048 IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController().dragOffset().x(), clientPosition.y() + m_page->dragController().dragOffset().y()); 3049 IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController().dragOffset().x(), globalPosition.y() + m_page->dragController().dragOffset().y()); 3050 3051 m_page->dragController().dragEnded(); 3052 FrameView* view = m_page->mainFrame().view(); 3053 if (!view) 3054 return; 3055 // FIXME: These are fake modifier keys here, but they should be real ones instead. 3056 PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime()); 3057 m_page->mainFrame().eventHandler().dragSourceEndedAt(event, (DragOperation)operation); 3058} 3059 3060void WebPage::willPerformLoadDragDestinationAction() 3061{ 3062 m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(m_pendingDropSandboxExtension.release()); 3063} 3064 3065void WebPage::mayPerformUploadDragDestinationAction() 3066{ 3067 for (size_t i = 0; i < m_pendingDropExtensionsForFileUpload.size(); i++) 3068 m_pendingDropExtensionsForFileUpload[i]->consumePermanently(); 3069 m_pendingDropExtensionsForFileUpload.clear(); 3070} 3071 3072#endif // ENABLE(DRAG_SUPPORT) 3073 3074WebUndoStep* WebPage::webUndoStep(uint64_t stepID) 3075{ 3076 return m_undoStepMap.get(stepID); 3077} 3078 3079void WebPage::addWebUndoStep(uint64_t stepID, WebUndoStep* entry) 3080{ 3081 m_undoStepMap.set(stepID, entry); 3082} 3083 3084void WebPage::removeWebEditCommand(uint64_t stepID) 3085{ 3086 m_undoStepMap.remove(stepID); 3087} 3088 3089void WebPage::unapplyEditCommand(uint64_t stepID) 3090{ 3091 WebUndoStep* step = webUndoStep(stepID); 3092 if (!step) 3093 return; 3094 3095 step->step()->unapply(); 3096} 3097 3098void WebPage::reapplyEditCommand(uint64_t stepID) 3099{ 3100 WebUndoStep* step = webUndoStep(stepID); 3101 if (!step) 3102 return; 3103 3104 m_isInRedo = true; 3105 step->step()->reapply(); 3106 m_isInRedo = false; 3107} 3108 3109void WebPage::didRemoveEditCommand(uint64_t commandID) 3110{ 3111 removeWebEditCommand(commandID); 3112} 3113 3114void WebPage::setActivePopupMenu(WebPopupMenu* menu) 3115{ 3116 m_activePopupMenu = menu; 3117} 3118 3119#if ENABLE(INPUT_TYPE_COLOR) 3120void WebPage::setActiveColorChooser(WebColorChooser* colorChooser) 3121{ 3122 m_activeColorChooser = colorChooser; 3123} 3124 3125void WebPage::didEndColorPicker() 3126{ 3127 m_activeColorChooser->didEndChooser(); 3128} 3129 3130void WebPage::didChooseColor(const WebCore::Color& color) 3131{ 3132 m_activeColorChooser->didChooseColor(color); 3133} 3134#endif 3135 3136void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener) 3137{ 3138 m_activeOpenPanelResultListener = openPanelResultListener; 3139} 3140 3141bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options) 3142{ 3143 return m_page->findString(target, options); 3144} 3145 3146void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount) 3147{ 3148 m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount); 3149} 3150 3151void WebPage::findStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount) 3152{ 3153 m_findController.findStringMatches(string, static_cast<FindOptions>(options), maxMatchCount); 3154} 3155 3156void WebPage::getImageForFindMatch(uint32_t matchIndex) 3157{ 3158 m_findController.getImageForFindMatch(matchIndex); 3159} 3160 3161void WebPage::selectFindMatch(uint32_t matchIndex) 3162{ 3163 m_findController.selectFindMatch(matchIndex); 3164} 3165 3166void WebPage::hideFindUI() 3167{ 3168 m_findController.hideFindUI(); 3169} 3170 3171void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount) 3172{ 3173 m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount); 3174} 3175 3176void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex) 3177{ 3178 changeSelectedIndex(newIndex); 3179 m_activePopupMenu = 0; 3180} 3181 3182void WebPage::changeSelectedIndex(int32_t index) 3183{ 3184 if (!m_activePopupMenu) 3185 return; 3186 3187 m_activePopupMenu->didChangeSelectedIndex(index); 3188} 3189 3190#if PLATFORM(IOS) 3191void WebPage::didChooseFilesForOpenPanelWithDisplayStringAndIcon(const Vector<String>& files, const String& displayString, const IPC::DataReference& iconData) 3192{ 3193 if (!m_activeOpenPanelResultListener) 3194 return; 3195 3196 RefPtr<Icon> icon; 3197 if (!iconData.isEmpty()) { 3198 RetainPtr<CFDataRef> dataRef = adoptCF(CFDataCreate(nullptr, iconData.data(), iconData.size())); 3199 RetainPtr<CGDataProviderRef> imageProviderRef = adoptCF(CGDataProviderCreateWithCFData(dataRef.get())); 3200 RetainPtr<CGImageRef> imageRef = adoptCF(CGImageCreateWithJPEGDataProvider(imageProviderRef.get(), nullptr, true, kCGRenderingIntentDefault)); 3201 icon = Icon::createIconForImage(imageRef.get()); 3202 } 3203 3204 m_activeOpenPanelResultListener->didChooseFilesWithDisplayStringAndIcon(files, displayString, icon.get()); 3205 m_activeOpenPanelResultListener = nullptr; 3206} 3207#endif 3208 3209void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files) 3210{ 3211 if (!m_activeOpenPanelResultListener) 3212 return; 3213 3214 m_activeOpenPanelResultListener->didChooseFiles(files); 3215 m_activeOpenPanelResultListener = 0; 3216} 3217 3218void WebPage::didCancelForOpenPanel() 3219{ 3220 m_activeOpenPanelResultListener = 0; 3221} 3222 3223#if ENABLE(SANDBOX_EXTENSIONS) 3224void WebPage::extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle& handle) 3225{ 3226 SandboxExtension::create(handle)->consumePermanently(); 3227} 3228#endif 3229 3230#if ENABLE(GEOLOCATION) 3231void WebPage::didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed) 3232{ 3233 m_geolocationPermissionRequestManager.didReceiveGeolocationPermissionDecision(geolocationID, allowed); 3234} 3235#endif 3236 3237void WebPage::didReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed) 3238{ 3239 notificationPermissionRequestManager()->didReceiveNotificationPermissionDecision(notificationID, allowed); 3240} 3241 3242#if !PLATFORM(IOS) 3243void WebPage::advanceToNextMisspelling(bool startBeforeSelection) 3244{ 3245 Frame& frame = m_page->focusController().focusedOrMainFrame(); 3246 frame.editor().advanceToNextMisspelling(startBeforeSelection); 3247} 3248#endif 3249 3250void WebPage::changeSpellingToWord(const String& word) 3251{ 3252 replaceSelectionWithText(&m_page->focusController().focusedOrMainFrame(), word); 3253} 3254 3255void WebPage::unmarkAllMisspellings() 3256{ 3257 for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) { 3258 if (Document* document = frame->document()) 3259 document->markers().removeMarkers(DocumentMarker::Spelling); 3260 } 3261} 3262 3263void WebPage::unmarkAllBadGrammar() 3264{ 3265 for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) { 3266 if (Document* document = frame->document()) 3267 document->markers().removeMarkers(DocumentMarker::Grammar); 3268 } 3269} 3270 3271#if USE(APPKIT) 3272void WebPage::uppercaseWord() 3273{ 3274 m_page->focusController().focusedOrMainFrame().editor().uppercaseWord(); 3275} 3276 3277void WebPage::lowercaseWord() 3278{ 3279 m_page->focusController().focusedOrMainFrame().editor().lowercaseWord(); 3280} 3281 3282void WebPage::capitalizeWord() 3283{ 3284 m_page->focusController().focusedOrMainFrame().editor().capitalizeWord(); 3285} 3286#endif 3287 3288void WebPage::setTextForActivePopupMenu(int32_t index) 3289{ 3290 if (!m_activePopupMenu) 3291 return; 3292 3293 m_activePopupMenu->setTextForIndex(index); 3294} 3295 3296#if PLATFORM(GTK) 3297void WebPage::failedToShowPopupMenu() 3298{ 3299 if (!m_activePopupMenu) 3300 return; 3301 3302 m_activePopupMenu->client()->popupDidHide(); 3303} 3304#endif 3305 3306#if ENABLE(CONTEXT_MENUS) 3307void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item) 3308{ 3309 if (!m_contextMenu) 3310 return; 3311 3312 m_contextMenu->itemSelected(item); 3313 m_contextMenu = 0; 3314} 3315#endif 3316 3317void WebPage::replaceSelectionWithText(Frame* frame, const String& text) 3318{ 3319 bool selectReplacement = true; 3320 bool smartReplace = false; 3321 return frame->editor().replaceSelectionWithText(text, selectReplacement, smartReplace); 3322} 3323 3324#if !PLATFORM(IOS) 3325void WebPage::clearSelection() 3326{ 3327 m_page->focusController().focusedOrMainFrame().selection().clear(); 3328} 3329#endif 3330 3331bool WebPage::mainFrameHasCustomContentProvider() const 3332{ 3333 if (Frame* frame = mainFrame()) { 3334 WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(frame->loader().client()); 3335 ASSERT(webFrameLoaderClient); 3336 return webFrameLoaderClient->frameHasCustomContentProvider(); 3337 } 3338 3339 return false; 3340} 3341 3342void WebPage::addMIMETypeWithCustomContentProvider(const String& mimeType) 3343{ 3344 m_mimeTypesWithCustomContentProviders.add(mimeType); 3345} 3346 3347void WebPage::updateMainFrameScrollOffsetPinning() 3348{ 3349 Frame& frame = m_page->mainFrame(); 3350 IntPoint scrollPosition = frame.view()->scrollPosition(); 3351 IntPoint maximumScrollPosition = frame.view()->maximumScrollPosition(); 3352 IntPoint minimumScrollPosition = frame.view()->minimumScrollPosition(); 3353 3354 bool isPinnedToLeftSide = (scrollPosition.x() <= minimumScrollPosition.x()); 3355 bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x()); 3356 bool isPinnedToTopSide = (scrollPosition.y() <= minimumScrollPosition.y()); 3357 bool isPinnedToBottomSide = (scrollPosition.y() >= maximumScrollPosition.y()); 3358 3359 if (isPinnedToLeftSide != m_cachedMainFrameIsPinnedToLeftSide || isPinnedToRightSide != m_cachedMainFrameIsPinnedToRightSide || isPinnedToTopSide != m_cachedMainFrameIsPinnedToTopSide || isPinnedToBottomSide != m_cachedMainFrameIsPinnedToBottomSide) { 3360 send(Messages::WebPageProxy::DidChangeScrollOffsetPinningForMainFrame(isPinnedToLeftSide, isPinnedToRightSide, isPinnedToTopSide, isPinnedToBottomSide)); 3361 3362 m_cachedMainFrameIsPinnedToLeftSide = isPinnedToLeftSide; 3363 m_cachedMainFrameIsPinnedToRightSide = isPinnedToRightSide; 3364 m_cachedMainFrameIsPinnedToTopSide = isPinnedToTopSide; 3365 m_cachedMainFrameIsPinnedToBottomSide = isPinnedToBottomSide; 3366 } 3367} 3368 3369void WebPage::mainFrameDidLayout() 3370{ 3371 unsigned pageCount = m_page->pageCount(); 3372 if (pageCount != m_cachedPageCount) { 3373 send(Messages::WebPageProxy::DidChangePageCount(pageCount)); 3374 m_cachedPageCount = pageCount; 3375 } 3376 3377#if USE(TILED_BACKING_STORE) 3378 if (m_drawingArea && m_drawingArea->layerTreeHost()) { 3379 double red, green, blue, alpha; 3380 m_mainFrame->getDocumentBackgroundColor(&red, &green, &blue, &alpha); 3381 RGBA32 rgba = makeRGBA32FromFloats(red, green, blue, alpha); 3382 if (m_backgroundColor.rgb() != rgba) { 3383 m_backgroundColor.setRGB(rgba); 3384 m_drawingArea->layerTreeHost()->setBackgroundColor(m_backgroundColor); 3385 } 3386 } 3387#endif 3388 3389#if PLATFORM(MAC) 3390 m_viewGestureGeometryCollector.mainFrameDidLayout(); 3391#endif 3392#if PLATFORM(IOS) 3393 if (FrameView* frameView = mainFrameView()) { 3394 IntSize newContentSize = frameView->contentsSize(); 3395 if (m_viewportConfiguration.contentsSize() != newContentSize) { 3396 m_viewportConfiguration.setContentsSize(newContentSize); 3397 viewportConfigurationChanged(); 3398 } 3399 } 3400#endif 3401} 3402 3403void WebPage::addPluginView(PluginView* pluginView) 3404{ 3405 ASSERT(!m_pluginViews.contains(pluginView)); 3406 3407 m_pluginViews.add(pluginView); 3408 m_hasSeenPlugin = true; 3409#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 3410 LOG(Plugins, "Primary Plug-In Detection: triggering detection from addPluginView(%p)", pluginView); 3411 m_determinePrimarySnapshottedPlugInTimer.startOneShot(0); 3412#endif 3413} 3414 3415void WebPage::removePluginView(PluginView* pluginView) 3416{ 3417 ASSERT(m_pluginViews.contains(pluginView)); 3418 3419 m_pluginViews.remove(pluginView); 3420#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 3421 LOG(Plugins, "Primary Plug-In Detection: removePluginView(%p)", pluginView); 3422#endif 3423} 3424 3425void WebPage::sendSetWindowFrame(const FloatRect& windowFrame) 3426{ 3427#if PLATFORM(COCOA) 3428 m_hasCachedWindowFrame = false; 3429#endif 3430 send(Messages::WebPageProxy::SetWindowFrame(windowFrame)); 3431} 3432 3433#if PLATFORM(COCOA) 3434void WebPage::windowAndViewFramesChanged(const FloatRect& windowFrameInScreenCoordinates, const FloatRect& windowFrameInUnflippedScreenCoordinates, const FloatRect& viewFrameInWindowCoordinates, const FloatPoint& accessibilityViewCoordinates) 3435{ 3436 m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates; 3437 m_windowFrameInUnflippedScreenCoordinates = windowFrameInUnflippedScreenCoordinates; 3438 m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates; 3439 m_accessibilityPosition = accessibilityViewCoordinates; 3440 3441 // Tell all our plug-in views that the window and view frames have changed. 3442 for (auto* pluginView : m_pluginViews) 3443 pluginView->windowAndViewFramesChanged(enclosingIntRect(windowFrameInScreenCoordinates), enclosingIntRect(viewFrameInWindowCoordinates)); 3444 3445 m_hasCachedWindowFrame = !m_windowFrameInUnflippedScreenCoordinates.isEmpty(); 3446} 3447#endif 3448 3449void WebPage::setMainFrameIsScrollable(bool isScrollable) 3450{ 3451 m_mainFrameIsScrollable = isScrollable; 3452 m_drawingArea->mainFrameScrollabilityChanged(isScrollable); 3453 3454 if (FrameView* frameView = m_mainFrame->coreFrame()->view()) { 3455 frameView->setCanHaveScrollbars(isScrollable); 3456 frameView->setProhibitsScrolling(!isScrollable); 3457 } 3458} 3459 3460bool WebPage::windowIsFocused() const 3461{ 3462 return m_page->focusController().isActive(); 3463} 3464 3465bool WebPage::windowAndWebPageAreFocused() const 3466{ 3467 if (!isVisible()) 3468 return false; 3469 3470 return m_page->focusController().isFocused() && m_page->focusController().isActive(); 3471} 3472 3473void WebPage::didReceiveMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder) 3474{ 3475 if (decoder.messageReceiverName() == Messages::DrawingArea::messageReceiverName()) { 3476 if (m_drawingArea) 3477 m_drawingArea->didReceiveDrawingAreaMessage(connection, decoder); 3478 return; 3479 } 3480 3481#if USE(TILED_BACKING_STORE) 3482 if (decoder.messageReceiverName() == Messages::CoordinatedLayerTreeHost::messageReceiverName()) { 3483 if (m_drawingArea) 3484 m_drawingArea->didReceiveCoordinatedLayerTreeHostMessage(connection, decoder); 3485 return; 3486 } 3487#endif 3488 3489#if ENABLE(INSPECTOR) 3490 if (decoder.messageReceiverName() == Messages::WebInspector::messageReceiverName()) { 3491 if (WebInspector* inspector = this->inspector()) 3492 inspector->didReceiveWebInspectorMessage(connection, decoder); 3493 return; 3494 } 3495#endif 3496 3497#if ENABLE(FULLSCREEN_API) 3498 if (decoder.messageReceiverName() == Messages::WebFullScreenManager::messageReceiverName()) { 3499 fullScreenManager()->didReceiveMessage(connection, decoder); 3500 return; 3501 } 3502#endif 3503 3504 didReceiveWebPageMessage(connection, decoder); 3505} 3506 3507void WebPage::didReceiveSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder) 3508{ 3509 didReceiveSyncWebPageMessage(connection, decoder, replyEncoder); 3510} 3511 3512InjectedBundleBackForwardList* WebPage::backForwardList() 3513{ 3514 if (!m_backForwardList) 3515 m_backForwardList = InjectedBundleBackForwardList::create(this); 3516 return m_backForwardList.get(); 3517} 3518 3519#if ENABLE(ASYNC_SCROLLING) 3520ScrollingCoordinator* WebPage::scrollingCoordinator() const 3521{ 3522 return m_page->scrollingCoordinator(); 3523} 3524#endif 3525 3526WebPage::SandboxExtensionTracker::~SandboxExtensionTracker() 3527{ 3528 invalidate(); 3529} 3530 3531void WebPage::SandboxExtensionTracker::invalidate() 3532{ 3533 m_pendingProvisionalSandboxExtension = nullptr; 3534 3535 if (m_provisionalSandboxExtension) { 3536 m_provisionalSandboxExtension->revoke(); 3537 m_provisionalSandboxExtension = nullptr; 3538 } 3539 3540 if (m_committedSandboxExtension) { 3541 m_committedSandboxExtension->revoke(); 3542 m_committedSandboxExtension = nullptr; 3543 } 3544} 3545 3546void WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension) 3547{ 3548 setPendingProvisionalSandboxExtension(pendingDropSandboxExtension); 3549} 3550 3551void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle) 3552{ 3553 ASSERT_UNUSED(frame, frame->isMainFrame()); 3554 3555 setPendingProvisionalSandboxExtension(SandboxExtension::create(handle)); 3556} 3557 3558void WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension> pendingProvisionalSandboxExtension) 3559{ 3560 m_pendingProvisionalSandboxExtension = pendingProvisionalSandboxExtension; 3561} 3562 3563static bool shouldReuseCommittedSandboxExtension(WebFrame* frame) 3564{ 3565 ASSERT(frame->isMainFrame()); 3566 3567 FrameLoader& frameLoader = frame->coreFrame()->loader(); 3568 FrameLoadType frameLoadType = frameLoader.loadType(); 3569 3570 // If the page is being reloaded, it should reuse whatever extension is committed. 3571 if (frameLoadType == FrameLoadType::Reload || frameLoadType == FrameLoadType::ReloadFromOrigin) 3572 return true; 3573 3574 DocumentLoader* documentLoader = frameLoader.documentLoader(); 3575 DocumentLoader* provisionalDocumentLoader = frameLoader.provisionalDocumentLoader(); 3576 if (!documentLoader || !provisionalDocumentLoader) 3577 return false; 3578 3579 if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile()) 3580 return true; 3581 3582 return false; 3583} 3584 3585void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame) 3586{ 3587 if (!frame->isMainFrame()) 3588 return; 3589 3590 // We should only reuse the commited sandbox extension if it is not null. It can be 3591 // null if the last load was for an error page. 3592 if (m_committedSandboxExtension && shouldReuseCommittedSandboxExtension(frame)) 3593 m_pendingProvisionalSandboxExtension = m_committedSandboxExtension; 3594 3595 ASSERT(!m_provisionalSandboxExtension); 3596 3597 m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release(); 3598 if (!m_provisionalSandboxExtension) 3599 return; 3600 3601 ASSERT(!m_provisionalSandboxExtension || frame->coreFrame()->loader().provisionalDocumentLoader()->url().isLocalFile()); 3602 3603 m_provisionalSandboxExtension->consume(); 3604} 3605 3606void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame) 3607{ 3608 if (!frame->isMainFrame()) 3609 return; 3610 3611 if (m_committedSandboxExtension) 3612 m_committedSandboxExtension->revoke(); 3613 3614 m_committedSandboxExtension = m_provisionalSandboxExtension.release(); 3615 3616 // We can also have a non-null m_pendingProvisionalSandboxExtension if a new load is being started. 3617 // This extension is not cleared, because it does not pertain to the failed load, and will be needed. 3618} 3619 3620void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame) 3621{ 3622 if (!frame->isMainFrame()) 3623 return; 3624 3625 if (!m_provisionalSandboxExtension) 3626 return; 3627 3628 m_provisionalSandboxExtension->revoke(); 3629 m_provisionalSandboxExtension = nullptr; 3630 3631 // We can also have a non-null m_pendingProvisionalSandboxExtension if a new load is being started 3632 // (notably, if the current one fails because the new one cancels it). This extension is not cleared, 3633 // because it does not pertain to the failed load, and will be needed. 3634} 3635 3636bool WebPage::hasLocalDataForURL(const URL& url) 3637{ 3638 if (url.isLocalFile()) 3639 return true; 3640 3641 DocumentLoader* documentLoader = m_page->mainFrame().loader().documentLoader(); 3642 if (documentLoader && documentLoader->subresource(url)) 3643 return true; 3644 3645 return platformHasLocalDataForURL(url); 3646} 3647 3648void WebPage::setCustomTextEncodingName(const String& encoding) 3649{ 3650 m_page->mainFrame().loader().reloadWithOverrideEncoding(encoding); 3651} 3652 3653void WebPage::didRemoveBackForwardItem(uint64_t itemID) 3654{ 3655 WebBackForwardListProxy::removeItem(itemID); 3656} 3657 3658#if PLATFORM(COCOA) 3659 3660bool WebPage::isSpeaking() 3661{ 3662 bool result; 3663 return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result; 3664} 3665 3666void WebPage::speak(const String& string) 3667{ 3668 send(Messages::WebPageProxy::Speak(string)); 3669} 3670 3671void WebPage::stopSpeaking() 3672{ 3673 send(Messages::WebPageProxy::StopSpeaking()); 3674} 3675 3676#endif 3677 3678#if PLATFORM(MAC) 3679RetainPtr<PDFDocument> WebPage::pdfDocumentForPrintingFrame(Frame* coreFrame) 3680{ 3681 Document* document = coreFrame->document(); 3682 if (!document) 3683 return 0; 3684 3685 if (!document->isPluginDocument()) 3686 return 0; 3687 3688 PluginView* pluginView = static_cast<PluginView*>(toPluginDocument(document)->pluginWidget()); 3689 if (!pluginView) 3690 return 0; 3691 3692 return pluginView->pdfDocumentForPrinting(); 3693} 3694#endif // PLATFORM(MAC) 3695 3696void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo) 3697{ 3698 WebFrame* frame = WebProcess::shared().webFrame(frameID); 3699 if (!frame) 3700 return; 3701 3702 Frame* coreFrame = frame->coreFrame(); 3703 if (!coreFrame) 3704 return; 3705 3706#if PLATFORM(MAC) 3707 if (pdfDocumentForPrintingFrame(coreFrame)) 3708 return; 3709#endif // PLATFORM(MAC) 3710 3711 if (!m_printContext) 3712 m_printContext = std::make_unique<PrintContext>(coreFrame); 3713 3714 drawingArea()->setLayerTreeStateIsFrozen(true); 3715 m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight); 3716 3717 float fullPageHeight; 3718 m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true); 3719 3720#if PLATFORM(GTK) 3721 if (!m_printOperation) 3722 m_printOperation = WebPrintOperationGtk::create(this, printInfo); 3723#endif 3724} 3725 3726void WebPage::endPrinting() 3727{ 3728 drawingArea()->setLayerTreeStateIsFrozen(false); 3729 m_printContext = nullptr; 3730} 3731 3732void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID) 3733{ 3734 Vector<IntRect> resultPageRects; 3735 double resultTotalScaleFactorForPrinting = 1; 3736 computePagesForPrintingImpl(frameID, printInfo, resultPageRects, resultTotalScaleFactorForPrinting); 3737 send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID)); 3738} 3739 3740void WebPage::computePagesForPrintingImpl(uint64_t frameID, const PrintInfo& printInfo, Vector<WebCore::IntRect>& resultPageRects, double& resultTotalScaleFactorForPrinting) 3741{ 3742 ASSERT(resultPageRects.isEmpty()); 3743 3744 beginPrinting(frameID, printInfo); 3745 3746 if (m_printContext) { 3747 resultPageRects = m_printContext->pageRects(); 3748 resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(FloatSize(printInfo.availablePaperWidth, printInfo.availablePaperHeight)) * printInfo.pageSetupScaleFactor; 3749 } 3750#if PLATFORM(COCOA) 3751 else 3752 computePagesForPrintingPDFDocument(frameID, printInfo, resultPageRects); 3753#endif // PLATFORM(COCOA) 3754 3755 // If we're asked to print, we should actually print at least a blank page. 3756 if (resultPageRects.isEmpty()) 3757 resultPageRects.append(IntRect(0, 0, 1, 1)); 3758} 3759 3760#if PLATFORM(COCOA) 3761void WebPage::drawRectToImage(uint64_t frameID, const PrintInfo& printInfo, const IntRect& rect, const WebCore::IntSize& imageSize, uint64_t callbackID) 3762{ 3763 WebFrame* frame = WebProcess::shared().webFrame(frameID); 3764 Frame* coreFrame = frame ? frame->coreFrame() : 0; 3765 3766 RefPtr<WebImage> image; 3767 3768#if USE(CG) 3769 if (coreFrame) { 3770#if PLATFORM(MAC) 3771 ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame)); 3772#else 3773 ASSERT(coreFrame->document()->printing()); 3774#endif 3775 3776 RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(imageSize, ShareableBitmap::SupportsAlpha); 3777 auto graphicsContext = bitmap->createGraphicsContext(); 3778 3779 float printingScale = static_cast<float>(imageSize.width()) / rect.width(); 3780 graphicsContext->scale(FloatSize(printingScale, printingScale)); 3781 3782#if PLATFORM(MAC) 3783 if (RetainPtr<PDFDocument> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) { 3784 ASSERT(!m_printContext); 3785 graphicsContext->scale(FloatSize(1, -1)); 3786 graphicsContext->translate(0, -rect.height()); 3787 drawPDFDocument(graphicsContext->platformContext(), pdfDocument.get(), printInfo, rect); 3788 } else 3789#endif 3790 { 3791 m_printContext->spoolRect(*graphicsContext, rect); 3792 } 3793 3794 image = WebImage::create(bitmap.release()); 3795 } 3796#endif 3797 3798 ShareableBitmap::Handle handle; 3799 3800 if (image) 3801 image->bitmap()->createHandle(handle, SharedMemory::ReadOnly); 3802 3803 send(Messages::WebPageProxy::ImageCallback(handle, callbackID)); 3804} 3805 3806void WebPage::drawPagesToPDF(uint64_t frameID, const PrintInfo& printInfo, uint32_t first, uint32_t count, uint64_t callbackID) 3807{ 3808 RetainPtr<CFMutableDataRef> pdfPageData; 3809 drawPagesToPDFImpl(frameID, printInfo, first, count, pdfPageData); 3810 send(Messages::WebPageProxy::DataCallback(IPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID)); 3811} 3812 3813void WebPage::drawPagesToPDFImpl(uint64_t frameID, const PrintInfo& printInfo, uint32_t first, uint32_t count, RetainPtr<CFMutableDataRef>& pdfPageData) 3814{ 3815 WebFrame* frame = WebProcess::shared().webFrame(frameID); 3816 Frame* coreFrame = frame ? frame->coreFrame() : 0; 3817 3818 pdfPageData = adoptCF(CFDataCreateMutable(0, 0)); 3819 3820#if USE(CG) 3821 if (coreFrame) { 3822 3823#if PLATFORM(MAC) 3824 ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame)); 3825#else 3826 ASSERT(coreFrame->document()->printing()); 3827#endif 3828 3829 // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data. 3830 RetainPtr<CGDataConsumerRef> pdfDataConsumer = adoptCF(CGDataConsumerCreateWithCFData(pdfPageData.get())); 3831 3832 CGRect mediaBox = (m_printContext && m_printContext->pageCount()) ? m_printContext->pageRect(0) : CGRectMake(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight); 3833 RetainPtr<CGContextRef> context = adoptCF(CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0)); 3834 3835#if PLATFORM(MAC) 3836 if (RetainPtr<PDFDocument> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) { 3837 ASSERT(!m_printContext); 3838 drawPagesToPDFFromPDFDocument(context.get(), pdfDocument.get(), printInfo, first, count); 3839 } else 3840#endif 3841 { 3842 size_t pageCount = m_printContext->pageCount(); 3843 for (uint32_t page = first; page < first + count; ++page) { 3844 if (page >= pageCount) 3845 break; 3846 3847 RetainPtr<CFDictionaryRef> pageInfo = adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); 3848 CGPDFContextBeginPage(context.get(), pageInfo.get()); 3849 3850 GraphicsContext ctx(context.get()); 3851 ctx.scale(FloatSize(1, -1)); 3852 ctx.translate(0, -m_printContext->pageRect(page).height()); 3853 m_printContext->spoolPage(ctx, page, m_printContext->pageRect(page).width()); 3854 3855 CGPDFContextEndPage(context.get()); 3856 } 3857 } 3858 CGPDFContextClose(context.get()); 3859 } 3860#endif 3861} 3862 3863#elif PLATFORM(GTK) 3864void WebPage::drawPagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID) 3865{ 3866 beginPrinting(frameID, printInfo); 3867 if (m_printContext && m_printOperation) { 3868 m_printOperation->startPrint(m_printContext.get(), callbackID); 3869 return; 3870 } 3871 3872 send(Messages::WebPageProxy::VoidCallback(callbackID)); 3873} 3874 3875void WebPage::didFinishPrintOperation(const WebCore::ResourceError& error, uint64_t callbackID) 3876{ 3877 send(Messages::WebPageProxy::PrintFinishedCallback(error, callbackID)); 3878 m_printOperation = nullptr; 3879} 3880#endif 3881 3882void WebPage::savePDFToFileInDownloadsFolder(const String& suggestedFilename, const String& originatingURLString, const uint8_t* data, unsigned long size) 3883{ 3884 send(Messages::WebPageProxy::SavePDFToFileInDownloadsFolder(suggestedFilename, originatingURLString, IPC::DataReference(data, size))); 3885} 3886 3887#if PLATFORM(COCOA) 3888void WebPage::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String& suggestedFilename, const String& originatingURLString, const uint8_t* data, unsigned long size, const String& pdfUUID) 3889{ 3890 send(Messages::WebPageProxy::SavePDFToTemporaryFolderAndOpenWithNativeApplication(suggestedFilename, originatingURLString, IPC::DataReference(data, size), pdfUUID)); 3891} 3892#endif 3893 3894void WebPage::addResourceRequest(unsigned long identifier, const WebCore::ResourceRequest& request) 3895{ 3896 if (!request.url().protocolIsInHTTPFamily()) 3897 return; 3898 3899 ASSERT(!m_networkResourceRequestIdentifiers.contains(identifier)); 3900 bool wasEmpty = m_networkResourceRequestIdentifiers.isEmpty(); 3901 m_networkResourceRequestIdentifiers.add(identifier); 3902 if (wasEmpty) 3903 send(Messages::WebPageProxy::SetNetworkRequestsInProgress(true)); 3904} 3905 3906void WebPage::removeResourceRequest(unsigned long identifier) 3907{ 3908 if (!m_networkResourceRequestIdentifiers.remove(identifier)) 3909 return; 3910 3911 if (m_networkResourceRequestIdentifiers.isEmpty()) 3912 send(Messages::WebPageProxy::SetNetworkRequestsInProgress(false)); 3913} 3914 3915void WebPage::setMediaVolume(float volume) 3916{ 3917 m_page->setMediaVolume(volume); 3918} 3919 3920void WebPage::setMayStartMediaWhenInWindow(bool mayStartMedia) 3921{ 3922 if (mayStartMedia == m_mayStartMediaWhenInWindow) 3923 return; 3924 3925 m_mayStartMediaWhenInWindow = mayStartMedia; 3926 if (m_mayStartMediaWhenInWindow && m_page->isInWindow()) 3927 m_setCanStartMediaTimer.startOneShot(0); 3928} 3929 3930void WebPage::runModal() 3931{ 3932 if (m_isClosed) 3933 return; 3934 if (m_isRunningModal) 3935 return; 3936 3937 m_isRunningModal = true; 3938 send(Messages::WebPageProxy::RunModal()); 3939#if !ASSERT_DISABLED 3940 Ref<WebPage> protector(*this); 3941#endif 3942 RunLoop::run(); 3943 ASSERT(!m_isRunningModal); 3944} 3945 3946bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request) 3947{ 3948 if (SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(request.url().protocol())) 3949 return true; 3950 3951 if (request.url().protocolIs("blob")) 3952 return true; 3953 3954 return platformCanHandleRequest(request); 3955} 3956 3957#if USE(TILED_BACKING_STORE) 3958void WebPage::commitPageTransitionViewport() 3959{ 3960 m_drawingArea->setLayerTreeStateIsFrozen(false); 3961} 3962#endif 3963 3964#if PLATFORM(COCOA) 3965void WebPage::handleAlternativeTextUIResult(const String& result) 3966{ 3967 Frame& frame = m_page->focusController().focusedOrMainFrame(); 3968 frame.editor().handleAlternativeTextUIResult(result); 3969} 3970#endif 3971 3972void WebPage::simulateMouseDown(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time) 3973{ 3974 mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time)); 3975} 3976 3977void WebPage::simulateMouseUp(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time) 3978{ 3979 mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time)); 3980} 3981 3982void WebPage::simulateMouseMotion(WebCore::IntPoint position, double time) 3983{ 3984 mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time)); 3985} 3986 3987void WebPage::setCompositionForTesting(const String& compositionString, uint64_t from, uint64_t length) 3988{ 3989 Frame& frame = m_page->focusController().focusedOrMainFrame(); 3990 if (!frame.editor().canEdit()) 3991 return; 3992 3993 Vector<CompositionUnderline> underlines; 3994 underlines.append(CompositionUnderline(0, compositionString.length(), Color(Color::black), false)); 3995 frame.editor().setComposition(compositionString, underlines, from, from + length); 3996} 3997 3998bool WebPage::hasCompositionForTesting() 3999{ 4000 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4001 return frame.editor().hasComposition(); 4002} 4003 4004void WebPage::confirmCompositionForTesting(const String& compositionString) 4005{ 4006 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4007 if (!frame.editor().canEdit()) 4008 return; 4009 4010 if (compositionString.isNull()) 4011 frame.editor().confirmComposition(); 4012 frame.editor().confirmComposition(compositionString); 4013} 4014 4015void WebPage::numWheelEventHandlersChanged(unsigned numWheelEventHandlers) 4016{ 4017 if (m_numWheelEventHandlers == numWheelEventHandlers) 4018 return; 4019 4020 m_numWheelEventHandlers = numWheelEventHandlers; 4021 recomputeShortCircuitHorizontalWheelEventsState(); 4022} 4023 4024static bool hasEnabledHorizontalScrollbar(ScrollableArea* scrollableArea) 4025{ 4026 if (Scrollbar* scrollbar = scrollableArea->horizontalScrollbar()) 4027 return scrollbar->enabled(); 4028 4029 return false; 4030} 4031 4032static bool pageContainsAnyHorizontalScrollbars(Frame* mainFrame) 4033{ 4034 if (FrameView* frameView = mainFrame->view()) { 4035 if (hasEnabledHorizontalScrollbar(frameView)) 4036 return true; 4037 } 4038 4039 for (Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) { 4040 FrameView* frameView = frame->view(); 4041 if (!frameView) 4042 continue; 4043 4044 const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas(); 4045 if (!scrollableAreas) 4046 continue; 4047 4048 for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) { 4049 ScrollableArea* scrollableArea = *it; 4050 if (!scrollableArea->scrollbarsCanBeActive()) 4051 continue; 4052 4053 if (hasEnabledHorizontalScrollbar(scrollableArea)) 4054 return true; 4055 } 4056 } 4057 4058 return false; 4059} 4060 4061void WebPage::recomputeShortCircuitHorizontalWheelEventsState() 4062{ 4063 bool canShortCircuitHorizontalWheelEvents = !m_numWheelEventHandlers; 4064 4065 if (canShortCircuitHorizontalWheelEvents) { 4066 // Check if we have any horizontal scroll bars on the page. 4067 if (pageContainsAnyHorizontalScrollbars(mainFrame())) 4068 canShortCircuitHorizontalWheelEvents = false; 4069 } 4070 4071 if (m_canShortCircuitHorizontalWheelEvents == canShortCircuitHorizontalWheelEvents) 4072 return; 4073 4074 m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents; 4075 send(Messages::WebPageProxy::SetCanShortCircuitHorizontalWheelEvents(m_canShortCircuitHorizontalWheelEvents)); 4076} 4077 4078Frame* WebPage::mainFrame() const 4079{ 4080 return m_page ? &m_page->mainFrame() : nullptr; 4081} 4082 4083FrameView* WebPage::mainFrameView() const 4084{ 4085 if (Frame* frame = mainFrame()) 4086 return frame->view(); 4087 4088 return nullptr; 4089} 4090 4091void WebPage::setScrollingPerformanceLoggingEnabled(bool enabled) 4092{ 4093 m_scrollingPerformanceLoggingEnabled = enabled; 4094 4095 FrameView* frameView = m_mainFrame->coreFrame()->view(); 4096 if (!frameView) 4097 return; 4098 4099 frameView->setScrollingPerformanceLoggingEnabled(enabled); 4100} 4101 4102bool WebPage::canPluginHandleResponse(const ResourceResponse& response) 4103{ 4104#if ENABLE(NETSCAPE_PLUGIN_API) 4105 uint32_t pluginLoadPolicy; 4106 bool allowOnlyApplicationPlugins = !m_mainFrame->coreFrame()->loader().subframeLoader().allowPlugins(NotAboutToInstantiatePlugin); 4107 4108 uint64_t pluginProcessToken; 4109 String newMIMEType; 4110 String unavailabilityDescription; 4111 if (!sendSync(Messages::WebPageProxy::FindPlugin(response.mimeType(), PluginProcessTypeNormal, response.url().string(), response.url().string(), response.url().string(), allowOnlyApplicationPlugins), Messages::WebPageProxy::FindPlugin::Reply(pluginProcessToken, newMIMEType, pluginLoadPolicy, unavailabilityDescription))) 4112 return false; 4113 4114 return pluginLoadPolicy != PluginModuleBlocked && pluginProcessToken; 4115#else 4116 UNUSED_PARAM(response); 4117 return false; 4118#endif 4119} 4120 4121bool WebPage::shouldUseCustomContentProviderForResponse(const ResourceResponse& response) 4122{ 4123 // If a plug-in exists that claims to support this response, it should take precedence over the custom content provider. 4124 return m_mimeTypesWithCustomContentProviders.contains(response.mimeType()) && !canPluginHandleResponse(response); 4125} 4126 4127#if PLATFORM(COCOA) 4128 4129void WebPage::insertTextAsync(const String& text, const EditingRange& replacementEditingRange, bool registerUndoGroup) 4130{ 4131 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4132 4133 if (replacementEditingRange.location != notFound) { 4134 RefPtr<Range> replacementRange = rangeFromEditingRange(frame, replacementEditingRange); 4135 if (replacementRange) 4136 frame.selection().setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY)); 4137 } 4138 4139 if (registerUndoGroup) 4140 send(Messages::WebPageProxy::RegisterInsertionUndoGrouping()); 4141 4142 if (!frame.editor().hasComposition()) { 4143 // An insertText: might be handled by other responders in the chain if we don't handle it. 4144 // One example is space bar that results in scrolling down the page. 4145 frame.editor().insertText(text, nullptr); 4146 } else 4147 frame.editor().confirmComposition(text); 4148} 4149 4150void WebPage::getMarkedRangeAsync(uint64_t callbackID) 4151{ 4152 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4153 4154 RefPtr<Range> range = frame.editor().compositionRange(); 4155 size_t location; 4156 size_t length; 4157 if (!range || !TextIterator::getLocationAndLengthFromRange(frame.selection().rootEditableElementOrDocumentElement(), range.get(), location, length)) { 4158 location = notFound; 4159 length = 0; 4160 } 4161 4162 send(Messages::WebPageProxy::EditingRangeCallback(EditingRange(location, length), callbackID)); 4163} 4164 4165void WebPage::getSelectedRangeAsync(uint64_t callbackID) 4166{ 4167 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4168 4169 size_t location; 4170 size_t length; 4171 RefPtr<Range> range = frame.selection().toNormalizedRange(); 4172 if (!range || !TextIterator::getLocationAndLengthFromRange(frame.selection().rootEditableElementOrDocumentElement(), range.get(), location, length)) { 4173 location = notFound; 4174 length = 0; 4175 } 4176 4177 send(Messages::WebPageProxy::EditingRangeCallback(EditingRange(location, length), callbackID)); 4178} 4179 4180void WebPage::characterIndexForPointAsync(const WebCore::IntPoint& point, uint64_t callbackID) 4181{ 4182 uint64_t index = notFound; 4183 4184 HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(point); 4185 Frame* frame = result.innerNonSharedNode() ? result.innerNodeFrame() : &m_page->focusController().focusedOrMainFrame(); 4186 4187 RefPtr<Range> range = frame->rangeForPoint(result.roundedPointInInnerNodeFrame()); 4188 if (range) { 4189 size_t location; 4190 size_t length; 4191 if (TextIterator::getLocationAndLengthFromRange(frame->selection().rootEditableElementOrDocumentElement(), range.get(), location, length)) 4192 index = static_cast<uint64_t>(location); 4193 } 4194 4195 send(Messages::WebPageProxy::UnsignedCallback(index, callbackID)); 4196} 4197 4198void WebPage::firstRectForCharacterRangeAsync(const EditingRange& editingRange, uint64_t callbackID) 4199{ 4200 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4201 IntRect result(IntPoint(0, 0), IntSize(0, 0)); 4202 4203 RefPtr<Range> range = rangeFromEditingRange(frame, editingRange); 4204 if (!range) { 4205 send(Messages::WebPageProxy::RectForCharacterRangeCallback(result, EditingRange(notFound, 0), callbackID)); 4206 return; 4207 } 4208 4209 ASSERT(range->startContainer()); 4210 ASSERT(range->endContainer()); 4211 4212 result = frame.view()->contentsToWindow(frame.editor().firstRectForRange(range.get())); 4213 4214 // FIXME: Update actualRange to match the range of first rect. 4215 send(Messages::WebPageProxy::RectForCharacterRangeCallback(result, editingRange, callbackID)); 4216} 4217 4218void WebPage::setCompositionAsync(const String& text, Vector<CompositionUnderline> underlines, const EditingRange& selection, const EditingRange& replacementEditingRange) 4219{ 4220 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4221 4222 if (frame.selection().selection().isContentEditable()) { 4223 RefPtr<Range> replacementRange; 4224 if (replacementEditingRange.location != notFound) { 4225 replacementRange = rangeFromEditingRange(frame, replacementEditingRange); 4226 frame.selection().setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY)); 4227 } 4228 4229 frame.editor().setComposition(text, underlines, selection.location, selection.location + selection.length); 4230 } 4231} 4232 4233void WebPage::confirmCompositionAsync() 4234{ 4235 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4236 frame.editor().confirmComposition(); 4237} 4238 4239#endif // PLATFORM(COCOA) 4240 4241#if PLATFORM(GTK) 4242static Frame* targetFrameForEditing(WebPage* page) 4243{ 4244 Frame& targetFrame = page->corePage()->focusController().focusedOrMainFrame(); 4245 4246 Editor& editor = targetFrame.editor(); 4247 if (!editor.canEdit()) 4248 return 0; 4249 4250 if (editor.hasComposition()) { 4251 // We should verify the parent node of this IME composition node are 4252 // editable because JavaScript may delete a parent node of the composition 4253 // node. In this case, WebKit crashes while deleting texts from the parent 4254 // node, which doesn't exist any longer. 4255 if (PassRefPtr<Range> range = editor.compositionRange()) { 4256 Node* node = range->startContainer(); 4257 if (!node || !node->isContentEditable()) 4258 return 0; 4259 } 4260 } 4261 return &targetFrame; 4262} 4263 4264void WebPage::confirmComposition(const String& compositionString, int64_t selectionStart, int64_t selectionLength) 4265{ 4266 Frame* targetFrame = targetFrameForEditing(this); 4267 if (!targetFrame) { 4268 send(Messages::WebPageProxy::EditorStateChanged(editorState())); 4269 return; 4270 } 4271 4272 targetFrame->editor().confirmComposition(compositionString); 4273 4274 if (selectionStart == -1) { 4275 send(Messages::WebPageProxy::EditorStateChanged(editorState())); 4276 return; 4277 } 4278 4279 Element* scope = targetFrame->selection().selection().rootEditableElement(); 4280 RefPtr<Range> selectionRange = TextIterator::rangeFromLocationAndLength(scope, selectionStart, selectionLength); 4281 ASSERT_WITH_MESSAGE(selectionRange, "Invalid selection: [%lld:%lld] in text of length %d", static_cast<long long>(selectionStart), static_cast<long long>(selectionLength), scope->innerText().length()); 4282 4283 if (selectionRange) { 4284 VisibleSelection selection(selectionRange.get(), SEL_DEFAULT_AFFINITY); 4285 targetFrame->selection().setSelection(selection); 4286 } 4287 send(Messages::WebPageProxy::EditorStateChanged(editorState())); 4288} 4289 4290void WebPage::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, uint64_t selectionStart, uint64_t selectionLength, uint64_t replacementStart, uint64_t replacementLength) 4291{ 4292 Frame* targetFrame = targetFrameForEditing(this); 4293 if (!targetFrame || !targetFrame->selection().selection().isContentEditable()) { 4294 send(Messages::WebPageProxy::EditorStateChanged(editorState())); 4295 return; 4296 } 4297 4298 if (replacementLength > 0) { 4299 // The layout needs to be uptodate before setting a selection 4300 targetFrame->document()->updateLayout(); 4301 4302 Element* scope = targetFrame->selection().selection().rootEditableElement(); 4303 RefPtr<Range> replacementRange = TextIterator::rangeFromLocationAndLength(scope, replacementStart, replacementLength); 4304 targetFrame->editor().setIgnoreCompositionSelectionChange(true); 4305 targetFrame->selection().setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY)); 4306 targetFrame->editor().setIgnoreCompositionSelectionChange(false); 4307 } 4308 4309 targetFrame->editor().setComposition(text, underlines, selectionStart, selectionStart + selectionLength); 4310 send(Messages::WebPageProxy::EditorStateChanged(editorState())); 4311} 4312 4313void WebPage::cancelComposition() 4314{ 4315 if (Frame* targetFrame = targetFrameForEditing(this)) 4316 targetFrame->editor().cancelComposition(); 4317 send(Messages::WebPageProxy::EditorStateChanged(editorState())); 4318} 4319#endif 4320 4321void WebPage::didChangeSelection() 4322{ 4323#if (PLATFORM(MAC) && USE(ASYNC_NSTEXTINPUTCLIENT)) 4324 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4325 // Abandon the current inline input session if selection changed for any other reason but an input method direct action. 4326 // FIXME: Many changes that affect composition node do not go through didChangeSelection(). We need to do something when DOM manipulation affects the composition, because otherwise input method's idea about it will be different from Editor's. 4327 // FIXME: We can't cancel composition when selection changes to NoSelection, but we probably should. 4328 if (frame.editor().hasComposition() && !frame.editor().ignoreCompositionSelectionChange() && !frame.selection().isNone()) { 4329 frame.editor().cancelComposition(); 4330 send(Messages::WebPageProxy::CompositionWasCanceled(editorState())); 4331 } else 4332#endif 4333 send(Messages::WebPageProxy::EditorStateChanged(editorState())); 4334 4335#if PLATFORM(IOS) 4336 m_drawingArea->scheduleCompositingLayerFlush(); 4337#endif 4338} 4339 4340void WebPage::setMinimumLayoutSize(const IntSize& minimumLayoutSize) 4341{ 4342 if (m_minimumLayoutSize == minimumLayoutSize) 4343 return; 4344 4345 m_minimumLayoutSize = minimumLayoutSize; 4346 if (minimumLayoutSize.width() <= 0) { 4347 corePage()->mainFrame().view()->enableAutoSizeMode(false, IntSize(), IntSize()); 4348 return; 4349 } 4350 4351 int minimumLayoutWidth = minimumLayoutSize.width(); 4352 int minimumLayoutHeight = std::max(minimumLayoutSize.height(), 1); 4353 4354 int maximumSize = std::numeric_limits<int>::max(); 4355 4356 corePage()->mainFrame().view()->enableAutoSizeMode(true, IntSize(minimumLayoutWidth, minimumLayoutHeight), IntSize(maximumSize, maximumSize)); 4357} 4358 4359void WebPage::setAutoSizingShouldExpandToViewHeight(bool shouldExpand) 4360{ 4361 if (m_autoSizingShouldExpandToViewHeight == shouldExpand) 4362 return; 4363 4364 m_autoSizingShouldExpandToViewHeight = shouldExpand; 4365 4366 corePage()->mainFrame().view()->setAutoSizeFixedMinimumHeight(shouldExpand ? m_viewSize.height() : 0); 4367} 4368 4369bool WebPage::isSmartInsertDeleteEnabled() 4370{ 4371 return m_page->settings().smartInsertDeleteEnabled(); 4372} 4373 4374void WebPage::setSmartInsertDeleteEnabled(bool enabled) 4375{ 4376 if (m_page->settings().smartInsertDeleteEnabled() != enabled) { 4377 m_page->settings().setSmartInsertDeleteEnabled(enabled); 4378 setSelectTrailingWhitespaceEnabled(!enabled); 4379 } 4380} 4381 4382bool WebPage::isSelectTrailingWhitespaceEnabled() 4383{ 4384 return m_page->settings().selectTrailingWhitespaceEnabled(); 4385} 4386 4387void WebPage::setSelectTrailingWhitespaceEnabled(bool enabled) 4388{ 4389 if (m_page->settings().selectTrailingWhitespaceEnabled() != enabled) { 4390 m_page->settings().setSelectTrailingWhitespaceEnabled(enabled); 4391 setSmartInsertDeleteEnabled(!enabled); 4392 } 4393} 4394 4395bool WebPage::canShowMIMEType(const String& MIMEType) const 4396{ 4397 if (MIMETypeRegistry::canShowMIMEType(MIMEType)) 4398 return true; 4399 4400 if (m_mimeTypesWithCustomContentProviders.contains(MIMEType)) 4401 return true; 4402 4403 const PluginData& pluginData = m_page->pluginData(); 4404 if (pluginData.supportsMimeType(MIMEType, PluginData::AllPlugins) && corePage()->mainFrame().loader().subframeLoader().allowPlugins(NotAboutToInstantiatePlugin)) 4405 return true; 4406 4407 // We can use application plugins even if plugins aren't enabled. 4408 if (pluginData.supportsMimeType(MIMEType, PluginData::OnlyApplicationPlugins)) 4409 return true; 4410 4411 return false; 4412} 4413 4414void WebPage::addTextCheckingRequest(uint64_t requestID, PassRefPtr<TextCheckingRequest> request) 4415{ 4416 m_pendingTextCheckingRequestMap.add(requestID, request); 4417} 4418 4419void WebPage::didFinishCheckingText(uint64_t requestID, const Vector<TextCheckingResult>& result) 4420{ 4421 RefPtr<TextCheckingRequest> request = m_pendingTextCheckingRequestMap.take(requestID); 4422 if (!request) 4423 return; 4424 4425 request->didSucceed(result); 4426} 4427 4428void WebPage::didCancelCheckingText(uint64_t requestID) 4429{ 4430 RefPtr<TextCheckingRequest> request = m_pendingTextCheckingRequestMap.take(requestID); 4431 if (!request) 4432 return; 4433 4434 request->didCancel(); 4435} 4436 4437void WebPage::didCommitLoad(WebFrame* frame) 4438{ 4439 if (!frame->isMainFrame()) 4440 return; 4441 4442 // If previous URL is invalid, then it's not a real page that's being navigated away from. 4443 // Most likely, this is actually the first load to be committed in this page. 4444 if (frame->coreFrame()->loader().previousURL().isValid()) 4445 reportUsedFeatures(); 4446 4447 // Only restore the scale factor for standard frame loads (of the main frame). 4448 if (frame->coreFrame()->loader().loadType() == FrameLoadType::Standard) { 4449 Page* page = frame->coreFrame()->page(); 4450 4451 if (page && page->pageScaleFactor() != 1) 4452 scalePage(1, IntPoint()); 4453 } 4454#if PLATFORM(IOS) 4455 m_hasReceivedVisibleContentRectsAfterDidCommitLoad = false; 4456 m_scaleWasSetByUIProcess = false; 4457 m_firstLayerTreeTransactionIDAfterDidCommitLoad = toRemoteLayerTreeDrawingArea(*m_drawingArea).nextTransactionID(); 4458 m_userHasChangedPageScaleFactor = false; 4459 m_estimatedLatency = std::chrono::milliseconds(1000 / 60); 4460 4461 WebProcess::shared().eventDispatcher().clearQueuedTouchEventsForPage(*this); 4462 4463 resetViewportDefaultConfiguration(frame); 4464 m_viewportConfiguration.resetMinimalUI(); 4465 const Frame* coreFrame = frame->coreFrame(); 4466 m_viewportConfiguration.setContentsSize(coreFrame->view()->contentsSize()); 4467 m_viewportConfiguration.setViewportArguments(coreFrame->document()->viewportArguments()); 4468 viewportConfigurationChanged(); 4469#endif 4470 4471#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 4472 resetPrimarySnapshottedPlugIn(); 4473#endif 4474 4475 WebProcess::shared().updateActivePages(); 4476 4477 updateMainFrameScrollOffsetPinning(); 4478} 4479 4480void WebPage::didFinishDocumentLoad(WebFrame* frame) 4481{ 4482#if PLATFORM(IOS) 4483 if (!frame->isMainFrame()) 4484 return; 4485 4486 m_viewportConfiguration.didFinishDocumentLoad(); 4487#else 4488 UNUSED_PARAM(frame); 4489#endif // PLATFORM(IOS) 4490} 4491 4492void WebPage::didFinishLoad(WebFrame* frame) 4493{ 4494#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 4495 if (!frame->isMainFrame()) 4496 return; 4497 4498 m_readyToFindPrimarySnapshottedPlugin = true; 4499 LOG(Plugins, "Primary Plug-In Detection: triggering detection from didFinishLoad (marking as ready to detect)."); 4500 m_determinePrimarySnapshottedPlugInTimer.startOneShot(0); 4501#else 4502 UNUSED_PARAM(frame); 4503#endif 4504} 4505 4506#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 4507static int primarySnapshottedPlugInSearchLimit = 3000; 4508static float primarySnapshottedPlugInSearchBucketSize = 1.1; 4509static int primarySnapshottedPlugInMinimumWidth = 400; 4510static int primarySnapshottedPlugInMinimumHeight = 300; 4511static unsigned maxPrimarySnapshottedPlugInDetectionAttempts = 2; 4512static int deferredPrimarySnapshottedPlugInDetectionDelay = 3; 4513static float overlappingImageBoundsScale = 1.1; 4514static float minimumOverlappingImageToPluginDimensionScale = .9; 4515 4516#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 4517void WebPage::determinePrimarySnapshottedPlugInTimerFired() 4518{ 4519 if (!m_page) 4520 return; 4521 4522 Settings& settings = m_page->settings(); 4523 if (!settings.snapshotAllPlugIns() && settings.primaryPlugInSnapshotDetectionEnabled()) 4524 determinePrimarySnapshottedPlugIn(); 4525} 4526#endif 4527 4528void WebPage::determinePrimarySnapshottedPlugIn() 4529{ 4530 if (!m_page->settings().plugInSnapshottingEnabled()) 4531 return; 4532 4533 LOG(Plugins, "Primary Plug-In Detection: began."); 4534 4535 if (!m_readyToFindPrimarySnapshottedPlugin) { 4536 LOG(Plugins, "Primary Plug-In Detection: exiting - not ready to find plugins."); 4537 return; 4538 } 4539 4540 if (!m_hasSeenPlugin) { 4541 LOG(Plugins, "Primary Plug-In Detection: exiting - we never saw a plug-in get added to the page."); 4542 return; 4543 } 4544 4545 if (m_didFindPrimarySnapshottedPlugin) { 4546 LOG(Plugins, "Primary Plug-In Detection: exiting - we've already found a primary plug-in."); 4547 return; 4548 } 4549 4550 ++m_numberOfPrimarySnapshotDetectionAttempts; 4551 4552 MainFrame& mainFrame = corePage()->mainFrame(); 4553 if (!mainFrame.view()) 4554 return; 4555 if (!mainFrame.view()->renderView()) 4556 return; 4557 RenderView& mainRenderView = *mainFrame.view()->renderView(); 4558 4559 IntRect searchRect = IntRect(IntPoint(), corePage()->mainFrame().view()->contentsSize()); 4560 searchRect.intersect(IntRect(IntPoint(), IntSize(primarySnapshottedPlugInSearchLimit, primarySnapshottedPlugInSearchLimit))); 4561 4562 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); 4563 4564 HTMLPlugInImageElement* candidatePlugIn = nullptr; 4565 unsigned candidatePlugInArea = 0; 4566 4567 for (Frame* frame = &mainFrame; frame; frame = frame->tree().traverseNext()) { 4568 if (!frame->loader().subframeLoader().containsPlugins()) 4569 continue; 4570 if (!frame->document() || !frame->view()) 4571 continue; 4572 for (auto& plugInImageElement : descendantsOfType<HTMLPlugInImageElement>(*frame->document())) { 4573 if (plugInImageElement.displayState() == HTMLPlugInElement::Playing) 4574 continue; 4575 4576 auto pluginRenderer = plugInImageElement.renderer(); 4577 if (!pluginRenderer || !pluginRenderer->isBox()) 4578 continue; 4579 auto& pluginRenderBox = toRenderBox(*pluginRenderer); 4580 if (!plugInIntersectsSearchRect(plugInImageElement)) 4581 continue; 4582 4583 IntRect plugInRectRelativeToView = plugInImageElement.clientRect(); 4584 IntSize scrollOffset = mainFrame.view()->documentScrollOffsetRelativeToViewOrigin(); 4585 IntRect plugInRectRelativeToTopDocument(plugInRectRelativeToView.location() + scrollOffset, plugInRectRelativeToView.size()); 4586 HitTestResult hitTestResult(plugInRectRelativeToTopDocument.center()); 4587 mainRenderView.hitTest(request, hitTestResult); 4588 4589 Element* element = hitTestResult.innerElement(); 4590 if (!element) 4591 continue; 4592 4593 IntRect elementRectRelativeToView = element->clientRect(); 4594 IntRect elementRectRelativeToTopDocument(elementRectRelativeToView.location() + scrollOffset, elementRectRelativeToView.size()); 4595 LayoutRect inflatedPluginRect = plugInRectRelativeToTopDocument; 4596 LayoutUnit xOffset = (inflatedPluginRect.width() * overlappingImageBoundsScale - inflatedPluginRect.width()) / 2; 4597 LayoutUnit yOffset = (inflatedPluginRect.height() * overlappingImageBoundsScale - inflatedPluginRect.height()) / 2; 4598 inflatedPluginRect.inflateX(xOffset); 4599 inflatedPluginRect.inflateY(yOffset); 4600 4601 if (element != &plugInImageElement) { 4602 if (!(isHTMLImageElement(element) 4603 && inflatedPluginRect.contains(elementRectRelativeToTopDocument) 4604 && elementRectRelativeToTopDocument.width() > pluginRenderBox.width() * minimumOverlappingImageToPluginDimensionScale 4605 && elementRectRelativeToTopDocument.height() > pluginRenderBox.height() * minimumOverlappingImageToPluginDimensionScale)) 4606 continue; 4607 LOG(Plugins, "Primary Plug-In Detection: Plug-in is hidden by an image that is roughly aligned with it, autoplaying regardless of whether or not it's actually the primary plug-in."); 4608 plugInImageElement.restartSnapshottedPlugIn(); 4609 } 4610 4611 if (plugInIsPrimarySize(plugInImageElement, candidatePlugInArea)) 4612 candidatePlugIn = &plugInImageElement; 4613 } 4614 } 4615 if (!candidatePlugIn) { 4616 LOG(Plugins, "Primary Plug-In Detection: fail - did not find a candidate plug-in."); 4617 if (m_numberOfPrimarySnapshotDetectionAttempts < maxPrimarySnapshottedPlugInDetectionAttempts) { 4618 LOG(Plugins, "Primary Plug-In Detection: will attempt again in %ds.", deferredPrimarySnapshottedPlugInDetectionDelay); 4619 m_determinePrimarySnapshottedPlugInTimer.startOneShot(deferredPrimarySnapshottedPlugInDetectionDelay); 4620 } 4621 return; 4622 } 4623 4624 LOG(Plugins, "Primary Plug-In Detection: success - found a candidate plug-in - inform it."); 4625 m_didFindPrimarySnapshottedPlugin = true; 4626 m_primaryPlugInPageOrigin = m_page->mainFrame().document()->baseURL().host(); 4627 m_primaryPlugInOrigin = candidatePlugIn->loadedUrl().host(); 4628 m_primaryPlugInMimeType = candidatePlugIn->loadedMimeType(); 4629 4630 candidatePlugIn->setIsPrimarySnapshottedPlugIn(true); 4631} 4632 4633void WebPage::resetPrimarySnapshottedPlugIn() 4634{ 4635 m_readyToFindPrimarySnapshottedPlugin = false; 4636 m_didFindPrimarySnapshottedPlugin = false; 4637 m_numberOfPrimarySnapshotDetectionAttempts = 0; 4638 m_hasSeenPlugin = false; 4639} 4640 4641bool WebPage::matchesPrimaryPlugIn(const String& pageOrigin, const String& pluginOrigin, const String& mimeType) const 4642{ 4643 if (!m_didFindPrimarySnapshottedPlugin) 4644 return false; 4645 4646 return (pageOrigin == m_primaryPlugInPageOrigin && pluginOrigin == m_primaryPlugInOrigin && mimeType == m_primaryPlugInMimeType); 4647} 4648 4649bool WebPage::plugInIntersectsSearchRect(HTMLPlugInImageElement& plugInImageElement) 4650{ 4651 MainFrame& mainFrame = corePage()->mainFrame(); 4652 if (!mainFrame.view()) 4653 return false; 4654 if (!mainFrame.view()->renderView()) 4655 return false; 4656 4657 IntRect searchRect = IntRect(IntPoint(), corePage()->mainFrame().view()->contentsSize()); 4658 searchRect.intersect(IntRect(IntPoint(), IntSize(primarySnapshottedPlugInSearchLimit, primarySnapshottedPlugInSearchLimit))); 4659 4660 IntRect plugInRectRelativeToView = plugInImageElement.clientRect(); 4661 if (plugInRectRelativeToView.isEmpty()) 4662 return false; 4663 IntSize scrollOffset = mainFrame.view()->documentScrollOffsetRelativeToViewOrigin(); 4664 IntRect plugInRectRelativeToTopDocument(plugInRectRelativeToView.location() + scrollOffset, plugInRectRelativeToView.size()); 4665 4666 return plugInRectRelativeToTopDocument.intersects(searchRect); 4667} 4668 4669bool WebPage::plugInIsPrimarySize(WebCore::HTMLPlugInImageElement& plugInImageElement, unsigned& candidatePlugInArea) 4670{ 4671 auto& pluginRenderBox = toRenderBox(*(plugInImageElement.renderer())); 4672 if (pluginRenderBox.contentWidth() < primarySnapshottedPlugInMinimumWidth || pluginRenderBox.contentHeight() < primarySnapshottedPlugInMinimumHeight) 4673 return false; 4674 4675 LayoutUnit contentArea = pluginRenderBox.contentWidth() * pluginRenderBox.contentHeight(); 4676 if (contentArea > candidatePlugInArea * primarySnapshottedPlugInSearchBucketSize) { 4677 candidatePlugInArea = contentArea; 4678 return true; 4679 } 4680 return false; 4681} 4682#endif // ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) 4683 4684PassRefPtr<Range> WebPage::currentSelectionAsRange() 4685{ 4686 Frame* frame = frameWithSelection(m_page.get()); 4687 if (!frame) 4688 return 0; 4689 4690 return frame->selection().toNormalizedRange(); 4691} 4692 4693void WebPage::reportUsedFeatures() 4694{ 4695 Vector<String> namedFeatures; 4696 m_loaderClient.featuresUsedInPage(this, namedFeatures); 4697} 4698 4699unsigned WebPage::extendIncrementalRenderingSuppression() 4700{ 4701 unsigned token = m_maximumRenderingSuppressionToken + 1; 4702 while (!HashSet<unsigned>::isValidValue(token) || m_activeRenderingSuppressionTokens.contains(token)) 4703 token++; 4704 4705 m_activeRenderingSuppressionTokens.add(token); 4706 m_page->mainFrame().view()->setVisualUpdatesAllowedByClient(false); 4707 4708 m_maximumRenderingSuppressionToken = token; 4709 4710 return token; 4711} 4712 4713void WebPage::stopExtendingIncrementalRenderingSuppression(unsigned token) 4714{ 4715 if (!m_activeRenderingSuppressionTokens.remove(token)) 4716 return; 4717 4718 m_page->mainFrame().view()->setVisualUpdatesAllowedByClient(!shouldExtendIncrementalRenderingSuppression()); 4719} 4720 4721void WebPage::setScrollPinningBehavior(uint32_t pinning) 4722{ 4723 m_scrollPinningBehavior = static_cast<ScrollPinningBehavior>(pinning); 4724 m_page->mainFrame().view()->setScrollPinningBehavior(m_scrollPinningBehavior); 4725} 4726 4727PassRefPtr<DocumentLoader> WebPage::createDocumentLoader(Frame& frame, const ResourceRequest& request, const SubstituteData& substituteData) 4728{ 4729 RefPtr<WebDocumentLoader> documentLoader = WebDocumentLoader::create(request, substituteData); 4730 4731 if (m_pendingNavigationID && frame.isMainFrame()) { 4732 documentLoader->setNavigationID(m_pendingNavigationID); 4733 m_pendingNavigationID = 0; 4734 } 4735 4736 return documentLoader.release(); 4737} 4738 4739void WebPage::getBytecodeProfile(uint64_t callbackID) 4740{ 4741 ASSERT(JSDOMWindow::commonVM().m_perBytecodeProfiler); 4742 if (!JSDOMWindow::commonVM().m_perBytecodeProfiler) 4743 send(Messages::WebPageProxy::StringCallback(String(), callbackID)); 4744 String result = JSDOMWindow::commonVM().m_perBytecodeProfiler->toJSON(); 4745 ASSERT(result.length()); 4746 send(Messages::WebPageProxy::StringCallback(result, callbackID)); 4747} 4748 4749PassRefPtr<WebCore::Range> WebPage::rangeFromEditingRange(WebCore::Frame& frame, const EditingRange& range) 4750{ 4751 ASSERT(range.location != notFound); 4752 4753 // Sanitize the input, because TextIterator::rangeFromLocationAndLength takes signed integers. 4754 if (range.location > INT_MAX) 4755 return 0; 4756 int length; 4757 if (range.length <= INT_MAX && range.location + range.length <= INT_MAX) 4758 length = static_cast<int>(range.length); 4759 else 4760 length = INT_MAX - range.location; 4761 4762 // Our critical assumption is that we are only called by input methods that 4763 // concentrate on a given area containing the selection. 4764 // We have to do this because of text fields and textareas. The DOM for those is not 4765 // directly in the document DOM, so serialization is problematic. Our solution is 4766 // to use the root editable element of the selection start as the positional base. 4767 // That fits with AppKit's idea of an input context. 4768 return TextIterator::rangeFromLocationAndLength(frame.selection().rootEditableElementOrDocumentElement(), static_cast<int>(range.location), length); 4769} 4770 4771bool WebPage::synchronousMessagesShouldSpinRunLoop() 4772{ 4773#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000 4774 return WebCore::AXObjectCache::accessibilityEnabled(); 4775#endif 4776 return false; 4777} 4778 4779#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION) 4780ServicesOverlayController& WebPage::servicesOverlayController() 4781{ 4782 if (!m_servicesOverlayController) 4783 m_servicesOverlayController = std::make_unique<ServicesOverlayController>(*this); 4784 4785 return *m_servicesOverlayController; 4786} 4787#endif 4788 4789void WebPage::didChangeScrollOffsetForFrame(Frame* frame) 4790{ 4791 m_pageOverlayController.didScrollFrame(frame); 4792 4793 if (!frame->isMainFrame()) 4794 return; 4795 4796 // If this is called when tearing down a FrameView, the WebCore::Frame's 4797 // current FrameView will be null. 4798 if (!frame->view()) 4799 return; 4800 4801 updateMainFrameScrollOffsetPinning(); 4802} 4803 4804void WebPage::willChangeCurrentHistoryItemForMainFrame() 4805{ 4806 send(Messages::WebPageProxy::WillChangeCurrentHistoryItemForMainFrame()); 4807} 4808 4809} // namespace WebKit 4810