diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebKit2/WebProcess/WebPage/WebPage.cpp | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage/WebPage.cpp')
-rw-r--r-- | Source/WebKit2/WebProcess/WebPage/WebPage.cpp | 3501 |
1 files changed, 2313 insertions, 1188 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp index 1351a095d..71fe0688e 100644 --- a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp +++ b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2011, 2012, 2013-2015 Apple Inc. All rights reserved. * Copyright (C) 2012 Intel Corporation. All rights reserved. * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) * @@ -28,74 +28,96 @@ #include "config.h" #include "WebPage.h" +#include "APIArray.h" +#include "APIGeometry.h" #include "Arguments.h" #include "DataReference.h" -#include "DecoderAdapter.h" +#include "DragControllerAction.h" #include "DrawingArea.h" #include "DrawingAreaMessages.h" +#include "EditorState.h" +#include "EventDispatcher.h" #include "InjectedBundle.h" #include "InjectedBundleBackForwardList.h" -#include "InjectedBundleUserMessageCoders.h" -#include "LayerTreeHost.h" +#include "Logging.h" #include "NetscapePlugin.h" #include "NotificationPermissionRequestManager.h" #include "PageBanner.h" -#include "PageOverlay.h" #include "PluginProcessAttributes.h" #include "PluginProxy.h" #include "PluginView.h" #include "PrintInfo.h" #include "SessionState.h" +#include "SessionStateConversion.h" +#include "SessionTracker.h" #include "ShareableBitmap.h" +#include "VisitedLinkTableController.h" +#include "WKBundleAPICast.h" +#include "WKRetainPtr.h" +#include "WKSharedAPICast.h" #include "WebAlternativeTextClient.h" -#include "WebBackForwardList.h" #include "WebBackForwardListItem.h" #include "WebBackForwardListProxy.h" #include "WebChromeClient.h" #include "WebColorChooser.h" #include "WebContextMenu.h" #include "WebContextMenuClient.h" -#include "WebContextMessages.h" #include "WebCoreArgumentCoders.h" +#include "WebDatabaseProvider.h" +#include "WebDiagnosticLoggingClient.h" +#include "WebDocumentLoader.h" #include "WebDragClient.h" #include "WebEditorClient.h" #include "WebEvent.h" #include "WebEventConversion.h" +#include "WebEventFactory.h" #include "WebFrame.h" +#include "WebFrameLoaderClient.h" #include "WebFullScreenManager.h" #include "WebFullScreenManagerMessages.h" #include "WebGeolocationClient.h" -#include "WebGeometry.h" #include "WebImage.h" #include "WebInspector.h" #include "WebInspectorClient.h" #include "WebInspectorMessages.h" +#include "WebInspectorUI.h" +#include "WebInspectorUIMessages.h" +#include "WebMediaKeyStorageManager.h" #include "WebNotificationClient.h" #include "WebOpenPanelResultListener.h" #include "WebPageCreationParameters.h" #include "WebPageGroupProxy.h" #include "WebPageMessages.h" +#include "WebPageOverlay.h" #include "WebPageProxyMessages.h" #include "WebPlugInClient.h" #include "WebPopupMenu.h" +#include "WebPreferencesDefinitions.h" +#include "WebPreferencesKeys.h" #include "WebPreferencesStore.h" #include "WebProcess.h" +#include "WebProcessPoolMessages.h" #include "WebProcessProxyMessages.h" +#include "WebProgressTrackerClient.h" +#include "WebStorageNamespaceProvider.h" +#include "WebUndoStep.h" +#include "WebUserContentController.h" +#include "WebUserMediaClient.h" #include <JavaScriptCore/APICast.h> #include <WebCore/ArchiveResource.h> #include <WebCore/Chrome.h> #include <WebCore/ContextMenuController.h> +#include <WebCore/DataTransfer.h> #include <WebCore/DatabaseManager.h> #include <WebCore/DocumentFragment.h> #include <WebCore/DocumentLoader.h> #include <WebCore/DocumentMarkerController.h> #include <WebCore/DragController.h> #include <WebCore/DragData.h> -#include <WebCore/DragSession.h> +#include <WebCore/ElementIterator.h> #include <WebCore/EventHandler.h> #include <WebCore/FocusController.h> #include <WebCore/FormState.h> -#include <WebCore/Frame.h> #include <WebCore/FrameLoadRequest.h> #include <WebCore/FrameLoaderTypes.h> #include <WebCore/FrameView.h> @@ -105,11 +127,15 @@ #include <WebCore/HTMLPlugInImageElement.h> #include <WebCore/HistoryController.h> #include <WebCore/HistoryItem.h> +#include <WebCore/HitTestResult.h> #include <WebCore/JSDOMWindow.h> #include <WebCore/KeyboardEvent.h> #include <WebCore/MIMETypeRegistry.h> +#include <WebCore/MainFrame.h> #include <WebCore/MouseEvent.h> #include <WebCore/Page.h> +#include <WebCore/PageConfiguration.h> +#include <WebCore/PageThrottler.h> #include <WebCore/PlatformKeyboardEvent.h> #include <WebCore/PluginDocument.h> #include <WebCore/PrintContext.h> @@ -117,43 +143,44 @@ #include <WebCore/RenderLayer.h> #include <WebCore/RenderTreeAsText.h> #include <WebCore/RenderView.h> -#include <WebCore/ResourceBuffer.h> #include <WebCore/ResourceRequest.h> #include <WebCore/ResourceResponse.h> -#include <WebCore/RunLoop.h> #include <WebCore/RuntimeEnabledFeatures.h> #include <WebCore/SchemeRegistry.h> #include <WebCore/ScriptController.h> -#include <WebCore/ScriptValue.h> #include <WebCore/SerializedScriptValue.h> +#include <WebCore/SessionID.h> #include <WebCore/Settings.h> +#include <WebCore/ShadowRoot.h> #include <WebCore/SharedBuffer.h> +#include <WebCore/StyleProperties.h> +#include <WebCore/SubframeLoader.h> #include <WebCore/SubstituteData.h> #include <WebCore/TextIterator.h> +#include <WebCore/UserInputBridge.h> #include <WebCore/VisiblePosition.h> +#include <WebCore/VisibleUnits.h> #include <WebCore/markup.h> +#include <bindings/ScriptValue.h> +#include <profiler/ProfilerDatabase.h> +#include <runtime/JSCInlines.h> #include <runtime/JSCJSValue.h> #include <runtime/JSLock.h> -#include <runtime/Operations.h> +#include <wtf/RunLoop.h> +#include <wtf/TemporaryChange.h> -#if ENABLE(MHTML) -#include <WebCore/MHTMLArchive.h> +#if ENABLE(DATA_DETECTION) +#include "DataDetectionResult.h" #endif -#if ENABLE(PLUGIN_PROCESS) -#if PLATFORM(MAC) -#include "MachPort.h" -#endif +#if ENABLE(MHTML) +#include <WebCore/MHTMLArchive.h> #endif #if ENABLE(BATTERY_STATUS) #include "WebBatteryClient.h" #endif -#if ENABLE(NETWORK_INFO) -#include "WebNetworkInfoClient.h" -#endif - #if ENABLE(VIBRATION) #include "WebVibrationClient.h" #endif @@ -162,11 +189,11 @@ #include "WebDeviceProximityClient.h" #endif -#if PLATFORM(MAC) -#include "SimplePDFPlugin.h" -#if ENABLE(PDFKIT_PLUGIN) +#if PLATFORM(COCOA) #include "PDFPlugin.h" -#endif +#include "RemoteLayerTreeTransaction.h" +#include "WKStringCF.h" +#include "WebVideoFullscreenManager.h" #include <WebCore/LegacyWebArchive.h> #endif @@ -185,19 +212,44 @@ #include "WebPrintOperationGtk.h" #endif +#if PLATFORM(IOS) +#include "RemoteLayerTreeDrawingArea.h" +#include <CoreGraphics/CoreGraphics.h> +#include <WebCore/CoreTextSPI.h> +#include <WebCore/Icon.h> +#endif + #ifndef NDEBUG #include <wtf/RefCountedLeakCounter.h> #endif -#if USE(COORDINATED_GRAPHICS) +#if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER) +#include "LayerTreeHost.h" +#endif + +#if USE(COORDINATED_GRAPHICS_MULTIPROCESS) #include "CoordinatedLayerTreeHostMessages.h" #endif +#if ENABLE(DATA_DETECTION) +#include <WebCore/DataDetection.h> +#endif + +#if ENABLE(VIDEO) && USE(GSTREAMER) +#include <WebCore/MediaPlayerRequestInstallMissingPluginsCallback.h> +#endif + +#if USE(APPLE_INTERNAL_SDK) +#include <WebKitAdditions/WebPageIncludes.h> +#endif + using namespace JSC; using namespace WebCore; namespace WebKit { +static const double pageScrollHysteresisSeconds = 0.3; + class SendStopResponsivenessTimer { public: SendStopResponsivenessTimer(WebPage* page) @@ -216,21 +268,22 @@ private: DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageCounter, ("WebPage")); -PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters) +Ref<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters) { - RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters)); + Ref<WebPage> page = adoptRef(*new WebPage(pageID, parameters)); - if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle()) - WebProcess::shared().injectedBundle()->didCreatePage(page.get()); + if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::singleton().injectedBundle()) + WebProcess::singleton().injectedBundle()->didCreatePage(page.ptr()); - return page.release(); + return page; } WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters) - : m_viewSize(parameters.viewSize) + : m_pageID(pageID) + , m_viewSize(parameters.viewSize) + , m_hasSeenPlugin(false) , m_useFixedLayout(false) , m_drawsBackground(true) - , m_drawsTransparentBackground(false) , m_isInRedo(false) , m_isClosed(false) , m_tabToLinks(false) @@ -242,19 +295,23 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters) #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) , m_readyToFindPrimarySnapshottedPlugin(false) , m_didFindPrimarySnapshottedPlugin(false) + , m_numberOfPrimarySnapshotDetectionAttempts(0) , m_determinePrimarySnapshottedPlugInTimer(RunLoop::main(), this, &WebPage::determinePrimarySnapshottedPlugInTimerFired) #endif -#if PLATFORM(MAC) + , m_layerHostingMode(parameters.layerHostingMode) +#if PLATFORM(COCOA) , m_pdfPluginEnabled(false) , m_hasCachedWindowFrame(false) - , m_windowIsVisible(false) - , m_layerHostingMode(parameters.layerHostingMode) - , m_keyboardEventBeingInterpreted(0) -#elif PLATFORM(GTK) - , m_accessibilityObject(0) + , m_viewGestureGeometryCollector(*this) +#elif HAVE(ACCESSIBILITY) && (PLATFORM(GTK) || PLATFORM(EFL)) + , m_accessibilityObject(nullptr) #endif , m_setCanStartMediaTimer(RunLoop::main(), this, &WebPage::setCanStartMediaTimerFired) - , m_sendDidUpdateInWindowStateTimer(RunLoop::main(), this, &WebPage::didUpdateInWindowStateTimerFired) +#if ENABLE(CONTEXT_MENUS) + , m_contextMenuClient(std::make_unique<API::InjectedBundle::PageContextMenuClient>()) +#endif + , m_formClient(std::make_unique<API::InjectedBundle::FormClient>()) + , m_uiClient(std::make_unique<API::InjectedBundle::PageUIClient>()) , m_findController(this) #if ENABLE(TOUCH_EVENTS) #if PLATFORM(QT) @@ -264,57 +321,116 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters) #if ENABLE(INPUT_TYPE_COLOR) , m_activeColorChooser(0) #endif + , m_userContentController(parameters.userContentControllerID ? WebUserContentController::getOrCreate(parameters.userContentControllerID) : nullptr) #if ENABLE(GEOLOCATION) , m_geolocationPermissionRequestManager(this) #endif - , m_pageID(pageID) +#if ENABLE(MEDIA_STREAM) + , m_userMediaPermissionRequestManager(*this) +#endif + , m_pageScrolledHysteresis([this](HysteresisState state) { if (state == HysteresisState::Stopped) pageStoppedScrolling(); }, pageScrollHysteresisSeconds) , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel) , m_canRunModal(parameters.canRunModal) , m_isRunningModal(false) - , m_cachedMainFrameIsPinnedToLeftSide(false) - , m_cachedMainFrameIsPinnedToRightSide(false) - , m_cachedMainFrameIsPinnedToTopSide(false) - , m_cachedMainFrameIsPinnedToBottomSide(false) +#if ENABLE(DRAG_SUPPORT) + , m_isStartingDrag(false) +#endif + , m_cachedMainFrameIsPinnedToLeftSide(true) + , m_cachedMainFrameIsPinnedToRightSide(true) + , m_cachedMainFrameIsPinnedToTopSide(true) + , m_cachedMainFrameIsPinnedToBottomSide(true) , m_canShortCircuitHorizontalWheelEvents(false) - , m_numWheelEventHandlers(0) + , m_hasWheelEventHandlers(false) , m_cachedPageCount(0) + , m_autoSizingShouldExpandToViewHeight(false) #if ENABLE(CONTEXT_MENUS) , m_isShowingContextMenu(false) #endif - , m_willGoToBackForwardItemCallbackEnabled(true) -#if ENABLE(PAGE_VISIBILITY_API) - , m_visibilityState(WebCore::PageVisibilityStateVisible) +#if PLATFORM(IOS) + , m_selectionAnchor(Start) + , m_hasReceivedVisibleContentRectsAfterDidCommitLoad(false) + , m_scaleWasSetByUIProcess(false) + , m_userHasChangedPageScaleFactor(false) + , m_hasStablePageScaleFactor(true) + , m_userIsInteracting(false) + , m_hasPendingBlurNotification(false) + , m_useTestingViewportConfiguration(false) + , m_isInStableState(true) + , m_oldestNonStableUpdateVisibleContentRectsTimestamp(std::chrono::milliseconds::zero()) + , m_estimatedLatency(std::chrono::milliseconds::zero()) + , m_screenSize(parameters.screenSize) + , m_availableScreenSize(parameters.availableScreenSize) + , m_deviceOrientation(0) + , m_inDynamicSizeUpdate(false) + , m_volatilityTimer(*this, &WebPage::volatilityTimerFired) #endif - , m_inspectorClient(0) , m_backgroundColor(Color::white) , m_maximumRenderingSuppressionToken(0) , m_scrollPinningBehavior(DoNotPin) + , m_useAsyncScrolling(false) + , m_viewState(parameters.viewState) + , m_processSuppressionEnabled(true) + , m_userActivity("Process suppression disabled for page.") + , m_pendingNavigationID(0) +#if ENABLE(WEBGL) + , m_systemWebGLPolicy(WebGLAllowCreation) +#endif + , m_mainFrameProgressCompleted(false) + , m_shouldDispatchFakeMouseMoveEvents(true) { ASSERT(m_pageID); - // FIXME: This is a non-ideal location for this Setting and - // 4ms should be adopted project-wide now, https://bugs.webkit.org/show_bug.cgi?id=61214 - Settings::setDefaultMinDOMTimerInterval(0.004); - Page::PageClients pageClients; - pageClients.chromeClient = new WebChromeClient(this); + m_pageGroup = WebProcess::singleton().webPageGroup(parameters.pageGroupData); + +#if PLATFORM(IOS) + Settings::setShouldManageAudioSessionCategory(true); +#endif + + PageConfiguration pageConfiguration; + pageConfiguration.chromeClient = new WebChromeClient(this); #if ENABLE(CONTEXT_MENUS) - pageClients.contextMenuClient = new WebContextMenuClient(this); + pageConfiguration.contextMenuClient = new WebContextMenuClient(this); #endif - pageClients.editorClient = new WebEditorClient(this); + pageConfiguration.editorClient = new WebEditorClient(this); #if ENABLE(DRAG_SUPPORT) - pageClients.dragClient = new WebDragClient(this); -#endif - pageClients.backForwardClient = WebBackForwardListProxy::create(this); -#if ENABLE(INSPECTOR) - m_inspectorClient = new WebInspectorClient(this); - pageClients.inspectorClient = m_inspectorClient; + pageConfiguration.dragClient = new WebDragClient(this); #endif + pageConfiguration.backForwardClient = WebBackForwardListProxy::create(this); + pageConfiguration.inspectorClient = new WebInspectorClient(this); #if USE(AUTOCORRECTION_PANEL) - pageClients.alternativeTextClient = new WebAlternativeTextClient(this); + pageConfiguration.alternativeTextClient = new WebAlternativeTextClient(this); +#endif + + pageConfiguration.plugInClient = new WebPlugInClient(*this); + pageConfiguration.loaderClientForMainFrame = new WebFrameLoaderClient; + pageConfiguration.progressTrackerClient = new WebProgressTrackerClient(*this); + pageConfiguration.diagnosticLoggingClient = new WebDiagnosticLoggingClient(*this); + + pageConfiguration.databaseProvider = WebDatabaseProvider::getOrCreate(m_pageGroup->pageGroupID()); + pageConfiguration.storageNamespaceProvider = WebStorageNamespaceProvider::getOrCreate(m_pageGroup->pageGroupID()); + pageConfiguration.userContentController = m_userContentController ? &m_userContentController->userContentController() : &m_pageGroup->userContentController(); + pageConfiguration.visitedLinkStore = VisitedLinkTableController::getOrCreate(parameters.visitedLinkTableID); + +#if USE(APPLE_INTERNAL_SDK) +#include <WebKitAdditions/WebPageInitialization.h> +#endif + + m_page = std::make_unique<Page>(pageConfiguration); + updatePreferences(parameters.store); + + m_drawingArea = DrawingArea::create(*this, parameters); + m_drawingArea->setPaintingEnabled(false); + m_drawingArea->setShouldScaleViewToFitDocument(parameters.shouldScaleViewToFitDocument); + +#if ENABLE(ASYNC_SCROLLING) + m_useAsyncScrolling = parameters.store.getBoolValueForKey(WebPreferencesKey::threadedScrollingEnabledKey()); + if (!m_drawingArea->supportsAsyncScrolling()) + m_useAsyncScrolling = false; + m_page->settings().setScrollingCoordinatorEnabled(m_useAsyncScrolling); #endif - pageClients.plugInClient = new WebPlugInClient(this); - m_page = adoptPtr(new Page(pageClients)); + m_mainFrame = WebFrame::createWithCoreMainFrame(this, &m_page->mainFrame()); + m_drawingArea->updatePreferences(parameters.store); #if ENABLE(BATTERY_STATUS) WebCore::provideBatteryTo(m_page.get(), new WebBatteryClient(this)); @@ -326,9 +442,6 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters) WebCore::provideDeviceMotionTo(m_page.get(), new DeviceMotionClientQt); WebCore::provideDeviceOrientationTo(m_page.get(), new DeviceOrientationClientQt); #endif -#if ENABLE(NETWORK_INFO) - WebCore::provideNetworkInfoTo(m_page.get(), new WebNetworkInfoClient(this)); -#endif #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) WebCore::provideNotification(m_page.get(), new WebNotificationClient(this)); #endif @@ -338,26 +451,29 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters) #if ENABLE(PROXIMITY_EVENTS) WebCore::provideDeviceProximityTo(m_page.get(), new WebDeviceProximityClient(this)); #endif +#if ENABLE(MEDIA_STREAM) + WebCore::provideUserMediaTo(m_page.get(), new WebUserMediaClient(*this)); +#endif + +#if ENABLE(REMOTE_INSPECTOR) + m_page->setRemoteInspectionAllowed(parameters.allowsRemoteInspection); + m_page->setRemoteInspectionNameOverride(parameters.remoteInspectionNameOverride); +#endif m_page->setCanStartMedia(false); m_mayStartMediaWhenInWindow = parameters.mayStartMediaWhenInWindow; - m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData); m_page->setGroupName(m_pageGroup->identifier()); m_page->setDeviceScaleFactor(parameters.deviceScaleFactor); +#if PLATFORM(IOS) + m_page->setTextAutosizingWidth(parameters.textAutosizingWidth); +#endif - m_drawingArea = DrawingArea::create(this, parameters); - m_drawingArea->setPaintingEnabled(false); - - updatePreferences(parameters.store); platformInitialize(); - m_mainFrame = WebFrame::createMainFrame(this); - setUseFixedLayout(parameters.useFixedLayout); setDrawsBackground(parameters.drawsBackground); - setDrawsTransparentBackground(parameters.drawsTransparentBackground); setUnderlayColor(parameters.underlayColor); @@ -365,55 +481,113 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters) setPaginationBehavesLikeColumns(parameters.paginationBehavesLikeColumns); setPageLength(parameters.pageLength); setGapBetweenPages(parameters.gapBetweenPages); + setPaginationLineGridEnabled(parameters.paginationLineGridEnabled); + + // If the page is created off-screen, its visibilityState should be prerender. + m_page->setViewState(m_viewState); + if (!isVisible()) + m_page->setIsPrerender(); + updateUserActivity(); - setMemoryCacheMessagesEnabled(parameters.areMemoryCacheClientCallsEnabled); - - setActive(parameters.isActive); - setFocused(parameters.isFocused); - - // Page defaults to in-window, but setIsInWindow depends on it being a valid indicator of actually having been put into a window. - if (!parameters.isInWindow) - m_page->setIsInWindow(false); - else - WebProcess::shared().pageDidEnterWindow(m_pageID); - - setIsInWindow(parameters.isInWindow); + updateIsInWindow(true); setMinimumLayoutSize(parameters.minimumLayoutSize); + setAutoSizingShouldExpandToViewHeight(parameters.autoSizingShouldExpandToViewHeight); setScrollPinningBehavior(parameters.scrollPinningBehavior); + if (parameters.scrollbarOverlayStyle) + m_scrollbarOverlayStyle = static_cast<ScrollbarOverlayStyle>(parameters.scrollbarOverlayStyle.value()); + else + m_scrollbarOverlayStyle = WTF::Optional<ScrollbarOverlayStyle>(); + + setBackgroundExtendsBeyondPage(parameters.backgroundExtendsBeyondPage); + + setTopContentInset(parameters.topContentInset); m_userAgent = parameters.userAgent; WebBackForwardListProxy::setHighestItemIDFromUIProcess(parameters.highestUsedBackForwardItemID); - if (!parameters.sessionState.isEmpty()) - restoreSession(parameters.sessionState); + if (!parameters.itemStates.isEmpty()) + restoreSessionInternal(parameters.itemStates, WasRestoredByAPIRequest::No); + + if (parameters.sessionID.isValid()) + setSessionID(parameters.sessionID); m_drawingArea->setPaintingEnabled(true); setMediaVolume(parameters.mediaVolume); - // We use the DidFirstLayout milestone to determine when to unfreeze the layer tree. - m_page->addLayoutMilestones(DidFirstLayout); + setMuted(parameters.muted); + + // We use the DidFirstVisuallyNonEmptyLayout milestone to determine when to unfreeze the layer tree. + m_page->addLayoutMilestones(DidFirstLayout | DidFirstVisuallyNonEmptyLayout); - WebProcess::shared().addMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID, this); + auto& webProcess = WebProcess::singleton(); + webProcess.addMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID, *this); // FIXME: This should be done in the object constructors, and the objects themselves should be message receivers. - WebProcess::shared().addMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_pageID, this); -#if USE(COORDINATED_GRAPHICS) - WebProcess::shared().addMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID, this); -#endif -#if ENABLE(INSPECTOR) - WebProcess::shared().addMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID, this); +#if USE(COORDINATED_GRAPHICS_MULTIPROCESS) + webProcess.addMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID, *this); #endif + webProcess.addMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID, *this); + webProcess.addMessageReceiver(Messages::WebInspectorUI::messageReceiverName(), m_pageID, *this); #if ENABLE(FULLSCREEN_API) - WebProcess::shared().addMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID, this); + webProcess.addMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID, *this); #endif #ifndef NDEBUG webPageCounter.increment(); #endif + +#if ENABLE(ASYNC_SCROLLING) + if (m_useAsyncScrolling) + webProcess.eventDispatcher().addScrollingTreeForPage(this); +#endif + + for (auto& mimeType : parameters.mimeTypesWithCustomContentProviders) + m_mimeTypesWithCustomContentProviders.add(mimeType); + + +#if ENABLE(ENCRYPTED_MEDIA_V2) + if (WebMediaKeyStorageManager* manager = webProcess.supplement<WebMediaKeyStorageManager>()) + m_page->settings().setMediaKeysStorageDirectory(manager->mediaKeyStorageDirectory()); +#endif + m_page->settings().setAppleMailPaginationQuirkEnabled(parameters.appleMailPaginationQuirkEnabled); + + if (parameters.viewScaleFactor != 1) + scaleView(parameters.viewScaleFactor); + +#if PLATFORM(IOS) + m_page->settings().setContentDispositionAttachmentSandboxEnabled(true); +#endif +} + +void WebPage::reinitializeWebPage(const WebPageCreationParameters& parameters) +{ + if (m_viewState != parameters.viewState) + setViewState(parameters.viewState, false, Vector<uint64_t>()); + if (m_layerHostingMode != parameters.layerHostingMode) + setLayerHostingMode(static_cast<unsigned>(parameters.layerHostingMode)); +} + +void WebPage::setPageActivityState(PageActivityState::Flags activityState) +{ + PageActivityState::Flags changed = m_activityState ^ activityState; + m_activityState = activityState; + + if (changed) + updateUserActivity(); +} + +void WebPage::updateUserActivity() +{ + // Start the activity to prevent AppNap if the page activity is in progress, + // the page is visible and non-idle, or process suppression is disabled. + if (m_activityState || !(m_viewState & ViewState::IsVisuallyIdle) || !m_processSuppressionEnabled) + m_userActivity.start(); + else + m_userActivity.stop(); } WebPage::~WebPage() @@ -423,28 +597,36 @@ WebPage::~WebPage() ASSERT(!m_page); + auto& webProcess = WebProcess::singleton(); +#if ENABLE(ASYNC_SCROLLING) + if (m_useAsyncScrolling) + webProcess.eventDispatcher().removeScrollingTreeForPage(this); +#endif + + platformDetach(); + m_sandboxExtensionTracker.invalidate(); - for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) - (*it)->webPageDestroyed(); + for (auto* pluginView : m_pluginViews) + pluginView->webPageDestroyed(); +#if !PLATFORM(IOS) if (m_headerBanner) m_headerBanner->detachFromPage(); if (m_footerBanner) m_footerBanner->detachFromPage(); +#endif // !PLATFORM(IOS) - WebProcess::shared().removeMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID); + webProcess.removeMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID); // FIXME: This should be done in the object destructors, and the objects themselves should be message receivers. - WebProcess::shared().removeMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_pageID); -#if USE(COORDINATED_GRAPHICS) - WebProcess::shared().removeMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID); -#endif -#if ENABLE(INSPECTOR) - WebProcess::shared().removeMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID); +#if USE(COORDINATED_GRAPHICS_MULTIPROCESS) + webProcess.removeMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID); #endif + webProcess.removeMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID); + webProcess.removeMessageReceiver(Messages::WebInspectorUI::messageReceiverName(), m_pageID); #if ENABLE(FULLSCREEN_API) - WebProcess::shared().removeMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID); + webProcess.removeMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID); #endif #ifndef NDEBUG @@ -456,9 +638,9 @@ void WebPage::dummy(bool&) { } -CoreIPC::Connection* WebPage::messageSenderConnection() +IPC::Connection* WebPage::messageSenderConnection() { - return WebProcess::shared().parentProcessConnection(); + return WebProcess::singleton().parentProcessConnection(); } uint64_t WebPage::messageSenderDestinationID() @@ -467,66 +649,79 @@ uint64_t WebPage::messageSenderDestinationID() } #if ENABLE(CONTEXT_MENUS) -void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client) +void WebPage::setInjectedBundleContextMenuClient(std::unique_ptr<API::InjectedBundle::PageContextMenuClient> contextMenuClient) { - m_contextMenuClient.initialize(client); + if (!contextMenuClient) { + m_contextMenuClient = std::make_unique<API::InjectedBundle::PageContextMenuClient>(); + return; + } + + m_contextMenuClient = WTFMove(contextMenuClient); } #endif -void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client) +void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClientBase* client) { m_editorClient.initialize(client); } -void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client) +void WebPage::setInjectedBundleFormClient(std::unique_ptr<API::InjectedBundle::FormClient> formClient) { - m_formClient.initialize(client); + if (!formClient) { + m_formClient = std::make_unique<API::InjectedBundle::FormClient>(); + return; + } + + m_formClient = WTFMove(formClient); } -void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client) +void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClientBase* client) { + m_loaderClient.initialize(client); + // It would be nice to get rid of this code and transition all clients to using didLayout instead of // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required // for backwards compatibility. LayoutMilestones milestones = 0; if (client) { - if (client->didFirstLayoutForFrame) + if (m_loaderClient.client().didFirstLayoutForFrame) milestones |= WebCore::DidFirstLayout; - if (client->didFirstVisuallyNonEmptyLayoutForFrame) + if (m_loaderClient.client().didFirstVisuallyNonEmptyLayoutForFrame) milestones |= WebCore::DidFirstVisuallyNonEmptyLayout; - if (client->didNewFirstVisuallyNonEmptyLayout) - milestones |= WebCore::DidHitRelevantRepaintedObjectsAreaThreshold; } if (milestones) listenForLayoutMilestones(milestones); - - m_loaderClient.initialize(client); } -void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClient* client) +void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClientBase* client) { m_policyClient.initialize(client); } -void WebPage::initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClient* client) +void WebPage::initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClientBase* client) { m_resourceLoadClient.initialize(client); } -void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client) +void WebPage::setInjectedBundleUIClient(std::unique_ptr<API::InjectedBundle::PageUIClient> uiClient) { - m_uiClient.initialize(client); + if (!uiClient) { + m_uiClient = std::make_unique<API::InjectedBundle::PageUIClient>(); + return; + } + + m_uiClient = WTFMove(uiClient); } #if ENABLE(FULLSCREEN_API) -void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient* client) +void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClientBase* client) { m_fullScreenClient.initialize(client); } #endif -void WebPage::initializeInjectedBundleDiagnosticLoggingClient(WKBundlePageDiagnosticLoggingClient* client) +void WebPage::initializeInjectedBundleDiagnosticLoggingClient(WKBundlePageDiagnosticLoggingClientBase* client) { m_logDiagnosticMessageClient.initialize(client); } @@ -534,63 +729,77 @@ void WebPage::initializeInjectedBundleDiagnosticLoggingClient(WKBundlePageDiagno #if ENABLE(NETSCAPE_PLUGIN_API) PassRefPtr<Plugin> WebPage::createPlugin(WebFrame* frame, HTMLPlugInElement* pluginElement, const Plugin::Parameters& parameters, String& newMIMEType) { - String frameURLString = frame->coreFrame()->loader()->documentLoader()->responseURL().string(); - String pageURLString = m_page->mainFrame()->loader()->documentLoader()->responseURL().string(); + String frameURLString = frame->coreFrame()->loader().documentLoader()->responseURL().string(); + String pageURLString = m_page->mainFrame().loader().documentLoader()->responseURL().string(); + +#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) + HTMLPlugInImageElement& pluginImageElement = downcast<HTMLPlugInImageElement>(*pluginElement); + unsigned pluginArea = 0; + PluginProcessType processType = pluginElement->displayState() == HTMLPlugInElement::WaitingForSnapshot && !(plugInIsPrimarySize(pluginImageElement, pluginArea) && !plugInIntersectsSearchRect(pluginImageElement)) ? PluginProcessTypeSnapshot : PluginProcessTypeNormal; +#else PluginProcessType processType = pluginElement->displayState() == HTMLPlugInElement::WaitingForSnapshot ? PluginProcessTypeSnapshot : PluginProcessTypeNormal; +#endif - bool allowOnlyApplicationPlugins = !frame->coreFrame()->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin); + bool allowOnlyApplicationPlugins = !frame->coreFrame()->loader().subframeLoader().allowPlugins(); uint64_t pluginProcessToken; uint32_t pluginLoadPolicy; String unavailabilityDescription; - 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))) { - return 0; - } - - switch (static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy)) { - case PluginModuleLoadNormally: - case PluginModuleLoadUnsandboxed: - break; + 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))) + return nullptr; - case PluginModuleBlocked: - bool replacementObscured = false; - if (pluginElement->renderer()->isEmbeddedObject()) { - RenderEmbeddedObject* renderObject = toRenderEmbeddedObject(pluginElement->renderer()); - renderObject->setPluginUnavailabilityReasonWithDescription(RenderEmbeddedObject::InsecurePluginVersion, unavailabilityDescription); - replacementObscured = renderObject->isReplacementObscured(); - renderObject->setUnavailablePluginIndicatorIsHidden(replacementObscured); - } - - send(Messages::WebPageProxy::DidBlockInsecurePluginVersion(parameters.mimeType, parameters.url.string(), frameURLString, pageURLString, replacementObscured)); - return 0; - } + PluginModuleLoadPolicy loadPolicy = static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy); + bool isBlockedPlugin = (loadPolicy == PluginModuleBlockedForSecurity) || (loadPolicy == PluginModuleBlockedForCompatibility); - if (!pluginProcessToken) { -#if PLATFORM(MAC) - String path = parameters.url.path(); - if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(parameters.mimeType) || (parameters.mimeType.isEmpty() && (path.endsWith(".pdf", false) || path.endsWith(".ps", false)))) { + if (isBlockedPlugin || !pluginProcessToken) { #if ENABLE(PDFKIT_PLUGIN) - if (shouldUsePDFPlugin()) - return PDFPlugin::create(frame); -#endif - return SimplePDFPlugin::create(frame); + String path = parameters.url.path(); + if (shouldUsePDFPlugin() && (MIMETypeRegistry::isPDFOrPostScriptMIMEType(parameters.mimeType) || (parameters.mimeType.isEmpty() && (path.endsWith(".pdf", false) || path.endsWith(".ps", false))))) { + RefPtr<PDFPlugin> pdfPlugin = PDFPlugin::create(frame); + return pdfPlugin.release(); } #else UNUSED_PARAM(frame); #endif - return 0; } + if (isBlockedPlugin) { + bool replacementObscured = false; + if (is<RenderEmbeddedObject>(*pluginElement->renderer())) { + auto& renderObject = downcast<RenderEmbeddedObject>(*pluginElement->renderer()); + renderObject.setPluginUnavailabilityReasonWithDescription(RenderEmbeddedObject::InsecurePluginVersion, unavailabilityDescription); + replacementObscured = renderObject.isReplacementObscured(); + renderObject.setUnavailablePluginIndicatorIsHidden(replacementObscured); + } + + send(Messages::WebPageProxy::DidBlockInsecurePluginVersion(parameters.mimeType, parameters.url.string(), frameURLString, pageURLString, replacementObscured)); + return nullptr; + } + + if (!pluginProcessToken) + return nullptr; + bool isRestartedProcess = (pluginElement->displayState() == HTMLPlugInElement::Restarting || pluginElement->displayState() == HTMLPlugInElement::RestartingWithPendingMouseClick); return PluginProxy::create(pluginProcessToken, isRestartedProcess); } #endif // ENABLE(NETSCAPE_PLUGIN_API) -EditorState WebPage::editorState() const +#if ENABLE(WEBGL) && !PLATFORM(COCOA) +WebCore::WebGLLoadPolicy WebPage::webGLPolicyForURL(WebFrame*, const String& /* url */) { - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - ASSERT(frame); + return WebGLAllowCreation; +} + +WebCore::WebGLLoadPolicy WebPage::resolveWebGLPolicyForURL(WebFrame*, const String& /* url */) +{ + return WebGLAllowCreation; +} +#endif + +EditorState WebPage::editorState(IncludePostLayoutDataHint shouldIncludePostLayoutData) const +{ + Frame& frame = m_page->focusController().focusedOrMainFrame(); EditorState result; @@ -603,20 +812,24 @@ EditorState WebPage::editorState() const } } - result.selectionIsNone = frame->selection()->isNone(); - result.selectionIsRange = frame->selection()->isRange(); - result.isContentEditable = frame->selection()->isContentEditable(); - result.isContentRichlyEditable = frame->selection()->isContentRichlyEditable(); - result.isInPasswordField = frame->selection()->isInPasswordField(); - result.hasComposition = frame->editor().hasComposition(); - result.shouldIgnoreCompositionSelectionChange = frame->editor().ignoreCompositionSelectionChange(); + const VisibleSelection& selection = frame.selection().selection(); + + result.selectionIsNone = selection.isNone(); + result.selectionIsRange = selection.isRange(); + result.isContentEditable = selection.isContentEditable(); + result.isContentRichlyEditable = selection.isContentRichlyEditable(); + result.isInPasswordField = selection.isInPasswordField(); + result.hasComposition = frame.editor().hasComposition(); + result.shouldIgnoreCompositionSelectionChange = frame.editor().ignoreCompositionSelectionChange(); + + platformEditorState(frame, result, shouldIncludePostLayoutData); #if PLATFORM(QT) size_t location = 0; size_t length = 0; - Element* selectionRoot = frame->selection()->rootEditableElementRespectingShadowTree(); - Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); + Element* selectionRoot = frame.selection().rootEditableElementRespectingShadowTree(); + Element* scope = selectionRoot ? selectionRoot : frame.document()->documentElement(); if (!scope) return result; @@ -645,38 +858,26 @@ EditorState WebPage::editorState() const } if (selectionRoot) - result.editorRect = frame->view()->contentsToWindow(selectionRoot->pixelSnappedBoundingBox()); + result.editorRect = frame.view()->contentsToWindow(selectionRoot->pixelSnappedBoundingBox()); RefPtr<Range> range; - if (result.hasComposition && (range = frame->editor().compositionRange())) { - frame->editor().getCompositionSelection(result.anchorPosition, result.cursorPosition); + if (result.hasComposition && (range = frame.editor().compositionRange())) { + frame.editor().getCompositionSelection(result.anchorPosition, result.cursorPosition); - result.compositionRect = frame->view()->contentsToWindow(range->boundingBox()); + result.compositionRect = frame.view()->contentsToWindow(range->boundingBox()); } - if (!result.hasComposition && !result.selectionIsNone && (range = frame->selection()->selection().firstRange())) { + if (!result.hasComposition && !result.selectionIsNone && (range = frame.selection().selection().firstRange())) { TextIterator::getLocationAndLengthFromRange(scope, range.get(), location, length); - bool baseIsFirst = frame->selection()->selection().isBaseFirst(); + bool baseIsFirst = frame.selection().selection().isBaseFirst(); result.cursorPosition = (baseIsFirst) ? location + length : location; result.anchorPosition = (baseIsFirst) ? location : location + length; result.selectedText = range->text(); } - if (range) { - result.cursorRect = frame->view()->contentsToWindow(frame->editor().firstRectForRange(range.get())); - // Check that at least one dimension is valid - if (result.cursorRect.width() != 0 || result.cursorRect.height() != 0) - { - if (result.cursorRect.width() == 0) - result.cursorRect.setWidth(1); - if (result.cursorRect.height() == 0) - result.cursorRect.setHeight(1); - } - // now adjust the cursor coordinates to take scrolling into account - result.cursorRect.moveBy(-frame->view()->visibleContentRect().location()); - } - + if (range) + result.cursorRect = frame.view()->contentsToWindow(frame.editor().firstRectForRange(range.get())); // FIXME: We should only transfer innerText when it changes and do this on the UI side. if (result.isContentEditable) { @@ -692,10 +893,6 @@ EditorState WebPage::editorState() const } #endif -#if PLATFORM(GTK) - result.cursorRect = frame->selection()->absoluteCaretBounds(); -#endif - return result; } @@ -713,7 +910,7 @@ uint64_t WebPage::renderTreeSize() const { if (!m_page) return 0; - return m_page->renderTreeSize().treeSize; + return m_page->renderTreeSize(); } void WebPage::setTracksRepaints(bool trackRepaints) @@ -736,32 +933,27 @@ void WebPage::resetTrackedRepaints() view->resetTrackedRepaints(); } -PassRefPtr<ImmutableArray> WebPage::trackedRepaintRects() +Ref<API::Array> WebPage::trackedRepaintRects() { FrameView* view = mainFrameView(); if (!view) - return ImmutableArray::create(); + return API::Array::create(); - const Vector<IntRect>& rects = view->trackedRepaintRects(); - size_t size = rects.size(); - if (!size) - return ImmutableArray::create(); + Vector<RefPtr<API::Object>> repaintRects; + repaintRects.reserveInitialCapacity(view->trackedRepaintRects().size()); - Vector<RefPtr<APIObject> > vector; - vector.reserveInitialCapacity(size); + for (const auto& repaintRect : view->trackedRepaintRects()) + repaintRects.uncheckedAppend(API::Rect::create(toAPI(repaintRect))); - for (size_t i = 0; i < size; ++i) - vector.uncheckedAppend(WebRect::create(toAPI(rects[i]))); - - return ImmutableArray::adopt(vector); + return API::Array::create(WTFMove(repaintRects)); } -PluginView* WebPage::focusedPluginViewForFrame(Frame* frame) +PluginView* WebPage::focusedPluginViewForFrame(Frame& frame) { - if (!frame->document()->isPluginDocument()) + if (!frame.document()->isPluginDocument()) return 0; - PluginDocument* pluginDocument = static_cast<PluginDocument*>(frame->document()); + PluginDocument* pluginDocument = static_cast<PluginDocument*>(frame.document()); if (pluginDocument->focusedElement() != pluginDocument->pluginElement()) return 0; @@ -782,38 +974,46 @@ PluginView* WebPage::pluginViewForFrame(Frame* frame) void WebPage::executeEditingCommand(const String& commandName, const String& argument) { - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (!frame) - return; + Frame& frame = m_page->focusController().focusedOrMainFrame(); if (PluginView* pluginView = focusedPluginViewForFrame(frame)) { pluginView->handleEditingCommand(commandName, argument); return; } - frame->editor().command(commandName).execute(argument); + frame.editor().command(commandName).execute(argument); +} + +void WebPage::setEditable(bool editable) +{ + m_page->setEditable(editable); + m_page->setTabKeyCyclesThroughElements(!editable); + Frame& frame = m_page->focusController().focusedOrMainFrame(); + if (editable) { + frame.editor().applyEditingStyleToBodyElement(); + // If the page is made editable and the selection is empty, set it to something. + if (frame.selection().isNone()) + frame.selection().setSelectionFromNone(); + } } bool WebPage::isEditingCommandEnabled(const String& commandName) { - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (!frame) - return false; + Frame& frame = m_page->focusController().focusedOrMainFrame(); if (PluginView* pluginView = focusedPluginViewForFrame(frame)) return pluginView->isEditingCommandEnabled(commandName); - Editor::Command command = frame->editor().command(commandName); + Editor::Command command = frame.editor().command(commandName); return command.isSupported() && command.isEnabled(); } void WebPage::clearMainFrameName() { if (Frame* frame = mainFrame()) - frame->tree()->clearName(); + frame->tree().clearName(); } -#if USE(ACCELERATED_COMPOSITING) void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer) { m_drawingArea->setRootCompositingLayer(layer); @@ -823,7 +1023,6 @@ void WebPage::exitAcceleratedCompositingMode() { m_drawingArea->setRootCompositingLayer(0); } -#endif void WebPage::close() { @@ -836,30 +1035,46 @@ void WebPage::close() if (!mainWebFrame()->url().isEmpty()) reportUsedFeatures(); - if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle()) - WebProcess::shared().injectedBundle()->willDestroyPage(this); + if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::singleton().injectedBundle()) + WebProcess::singleton().injectedBundle()->willDestroyPage(this); + + if (m_inspector) { + m_inspector->disconnectFromPage(); + m_inspector = nullptr; + } -#if ENABLE(INSPECTOR) - m_inspector = 0; -#endif #if ENABLE(FULLSCREEN_API) - m_fullScreenManager = 0; + m_fullScreenManager = nullptr; #endif if (m_activePopupMenu) { m_activePopupMenu->disconnectFromPage(); - m_activePopupMenu = 0; + m_activePopupMenu = nullptr; } if (m_activeOpenPanelResultListener) { m_activeOpenPanelResultListener->disconnectFromPage(); - m_activeOpenPanelResultListener = 0; + m_activeOpenPanelResultListener = nullptr; } #if ENABLE(INPUT_TYPE_COLOR) if (m_activeColorChooser) { m_activeColorChooser->disconnectFromPage(); - m_activeColorChooser = 0; + m_activeColorChooser = nullptr; + } +#endif + +#if PLATFORM(GTK) + if (m_printOperation) { + m_printOperation->disconnectFromPage(); + m_printOperation = nullptr; + } +#endif + +#if ENABLE(VIDEO) && USE(GSTREAMER) + if (m_installMediaPluginsCallback) { + m_installMediaPluginsCallback->invalidate(); + m_installMediaPluginsCallback = nullptr; } #endif @@ -870,22 +1085,21 @@ void WebPage::close() #endif #if ENABLE(CONTEXT_MENUS) - m_contextMenuClient.initialize(0); + m_contextMenuClient = std::make_unique<API::InjectedBundle::PageContextMenuClient>(); #endif m_editorClient.initialize(0); - m_formClient.initialize(0); + m_formClient = std::make_unique<API::InjectedBundle::FormClient>(); m_loaderClient.initialize(0); m_policyClient.initialize(0); m_resourceLoadClient.initialize(0); - m_uiClient.initialize(0); + m_uiClient = std::make_unique<API::InjectedBundle::PageUIClient>(); #if ENABLE(FULLSCREEN_API) m_fullScreenClient.initialize(0); #endif m_logDiagnosticMessageClient.initialize(0); - m_underlayPage = nullptr; m_printContext = nullptr; - m_mainFrame->coreFrame()->loader()->detachFromParent(); + m_mainFrame->coreFrame()->loader().detachFromParent(); m_page = nullptr; m_drawingArea = nullptr; @@ -893,17 +1107,19 @@ void WebPage::close() m_isRunningModal = false; // The WebPage can be destroyed by this call. - WebProcess::shared().removeWebPage(m_pageID); + WebProcess::singleton().removeWebPage(m_pageID); + + WebProcess::singleton().updateActivePages(); if (isRunningModal) - RunLoop::main()->stop(); + RunLoop::main().stop(); } void WebPage::tryClose() { SendStopResponsivenessTimer stopper(this); - if (!m_mainFrame->coreFrame()->loader()->shouldClose()) { + if (!corePage()->userInputBridge().tryClosePage()) { send(Messages::WebPageProxy::StopResponsivenessTimer()); return; } @@ -916,111 +1132,136 @@ void WebPage::sendClose() send(Messages::WebPageProxy::ClosePage(false)); } -void WebPage::loadURL(const String& url, const SandboxExtension::Handle& sandboxExtensionHandle, CoreIPC::MessageDecoder& decoder) +void WebPage::loadURLInFrame(const String& url, uint64_t frameID) { - loadURLRequest(ResourceRequest(KURL(KURL(), url)), sandboxExtensionHandle, decoder); + WebFrame* frame = WebProcess::singleton().webFrame(frameID); + if (!frame) + return; + + frame->coreFrame()->loader().load(FrameLoadRequest(frame->coreFrame(), ResourceRequest(URL(URL(), url)), ShouldOpenExternalURLsPolicy::ShouldNotAllow)); } -void WebPage::loadURLRequest(const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle, CoreIPC::MessageDecoder& decoder) +void WebPage::loadRequest(uint64_t navigationID, const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle, uint64_t shouldOpenExternalURLsPolicy, const UserData& userData) { SendStopResponsivenessTimer stopper(this); - RefPtr<APIObject> userData; - InjectedBundleUserMessageDecoder userMessageDecoder(userData); - if (!decoder.decode(userMessageDecoder)) - return; + m_pendingNavigationID = navigationID; m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle); // Let the InjectedBundle know we are about to start the load, passing the user data from the UIProcess // to all the client to set up any needed state. - m_loaderClient.willLoadURLRequest(this, request, userData.get()); + m_loaderClient.willLoadURLRequest(this, request, WebProcess::singleton().transformHandlesToObjects(userData.object()).get()); // Initate the load in WebCore. - m_mainFrame->coreFrame()->loader()->load(FrameLoadRequest(m_mainFrame->coreFrame(), request)); + FrameLoadRequest frameLoadRequest(m_mainFrame->coreFrame(), request, ShouldOpenExternalURLsPolicy::ShouldNotAllow); + ShouldOpenExternalURLsPolicy externalURLsPolicy = static_cast<ShouldOpenExternalURLsPolicy>(shouldOpenExternalURLsPolicy); + frameLoadRequest.setShouldOpenExternalURLsPolicy(externalURLsPolicy); + + corePage()->userInputBridge().loadRequest(frameLoadRequest); + + ASSERT(!m_pendingNavigationID); } -void WebPage::loadDataImpl(PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const KURL& baseURL, const KURL& unreachableURL, CoreIPC::MessageDecoder& decoder) +void WebPage::loadDataImpl(uint64_t navigationID, PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const URL& baseURL, const URL& unreachableURL, const UserData& userData) { SendStopResponsivenessTimer stopper(this); - RefPtr<APIObject> userData; - InjectedBundleUserMessageDecoder userMessageDecoder(userData); - if (!decoder.decode(userMessageDecoder)) - return; + m_pendingNavigationID = navigationID; ResourceRequest request(baseURL); - SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL); + ResourceResponse response(URL(), MIMEType, sharedBuffer->size(), encodingName); + SubstituteData substituteData(sharedBuffer, unreachableURL, response, SubstituteData::SessionHistoryVisibility::Hidden); // Let the InjectedBundle know we are about to start the load, passing the user data from the UIProcess // to all the client to set up any needed state. - m_loaderClient.willLoadDataRequest(this, request, substituteData.content(), substituteData.mimeType(), substituteData.textEncoding(), substituteData.failingURL(), userData.get()); + m_loaderClient.willLoadDataRequest(this, request, const_cast<SharedBuffer*>(substituteData.content()), substituteData.mimeType(), substituteData.textEncoding(), substituteData.failingURL(), WebProcess::singleton().transformHandlesToObjects(userData.object()).get()); // Initate the load in WebCore. - m_mainFrame->coreFrame()->loader()->load(FrameLoadRequest(m_mainFrame->coreFrame(), request, substituteData)); + m_mainFrame->coreFrame()->loader().load(FrameLoadRequest(m_mainFrame->coreFrame(), request, ShouldOpenExternalURLsPolicy::ShouldNotAllow, substituteData)); +} + +void WebPage::loadString(uint64_t navigationID, const String& htmlString, const String& MIMEType, const URL& baseURL, const URL& unreachableURL, const UserData& userData) +{ + if (!htmlString.isNull() && htmlString.is8Bit()) { + RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters8()), htmlString.length() * sizeof(LChar)); + loadDataImpl(navigationID, sharedBuffer, MIMEType, ASCIILiteral("latin1"), baseURL, unreachableURL, userData); + } else { + RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters16()), htmlString.length() * sizeof(UChar)); + loadDataImpl(navigationID, sharedBuffer, MIMEType, ASCIILiteral("utf-16"), baseURL, unreachableURL, userData); + } } -void WebPage::loadData(const CoreIPC::DataReference& data, const String& MIMEType, const String& encodingName, const String& baseURLString, CoreIPC::MessageDecoder& decoder) +void WebPage::loadData(uint64_t navigationID, const IPC::DataReference& data, const String& MIMEType, const String& encodingName, const String& baseURLString, const UserData& userData) { RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(data.data()), data.size()); - KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString); - loadDataImpl(sharedBuffer, MIMEType, encodingName, baseURL, KURL(), decoder); + URL baseURL = baseURLString.isEmpty() ? blankURL() : URL(URL(), baseURLString); + loadDataImpl(navigationID, sharedBuffer, MIMEType, encodingName, baseURL, URL(), userData); } -void WebPage::loadHTMLString(const String& htmlString, const String& baseURLString, CoreIPC::MessageDecoder& decoder) +void WebPage::loadHTMLString(uint64_t navigationID, const String& htmlString, const String& baseURLString, const UserData& userData) { - RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar)); - KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString); - loadDataImpl(sharedBuffer, "text/html", "utf-16", baseURL, KURL(), decoder); + URL baseURL = baseURLString.isEmpty() ? blankURL() : URL(URL(), baseURLString); + loadString(navigationID, htmlString, ASCIILiteral("text/html"), baseURL, URL(), userData); } -void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString, CoreIPC::MessageDecoder& decoder) +void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString, const String& provisionalLoadErrorURLString, const UserData& userData) { - RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar)); - KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString); - KURL unreachableURL = unreachableURLString.isEmpty() ? KURL() : KURL(KURL(), unreachableURLString); - loadDataImpl(sharedBuffer, "text/html", "utf-16", baseURL, unreachableURL, decoder); + URL baseURL = baseURLString.isEmpty() ? blankURL() : URL(URL(), baseURLString); + URL unreachableURL = unreachableURLString.isEmpty() ? URL() : URL(URL(), unreachableURLString); + URL provisionalLoadErrorURL = provisionalLoadErrorURLString.isEmpty() ? URL() : URL(URL(), provisionalLoadErrorURLString); + m_mainFrame->coreFrame()->loader().setProvisionalLoadErrorBeingHandledURL(provisionalLoadErrorURL); + loadString(0, htmlString, ASCIILiteral("text/html"), baseURL, unreachableURL, userData); + m_mainFrame->coreFrame()->loader().setProvisionalLoadErrorBeingHandledURL({ }); } -void WebPage::loadPlainTextString(const String& string, CoreIPC::MessageDecoder& decoder) +void WebPage::loadPlainTextString(const String& string, const UserData& userData) { - RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar)); - loadDataImpl(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL(), decoder); + loadString(0, string, ASCIILiteral("text/plain"), blankURL(), URL(), userData); } -void WebPage::loadWebArchiveData(const CoreIPC::DataReference& webArchiveData, CoreIPC::MessageDecoder& decoder) +void WebPage::loadWebArchiveData(const IPC::DataReference& webArchiveData, const UserData& userData) { RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(webArchiveData.data()), webArchiveData.size() * sizeof(uint8_t)); - loadDataImpl(sharedBuffer, "application/x-webarchive", "utf-16", blankURL(), KURL(), decoder); + loadDataImpl(0, sharedBuffer, ASCIILiteral("application/x-webarchive"), ASCIILiteral("utf-16"), blankURL(), URL(), userData); } -void WebPage::linkClicked(const String& url, const WebMouseEvent& event) +void WebPage::navigateToPDFLinkWithSimulatedClick(const String& url, IntPoint documentPoint, IntPoint screenPoint) { - Frame* frame = m_page->mainFrame(); - if (!frame) + Frame* mainFrame = m_mainFrame->coreFrame(); + Document* mainFrameDocument = mainFrame->document(); + if (!mainFrameDocument) return; - RefPtr<Event> coreEvent; - if (event.type() != WebEvent::NoType) - coreEvent = MouseEvent::create(eventNames().clickEvent, frame->document()->defaultView(), platform(event), 0, 0); + const int singleClick = 1; + RefPtr<MouseEvent> mouseEvent = MouseEvent::create(eventNames().clickEvent, true, true, currentTime(), nullptr, singleClick, screenPoint.x(), screenPoint.y(), documentPoint.x(), documentPoint.y(), +#if ENABLE(POINTER_LOCK) + 0, 0, +#endif + false, false, false, false, 0, nullptr, 0, nullptr); - frame->loader()->loadFrameRequest(FrameLoadRequest(frame, ResourceRequest(url)), false, false, coreEvent.get(), 0, MaybeSendReferrer); + mainFrame->loader().urlSelected(mainFrameDocument->completeURL(url), emptyString(), mouseEvent.get(), LockHistory::No, LockBackForwardList::No, ShouldSendReferrer::MaybeSendReferrer, ShouldOpenExternalURLsPolicy::ShouldNotAllow); } void WebPage::stopLoadingFrame(uint64_t frameID) { - WebFrame* frame = WebProcess::shared().webFrame(frameID); + WebFrame* frame = WebProcess::singleton().webFrame(frameID); if (!frame) return; - frame->coreFrame()->loader()->stopForUserCancel(); + corePage()->userInputBridge().stopLoadingFrame(frame->coreFrame()); } void WebPage::stopLoading() { SendStopResponsivenessTimer stopper(this); - m_mainFrame->coreFrame()->loader()->stopForUserCancel(); + corePage()->userInputBridge().stopLoadingFrame(m_mainFrame->coreFrame()); +} + +bool WebPage::defersLoading() const +{ + return m_page->defersLoading(); } void WebPage::setDefersLoading(bool defersLoading) @@ -1028,15 +1269,18 @@ void WebPage::setDefersLoading(bool defersLoading) m_page->setDefersLoading(defersLoading); } -void WebPage::reload(bool reloadFromOrigin, const SandboxExtension::Handle& sandboxExtensionHandle) +void WebPage::reload(uint64_t navigationID, bool reloadFromOrigin, bool contentBlockersEnabled, const SandboxExtension::Handle& sandboxExtensionHandle) { SendStopResponsivenessTimer stopper(this); + ASSERT(!m_mainFrame->coreFrame()->loader().frameHasLoaded() || !m_pendingNavigationID); + m_pendingNavigationID = navigationID; + m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle); - m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin); + corePage()->userInputBridge().reloadFrame(m_mainFrame->coreFrame(), reloadFromOrigin, contentBlockersEnabled); } -void WebPage::goForward(uint64_t backForwardItemID) +void WebPage::goForward(uint64_t navigationID, uint64_t backForwardItemID) { SendStopResponsivenessTimer stopper(this); @@ -1045,10 +1289,13 @@ void WebPage::goForward(uint64_t backForwardItemID) if (!item) return; - m_page->goToItem(item, FrameLoadTypeForward); + ASSERT(!m_pendingNavigationID); + m_pendingNavigationID = navigationID; + + m_page->goToItem(*item, FrameLoadType::Forward); } -void WebPage::goBack(uint64_t backForwardItemID) +void WebPage::goBack(uint64_t navigationID, uint64_t backForwardItemID) { SendStopResponsivenessTimer stopper(this); @@ -1057,10 +1304,13 @@ void WebPage::goBack(uint64_t backForwardItemID) if (!item) return; - m_page->goToItem(item, FrameLoadTypeBack); + ASSERT(!m_pendingNavigationID); + m_pendingNavigationID = navigationID; + + m_page->goToItem(*item, FrameLoadType::Back); } -void WebPage::goToBackForwardItem(uint64_t backForwardItemID) +void WebPage::goToBackForwardItem(uint64_t navigationID, uint64_t backForwardItemID) { SendStopResponsivenessTimer stopper(this); @@ -1069,55 +1319,51 @@ void WebPage::goToBackForwardItem(uint64_t backForwardItemID) if (!item) return; - m_page->goToItem(item, FrameLoadTypeIndexedBackForward); + ASSERT(!m_pendingNavigationID); + m_pendingNavigationID = navigationID; + + m_page->goToItem(*item, FrameLoadType::IndexedBackForward); } void WebPage::tryRestoreScrollPosition() { - m_page->mainFrame()->loader()->history()->restoreScrollPositionAndViewState(); + m_page->mainFrame().loader().history().restoreScrollPositionAndViewState(); } void WebPage::layoutIfNeeded() { if (m_mainFrame->coreFrame()->view()) m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive(); - - if (m_underlayPage) { - if (FrameView *frameView = m_underlayPage->mainFrameView()) - frameView->updateLayoutAndStyleIfNeededRecursive(); - } } WebPage* WebPage::fromCorePage(Page* page) { - return static_cast<WebChromeClient*>(page->chrome().client())->page(); + return static_cast<WebChromeClient&>(page->chrome().client()).page(); } void WebPage::setSize(const WebCore::IntSize& viewSize) { - FrameView* view = m_page->mainFrame()->view(); - if (m_viewSize == viewSize) return; + FrameView* view = m_page->mainFrame().view(); view->resize(viewSize); - view->setNeedsLayout(); m_drawingArea->setNeedsDisplay(); m_viewSize = viewSize; -#if USE(TILED_BACKING_STORE) +#if USE(COORDINATED_GRAPHICS) if (view->useFixedLayout()) sendViewportAttributesChanged(); #endif } -#if USE(TILED_BACKING_STORE) +#if USE(COORDINATED_GRAPHICS) void WebPage::setFixedVisibleContentRect(const IntRect& rect) { ASSERT(m_useFixedLayout); - m_page->mainFrame()->view()->setFixedVisibleContentRect(rect); + m_page->mainFrame().view()->setFixedVisibleContentRect(rect); } void WebPage::sendViewportAttributesChanged() @@ -1129,17 +1375,17 @@ void WebPage::sendViewportAttributesChanged() return; // Recalculate the recommended layout size, when the available size (device pixel) changes. - Settings* settings = m_page->settings(); + Settings& settings = m_page->settings(); - int minimumLayoutFallbackWidth = std::max(settings->layoutFallbackWidth(), m_viewSize.width()); + int minimumLayoutFallbackWidth = std::max(settings.layoutFallbackWidth(), m_viewSize.width()); // If unset we use the viewport dimensions. This fits with the behavior of desktop browsers. - int deviceWidth = (settings->deviceWidth() > 0) ? settings->deviceWidth() : m_viewSize.width(); - int deviceHeight = (settings->deviceHeight() > 0) ? settings->deviceHeight() : m_viewSize.height(); + int deviceWidth = (settings.deviceWidth() > 0) ? settings.deviceWidth() : m_viewSize.width(); + int deviceHeight = (settings.deviceHeight() > 0) ? settings.deviceHeight() : m_viewSize.height(); ViewportAttributes attr = computeViewportAttributes(m_page->viewportArguments(), minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewSize); - FrameView* view = m_page->mainFrame()->view(); + FrameView* view = m_page->mainFrame().view(); // If no layout was done yet set contentFixedOrigin to (0,0). IntPoint contentFixedOrigin = view->didFirstLayout() ? view->fixedVisibleContentRect().location() : IntPoint(); @@ -1162,16 +1408,21 @@ void WebPage::sendViewportAttributesChanged() // This also takes care of the relayout. setFixedLayoutSize(roundedIntSize(attr.layoutSize)); +#if USE(COORDINATED_GRAPHICS_THREADED) + if (m_drawingArea->layerTreeHost()) + m_drawingArea->layerTreeHost()->didChangeViewportProperties(attr); +#else send(Messages::WebPageProxy::DidChangeViewportProperties(attr)); +#endif } #endif void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset) { - Frame* frame = m_page->mainFrame(); + FrameView* frameView = m_page->mainFrame().view(); - IntPoint scrollPosition = frame->view()->scrollPosition(); - IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition(); + ScrollPosition scrollPosition = frameView->scrollPosition(); + ScrollPosition maximumScrollPosition = frameView->maximumScrollPosition(); // If the current scroll position in a direction is the max scroll position // we don't want to scroll at all. @@ -1184,7 +1435,7 @@ void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffse if (newScrollOffset.isZero()) return; - frame->view()->setScrollPosition(frame->view()->scrollPosition() + newScrollOffset); + frameView->setScrollPosition(frameView->scrollPosition() + newScrollOffset); } void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect) @@ -1192,29 +1443,18 @@ void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect) GraphicsContextStateSaver stateSaver(graphicsContext); graphicsContext.clip(rect); - if (m_underlayPage) { - m_underlayPage->drawRect(graphicsContext, rect); - - graphicsContext.beginTransparencyLayer(1); - m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect); - graphicsContext.endTransparencyLayer(); - return; - } - - m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect); -} - -void WebPage::drawPageOverlay(PageOverlay* pageOverlay, GraphicsContext& graphicsContext, const IntRect& rect) -{ - ASSERT(pageOverlay); - - GraphicsContextStateSaver stateSaver(graphicsContext); - graphicsContext.clip(rect); - pageOverlay->drawRect(graphicsContext, rect); + m_mainFrame->coreFrame()->view()->paint(graphicsContext, rect); } double WebPage::textZoomFactor() const { + PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); + if (pluginView && pluginView->requiresUnifiedScaleFactor()) { + if (pluginView->handlesPageScaleFactor()) + return pluginView->pageScaleFactor(); + return pageScaleFactor(); + } + Frame* frame = m_mainFrame->coreFrame(); if (!frame) return 1; @@ -1223,9 +1463,14 @@ double WebPage::textZoomFactor() const void WebPage::setTextZoomFactor(double zoomFactor) { - PluginView* pluginView = pluginViewForFrame(m_page->mainFrame()); - if (pluginView && pluginView->handlesPageScaleFactor()) + PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); + if (pluginView && pluginView->requiresUnifiedScaleFactor()) { + if (pluginView->handlesPageScaleFactor()) + pluginView->setPageScaleFactor(zoomFactor, IntPoint()); + else + scalePage(zoomFactor, IntPoint()); return; + } Frame* frame = m_mainFrame->coreFrame(); if (!frame) @@ -1235,9 +1480,12 @@ void WebPage::setTextZoomFactor(double zoomFactor) double WebPage::pageZoomFactor() const { - PluginView* pluginView = pluginViewForFrame(m_page->mainFrame()); - if (pluginView && pluginView->handlesPageScaleFactor()) - return pluginView->pageScaleFactor(); + PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); + if (pluginView && pluginView->requiresUnifiedScaleFactor()) { + if (pluginView->handlesPageScaleFactor()) + return pluginView->pageScaleFactor(); + return pageScaleFactor(); + } Frame* frame = m_mainFrame->coreFrame(); if (!frame) @@ -1247,9 +1495,12 @@ double WebPage::pageZoomFactor() const void WebPage::setPageZoomFactor(double zoomFactor) { - PluginView* pluginView = pluginViewForFrame(m_page->mainFrame()); - if (pluginView && pluginView->handlesPageScaleFactor()) { - pluginView->setPageScaleFactor(zoomFactor, IntPoint()); + PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); + if (pluginView && pluginView->requiresUnifiedScaleFactor()) { + if (pluginView->handlesPageScaleFactor()) + pluginView->setPageScaleFactor(zoomFactor, IntPoint()); + else + scalePage(zoomFactor, IntPoint()); return; } @@ -1261,9 +1512,12 @@ void WebPage::setPageZoomFactor(double zoomFactor) void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor) { - PluginView* pluginView = pluginViewForFrame(m_page->mainFrame()); - if (pluginView && pluginView->handlesPageScaleFactor()) { - pluginView->setPageScaleFactor(pageZoomFactor, IntPoint()); + PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); + if (pluginView && pluginView->requiresUnifiedScaleFactor()) { + if (pluginView->handlesPageScaleFactor()) + pluginView->setPageScaleFactor(pageZoomFactor, IntPoint()); + else + scalePage(pageZoomFactor, IntPoint()); return; } @@ -1273,39 +1527,103 @@ void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFa return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor)); } -void WebPage::windowScreenDidChange(uint64_t displayID) +void WebPage::windowScreenDidChange(uint32_t displayID) { m_page->chrome().windowScreenDidChange(static_cast<PlatformDisplayID>(displayID)); } void WebPage::scalePage(double scale, const IntPoint& origin) { - PluginView* pluginView = pluginViewForFrame(m_page->mainFrame()); + double totalScale = scale * viewScaleFactor(); + bool willChangeScaleFactor = totalScale != totalScaleFactor(); + +#if PLATFORM(IOS) + if (willChangeScaleFactor) { + if (!m_inDynamicSizeUpdate) + m_dynamicSizeUpdateHistory.clear(); + m_scaleWasSetByUIProcess = false; + } +#endif + PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); if (pluginView && pluginView->handlesPageScaleFactor()) { - pluginView->setPageScaleFactor(scale, origin); + // If the main-frame plugin wants to handle the page scale factor, make sure to reset WebCore's page scale. + // Otherwise, we can end up with an immutable but non-1 page scale applied by WebCore on top of whatever the plugin does. + if (m_page->pageScaleFactor() != 1) { + m_page->setPageScaleFactor(1, origin); + for (auto* pluginView : m_pluginViews) + pluginView->pageScaleFactorDidChange(); + } + + pluginView->setPageScaleFactor(totalScale, origin); return; } - m_page->setPageScaleFactor(scale, origin); + m_page->setPageScaleFactor(totalScale, origin); + + // We can't early return before setPageScaleFactor because the origin might be different. + if (!willChangeScaleFactor) + return; - for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) - (*it)->pageScaleFactorDidChange(); + for (auto* pluginView : m_pluginViews) + pluginView->pageScaleFactorDidChange(); +#if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER) if (m_drawingArea->layerTreeHost()) m_drawingArea->layerTreeHost()->deviceOrPageScaleFactorChanged(); +#endif send(Messages::WebPageProxy::PageScaleFactorDidChange(scale)); } -double WebPage::pageScaleFactor() const +void WebPage::scalePageInViewCoordinates(double scale, IntPoint centerInViewCoordinates) +{ + double totalScale = scale * viewScaleFactor(); + if (totalScale == totalScaleFactor()) + return; + + IntPoint scrollPositionAtNewScale = mainFrameView()->rootViewToContents(-centerInViewCoordinates); + double scaleRatio = scale / pageScaleFactor(); + scrollPositionAtNewScale.scale(scaleRatio, scaleRatio); + scalePage(scale, scrollPositionAtNewScale); +} + +double WebPage::totalScaleFactor() const { - PluginView* pluginView = pluginViewForFrame(m_page->mainFrame()); + PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame()); if (pluginView && pluginView->handlesPageScaleFactor()) return pluginView->pageScaleFactor(); - + return m_page->pageScaleFactor(); } +double WebPage::pageScaleFactor() const +{ + return totalScaleFactor() / viewScaleFactor(); +} + +double WebPage::viewScaleFactor() const +{ + return m_page->viewScaleFactor(); +} + +void WebPage::scaleView(double scale) +{ + if (viewScaleFactor() == scale) + return; + + float pageScale = pageScaleFactor(); + + IntPoint scrollPositionAtNewScale; + if (FrameView* mainFrameView = m_page->mainFrame().view()) { + double scaleRatio = scale / viewScaleFactor(); + scrollPositionAtNewScale = mainFrameView->scrollPosition(); + scrollPositionAtNewScale.scale(scaleRatio, scaleRatio); + } + + m_page->setViewScaleFactor(scale); + scalePage(pageScale, scrollPositionAtNewScale); +} + void WebPage::setDeviceScaleFactor(float scaleFactor) { if (scaleFactor == m_page->deviceScaleFactor()) @@ -1315,8 +1633,8 @@ void WebPage::setDeviceScaleFactor(float scaleFactor) // Tell all our plug-in views that the device scale factor changed. #if PLATFORM(MAC) - for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) - (*it)->setDeviceScaleFactor(scaleFactor); + for (auto* pluginView : m_pluginViews) + pluginView->setDeviceScaleFactor(scaleFactor); updateHeaderAndFooterLayersForDeviceScaleChange(scaleFactor); #endif @@ -1327,8 +1645,10 @@ void WebPage::setDeviceScaleFactor(float scaleFactor) m_findController.deviceScaleFactorDidChange(); } +#if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER) if (m_drawingArea->layerTreeHost()) m_drawingArea->layerTreeHost()->deviceOrPageScaleFactorChanged(); +#endif } float WebPage::deviceScaleFactor() const @@ -1343,31 +1663,35 @@ void WebPage::setUseFixedLayout(bool fixed) return; m_useFixedLayout = fixed; - m_page->settings()->setFixedElementsLayoutRelativeToFrame(fixed); +#if !PLATFORM(IOS) + m_page->settings().setFixedElementsLayoutRelativeToFrame(fixed); +#endif #if USE(COORDINATED_GRAPHICS) - m_page->settings()->setAcceleratedCompositingForFixedPositionEnabled(fixed); - m_page->settings()->setFixedPositionCreatesStackingContext(fixed); - m_page->settings()->setApplyPageScaleFactorInCompositor(fixed); - m_page->settings()->setScrollingCoordinatorEnabled(fixed); + m_page->settings().setAcceleratedCompositingForFixedPositionEnabled(fixed); + m_page->settings().setFixedPositionCreatesStackingContext(fixed); + m_page->settings().setDelegatesPageScaling(fixed); + m_page->settings().setScrollingCoordinatorEnabled(fixed); #endif -#if USE(TILED_BACKING_STORE) && ENABLE(SMOOTH_SCROLLING) +#if USE(COORDINATED_GRAPHICS) && ENABLE(SMOOTH_SCROLLING) // Delegated scrolling will be enabled when the FrameView is created if fixed layout is enabled. // Ensure we don't do animated scrolling in the WebProcess in that case. - m_page->settings()->setScrollAnimatorEnabled(!fixed); + m_page->settings().setScrollAnimatorEnabled(!fixed); #endif FrameView* view = mainFrameView(); if (!view) return; -#if USE(TILED_BACKING_STORE) +#if USE(COORDINATED_GRAPHICS) view->setDelegatesScrolling(fixed); view->setPaintsEntireContents(fixed); #endif view->setUseFixedLayout(fixed); if (!fixed) setFixedLayoutSize(IntSize()); + + send(Messages::WebPageProxy::UseFixedLayoutDidChange(fixed)); } void WebPage::setFixedLayoutSize(const IntSize& size) @@ -1377,9 +1701,16 @@ void WebPage::setFixedLayoutSize(const IntSize& size) return; view->setFixedLayoutSize(size); - // Do not force it until the first layout, this would then become our first layout prematurely. - if (view->didFirstLayout()) - view->forceLayout(); + + send(Messages::WebPageProxy::FixedLayoutSizeDidChange(size)); +} + +IntSize WebPage::fixedLayoutSize() const +{ + FrameView* view = mainFrameView(); + if (!view) + return IntSize(); + return view->fixedLayoutSize(); } void WebPage::listenForLayoutMilestones(uint32_t milestones) @@ -1393,15 +1724,21 @@ void WebPage::setSuppressScrollbarAnimations(bool suppressAnimations) { m_page->setShouldSuppressScrollbarAnimations(suppressAnimations); } - -void WebPage::setRubberBandsAtBottom(bool rubberBandsAtBottom) + +void WebPage::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding) +{ + m_page->setVerticalScrollElasticity(enableVerticalRubberBanding ? ScrollElasticityAllowed : ScrollElasticityNone); +} + +void WebPage::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding) { - m_page->setRubberBandsAtBottom(rubberBandsAtBottom); + m_page->setHorizontalScrollElasticity(enableHorizontalRubberBanding ? ScrollElasticityAllowed : ScrollElasticityNone); } -void WebPage::setRubberBandsAtTop(bool rubberBandsAtTop) +void WebPage::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage) { - m_page->setRubberBandsAtTop(rubberBandsAtTop); + if (m_page->settings().backgroundShouldExtendBeyondPage() != backgroundExtendsBeyondPage) + m_page->settings().setBackgroundShouldExtendBeyondPage(backgroundExtendsBeyondPage); } void WebPage::setPaginationMode(uint32_t mode) @@ -1432,53 +1769,22 @@ void WebPage::setGapBetweenPages(double gap) m_page->setPagination(pagination); } -void WebPage::postInjectedBundleMessage(const String& messageName, CoreIPC::MessageDecoder& decoder) -{ - InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle(); - if (!injectedBundle) - return; - - RefPtr<APIObject> messageBody; - InjectedBundleUserMessageDecoder messageBodyDecoder(messageBody); - if (!decoder.decode(messageBodyDecoder)) - return; - - injectedBundle->didReceiveMessageToPage(this, messageName, messageBody.get()); -} - -void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay, bool shouldFadeIn) +void WebPage::setPaginationLineGridEnabled(bool lineGridEnabled) { - RefPtr<PageOverlay> overlay = pageOverlay; - - if (m_pageOverlays.contains(overlay.get())) - return; - - m_pageOverlays.append(overlay); - overlay->setPage(this); - - if (shouldFadeIn) - overlay->startFadeInAnimation(); - - m_drawingArea->didInstallPageOverlay(overlay.get()); + m_page->setPaginationLineGridEnabled(lineGridEnabled); } -void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay, bool shouldFadeOut) +void WebPage::postInjectedBundleMessage(const String& messageName, const UserData& userData) { - size_t existingOverlayIndex = m_pageOverlays.find(pageOverlay); - if (existingOverlayIndex == notFound) - return; - - if (shouldFadeOut) { - pageOverlay->startFadeOutAnimation(); + auto& webProcess = WebProcess::singleton(); + InjectedBundle* injectedBundle = webProcess.injectedBundle(); + if (!injectedBundle) return; - } - pageOverlay->setPage(0); - m_pageOverlays.remove(existingOverlayIndex); - - m_drawingArea->didUninstallPageOverlay(pageOverlay); + injectedBundle->didReceiveMessageToPage(this, messageName, webProcess.transformHandlesToObjects(userData.object()).get()); } +#if !PLATFORM(IOS) void WebPage::setHeaderPageBanner(PassRefPtr<PageBanner> pageBanner) { if (m_headerBanner) @@ -1526,33 +1832,82 @@ void WebPage::showPageBanners() if (m_footerBanner) m_footerBanner->showIfHidden(); } +#endif // !PLATFORM(IOS) + +void WebPage::takeSnapshot(IntRect snapshotRect, IntSize bitmapSize, uint32_t options, uint64_t callbackID) +{ + SnapshotOptions snapshotOptions = static_cast<SnapshotOptions>(options); + snapshotOptions |= SnapshotOptionsShareable; + + RefPtr<WebImage> image = snapshotAtSize(snapshotRect, bitmapSize, snapshotOptions); + + ShareableBitmap::Handle handle; + if (image) + image->bitmap()->createHandle(handle, SharedMemory::Protection::ReadOnly); + + send(Messages::WebPageProxy::ImageCallback(handle, callbackID)); +} + +PassRefPtr<WebImage> WebPage::scaledSnapshotWithOptions(const IntRect& rect, double additionalScaleFactor, SnapshotOptions options) +{ + IntRect snapshotRect = rect; + IntSize bitmapSize = snapshotRect.size(); + if (options & SnapshotOptionsPrinting) { + ASSERT(additionalScaleFactor == 1); + Frame* coreFrame = m_mainFrame->coreFrame(); + if (!coreFrame) + return nullptr; + bitmapSize.setHeight(PrintContext::numberOfPages(*coreFrame, bitmapSize) * (bitmapSize.height() + 1) - 1); + } else { + double scaleFactor = additionalScaleFactor; + if (!(options & SnapshotOptionsExcludeDeviceScaleFactor)) + scaleFactor *= corePage()->deviceScaleFactor(); + bitmapSize.scale(scaleFactor); + } + + return snapshotAtSize(rect, bitmapSize, options); +} -PassRefPtr<WebImage> WebPage::scaledSnapshotWithOptions(const IntRect& rect, double scaleFactor, SnapshotOptions options) +PassRefPtr<WebImage> WebPage::snapshotAtSize(const IntRect& rect, const IntSize& bitmapSize, SnapshotOptions options) { Frame* coreFrame = m_mainFrame->coreFrame(); if (!coreFrame) - return 0; + return nullptr; FrameView* frameView = coreFrame->view(); if (!frameView) - return 0; + return nullptr; - IntSize bitmapSize = rect.size(); - float combinedScaleFactor = scaleFactor * corePage()->deviceScaleFactor(); - bitmapSize.scale(combinedScaleFactor); + IntRect snapshotRect = rect; + float horizontalScaleFactor = static_cast<float>(bitmapSize.width()) / rect.width(); + float verticalScaleFactor = static_cast<float>(bitmapSize.height()) / rect.height(); + float scaleFactor = std::max(horizontalScaleFactor, verticalScaleFactor); RefPtr<WebImage> snapshot = WebImage::create(bitmapSize, snapshotOptionsToImageOptions(options)); if (!snapshot->bitmap()) - return 0; + return nullptr; + + auto graphicsContext = snapshot->bitmap()->createGraphicsContext(); + + if (options & SnapshotOptionsPrinting) { + PrintContext::spoolAllPagesWithBoundaries(*coreFrame, *graphicsContext, snapshotRect.size()); + return snapshot.release(); + } - OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext(); + Color documentBackgroundColor = frameView->documentBackgroundColor(); + Color backgroundColor = (coreFrame->settings().backgroundShouldExtendBeyondPage() && documentBackgroundColor.isValid()) ? documentBackgroundColor : frameView->baseBackgroundColor(); + graphicsContext->fillRect(IntRect(IntPoint(), bitmapSize), backgroundColor); - graphicsContext->clearRect(IntRect(IntPoint(), bitmapSize)); + if (!(options & SnapshotOptionsExcludeDeviceScaleFactor)) { + double deviceScaleFactor = corePage()->deviceScaleFactor(); + graphicsContext->applyDeviceScaleFactor(deviceScaleFactor); + scaleFactor /= deviceScaleFactor; + } - graphicsContext->applyDeviceScaleFactor(combinedScaleFactor); - graphicsContext->translate(-rect.x(), -rect.y()); + graphicsContext->scale(FloatSize(scaleFactor, scaleFactor)); + graphicsContext->translate(-snapshotRect.x(), -snapshotRect.y()); - FrameView::SelectionInSnaphot shouldPaintSelection = FrameView::IncludeSelection; + FrameView::SelectionInSnapshot shouldPaintSelection = FrameView::IncludeSelection; if (options & SnapshotOptionsExcludeSelectionHighlighting) shouldPaintSelection = FrameView::ExcludeSelection; @@ -1560,28 +1915,98 @@ PassRefPtr<WebImage> WebPage::scaledSnapshotWithOptions(const IntRect& rect, dou if (options & SnapshotOptionsInViewCoordinates) coordinateSpace = FrameView::ViewCoordinates; - frameView->paintContentsForSnapshot(graphicsContext.get(), rect, shouldPaintSelection, coordinateSpace); + frameView->paintContentsForSnapshot(*graphicsContext, snapshotRect, shouldPaintSelection, coordinateSpace); if (options & SnapshotOptionsPaintSelectionRectangle) { - FloatRect selectionRectangle = m_mainFrame->coreFrame()->selection()->bounds(); - graphicsContext->setStrokeColor(Color(0xFF, 0, 0), ColorSpaceDeviceRGB); + FloatRect selectionRectangle = m_mainFrame->coreFrame()->selection().selectionBounds(); + graphicsContext->setStrokeColor(Color(0xFF, 0, 0)); graphicsContext->strokeRect(selectionRectangle, 1); } + + return snapshot.release(); +} + +PassRefPtr<WebImage> WebPage::snapshotNode(WebCore::Node& node, SnapshotOptions options, unsigned maximumPixelCount) +{ + Frame* coreFrame = m_mainFrame->coreFrame(); + if (!coreFrame) + return nullptr; + + FrameView* frameView = coreFrame->view(); + if (!frameView) + return nullptr; + + if (!node.renderer()) + return nullptr; + + LayoutRect topLevelRect; + IntRect snapshotRect = snappedIntRect(node.renderer()->paintingRootRect(topLevelRect)); + if (snapshotRect.isEmpty()) + return nullptr; + + double scaleFactor = 1; + IntSize snapshotSize = snapshotRect.size(); + unsigned maximumHeight = maximumPixelCount / snapshotSize.width(); + if (maximumHeight < static_cast<unsigned>(snapshotSize.height())) { + scaleFactor = static_cast<double>(maximumHeight) / snapshotSize.height(); + snapshotSize = IntSize(snapshotSize.width() * scaleFactor, maximumHeight); + } + + RefPtr<WebImage> snapshot = WebImage::create(snapshotSize, snapshotOptionsToImageOptions(options)); + if (!snapshot->bitmap()) + return nullptr; + + auto graphicsContext = snapshot->bitmap()->createGraphicsContext(); + + if (!(options & SnapshotOptionsExcludeDeviceScaleFactor)) { + double deviceScaleFactor = corePage()->deviceScaleFactor(); + graphicsContext->applyDeviceScaleFactor(deviceScaleFactor); + scaleFactor /= deviceScaleFactor; + } + + graphicsContext->scale(FloatSize(scaleFactor, scaleFactor)); + graphicsContext->translate(-snapshotRect.x(), -snapshotRect.y()); + + Color savedBackgroundColor = frameView->baseBackgroundColor(); + frameView->setBaseBackgroundColor(Color::transparent); + frameView->setNodeToDraw(&node); + + frameView->paintContentsForSnapshot(*graphicsContext, snapshotRect, FrameView::ExcludeSelection, FrameView::DocumentCoordinates); + + frameView->setBaseBackgroundColor(savedBackgroundColor); + frameView->setNodeToDraw(nullptr); return snapshot.release(); } void WebPage::pageDidScroll() { - m_uiClient.pageDidScroll(this); +#if PLATFORM(IOS) + if (!m_inDynamicSizeUpdate) + m_dynamicSizeUpdateHistory.clear(); +#endif + m_uiClient->pageDidScroll(this); + + m_pageScrolledHysteresis.impulse(); send(Messages::WebPageProxy::PageDidScroll()); } -#if USE(TILED_BACKING_STORE) +void WebPage::pageStoppedScrolling() +{ + // Maintain the current history item's scroll position up-to-date. + if (Frame* frame = m_mainFrame->coreFrame()) + frame->loader().history().saveScrollPositionAndViewStateToItem(frame->loader().history().currentItem()); +} + +#if USE(COORDINATED_GRAPHICS) void WebPage::pageDidRequestScroll(const IntPoint& point) { +#if USE(COORDINATED_GRAPHICS_THREADED) + drawingArea()->scroll(IntRect(point, IntSize()), IntSize()); +#elif USE(COORDINATED_GRAPHICS_MULTIPROCESS) send(Messages::WebPageProxy::PageDidRequestScroll(point)); +#endif } #endif @@ -1595,11 +2020,11 @@ WebContextMenu* WebPage::contextMenu() WebContextMenu* WebPage::contextMenuAtPointInWindow(const IntPoint& point) { - corePage()->contextMenuController()->clearContextMenu(); + corePage()->contextMenuController().clearContextMenu(); // Simulate a mouse click to generate the correct menu. - PlatformMouseEvent mouseEvent(point, point, RightButton, PlatformEvent::MousePressed, 1, false, false, false, false, currentTime()); - bool handled = corePage()->mainFrame()->eventHandler()->sendContextMenuEvent(mouseEvent); + PlatformMouseEvent mouseEvent(point, point, RightButton, PlatformEvent::MousePressed, 1, false, false, false, false, currentTime(), WebCore::ForceAtClick); + bool handled = corePage()->userInputBridge().handleContextMenuEvent(mouseEvent, &corePage()->mainFrame()); if (!handled) return 0; @@ -1619,6 +2044,24 @@ const WebEvent* WebPage::currentEvent() return g_currentEvent; } +void WebPage::setLayerTreeStateIsFrozen(bool frozen) +{ + auto* drawingArea = this->drawingArea(); + if (!drawingArea) + return; + + drawingArea->setLayerTreeStateIsFrozen(frozen); +} + +bool WebPage::markLayersVolatileImmediatelyIfPossible() +{ + auto* drawingArea = this->drawingArea(); + if (!drawingArea) + return true; + + return drawingArea->markLayersVolatileImmediatelyIfPossible(); +} + class CurrentEvent { public: explicit CurrentEvent(const WebEvent& event) @@ -1639,28 +2082,23 @@ private: #if ENABLE(CONTEXT_MENUS) static bool isContextClick(const PlatformMouseEvent& event) { - if (event.button() == WebCore::RightButton) - return true; - -#if PLATFORM(MAC) - // FIXME: this really should be about OSX-style UI, not about the Mac port - if (event.button() == WebCore::LeftButton && event.ctrlKey()) - return true; +#if PLATFORM(COCOA) + return WebEventFactory::shouldBeHandledAsContextClick(event); +#else + return event.button() == WebCore::RightButton; #endif - - return false; } static bool handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent, WebPage* page) { - IntPoint point = page->corePage()->mainFrame()->view()->windowToContents(platformMouseEvent.position()); - HitTestResult result = page->corePage()->mainFrame()->eventHandler()->hitTestResultAtPoint(point); + IntPoint point = page->corePage()->mainFrame().view()->windowToContents(platformMouseEvent.position()); + HitTestResult result = page->corePage()->mainFrame().eventHandler().hitTestResultAtPoint(point); - Frame* frame = page->corePage()->mainFrame(); + Frame* frame = &page->corePage()->mainFrame(); if (result.innerNonSharedNode()) - frame = result.innerNonSharedNode()->document()->frame(); - - bool handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent); + frame = result.innerNonSharedNode()->document().frame(); + + bool handled = page->corePage()->userInputBridge().handleContextMenuEvent(platformMouseEvent, frame); if (handled) page->contextMenu()->show(); @@ -1670,8 +2108,8 @@ static bool handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent, static bool handleMouseEvent(const WebMouseEvent& mouseEvent, WebPage* page, bool onlyUpdateScrollbars) { - Frame* frame = page->corePage()->mainFrame(); - if (!frame->view()) + Frame& frame = page->corePage()->mainFrame(); + if (!frame.view()) return false; PlatformMouseEvent platformMouseEvent = platform(mouseEvent); @@ -1680,10 +2118,10 @@ static bool handleMouseEvent(const WebMouseEvent& mouseEvent, WebPage* page, boo case PlatformEvent::MousePressed: { #if ENABLE(CONTEXT_MENUS) if (isContextClick(platformMouseEvent)) - page->corePage()->contextMenuController()->clearContextMenu(); + page->corePage()->contextMenuController().clearContextMenu(); #endif - bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent); + bool handled = page->corePage()->userInputBridge().handleMousePressEvent(platformMouseEvent); #if ENABLE(CONTEXT_MENUS) if (isContextClick(platformMouseEvent)) handled = handleContextMenuEvent(platformMouseEvent, page); @@ -1691,12 +2129,18 @@ static bool handleMouseEvent(const WebMouseEvent& mouseEvent, WebPage* page, boo return handled; } case PlatformEvent::MouseReleased: - return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent); + return page->corePage()->userInputBridge().handleMouseReleaseEvent(platformMouseEvent); case PlatformEvent::MouseMoved: if (onlyUpdateScrollbars) - return frame->eventHandler()->passMouseMovedEventToScrollbars(platformMouseEvent); - return frame->eventHandler()->mouseMoved(platformMouseEvent); + return page->corePage()->userInputBridge().handleMouseMoveOnScrollbarEvent(platformMouseEvent); + return page->corePage()->userInputBridge().handleMouseMoveEvent(platformMouseEvent); + + case PlatformEvent::MouseForceChanged: + case PlatformEvent::MouseForceDown: + case PlatformEvent::MouseForceUp: + return page->corePage()->userInputBridge().handleMouseForceEvent(platformMouseEvent); + default: ASSERT_NOT_REACHED(); return false; @@ -1705,26 +2149,33 @@ static bool handleMouseEvent(const WebMouseEvent& mouseEvent, WebPage* page, boo void WebPage::mouseEvent(const WebMouseEvent& mouseEvent) { + m_page->pageThrottler().didReceiveUserInput(); + + bool shouldHandleEvent = true; + #if ENABLE(CONTEXT_MENUS) // Don't try to handle any pending mouse events if a context menu is showing. - if (m_isShowingContextMenu) { + if (m_isShowingContextMenu) + shouldHandleEvent = false; +#endif +#if ENABLE(DRAG_SUPPORT) + if (m_isStartingDrag) + shouldHandleEvent = false; +#endif + + if (!shouldHandleEvent) { send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), false)); return; } -#endif + bool handled = false; - if (m_pageOverlays.size()) { - // Let the page overlay handle the event. - PageOverlayList::reverse_iterator end = m_pageOverlays.rend(); - for (PageOverlayList::reverse_iterator it = m_pageOverlays.rbegin(); it != end; ++it) - if ((handled = (*it)->mouseEvent(mouseEvent))) - break; - } +#if !PLATFORM(IOS) if (!handled && m_headerBanner) handled = m_headerBanner->mouseEvent(mouseEvent); if (!handled && m_footerBanner) handled = m_footerBanner->mouseEvent(mouseEvent); +#endif // !PLATFORM(IOS) if (!handled && canHandleUserEvents()) { CurrentEvent currentEvent(mouseEvent); @@ -1734,53 +2185,27 @@ void WebPage::mouseEvent(const WebMouseEvent& mouseEvent) // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one // of those cases where the page is not active and the mouse is not pressed, then we can fire a more // efficient scrollbars-only version of the event. - bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton)); + bool onlyUpdateScrollbars = !(m_page->focusController().isActive() || (mouseEvent.button() != WebMouseEvent::NoButton)); handled = handleMouseEvent(mouseEvent, this, onlyUpdateScrollbars); } send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled)); } -void WebPage::mouseEventSyncForTesting(const WebMouseEvent& mouseEvent, bool& handled) -{ - handled = false; - - if (m_pageOverlays.size()) { - PageOverlayList::reverse_iterator end = m_pageOverlays.rend(); - for (PageOverlayList::reverse_iterator it = m_pageOverlays.rbegin(); it != end; ++it) - if ((handled = (*it)->mouseEvent(mouseEvent))) - break; - } - if (!handled && m_headerBanner) - handled = m_headerBanner->mouseEvent(mouseEvent); - if (!handled && m_footerBanner) - handled = m_footerBanner->mouseEvent(mouseEvent); - - if (!handled) { - CurrentEvent currentEvent(mouseEvent); - - // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse - // button is currently pressed. It is possible that neither of those things will be true since on - // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one - // of those cases where the page is not active and the mouse is not pressed, then we can fire a more - // efficient scrollbars-only version of the event. - bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton)); - handled = handleMouseEvent(mouseEvent, this, onlyUpdateScrollbars); - } -} - static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page) { - Frame* frame = page->mainFrame(); - if (!frame->view()) + Frame& frame = page->mainFrame(); + if (!frame.view()) return false; PlatformWheelEvent platformWheelEvent = platform(wheelEvent); - return frame->eventHandler()->handleWheelEvent(platformWheelEvent); + return page->userInputBridge().handleWheelEvent(platformWheelEvent); } void WebPage::wheelEvent(const WebWheelEvent& wheelEvent) { + m_page->pageThrottler().didReceiveUserInput(); + bool handled = false; if (canHandleUserEvents()) { @@ -1791,25 +2216,20 @@ void WebPage::wheelEvent(const WebWheelEvent& wheelEvent) send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled)); } -void WebPage::wheelEventSyncForTesting(const WebWheelEvent& wheelEvent, bool& handled) -{ - CurrentEvent currentEvent(wheelEvent); - - handled = handleWheelEvent(wheelEvent, m_page.get()); -} - static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page) { - if (!page->mainFrame()->view()) + if (!page->mainFrame().view()) return false; if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey()) - return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent)); - return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent)); + return page->userInputBridge().handleAccessKeyEvent(platform(keyboardEvent)); + return page->userInputBridge().handleKeyEvent(platform(keyboardEvent)); } void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent) { + m_page->pageThrottler().didReceiveUserInput(); + bool handled = false; if (canHandleUserEvents()) { @@ -1823,90 +2243,39 @@ void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent) send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled)); } -void WebPage::keyEventSyncForTesting(const WebKeyboardEvent& keyboardEvent, bool& handled) -{ - CurrentEvent currentEvent(keyboardEvent); - - handled = handleKeyEvent(keyboardEvent, m_page.get()); - if (!handled) - handled = performDefaultBehaviorForKeyEvent(keyboardEvent); -} - -#if ENABLE(GESTURE_EVENTS) -static bool handleGestureEvent(const WebGestureEvent& gestureEvent, Page* page) -{ - Frame* frame = page->mainFrame(); - if (!frame->view()) - return false; - - PlatformGestureEvent platformGestureEvent = platform(gestureEvent); - return frame->eventHandler()->handleGestureEvent(platformGestureEvent); -} - -void WebPage::gestureEvent(const WebGestureEvent& gestureEvent) -{ - bool handled = false; - - if (canHandleUserEvents()) { - CurrentEvent currentEvent(gestureEvent); - - handled = handleGestureEvent(gestureEvent, m_page.get()); - } - send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled)); -} -#endif - void WebPage::validateCommand(const String& commandName, uint64_t callbackID) { bool isEnabled = false; int32_t state = 0; - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (frame) { - if (PluginView* pluginView = focusedPluginViewForFrame(frame)) - isEnabled = pluginView->isEditingCommandEnabled(commandName); - else { - Editor::Command command = frame->editor().command(commandName); - state = command.state(); - isEnabled = command.isSupported() && command.isEnabled(); - } + Frame& frame = m_page->focusController().focusedOrMainFrame(); + if (PluginView* pluginView = focusedPluginViewForFrame(frame)) + isEnabled = pluginView->isEditingCommandEnabled(commandName); + else { + Editor::Command command = frame.editor().command(commandName); + state = command.state(); + isEnabled = command.isSupported() && command.isEnabled(); } send(Messages::WebPageProxy::ValidateCommandCallback(commandName, isEnabled, state, callbackID)); } -void WebPage::executeEditCommand(const String& commandName) +void WebPage::executeEditCommand(const String& commandName, const String& argument) { - executeEditingCommand(commandName, String()); + executeEditingCommand(commandName, argument); } -uint64_t WebPage::restoreSession(const SessionState& sessionState) +void WebPage::restoreSessionInternal(const Vector<BackForwardListItemState>& itemStates, WasRestoredByAPIRequest restoredByAPIRequest) { - const BackForwardListItemVector& list = sessionState.list(); - size_t size = list.size(); - uint64_t currentItemID = 0; - for (size_t i = 0; i < size; ++i) { - WebBackForwardListItem* webItem = list[i].get(); - DecoderAdapter decoder(webItem->backForwardData().data(), webItem->backForwardData().size()); - - RefPtr<HistoryItem> item = HistoryItem::decodeBackForwardTree(webItem->url(), webItem->title(), webItem->originalURL(), decoder); - if (!item) { - LOG_ERROR("Failed to decode a HistoryItem from session state data."); - return 0; - } - - if (i == sessionState.currentIndex()) - currentItemID = webItem->itemID(); - - WebBackForwardListProxy::addItemFromUIProcess(list[i]->itemID(), item.release()); - } - ASSERT(currentItemID); - return currentItemID; + for (const auto& itemState : itemStates) { + auto historyItem = toHistoryItem(itemState.pageState); + historyItem->setWasRestoredFromSession(restoredByAPIRequest == WasRestoredByAPIRequest::Yes); + WebBackForwardListProxy::addItemFromUIProcess(itemState.identifier, WTFMove(historyItem), m_pageID); + } } -void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& sessionState) +void WebPage::restoreSession(const Vector<BackForwardListItemState>& itemStates) { - if (uint64_t currentItemID = restoreSession(sessionState)) - goToBackForwardItem(currentItemID); + restoreSessionInternal(itemStates, WasRestoredByAPIRequest::Yes); } #if ENABLE(TOUCH_EVENTS) @@ -1917,17 +2286,17 @@ void WebPage::highlightPotentialActivation(const IntPoint& point, const IntSize& // An empty point deactivates the highlighting. tapHighlightController().hideHighlight(); } else { - Frame* mainframe = m_page->mainFrame(); + Frame* mainframe = &m_page->mainFrame(); Node* activationNode = 0; Node* adjustedNode = 0; IntPoint adjustedPoint; #if ENABLE(TOUCH_ADJUSTMENT) - if (!mainframe->eventHandler()->bestClickableNodeForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), adjustedPoint, adjustedNode)) + if (!mainframe->eventHandler().bestClickableNodeForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), adjustedPoint, adjustedNode)) return; #else - HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); + HitTestResult result = mainframe->eventHandler().hitTestResultAtPoint(mainframe->view()->windowToContents(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); adjustedNode = result.innerNode(); #endif // Find the node to highlight. This is not the same as the node responding the tap gesture, because many @@ -1958,17 +2327,38 @@ void WebPage::highlightPotentialActivation(const IntPoint& point, const IntSize& static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page) { - Frame* frame = page->mainFrame(); - if (!frame->view()) + if (!page->mainFrame().view()) return false; - return frame->eventHandler()->handleTouchEvent(platform(touchEvent)); + return page->mainFrame().eventHandler().handleTouchEvent(platform(touchEvent)); +} +#endif + +#if ENABLE(IOS_TOUCH_EVENTS) +void WebPage::dispatchTouchEvent(const WebTouchEvent& touchEvent, bool& handled) +{ + m_userIsInteracting = true; + + m_lastInteractionLocation = touchEvent.position(); + CurrentEvent currentEvent(touchEvent); + handled = handleTouchEvent(touchEvent, m_page.get()); + + m_userIsInteracting = false; } +void WebPage::touchEventSync(const WebTouchEvent& touchEvent, bool& handled) +{ + EventDispatcher::TouchEventQueue queuedEvents; + WebProcess::singleton().eventDispatcher().getQueuedTouchEventsForPage(*this, queuedEvents); + dispatchAsynchronousTouchEvents(queuedEvents); + + dispatchTouchEvent(touchEvent, handled); +} +#elif ENABLE(TOUCH_EVENTS) void WebPage::touchEvent(const WebTouchEvent& touchEvent) { - bool handled = false; + bool handled = false; if (canHandleUserEvents()) { CurrentEvent currentEvent(touchEvent); @@ -1976,49 +2366,62 @@ void WebPage::touchEvent(const WebTouchEvent& touchEvent) } send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled)); } +#endif -void WebPage::touchEventSyncForTesting(const WebTouchEvent& touchEvent, bool& handled) +#if ENABLE(MAC_GESTURE_EVENTS) +static bool handleGestureEvent(const WebGestureEvent& event, Page* page) { - CurrentEvent currentEvent(touchEvent); - handled = handleTouchEvent(touchEvent, m_page.get()); + if (!page->mainFrame().view()) + return false; + + return page->mainFrame().eventHandler().handleGestureEvent(platform(event)); } + +void WebPage::gestureEvent(const WebGestureEvent& gestureEvent) +{ + bool handled = false; + if (canHandleUserEvents()) { + CurrentEvent currentEvent(gestureEvent); + handled = handleGestureEvent(gestureEvent, m_page.get()); + } + send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled)); +} + #endif -void WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity) +bool WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity) { - page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity); + return page->userInputBridge().scrollRecursively(direction, granularity); } -void WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity) +bool WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity) { - page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity); + return page->userInputBridge().logicalScrollRecursively(direction, granularity); } -void WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity) +bool WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity) { - scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity)); + return scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity)); } void WebPage::centerSelectionInVisibleArea() { - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (!frame) - return; - - frame->selection()->revealSelection(ScrollAlignment::alignCenterAlways); + Frame& frame = m_page->focusController().focusedOrMainFrame(); + frame.selection().revealSelection(ScrollAlignment::alignCenterAlways); m_findController.showFindIndicatorInSelection(); } -void WebPage::setActive(bool isActive) +#if ENABLE(REMOTE_INSPECTOR) +void WebPage::setAllowsRemoteInspection(bool allow) { - m_page->focusController()->setActive(isActive); + m_page->setRemoteInspectionAllowed(allow); +} -#if PLATFORM(MAC) - // Tell all our plug-in views that the window focus changed. - for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) - (*it)->setWindowIsFocused(isActive); -#endif +void WebPage::setRemoteInspectionNameOverride(const String& name) +{ + m_page->setRemoteInspectionNameOverride(name); } +#endif void WebPage::setDrawsBackground(bool drawsBackground) { @@ -2027,7 +2430,7 @@ void WebPage::setDrawsBackground(bool drawsBackground) m_drawsBackground = drawsBackground; - for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) { + for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree().traverseNext()) { if (FrameView* view = coreFrame->view()) view->setTransparent(!drawsBackground); } @@ -2036,21 +2439,15 @@ void WebPage::setDrawsBackground(bool drawsBackground) m_drawingArea->setNeedsDisplay(); } -void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground) +void WebPage::setTopContentInset(float contentInset) { - if (m_drawsTransparentBackground == drawsTransparentBackground) + if (contentInset == m_page->topContentInset()) return; - m_drawsTransparentBackground = drawsTransparentBackground; - - Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white; - for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) { - if (FrameView* view = coreFrame->view()) - view->setBaseBackgroundColor(backgroundColor); - } + m_page->setTopContentInset(contentInset); - m_drawingArea->pageBackgroundTransparencyChanged(); - m_drawingArea->setNeedsDisplay(); + for (auto* pluginView : m_pluginViews) + pluginView->topContentInsetDidChange(); } void WebPage::viewWillStartLiveResize() @@ -2059,10 +2456,9 @@ void WebPage::viewWillStartLiveResize() return; // FIXME: This should propagate to all ScrollableAreas. - if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) { - if (FrameView* view = frame->view()) - view->willStartLiveResize(); - } + Frame& frame = m_page->focusController().focusedOrMainFrame(); + if (FrameView* view = frame.view()) + view->willStartLiveResize(); } void WebPage::viewWillEndLiveResize() @@ -2071,47 +2467,34 @@ void WebPage::viewWillEndLiveResize() return; // FIXME: This should propagate to all ScrollableAreas. - if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) { - if (FrameView* view = frame->view()) - view->willEndLiveResize(); - } + Frame& frame = m_page->focusController().focusedOrMainFrame(); + if (FrameView* view = frame.view()) + view->willEndLiveResize(); } -void WebPage::setFocused(bool isFocused) +void WebPage::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& event, uint64_t callbackID) { - m_page->focusController()->setFocused(isFocused); -} - -void WebPage::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& event) -{ - if (!m_page || !m_page->focusController()) + if (!m_page) return; - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - frame->document()->setFocusedElement(0); +#if PLATFORM(IOS) + TemporaryChange<bool> userIsInteractingChange { m_userIsInteracting, true }; +#endif + + Frame& frame = m_page->focusController().focusedOrMainFrame(); + frame.document()->setFocusedElement(0); if (isKeyboardEventValid && event.type() == WebEvent::KeyDown) { PlatformKeyboardEvent platformEvent(platform(event)); platformEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown); - m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, KeyboardEvent::create(platformEvent, frame->document()->defaultView()).get()); - return; - } + m_page->focusController().setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, &KeyboardEvent::create(platformEvent, frame.document()->defaultView()).get()); - m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0); -} - -void WebPage::setWindowResizerSize(const IntSize& windowResizerSize) -{ - if (m_windowResizerSize == windowResizerSize) + send(Messages::WebPageProxy::VoidCallback(callbackID)); return; - - m_windowResizerSize = windowResizerSize; - - for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) { - FrameView* view = coreFrame->view(); - if (view) - view->windowResizerRectChanged(); } + + m_page->focusController().setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0); + send(Messages::WebPageProxy::VoidCallback(callbackID)); } void WebPage::setCanStartMediaTimerFired() @@ -2120,31 +2503,26 @@ void WebPage::setCanStartMediaTimerFired() m_page->setCanStartMedia(true); } -void WebPage::didUpdateInWindowStateTimerFired() -{ - send(Messages::WebPageProxy::DidUpdateInWindowState()); -} - inline bool WebPage::canHandleUserEvents() const { -#if USE(TILED_BACKING_STORE) +#if USE(COORDINATED_GRAPHICS) // Should apply only if the area was frozen by didStartPageTransition(). return !m_drawingArea->layerTreeStateIsFrozen(); #endif return true; } -void WebPage::setIsInWindow(bool isInWindow) +void WebPage::updateIsInWindow(bool isInitialState) { - bool pageWasInWindow = m_page->isInWindow(); - + bool isInWindow = m_viewState & WebCore::ViewState::IsInWindow; + if (!isInWindow) { m_setCanStartMediaTimer.stop(); m_page->setCanStartMedia(false); - m_page->willMoveOffscreen(); - if (pageWasInWindow) - WebProcess::shared().pageWillLeaveWindow(m_pageID); + // The WebProcess does not yet know about this page; no need to tell it we're leaving the window. + if (!isInitialState) + WebProcess::singleton().pageWillLeaveWindow(m_pageID); } else { // Defer the call to Page::setCanStartMedia() since it ends up sending a synchronous message to the UI process // in order to get plug-in connections, and the UI process will be waiting for the Web process to update the backing @@ -2152,36 +2530,72 @@ void WebPage::setIsInWindow(bool isInWindow) if (m_mayStartMediaWhenInWindow) m_setCanStartMediaTimer.startOneShot(0); - m_page->didMoveOnscreen(); - - if (!pageWasInWindow) - WebProcess::shared().pageDidEnterWindow(m_pageID); + WebProcess::singleton().pageDidEnterWindow(m_pageID); } - m_page->setIsInWindow(isInWindow); - m_sendDidUpdateInWindowStateTimer.startOneShot(0); + if (isInWindow) + layoutIfNeeded(); } -void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID) +void WebPage::setViewState(ViewState::Flags viewState, bool wantsDidUpdateViewState, const Vector<uint64_t>& callbackIDs) { - WebFrame* frame = WebProcess::shared().webFrame(frameID); + ViewState::Flags changed = m_viewState ^ viewState; + m_viewState = viewState; + + if (changed) + updateUserActivity(); + + m_page->setViewState(viewState); + for (auto* pluginView : m_pluginViews) + pluginView->viewStateDidChange(changed); + + m_drawingArea->viewStateDidChange(changed, wantsDidUpdateViewState, callbackIDs); + + if (changed & ViewState::IsInWindow) + updateIsInWindow(); +} + +void WebPage::setLayerHostingMode(unsigned layerHostingMode) +{ + m_layerHostingMode = static_cast<LayerHostingMode>(layerHostingMode); + + m_drawingArea->setLayerHostingMode(m_layerHostingMode); + + for (auto* pluginView : m_pluginViews) + pluginView->setLayerHostingMode(m_layerHostingMode); +} + +void WebPage::setSessionID(SessionID sessionID) +{ + if (sessionID.isEphemeral()) + WebProcess::singleton().ensurePrivateBrowsingSession(sessionID); + m_page->setSessionID(sessionID); +} + +void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t navigationID, DownloadID downloadID) +{ + WebFrame* frame = WebProcess::singleton().webFrame(frameID); if (!frame) return; - frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID); + frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), navigationID, downloadID); } void WebPage::didStartPageTransition() { m_drawingArea->setLayerTreeStateIsFrozen(true); +#if PLATFORM(IOS) + m_hasFocusedDueToUserInteraction = false; +#endif } void WebPage::didCompletePageTransition() { -#if USE(TILED_BACKING_STORE) - if (m_mainFrame->coreFrame()->view()->delegatesScrolling()) +#if USE(COORDINATED_GRAPHICS_MULTIPROCESS) + // m_mainFrame can be null since r170163. + if (m_mainFrame && m_mainFrame->coreFrame()->view()->delegatesScrolling()) { // Wait until the UI process sent us the visible rect it wants rendered. send(Messages::WebPageProxy::PageTransitionViewportReady()); - else + } else #endif m_drawingArea->setLayerTreeStateIsFrozen(false); @@ -2192,6 +2606,25 @@ void WebPage::show() send(Messages::WebPageProxy::ShowPage()); } +String WebPage::userAgent(const URL& webCoreURL) const +{ + return userAgent(nullptr, webCoreURL); +} + +String WebPage::userAgent(WebFrame* frame, const URL& webcoreURL) const +{ + if (frame && m_loaderClient.client().userAgentForURL) { + API::String* apiString = m_loaderClient.userAgentForURL(frame, API::URL::create(webcoreURL).ptr()); + if (apiString) + return apiString->string(); + } + + String userAgent = platformUserAgent(webcoreURL); + if (!userAgent.isEmpty()) + return userAgent; + return m_userAgent; +} + void WebPage::setUserAgent(const String& userAgent) { m_userAgent = userAgent; @@ -2207,38 +2640,39 @@ void WebPage::resumeActiveDOMObjectsAndAnimations() m_page->resumeActiveDOMObjectsAndAnimations(); } -IntPoint WebPage::screenToWindow(const IntPoint& point) +IntPoint WebPage::screenToRootView(const IntPoint& point) { IntPoint windowPoint; - sendSync(Messages::WebPageProxy::ScreenToWindow(point), Messages::WebPageProxy::ScreenToWindow::Reply(windowPoint)); + sendSync(Messages::WebPageProxy::ScreenToRootView(point), Messages::WebPageProxy::ScreenToRootView::Reply(windowPoint)); return windowPoint; } -IntRect WebPage::windowToScreen(const IntRect& rect) +IntRect WebPage::rootViewToScreen(const IntRect& rect) { IntRect screenRect; - sendSync(Messages::WebPageProxy::WindowToScreen(rect), Messages::WebPageProxy::WindowToScreen::Reply(screenRect)); + sendSync(Messages::WebPageProxy::RootViewToScreen(rect), Messages::WebPageProxy::RootViewToScreen::Reply(screenRect)); return screenRect; } - -IntRect WebPage::windowResizerRect() const + +#if PLATFORM(IOS) +IntPoint WebPage::accessibilityScreenToRootView(const IntPoint& point) { - if (m_windowResizerSize.isEmpty()) - return IntRect(); - - IntSize frameViewSize; - if (Frame* coreFrame = m_mainFrame->coreFrame()) { - if (FrameView* view = coreFrame->view()) - frameViewSize = view->size(); - } + IntPoint windowPoint; + sendSync(Messages::WebPageProxy::AccessibilityScreenToRootView(point), Messages::WebPageProxy::AccessibilityScreenToRootView::Reply(windowPoint)); + return windowPoint; +} - return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), - m_windowResizerSize.width(), m_windowResizerSize.height()); +IntRect WebPage::rootViewToAccessibilityScreen(const IntRect& rect) +{ + IntRect screenRect; + sendSync(Messages::WebPageProxy::RootViewToAccessibilityScreen(rect), Messages::WebPageProxy::RootViewToAccessibilityScreen::Reply(screenRect)); + return screenRect; } +#endif KeyboardUIMode WebPage::keyboardUIMode() { - bool fullKeyboardAccessEnabled = WebProcess::shared().fullKeyboardAccessEnabled(); + bool fullKeyboardAccessEnabled = WebProcess::singleton().fullKeyboardAccessEnabled(); return static_cast<KeyboardUIMode>((fullKeyboardAccessEnabled ? KeyboardAccessFull : KeyboardAccessDefault) | (m_tabToLinks ? KeyboardAccessTabsToLinks : 0)); } @@ -2247,18 +2681,20 @@ void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID // NOTE: We need to be careful when running scripts that the objects we depend on don't // disappear during script execution. - // Retain the SerializedScriptValue at this level so it (and the internal data) lives - // long enough for the DataReference to be encoded by the sent message. RefPtr<SerializedScriptValue> serializedResultValue; - CoreIPC::DataReference dataReference; - JSLockHolder lock(JSDOMWindow::commonVM()); - if (JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue()) { - if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(), toRef(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0))) - dataReference = serializedResultValue->data(); + bool hadException = true; + ExceptionDetails details; + if (JSValue resultValue = m_mainFrame->coreFrame()->script().executeScript(script, true, &details).jsValue()) { + hadException = false; + serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(), + toRef(m_mainFrame->coreFrame()->script().globalObject(mainThreadNormalWorld())->globalExec(), resultValue), nullptr); } - send(Messages::WebPageProxy::ScriptValueCallback(dataReference, callbackID)); + IPC::DataReference dataReference; + if (serializedResultValue) + dataReference = serializedResultValue->data(); + send(Messages::WebPageProxy::ScriptValueCallback(dataReference, hadException, details, callbackID)); } void WebPage::getContentsAsString(uint64_t callbackID) @@ -2268,17 +2704,14 @@ void WebPage::getContentsAsString(uint64_t callbackID) } #if ENABLE(MHTML) -void WebPage::getContentsAsMHTMLData(uint64_t callbackID, bool useBinaryEncoding) +void WebPage::getContentsAsMHTMLData(uint64_t callbackID) { - CoreIPC::DataReference dataReference; - - RefPtr<SharedBuffer> buffer = useBinaryEncoding - ? MHTMLArchive::generateMHTMLDataUsingBinaryEncoding(m_page.get()) - : MHTMLArchive::generateMHTMLData(m_page.get()); + RefPtr<SharedBuffer> buffer = MHTMLArchive::generateMHTMLData(m_page.get()); + // FIXME: Use SharedBufferDataReference. + IPC::DataReference dataReference; if (buffer) - dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); - + dataReference = IPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); } #endif @@ -2291,8 +2724,8 @@ void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID) static Frame* frameWithSelection(Page* page) { - for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { - if (frame->selection()->isRange()) + for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) { + if (frame->selection().isRange()) return frame; } @@ -2301,20 +2734,17 @@ static Frame* frameWithSelection(Page* page) void WebPage::getSelectionAsWebArchiveData(uint64_t callbackID) { - CoreIPC::DataReference dataReference; - -#if PLATFORM(MAC) - RefPtr<LegacyWebArchive> archive; +#if PLATFORM(COCOA) RetainPtr<CFDataRef> data; - - Frame* frame = frameWithSelection(m_page.get()); - if (frame) { - archive = LegacyWebArchive::createFromSelection(frame); - data = archive->rawDataRepresentation(); - dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get())); - } + if (Frame* frame = frameWithSelection(m_page.get())) + data = LegacyWebArchive::createFromSelection(frame)->rawDataRepresentation(); #endif + IPC::DataReference dataReference; +#if PLATFORM(COCOA) + if (data) + dataReference = IPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get())); +#endif send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); } @@ -2329,7 +2759,7 @@ void WebPage::getSelectionOrContentsAsString(uint64_t callbackID) void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID) { String resultString; - if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) + if (WebFrame* frame = WebProcess::singleton().webFrame(frameID)) resultString = frame->source(); send(Messages::WebPageProxy::StringCallback(resultString, callbackID)); @@ -2337,30 +2767,26 @@ void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID) void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID) { - CoreIPC::DataReference dataReference; - - RefPtr<ResourceBuffer> buffer; - RefPtr<SharedBuffer> pdfResource; - if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) { - if (PluginView* pluginView = pluginViewForFrame(frame->coreFrame())) { - if ((pdfResource = pluginView->liveResourceData())) - dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(pdfResource->data()), pdfResource->size()); - } - - if (dataReference.isEmpty()) { - if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) { - if ((buffer = loader->mainResourceData())) - dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); - } + RefPtr<SharedBuffer> buffer; + if (WebFrame* frame = WebProcess::singleton().webFrame(frameID)) { + if (PluginView* pluginView = pluginViewForFrame(frame->coreFrame())) + buffer = pluginView->liveResourceData(); + if (!buffer) { + if (DocumentLoader* loader = frame->coreFrame()->loader().documentLoader()) + buffer = loader->mainResourceData(); } } + // FIXME: Use SharedBufferDataReference. + IPC::DataReference dataReference; + if (buffer) + dataReference = IPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); } -static PassRefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const KURL& resourceURL) +static PassRefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const URL& resourceURL) { - DocumentLoader* loader = frame->loader()->documentLoader(); + DocumentLoader* loader = frame->loader().documentLoader(); if (!loader) return 0; @@ -2373,38 +2799,38 @@ static PassRefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const KURL& r void WebPage::getResourceDataFromFrame(uint64_t frameID, const String& resourceURLString, uint64_t callbackID) { - CoreIPC::DataReference dataReference; - KURL resourceURL(KURL(), resourceURLString); - RefPtr<SharedBuffer> buffer; - if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) { + if (WebFrame* frame = WebProcess::singleton().webFrame(frameID)) { + URL resourceURL(URL(), resourceURLString); buffer = resourceDataForFrame(frame->coreFrame(), resourceURL); if (!buffer) { // Try to get the resource data from the cache. buffer = cachedResponseDataForURL(resourceURL); } - - if (buffer) - dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); } + // FIXME: Use SharedBufferDataReference. + IPC::DataReference dataReference; + if (buffer) + dataReference = IPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); } void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID) { - CoreIPC::DataReference dataReference; - -#if PLATFORM(MAC) +#if PLATFORM(COCOA) RetainPtr<CFDataRef> data; - if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) { - if ((data = frame->webArchiveData(0, 0))) - dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get())); - } + if (WebFrame* frame = WebProcess::singleton().webFrame(frameID)) + data = frame->webArchiveData(nullptr, nullptr); #else UNUSED_PARAM(frameID); #endif + IPC::DataReference dataReference; +#if PLATFORM(COCOA) + if (data) + dataReference = IPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get())); +#endif send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); } @@ -2430,7 +2856,7 @@ void WebPage::preferencesDidChange(const WebPreferencesStore& store) void WebPage::updatePreferences(const WebPreferencesStore& store) { - Settings* settings = m_page->settings(); + Settings& settings = m_page->settings(); m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey()); m_asynchronousPluginInitializationEnabled = store.getBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledKey()); @@ -2439,7 +2865,7 @@ void WebPage::updatePreferences(const WebPreferencesStore& store) m_scrollingPerformanceLoggingEnabled = store.getBoolValueForKey(WebPreferencesKey::scrollingPerformanceLoggingEnabledKey()); -#if PLATFORM(MAC) +#if PLATFORM(COCOA) m_pdfPluginEnabled = store.getBoolValueForKey(WebPreferencesKey::pdfPluginEnabledKey()); #endif @@ -2447,173 +2873,341 @@ void WebPage::updatePreferences(const WebPreferencesStore& store) // but we currently don't match the naming of WebCore exactly so we are // handrolling the boolean and integer preferences until that is fixed. -#define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key())); +#define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings.set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key())); FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS) #undef INITIALIZE_SETTINGS - settings->setScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey())); - settings->setScriptMarkupEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptMarkupEnabledKey())); - settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey())); - settings->setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey())); - settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey())); - settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey())); - settings->setJavaEnabledForLocalFiles(store.getBoolValueForKey(WebPreferencesKey::javaEnabledForLocalFilesKey())); - settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey())); - settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey())); - settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey())); - settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey())); - settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey())); - settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey())); - settings->setJavaScriptExperimentsEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptExperimentsEnabledKey())); - settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey())); - settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey())); - settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey())); - settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey())); - settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey())); + settings.setScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey())); + settings.setScriptMarkupEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptMarkupEnabledKey())); + settings.setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey())); + settings.setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey())); + settings.setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey())); + settings.setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey())); + settings.setJavaEnabledForLocalFiles(store.getBoolValueForKey(WebPreferencesKey::javaEnabledForLocalFilesKey())); + settings.setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey())); + settings.setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey())); + settings.setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey())); + settings.setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey())); + if (store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()) && !usesEphemeralSession()) + setSessionID(SessionID::legacyPrivateSessionID()); + else if (!store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()) && sessionID() == SessionID::legacyPrivateSessionID()) + setSessionID(SessionID::defaultSessionID()); + settings.setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey())); + settings.setJavaScriptRuntimeFlags(RuntimeFlags(store.getUInt32ValueForKey(WebPreferencesKey::javaScriptRuntimeFlagsKey()))); + settings.setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey())); + settings.setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey())); + settings.setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey())); + settings.setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey())); + settings.setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey())); + settings.setDOMTimersThrottlingEnabled(store.getBoolValueForKey(WebPreferencesKey::domTimersThrottlingEnabledKey())); #if ENABLE(WEB_ARCHIVE) - settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey())); -#endif - settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey())); - settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey())); - settings->setPageCacheSupportsPlugins(store.getBoolValueForKey(WebPreferencesKey::pageCacheSupportsPluginsKey())); - settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey())); - settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey())); - settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey())); - settings->setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey())); - settings->setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey())); - settings->setWebSecurityEnabled(store.getBoolValueForKey(WebPreferencesKey::webSecurityEnabledKey())); - settings->setAllowUniversalAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowUniversalAccessFromFileURLsKey())); - settings->setAllowFileAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowFileAccessFromFileURLsKey())); - - settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey())); - settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey())); - settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey())); - settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey())); - settings->setScreenFontSubstitutionEnabled(store.getBoolValueForKey(WebPreferencesKey::screenFontSubstitutionEnabledKey()) -#if PLATFORM(MAC) - || WebProcess::shared().shouldForceScreenFontSubstitution() -#endif - ); - settings->setLayoutFallbackWidth(store.getUInt32ValueForKey(WebPreferencesKey::layoutFallbackWidthKey())); - settings->setDeviceWidth(store.getUInt32ValueForKey(WebPreferencesKey::deviceWidthKey())); - settings->setDeviceHeight(store.getUInt32ValueForKey(WebPreferencesKey::deviceHeightKey())); - settings->setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey()))); - settings->setShowsToolTipOverTruncatedText(store.getBoolValueForKey(WebPreferencesKey::showsToolTipOverTruncatedTextKey())); - - settings->setAcceleratedCompositingForOverflowScrollEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingForOverflowScrollEnabledKey())); - settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing()); - settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing()); - settings->setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey()) && LayerTreeHost::supportsAcceleratedCompositing()); - settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey())); - settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey())); - settings->setShowTiledScrollingIndicator(store.getBoolValueForKey(WebPreferencesKey::tiledScrollingIndicatorVisibleKey())); - settings->setAggressiveTileRetentionEnabled(store.getBoolValueForKey(WebPreferencesKey::aggressiveTileRetentionEnabledKey())); - settings->setCSSCustomFilterEnabled(store.getBoolValueForKey(WebPreferencesKey::cssCustomFilterEnabledKey())); - RuntimeEnabledFeatures::setCSSRegionsEnabled(store.getBoolValueForKey(WebPreferencesKey::cssRegionsEnabledKey())); - RuntimeEnabledFeatures::setCSSCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::cssCompositingEnabledKey())); - settings->setCSSGridLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::cssGridLayoutEnabledKey())); - settings->setRegionBasedColumnsEnabled(store.getBoolValueForKey(WebPreferencesKey::regionBasedColumnsEnabledKey())); - settings->setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey())); - settings->setAccelerated2dCanvasEnabled(store.getBoolValueForKey(WebPreferencesKey::accelerated2dCanvasEnabledKey())); - settings->setMediaPlaybackRequiresUserGesture(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackRequiresUserGestureKey())); - settings->setMediaPlaybackAllowsInline(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackAllowsInlineKey())); - settings->setMockScrollbarsEnabled(store.getBoolValueForKey(WebPreferencesKey::mockScrollbarsEnabledKey())); - settings->setHyperlinkAuditingEnabled(store.getBoolValueForKey(WebPreferencesKey::hyperlinkAuditingEnabledKey())); - settings->setRequestAnimationFrameEnabled(store.getBoolValueForKey(WebPreferencesKey::requestAnimationFrameEnabledKey())); + settings.setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey())); +#endif + settings.setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey())); + settings.setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey())); + settings.setPageCacheSupportsPlugins(store.getBoolValueForKey(WebPreferencesKey::pageCacheSupportsPluginsKey())); + settings.setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey())); + settings.setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey())); + settings.setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey())); + settings.setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey())); + settings.setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey())); + settings.setWebSecurityEnabled(store.getBoolValueForKey(WebPreferencesKey::webSecurityEnabledKey())); + settings.setAllowUniversalAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowUniversalAccessFromFileURLsKey())); + settings.setAllowFileAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowFileAccessFromFileURLsKey())); + + settings.setMinimumFontSize(store.getDoubleValueForKey(WebPreferencesKey::minimumFontSizeKey())); + settings.setMinimumLogicalFontSize(store.getDoubleValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey())); + settings.setDefaultFontSize(store.getDoubleValueForKey(WebPreferencesKey::defaultFontSizeKey())); + settings.setDefaultFixedFontSize(store.getDoubleValueForKey(WebPreferencesKey::defaultFixedFontSizeKey())); + settings.setLayoutFallbackWidth(store.getUInt32ValueForKey(WebPreferencesKey::layoutFallbackWidthKey())); + settings.setDeviceWidth(store.getUInt32ValueForKey(WebPreferencesKey::deviceWidthKey())); + settings.setDeviceHeight(store.getUInt32ValueForKey(WebPreferencesKey::deviceHeightKey())); + settings.setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey()))); + settings.setShowsToolTipOverTruncatedText(store.getBoolValueForKey(WebPreferencesKey::showsToolTipOverTruncatedTextKey())); + + settings.setAcceleratedCompositingForOverflowScrollEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingForOverflowScrollEnabledKey())); + settings.setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey())); + settings.setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey())); + settings.setDisplayListDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::displayListDrawingEnabledKey())); + settings.setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey())); + settings.setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey())); + settings.setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey())); + settings.setShowTiledScrollingIndicator(store.getBoolValueForKey(WebPreferencesKey::tiledScrollingIndicatorVisibleKey())); + settings.setVisibleDebugOverlayRegions(store.getUInt32ValueForKey(WebPreferencesKey::visibleDebugOverlayRegionsKey())); + settings.setUseGiantTiles(store.getBoolValueForKey(WebPreferencesKey::useGiantTilesKey())); + + settings.setAggressiveTileRetentionEnabled(store.getBoolValueForKey(WebPreferencesKey::aggressiveTileRetentionEnabledKey())); + settings.setTemporaryTileCohortRetentionEnabled(store.getBoolValueForKey(WebPreferencesKey::temporaryTileCohortRetentionEnabledKey())); +#if ENABLE(CSS_ANIMATIONS_LEVEL_2) + RuntimeEnabledFeatures::sharedFeatures().setAnimationTriggersEnabled(store.getBoolValueForKey(WebPreferencesKey::cssAnimationTriggersEnabledKey())); +#endif +#if ENABLE(WEB_ANIMATIONS) + RuntimeEnabledFeatures::sharedFeatures().setWebAnimationsEnabled(store.getBoolValueForKey(WebPreferencesKey::webAnimationsEnabledKey())); +#endif + RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled(store.getBoolValueForKey(WebPreferencesKey::cssRegionsEnabledKey())); + RuntimeEnabledFeatures::sharedFeatures().setCSSCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::cssCompositingEnabledKey())); + settings.setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey())); + settings.setForceSoftwareWebGLRendering(store.getBoolValueForKey(WebPreferencesKey::forceSoftwareWebGLRenderingKey())); + settings.setAccelerated2dCanvasEnabled(store.getBoolValueForKey(WebPreferencesKey::accelerated2dCanvasEnabledKey())); + settings.setRequiresUserGestureForMediaPlayback(store.getBoolValueForKey(WebPreferencesKey::requiresUserGestureForMediaPlaybackKey())); + settings.setAudioPlaybackRequiresUserGesture(store.getBoolValueForKey(WebPreferencesKey::requiresUserGestureForAudioPlaybackKey())); + settings.setAllowsInlineMediaPlayback(store.getBoolValueForKey(WebPreferencesKey::allowsInlineMediaPlaybackKey())); + settings.setInlineMediaPlaybackRequiresPlaysInlineAttribute(store.getBoolValueForKey(WebPreferencesKey::inlineMediaPlaybackRequiresPlaysInlineAttributeKey())); + settings.setInvisibleAutoplayNotPermitted(store.getBoolValueForKey(WebPreferencesKey::invisibleAutoplayNotPermittedKey())); + settings.setMediaDataLoadsAutomatically(store.getBoolValueForKey(WebPreferencesKey::mediaDataLoadsAutomaticallyKey())); + settings.setAllowsPictureInPictureMediaPlayback(store.getBoolValueForKey(WebPreferencesKey::allowsPictureInPictureMediaPlaybackKey())); + settings.setMediaControlsScaleWithPageZoom(store.getBoolValueForKey(WebPreferencesKey::mediaControlsScaleWithPageZoomKey())); + settings.setMockScrollbarsEnabled(store.getBoolValueForKey(WebPreferencesKey::mockScrollbarsEnabledKey())); + settings.setHyperlinkAuditingEnabled(store.getBoolValueForKey(WebPreferencesKey::hyperlinkAuditingEnabledKey())); + settings.setRequestAnimationFrameEnabled(store.getBoolValueForKey(WebPreferencesKey::requestAnimationFrameEnabledKey())); #if ENABLE(SMOOTH_SCROLLING) - settings->setScrollAnimatorEnabled(store.getBoolValueForKey(WebPreferencesKey::scrollAnimatorEnabledKey())); + settings.setScrollAnimatorEnabled(store.getBoolValueForKey(WebPreferencesKey::scrollAnimatorEnabledKey())); #endif - settings->setInteractiveFormValidationEnabled(store.getBoolValueForKey(WebPreferencesKey::interactiveFormValidationEnabledKey())); - settings->setSpatialNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::spatialNavigationEnabledKey())); + settings.setForceUpdateScrollbarsOnMainThreadForPerformanceTesting(store.getBoolValueForKey(WebPreferencesKey::forceUpdateScrollbarsOnMainThreadForPerformanceTestingKey())); + settings.setInteractiveFormValidationEnabled(store.getBoolValueForKey(WebPreferencesKey::interactiveFormValidationEnabledKey())); + settings.setSpatialNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::spatialNavigationEnabledKey())); -#if ENABLE(SQL_DATABASE) - DatabaseManager::manager().setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey())); -#endif + settings.setHttpEquivEnabled(store.getBoolValueForKey(WebPreferencesKey::httpEquivEnabledKey())); + + DatabaseManager::singleton().setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey())); #if ENABLE(FULLSCREEN_API) - settings->setFullScreenEnabled(store.getBoolValueForKey(WebPreferencesKey::fullScreenEnabledKey())); + settings.setFullScreenEnabled(store.getBoolValueForKey(WebPreferencesKey::fullScreenEnabledKey())); #endif #if USE(AVFOUNDATION) - settings->setAVFoundationEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationEnabledKey())); + settings.setAVFoundationEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationEnabledKey())); + settings.setAVFoundationNSURLSessionEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationNSURLSessionEnabledKey())); #endif -#if PLATFORM(MAC) - settings->setQTKitEnabled(store.getBoolValueForKey(WebPreferencesKey::isQTKitEnabledKey())); +#if PLATFORM(COCOA) + settings.setQTKitEnabled(store.getBoolValueForKey(WebPreferencesKey::isQTKitEnabledKey())); +#endif + +#if PLATFORM(IOS) && HAVE(AVKIT) + settings.setAVKitEnabled(true); +#endif + +#if ENABLE(IOS_TEXT_AUTOSIZING) + settings.setMinimumZoomFontSize(store.getDoubleValueForKey(WebPreferencesKey::minimumZoomFontSizeKey())); #endif #if ENABLE(WEB_AUDIO) - settings->setWebAudioEnabled(store.getBoolValueForKey(WebPreferencesKey::webAudioEnabledKey())); + settings.setWebAudioEnabled(store.getBoolValueForKey(WebPreferencesKey::webAudioEnabledKey())); +#endif + +#if ENABLE(MEDIA_STREAM) + settings.setMediaStreamEnabled(store.getBoolValueForKey(WebPreferencesKey::mediaStreamEnabledKey())); #endif - settings->setApplicationChromeMode(store.getBoolValueForKey(WebPreferencesKey::applicationChromeModeKey())); - settings->setSuppressesIncrementalRendering(store.getBoolValueForKey(WebPreferencesKey::suppressesIncrementalRenderingKey())); - settings->setIncrementalRenderingSuppressionTimeoutInSeconds(store.getDoubleValueForKey(WebPreferencesKey::incrementalRenderingSuppressionTimeoutKey())); - settings->setBackspaceKeyNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::backspaceKeyNavigationEnabledKey())); - settings->setWantsBalancedSetDefersLoadingBehavior(store.getBoolValueForKey(WebPreferencesKey::wantsBalancedSetDefersLoadingBehaviorKey())); - settings->setCaretBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::caretBrowsingEnabledKey())); +#if ENABLE(SERVICE_CONTROLS) + settings.setImageControlsEnabled(store.getBoolValueForKey(WebPreferencesKey::imageControlsEnabledKey())); +#endif + +#if ENABLE(WIRELESS_PLAYBACK_TARGET) + settings.setAllowsAirPlayForMediaPlayback(store.getBoolValueForKey(WebPreferencesKey::allowsAirPlayForMediaPlaybackKey())); +#endif + +#if ENABLE(RESOURCE_USAGE) + settings.setResourceUsageOverlayVisible(store.getBoolValueForKey(WebPreferencesKey::resourceUsageOverlayVisibleKey())); +#endif + + settings.setSuppressesIncrementalRendering(store.getBoolValueForKey(WebPreferencesKey::suppressesIncrementalRenderingKey())); + settings.setIncrementalRenderingSuppressionTimeoutInSeconds(store.getDoubleValueForKey(WebPreferencesKey::incrementalRenderingSuppressionTimeoutKey())); + settings.setBackspaceKeyNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::backspaceKeyNavigationEnabledKey())); + settings.setWantsBalancedSetDefersLoadingBehavior(store.getBoolValueForKey(WebPreferencesKey::wantsBalancedSetDefersLoadingBehaviorKey())); + settings.setCaretBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::caretBrowsingEnabledKey())); #if ENABLE(VIDEO_TRACK) - settings->setShouldDisplaySubtitles(store.getBoolValueForKey(WebPreferencesKey::shouldDisplaySubtitlesKey())); - settings->setShouldDisplayCaptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayCaptionsKey())); - settings->setShouldDisplayTextDescriptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayTextDescriptionsKey())); + settings.setShouldDisplaySubtitles(store.getBoolValueForKey(WebPreferencesKey::shouldDisplaySubtitlesKey())); + settings.setShouldDisplayCaptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayCaptionsKey())); + settings.setShouldDisplayTextDescriptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayTextDescriptionsKey())); #endif #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) - settings->setNotificationsEnabled(store.getBoolValueForKey(WebPreferencesKey::notificationsEnabledKey())); + settings.setNotificationsEnabled(store.getBoolValueForKey(WebPreferencesKey::notificationsEnabledKey())); #endif - settings->setShouldRespectImageOrientation(store.getBoolValueForKey(WebPreferencesKey::shouldRespectImageOrientationKey())); - settings->setStorageBlockingPolicy(static_cast<SecurityOrigin::StorageBlockingPolicy>(store.getUInt32ValueForKey(WebPreferencesKey::storageBlockingPolicyKey()))); - settings->setCookieEnabled(store.getBoolValueForKey(WebPreferencesKey::cookieEnabledKey())); + settings.setShouldRespectImageOrientation(store.getBoolValueForKey(WebPreferencesKey::shouldRespectImageOrientationKey())); + settings.setStorageBlockingPolicy(static_cast<SecurityOrigin::StorageBlockingPolicy>(store.getUInt32ValueForKey(WebPreferencesKey::storageBlockingPolicyKey()))); + settings.setCookieEnabled(store.getBoolValueForKey(WebPreferencesKey::cookieEnabledKey())); - settings->setDiagnosticLoggingEnabled(store.getBoolValueForKey(WebPreferencesKey::diagnosticLoggingEnabledKey())); + settings.setDiagnosticLoggingEnabled(store.getBoolValueForKey(WebPreferencesKey::diagnosticLoggingEnabledKey())); - settings->setScrollingPerformanceLoggingEnabled(m_scrollingPerformanceLoggingEnabled); + settings.setScrollingPerformanceLoggingEnabled(m_scrollingPerformanceLoggingEnabled); - settings->setPlugInSnapshottingEnabled(store.getBoolValueForKey(WebPreferencesKey::plugInSnapshottingEnabledKey())); - settings->setSnapshotAllPlugIns(store.getBoolValueForKey(WebPreferencesKey::snapshotAllPlugInsKey())); - settings->setAutostartOriginPlugInSnapshottingEnabled(store.getBoolValueForKey(WebPreferencesKey::autostartOriginPlugInSnapshottingEnabledKey())); - settings->setPrimaryPlugInSnapshotDetectionEnabled(store.getBoolValueForKey(WebPreferencesKey::primaryPlugInSnapshotDetectionEnabledKey())); - settings->setUsesEncodingDetector(store.getBoolValueForKey(WebPreferencesKey::usesEncodingDetectorKey())); + settings.setPlugInSnapshottingEnabled(store.getBoolValueForKey(WebPreferencesKey::plugInSnapshottingEnabledKey())); + settings.setSnapshotAllPlugIns(store.getBoolValueForKey(WebPreferencesKey::snapshotAllPlugInsKey())); + settings.setAutostartOriginPlugInSnapshottingEnabled(store.getBoolValueForKey(WebPreferencesKey::autostartOriginPlugInSnapshottingEnabledKey())); + settings.setPrimaryPlugInSnapshotDetectionEnabled(store.getBoolValueForKey(WebPreferencesKey::primaryPlugInSnapshotDetectionEnabledKey())); + settings.setUsesEncodingDetector(store.getBoolValueForKey(WebPreferencesKey::usesEncodingDetectorKey())); #if ENABLE(TEXT_AUTOSIZING) - settings->setTextAutosizingEnabled(store.getBoolValueForKey(WebPreferencesKey::textAutosizingEnabledKey())); + settings.setTextAutosizingEnabled(store.getBoolValueForKey(WebPreferencesKey::textAutosizingEnabledKey())); #endif - settings->setLogsPageMessagesToSystemConsoleEnabled(store.getBoolValueForKey(WebPreferencesKey::logsPageMessagesToSystemConsoleEnabledKey())); - settings->setAsynchronousSpellCheckingEnabled(store.getBoolValueForKey(WebPreferencesKey::asynchronousSpellCheckingEnabledKey())); + settings.setLogsPageMessagesToSystemConsoleEnabled(store.getBoolValueForKey(WebPreferencesKey::logsPageMessagesToSystemConsoleEnabledKey())); + settings.setAsynchronousSpellCheckingEnabled(store.getBoolValueForKey(WebPreferencesKey::asynchronousSpellCheckingEnabledKey())); - settings->setSmartInsertDeleteEnabled(store.getBoolValueForKey(WebPreferencesKey::smartInsertDeleteEnabledKey())); - settings->setSelectTrailingWhitespaceEnabled(store.getBoolValueForKey(WebPreferencesKey::selectTrailingWhitespaceEnabledKey())); - settings->setShowsURLsInToolTips(store.getBoolValueForKey(WebPreferencesKey::showsURLsInToolTipsEnabledKey())); + settings.setSmartInsertDeleteEnabled(store.getBoolValueForKey(WebPreferencesKey::smartInsertDeleteEnabledKey())); + settings.setSelectTrailingWhitespaceEnabled(store.getBoolValueForKey(WebPreferencesKey::selectTrailingWhitespaceEnabledKey())); + settings.setShowsURLsInToolTips(store.getBoolValueForKey(WebPreferencesKey::showsURLsInToolTipsEnabledKey())); #if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING) - settings->setHiddenPageDOMTimerThrottlingEnabled(store.getBoolValueForKey(WebPreferencesKey::hiddenPageDOMTimerThrottlingEnabledKey())); + settings.setHiddenPageDOMTimerThrottlingEnabled(store.getBoolValueForKey(WebPreferencesKey::hiddenPageDOMTimerThrottlingEnabledKey())); +#endif + + settings.setHiddenPageCSSAnimationSuspensionEnabled(store.getBoolValueForKey(WebPreferencesKey::hiddenPageCSSAnimationSuspensionEnabledKey())); + settings.setLowPowerVideoAudioBufferSizeEnabled(store.getBoolValueForKey(WebPreferencesKey::lowPowerVideoAudioBufferSizeEnabledKey())); + settings.setSimpleLineLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::simpleLineLayoutEnabledKey())); + settings.setSimpleLineLayoutDebugBordersEnabled(store.getBoolValueForKey(WebPreferencesKey::simpleLineLayoutDebugBordersEnabledKey())); + + settings.setNewBlockInsideInlineModelEnabled(store.getBoolValueForKey(WebPreferencesKey::newBlockInsideInlineModelEnabledKey())); + settings.setAntialiasedFontDilationEnabled(store.getBoolValueForKey(WebPreferencesKey::antialiasedFontDilationEnabledKey())); + + settings.setSubpixelCSSOMElementMetricsEnabled(store.getBoolValueForKey(WebPreferencesKey::subpixelCSSOMElementMetricsEnabledKey())); + + settings.setUseLegacyTextAlignPositionedElementBehavior(store.getBoolValueForKey(WebPreferencesKey::useLegacyTextAlignPositionedElementBehaviorKey())); + +#if ENABLE(MEDIA_SOURCE) + settings.setMediaSourceEnabled(store.getBoolValueForKey(WebPreferencesKey::mediaSourceEnabledKey())); +#endif + +#if ENABLE(MEDIA_STREAM) + settings.setMockCaptureDevicesEnabled(store.getBoolValueForKey(WebPreferencesKey::mockCaptureDevicesEnabledKey())); +#endif + + settings.setShouldConvertPositionStyleOnCopy(store.getBoolValueForKey(WebPreferencesKey::shouldConvertPositionStyleOnCopyKey())); + + settings.setStandalone(store.getBoolValueForKey(WebPreferencesKey::standaloneKey())); + settings.setTelephoneNumberParsingEnabled(store.getBoolValueForKey(WebPreferencesKey::telephoneNumberParsingEnabledKey())); + settings.setAllowMultiElementImplicitSubmission(store.getBoolValueForKey(WebPreferencesKey::allowMultiElementImplicitSubmissionKey())); + settings.setAlwaysUseAcceleratedOverflowScroll(store.getBoolValueForKey(WebPreferencesKey::alwaysUseAcceleratedOverflowScrollKey())); + + settings.setPasswordEchoEnabled(store.getBoolValueForKey(WebPreferencesKey::passwordEchoEnabledKey())); + settings.setPasswordEchoDurationInSeconds(store.getDoubleValueForKey(WebPreferencesKey::passwordEchoDurationKey())); + + settings.setLayoutInterval(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::duration<double>(store.getDoubleValueForKey(WebPreferencesKey::layoutIntervalKey())))); + settings.setMaxParseDuration(store.getDoubleValueForKey(WebPreferencesKey::maxParseDurationKey())); + + settings.setEnableInheritURIQueryComponent(store.getBoolValueForKey(WebPreferencesKey::enableInheritURIQueryComponentKey())); + + settings.setShouldDispatchJavaScriptWindowOnErrorEvents(true); + +#if PLATFORM(IOS) + settings.setUseImageDocumentForSubframePDF(true); +#endif + +#if ENABLE(DATA_DETECTION) + settings.setDataDetectorTypes(static_cast<DataDetectorTypes>(store.getUInt32ValueForKey(WebPreferencesKey::dataDetectorTypesKey()))); #endif -#if ENABLE(PAGE_VISIBILITY_API) - settings->setHiddenPageCSSAnimationSuspensionEnabled(store.getBoolValueForKey(WebPreferencesKey::hiddenPageCSSAnimationSuspensionEnabledKey())); +#if ENABLE(GAMEPAD) + RuntimeEnabledFeatures::sharedFeatures().setGamepadsEnabled(store.getBoolValueForKey(WebPreferencesKey::gamepadsEnabledKey())); #endif - settings->setLowPowerVideoAudioBufferSizeEnabled(store.getBoolValueForKey(WebPreferencesKey::lowPowerVideoAudioBufferSizeEnabledKey())); +#if ENABLE(SERVICE_CONTROLS) + settings.setServiceControlsEnabled(store.getBoolValueForKey(WebPreferencesKey::serviceControlsEnabledKey())); +#endif + + bool processSuppressionEnabled = store.getBoolValueForKey(WebPreferencesKey::pageVisibilityBasedProcessSuppressionEnabledKey()); + if (m_processSuppressionEnabled != processSuppressionEnabled) { + m_processSuppressionEnabled = processSuppressionEnabled; + updateUserActivity(); + } platformPreferencesDidChange(store); if (m_drawingArea) m_drawingArea->updatePreferences(store); + +#if PLATFORM(IOS) + m_ignoreViewportScalingConstraints = store.getBoolValueForKey(WebPreferencesKey::ignoreViewportScalingConstraintsKey()); + m_viewportConfiguration.setCanIgnoreScalingConstraints(m_ignoreViewportScalingConstraints); + m_viewportConfiguration.setForceAlwaysUserScalable(store.getBoolValueForKey(WebPreferencesKey::forceAlwaysUserScalableKey())); +#endif +} + +#if ENABLE(DATA_DETECTION) +void WebPage::setDataDetectionResults(NSArray *detectionResults) +{ + DataDetectionResult dataDetectionResult; + dataDetectionResult.results = detectionResults; + send(Messages::WebPageProxy::SetDataDetectionResult(dataDetectionResult)); +} +#endif + +#if PLATFORM(COCOA) +void WebPage::willCommitLayerTree(RemoteLayerTreeTransaction& layerTransaction) +{ + layerTransaction.setContentsSize(corePage()->mainFrame().view()->contentsSize()); + layerTransaction.setScrollOrigin(corePage()->mainFrame().view()->scrollOrigin()); + layerTransaction.setPageScaleFactor(corePage()->pageScaleFactor()); + layerTransaction.setRenderTreeSize(corePage()->renderTreeSize()); + layerTransaction.setPageExtendedBackgroundColor(corePage()->pageExtendedBackgroundColor()); +#if PLATFORM(IOS) + layerTransaction.setScaleWasSetByUIProcess(scaleWasSetByUIProcess()); + layerTransaction.setMinimumScaleFactor(m_viewportConfiguration.minimumScale()); + layerTransaction.setMaximumScaleFactor(m_viewportConfiguration.maximumScale()); + layerTransaction.setInitialScaleFactor(m_viewportConfiguration.initialScale()); + layerTransaction.setViewportMetaTagWidth(m_viewportConfiguration.viewportArguments().width); + layerTransaction.setViewportMetaTagWidthWasExplicit(m_viewportConfiguration.viewportArguments().widthWasExplicit); + layerTransaction.setViewportMetaTagCameFromImageDocument(m_viewportConfiguration.viewportArguments().type == ViewportArguments::ImageDocument); + layerTransaction.setAllowsUserScaling(allowsUserScaling()); +#endif +#if PLATFORM(MAC) + layerTransaction.setScrollPosition(corePage()->mainFrame().view()->scrollPosition()); +#endif +} + +void WebPage::didFlushLayerTreeAtTime(std::chrono::milliseconds timestamp) +{ +#if PLATFORM(IOS) + if (m_oldestNonStableUpdateVisibleContentRectsTimestamp != std::chrono::milliseconds::zero()) { + std::chrono::milliseconds elapsed = timestamp - m_oldestNonStableUpdateVisibleContentRectsTimestamp; + m_oldestNonStableUpdateVisibleContentRectsTimestamp = std::chrono::milliseconds::zero(); + + m_estimatedLatency = std::chrono::milliseconds(static_cast<std::chrono::milliseconds::rep>(m_estimatedLatency.count() * 0.80 + elapsed.count() * 0.20)); + } +#else + UNUSED_PARAM(timestamp); +#endif } +#endif -#if ENABLE(INSPECTOR) -WebInspector* WebPage::inspector() +WebInspector* WebPage::inspector(LazyCreationPolicy behavior) { if (m_isClosed) - return 0; - if (!m_inspector) - m_inspector = WebInspector::create(this, m_inspectorClient); + return nullptr; + if (!m_inspector && behavior == LazyCreationPolicy::CreateIfNeeded) + m_inspector = WebInspector::create(this); return m_inspector.get(); } + +WebInspectorUI* WebPage::inspectorUI() +{ + if (m_isClosed) + return nullptr; + if (!m_inspectorUI) + m_inspectorUI = WebInspectorUI::create(*this); + return m_inspectorUI.get(); +} + +#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)) +WebVideoFullscreenManager* WebPage::videoFullscreenManager() +{ + if (!m_videoFullscreenManager) + m_videoFullscreenManager = WebVideoFullscreenManager::create(this); + return m_videoFullscreenManager.get(); +} +#endif + +#if PLATFORM(IOS) +void WebPage::setAllowsMediaDocumentInlinePlayback(bool allows) +{ + m_page->setAllowsMediaDocumentInlinePlayback(allows); +} #endif #if ENABLE(FULLSCREEN_API) @@ -2634,12 +3228,12 @@ NotificationPermissionRequestManager* WebPage::notificationPermissionRequestMana return m_notificationPermissionRequestManager.get(); } -#if !PLATFORM(GTK) && !PLATFORM(MAC) +#if !PLATFORM(GTK) && !PLATFORM(COCOA) bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt) { Node* node = evt->target()->toNode(); ASSERT(node); - Frame* frame = node->document()->frame(); + Frame* frame = node->document().frame(); ASSERT(frame); const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); @@ -2676,7 +3270,7 @@ bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt) void WebPage::performDragControllerAction(uint64_t action, WebCore::DragData dragData) { if (!m_page) { - send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession())); + send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone, false, 0)); #if PLATFORM(QT) QMimeData* data = const_cast<QMimeData*>(dragData.platformData()); delete data; @@ -2688,20 +3282,22 @@ void WebPage::performDragControllerAction(uint64_t action, WebCore::DragData dra } switch (action) { - case DragControllerActionEntered: - send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData))); + case DragControllerActionEntered: { + DragOperation resolvedDragOperation = m_page->dragController().dragEntered(dragData); + send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted())); break; - - case DragControllerActionUpdated: - send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData))); + } + case DragControllerActionUpdated: { + DragOperation resolvedDragOperation = m_page->dragController().dragEntered(dragData); + send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted())); break; - + } case DragControllerActionExited: - m_page->dragController()->dragExited(&dragData); + m_page->dragController().dragExited(dragData); break; - case DragControllerActionPerformDrag: { - m_page->dragController()->performDrag(&dragData); + case DragControllerActionPerformDragOperation: { + m_page->dragController().performDragOperation(dragData); break; } @@ -2722,25 +3318,28 @@ void WebPage::performDragControllerAction(uint64_t action, WebCore::DragData dra void 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) { if (!m_page) { - send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession())); + send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone, false, 0)); return; } DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags)); switch (action) { - case DragControllerActionEntered: - send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData))); + case DragControllerActionEntered: { + DragOperation resolvedDragOperation = m_page->dragController().dragEntered(dragData); + send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted())); break; - case DragControllerActionUpdated: - send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData))); + } + case DragControllerActionUpdated: { + DragOperation resolvedDragOperation = m_page->dragController().dragUpdated(dragData); + send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted())); break; - + } case DragControllerActionExited: - m_page->dragController()->dragExited(&dragData); + m_page->dragController().dragExited(dragData); break; - case DragControllerActionPerformDrag: { + case DragControllerActionPerformDragOperation: { ASSERT(!m_pendingDropSandboxExtension); m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle); @@ -2749,7 +3348,7 @@ void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint cli m_pendingDropExtensionsForFileUpload.append(extension); } - m_page->dragController()->performDrag(&dragData); + m_page->dragController().performDragOperation(dragData); // If we started loading a local file, the sandbox extension tracker would have adopted this // pending drop sandbox extension. If not, we'll play it safe and clear it. @@ -2767,16 +3366,16 @@ void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint cli void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation) { - IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController()->dragOffset().x(), clientPosition.y() + m_page->dragController()->dragOffset().y()); - IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController()->dragOffset().x(), globalPosition.y() + m_page->dragController()->dragOffset().y()); + IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController().dragOffset().x(), clientPosition.y() + m_page->dragController().dragOffset().y()); + IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController().dragOffset().x(), globalPosition.y() + m_page->dragController().dragOffset().y()); - m_page->dragController()->dragEnded(); - FrameView* view = m_page->mainFrame()->view(); + m_page->dragController().dragEnded(); + FrameView* view = m_page->mainFrame().view(); if (!view) return; // FIXME: These are fake modifier keys here, but they should be real ones instead. - PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime()); - m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation); + PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime(), 0); + m_page->mainFrame().eventHandler().dragSourceEndedAt(event, (DragOperation)operation); } void WebPage::willPerformLoadDragDestinationAction() @@ -2844,7 +3443,7 @@ void WebPage::setActiveColorChooser(WebColorChooser* colorChooser) m_activeColorChooser = colorChooser; } -void WebPage::didEndColorChooser() +void WebPage::didEndColorPicker() { m_activeColorChooser->didEndChooser(); } @@ -2898,7 +3497,7 @@ void WebPage::countStringMatches(const String& string, uint32_t options, uint32_ void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex) { changeSelectedIndex(newIndex); - m_activePopupMenu = 0; + m_activePopupMenu = nullptr; } void WebPage::changeSelectedIndex(int32_t index) @@ -2909,24 +3508,47 @@ void WebPage::changeSelectedIndex(int32_t index) m_activePopupMenu->didChangeSelectedIndex(index); } +#if PLATFORM(IOS) +void WebPage::didChooseFilesForOpenPanelWithDisplayStringAndIcon(const Vector<String>& files, const String& displayString, const IPC::DataReference& iconData) +{ + if (!m_activeOpenPanelResultListener) + return; + + RefPtr<Icon> icon; + if (!iconData.isEmpty()) { + RetainPtr<CFDataRef> dataRef = adoptCF(CFDataCreate(nullptr, iconData.data(), iconData.size())); + RetainPtr<CGDataProviderRef> imageProviderRef = adoptCF(CGDataProviderCreateWithCFData(dataRef.get())); + RetainPtr<CGImageRef> imageRef = adoptCF(CGImageCreateWithJPEGDataProvider(imageProviderRef.get(), nullptr, true, kCGRenderingIntentDefault)); + icon = Icon::createIconForImage(imageRef.get()); + } + + m_activeOpenPanelResultListener->didChooseFilesWithDisplayStringAndIcon(files, displayString, icon.get()); + m_activeOpenPanelResultListener = nullptr; +} +#endif + void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files) { if (!m_activeOpenPanelResultListener) return; m_activeOpenPanelResultListener->didChooseFiles(files); - m_activeOpenPanelResultListener = 0; + m_activeOpenPanelResultListener = nullptr; } void WebPage::didCancelForOpenPanel() { - m_activeOpenPanelResultListener = 0; + m_activeOpenPanelResultListener = nullptr; } -#if ENABLE(WEB_PROCESS_SANDBOX) +#if ENABLE(SANDBOX_EXTENSIONS) void WebPage::extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle& handle) { - SandboxExtension::create(handle)->consumePermanently(); + bool result = SandboxExtension::consumePermanently(handle); + if (!result) { + // We have reports of cases where this fails for some unknown reason, <rdar://problem/10156710>. + WTFLogAlways("WebPage::extendSandboxForFileFromOpenPanel(): Could not consume a sandbox extension"); + } } #endif @@ -2942,47 +3564,61 @@ void WebPage::didReceiveNotificationPermissionDecision(uint64_t notificationID, notificationPermissionRequestManager()->didReceiveNotificationPermissionDecision(notificationID, allowed); } +#if ENABLE(MEDIA_STREAM) +void WebPage::didReceiveUserMediaPermissionDecision(uint64_t userMediaID, bool allowed, const String& audioDeviceUID, const String& videoDeviceUID) +{ + m_userMediaPermissionRequestManager.didReceiveUserMediaPermissionDecision(userMediaID, allowed, audioDeviceUID, videoDeviceUID); +} + +void WebPage::didCompleteUserMediaPermissionCheck(uint64_t userMediaID, bool allowed) +{ + m_userMediaPermissionRequestManager.didCompleteUserMediaPermissionCheck(userMediaID, allowed); +} +#endif + +#if !PLATFORM(IOS) void WebPage::advanceToNextMisspelling(bool startBeforeSelection) { - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - frame->editor().advanceToNextMisspelling(startBeforeSelection); + Frame& frame = m_page->focusController().focusedOrMainFrame(); + frame.editor().advanceToNextMisspelling(startBeforeSelection); } +#endif void WebPage::changeSpellingToWord(const String& word) { - replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word); + replaceSelectionWithText(&m_page->focusController().focusedOrMainFrame(), word); } void WebPage::unmarkAllMisspellings() { - for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) { if (Document* document = frame->document()) - document->markers()->removeMarkers(DocumentMarker::Spelling); + document->markers().removeMarkers(DocumentMarker::Spelling); } } void WebPage::unmarkAllBadGrammar() { - for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) { if (Document* document = frame->document()) - document->markers()->removeMarkers(DocumentMarker::Grammar); + document->markers().removeMarkers(DocumentMarker::Grammar); } } #if USE(APPKIT) void WebPage::uppercaseWord() { - m_page->focusController()->focusedOrMainFrame()->editor().uppercaseWord(); + m_page->focusController().focusedOrMainFrame().editor().uppercaseWord(); } void WebPage::lowercaseWord() { - m_page->focusController()->focusedOrMainFrame()->editor().lowercaseWord(); + m_page->focusController().focusedOrMainFrame().editor().lowercaseWord(); } void WebPage::capitalizeWord() { - m_page->focusController()->focusedOrMainFrame()->editor().capitalizeWord(); + m_page->focusController().focusedOrMainFrame().editor().capitalizeWord(); } #endif @@ -3011,7 +3647,7 @@ void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& i return; m_contextMenu->itemSelected(item); - m_contextMenu = 0; + m_contextMenu = nullptr; } #endif @@ -3022,17 +3658,47 @@ void WebPage::replaceSelectionWithText(Frame* frame, const String& text) return frame->editor().replaceSelectionWithText(text, selectReplacement, smartReplace); } +#if !PLATFORM(IOS) void WebPage::clearSelection() { - m_page->focusController()->focusedOrMainFrame()->selection()->clear(); + m_page->focusController().focusedOrMainFrame().selection().clear(); +} +#endif + +void WebPage::restoreSelectionInFocusedEditableElement() +{ + Frame& frame = m_page->focusController().focusedOrMainFrame(); + if (!frame.selection().isNone()) + return; + + if (auto document = frame.document()) { + if (auto element = document->focusedElement()) + element->updateFocusAppearance(SelectionRestorationMode::Restore, SelectionRevealMode::DoNotReveal); + } +} + +bool WebPage::mainFrameHasCustomContentProvider() const +{ + if (Frame* frame = mainFrame()) { + WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(frame->loader().client()); + ASSERT(webFrameLoaderClient); + return webFrameLoaderClient->frameHasCustomContentProvider(); + } + + return false; +} + +void WebPage::addMIMETypeWithCustomContentProvider(const String& mimeType) +{ + m_mimeTypesWithCustomContentProviders.add(mimeType); } -void WebPage::didChangeScrollOffsetForMainFrame() +void WebPage::updateMainFrameScrollOffsetPinning() { - Frame* frame = m_page->mainFrame(); - IntPoint scrollPosition = frame->view()->scrollPosition(); - IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition(); - IntPoint minimumScrollPosition = frame->view()->minimumScrollPosition(); + Frame& frame = m_page->mainFrame(); + ScrollPosition scrollPosition = frame.view()->scrollPosition(); + ScrollPosition maximumScrollPosition = frame.view()->maximumScrollPosition(); + ScrollPosition minimumScrollPosition = frame.view()->minimumScrollPosition(); bool isPinnedToLeftSide = (scrollPosition.x() <= minimumScrollPosition.x()); bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x()); @@ -3057,16 +3723,16 @@ void WebPage::mainFrameDidLayout() m_cachedPageCount = pageCount; } -#if USE(TILED_BACKING_STORE) && USE(ACCELERATED_COMPOSITING) - if (m_drawingArea && m_drawingArea->layerTreeHost()) { - double red, green, blue, alpha; - m_mainFrame->getDocumentBackgroundColor(&red, &green, &blue, &alpha); - RGBA32 rgba = makeRGBA32FromFloats(red, green, blue, alpha); - if (m_backgroundColor.rgb() != rgba) { - m_backgroundColor.setRGB(rgba); - m_drawingArea->layerTreeHost()->setBackgroundColor(m_backgroundColor); - } +#if PLATFORM(MAC) + m_viewGestureGeometryCollector.mainFrameDidLayout(); +#endif +#if PLATFORM(IOS) + if (FrameView* frameView = mainFrameView()) { + IntSize newContentSize = frameView->contentsSize(); + if (m_viewportConfiguration.setContentsSize(newContentSize)) + viewportConfigurationChanged(); } + m_findController.redraw(); #endif } @@ -3075,7 +3741,9 @@ void WebPage::addPluginView(PluginView* pluginView) ASSERT(!m_pluginViews.contains(pluginView)); m_pluginViews.add(pluginView); + m_hasSeenPlugin = true; #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) + LOG(Plugins, "Primary Plug-In Detection: triggering detection from addPluginView(%p)", pluginView); m_determinePrimarySnapshottedPlugInTimer.startOneShot(0); #endif } @@ -3085,28 +3753,20 @@ void WebPage::removePluginView(PluginView* pluginView) ASSERT(m_pluginViews.contains(pluginView)); m_pluginViews.remove(pluginView); +#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) + LOG(Plugins, "Primary Plug-In Detection: removePluginView(%p)", pluginView); +#endif } void WebPage::sendSetWindowFrame(const FloatRect& windowFrame) { -#if PLATFORM(MAC) +#if PLATFORM(COCOA) m_hasCachedWindowFrame = false; #endif send(Messages::WebPageProxy::SetWindowFrame(windowFrame)); } -#if PLATFORM(MAC) -void WebPage::setWindowIsVisible(bool windowIsVisible) -{ - m_windowIsVisible = windowIsVisible; - - corePage()->focusController()->setContainingWindowIsVisible(windowIsVisible); - - // Tell all our plug-in views that the window visibility changed. - for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) - (*it)->setWindowIsVisible(windowIsVisible); -} - +#if PLATFORM(COCOA) void WebPage::windowAndViewFramesChanged(const FloatRect& windowFrameInScreenCoordinates, const FloatRect& windowFrameInUnflippedScreenCoordinates, const FloatRect& viewFrameInWindowCoordinates, const FloatPoint& accessibilityViewCoordinates) { m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates; @@ -3115,19 +3775,13 @@ void WebPage::windowAndViewFramesChanged(const FloatRect& windowFrameInScreenCoo m_accessibilityPosition = accessibilityViewCoordinates; // Tell all our plug-in views that the window and view frames have changed. - for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) - (*it)->windowAndViewFramesChanged(enclosingIntRect(windowFrameInScreenCoordinates), enclosingIntRect(viewFrameInWindowCoordinates)); + for (auto* pluginView : m_pluginViews) + pluginView->windowAndViewFramesChanged(enclosingIntRect(windowFrameInScreenCoordinates), enclosingIntRect(viewFrameInWindowCoordinates)); m_hasCachedWindowFrame = !m_windowFrameInUnflippedScreenCoordinates.isEmpty(); } #endif -void WebPage::viewExposedRectChanged(const FloatRect& exposedRect, bool clipsToExposedRect) -{ - m_drawingArea->setExposedRect(exposedRect); - m_drawingArea->setClipsToExposedRect(clipsToExposedRect); -} - void WebPage::setMainFrameIsScrollable(bool isScrollable) { m_mainFrameIsScrollable = isScrollable; @@ -3141,41 +3795,38 @@ void WebPage::setMainFrameIsScrollable(bool isScrollable) bool WebPage::windowIsFocused() const { - return m_page->focusController()->isActive(); + return m_page->focusController().isActive(); } bool WebPage::windowAndWebPageAreFocused() const { -#if PLATFORM(MAC) - if (!m_windowIsVisible) + if (!isVisible()) return false; -#endif - return m_page->focusController()->isFocused() && m_page->focusController()->isActive(); + + return m_page->focusController().isFocused() && m_page->focusController().isActive(); } -void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder) +void WebPage::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder) { - if (decoder.messageReceiverName() == Messages::DrawingArea::messageReceiverName()) { - if (m_drawingArea) - m_drawingArea->didReceiveDrawingAreaMessage(connection, decoder); - return; - } - -#if USE(TILED_BACKING_STORE) && USE(ACCELERATED_COMPOSITING) +#if USE(COORDINATED_GRAPHICS_MULTIPROCESS) if (decoder.messageReceiverName() == Messages::CoordinatedLayerTreeHost::messageReceiverName()) { if (m_drawingArea) m_drawingArea->didReceiveCoordinatedLayerTreeHostMessage(connection, decoder); return; } #endif - -#if ENABLE(INSPECTOR) + if (decoder.messageReceiverName() == Messages::WebInspector::messageReceiverName()) { if (WebInspector* inspector = this->inspector()) - inspector->didReceiveWebInspectorMessage(connection, decoder); + inspector->didReceiveMessage(connection, decoder); + return; + } + + if (decoder.messageReceiverName() == Messages::WebInspectorUI::messageReceiverName()) { + if (WebInspectorUI* inspectorUI = this->inspectorUI()) + inspectorUI->didReceiveMessage(connection, decoder); return; } -#endif #if ENABLE(FULLSCREEN_API) if (decoder.messageReceiverName() == Messages::WebFullScreenManager::messageReceiverName()) { @@ -3187,7 +3838,7 @@ void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::Messag didReceiveWebPageMessage(connection, decoder); } -void WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder) +void WebPage::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder) { didReceiveSyncWebPageMessage(connection, decoder, replyEncoder); } @@ -3199,6 +3850,13 @@ InjectedBundleBackForwardList* WebPage::backForwardList() return m_backForwardList.get(); } +#if ENABLE(ASYNC_SCROLLING) +ScrollingCoordinator* WebPage::scrollingCoordinator() const +{ + return m_page->scrollingCoordinator(); +} +#endif + WebPage::SandboxExtensionTracker::~SandboxExtensionTracker() { invalidate(); @@ -3240,15 +3898,15 @@ static bool shouldReuseCommittedSandboxExtension(WebFrame* frame) { ASSERT(frame->isMainFrame()); - FrameLoader* frameLoader = frame->coreFrame()->loader(); - FrameLoadType frameLoadType = frameLoader->loadType(); + FrameLoader& frameLoader = frame->coreFrame()->loader(); + FrameLoadType frameLoadType = frameLoader.loadType(); // If the page is being reloaded, it should reuse whatever extension is committed. - if (frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadFromOrigin) + if (frameLoadType == FrameLoadType::Reload || frameLoadType == FrameLoadType::ReloadFromOrigin) return true; - DocumentLoader* documentLoader = frameLoader->documentLoader(); - DocumentLoader* provisionalDocumentLoader = frameLoader->provisionalDocumentLoader(); + DocumentLoader* documentLoader = frameLoader.documentLoader(); + DocumentLoader* provisionalDocumentLoader = frameLoader.provisionalDocumentLoader(); if (!documentLoader || !provisionalDocumentLoader) return false; @@ -3274,7 +3932,7 @@ void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame) if (!m_provisionalSandboxExtension) return; - ASSERT(!m_provisionalSandboxExtension || frame->coreFrame()->loader()->provisionalDocumentLoader()->url().isLocalFile()); + ASSERT(!m_provisionalSandboxExtension || frame->coreFrame()->loader().provisionalDocumentLoader()->url().isLocalFile()); m_provisionalSandboxExtension->consume(); } @@ -3309,13 +3967,12 @@ void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame) // because it does not pertain to the failed load, and will be needed. } -bool WebPage::hasLocalDataForURL(const KURL& url) +bool WebPage::hasLocalDataForURL(const URL& url) { if (url.isLocalFile()) return true; - FrameLoader* frameLoader = m_page->mainFrame()->loader(); - DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0; + DocumentLoader* documentLoader = m_page->mainFrame().loader().documentLoader(); if (documentLoader && documentLoader->subresource(url)) return true; @@ -3324,7 +3981,7 @@ bool WebPage::hasLocalDataForURL(const KURL& url) void WebPage::setCustomTextEncodingName(const String& encoding) { - m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding); + m_page->mainFrame().loader().reloadWithOverrideEncoding(encoding); } void WebPage::didRemoveBackForwardItem(uint64_t itemID) @@ -3332,7 +3989,7 @@ void WebPage::didRemoveBackForwardItem(uint64_t itemID) WebBackForwardListProxy::removeItem(itemID); } -#if PLATFORM(MAC) +#if PLATFORM(COCOA) bool WebPage::isSpeaking() { @@ -3356,15 +4013,12 @@ void WebPage::stopSpeaking() RetainPtr<PDFDocument> WebPage::pdfDocumentForPrintingFrame(Frame* coreFrame) { Document* document = coreFrame->document(); - if (!document) - return 0; - - if (!document->isPluginDocument()) - return 0; + if (!is<PluginDocument>(document)) + return nullptr; - PluginView* pluginView = static_cast<PluginView*>(toPluginDocument(document)->pluginWidget()); + PluginView* pluginView = static_cast<PluginView*>(downcast<PluginDocument>(*document).pluginWidget()); if (!pluginView) - return 0; + return nullptr; return pluginView->pdfDocumentForPrinting(); } @@ -3372,7 +4026,7 @@ RetainPtr<PDFDocument> WebPage::pdfDocumentForPrintingFrame(Frame* coreFrame) void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo) { - WebFrame* frame = WebProcess::shared().webFrame(frameID); + WebFrame* frame = WebProcess::singleton().webFrame(frameID); if (!frame) return; @@ -3386,7 +4040,7 @@ void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo) #endif // PLATFORM(MAC) if (!m_printContext) - m_printContext = adoptPtr(new PrintContext(coreFrame)); + m_printContext = std::make_unique<PrintContext>(coreFrame); drawingArea()->setLayerTreeStateIsFrozen(true); m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight); @@ -3403,9 +4057,6 @@ void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo) void WebPage::endPrinting() { drawingArea()->setLayerTreeStateIsFrozen(false); -#if PLATFORM(GTK) - m_printOperation = 0; -#endif m_printContext = nullptr; } @@ -3413,6 +4064,13 @@ void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printIn { Vector<IntRect> resultPageRects; double resultTotalScaleFactorForPrinting = 1; + computePagesForPrintingImpl(frameID, printInfo, resultPageRects, resultTotalScaleFactorForPrinting); + send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID)); +} + +void WebPage::computePagesForPrintingImpl(uint64_t frameID, const PrintInfo& printInfo, Vector<WebCore::IntRect>& resultPageRects, double& resultTotalScaleFactorForPrinting) +{ + ASSERT(resultPageRects.isEmpty()); beginPrinting(frameID, printInfo); @@ -3420,22 +4078,20 @@ void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printIn resultPageRects = m_printContext->pageRects(); resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(FloatSize(printInfo.availablePaperWidth, printInfo.availablePaperHeight)) * printInfo.pageSetupScaleFactor; } -#if PLATFORM(MAC) +#if PLATFORM(COCOA) else computePagesForPrintingPDFDocument(frameID, printInfo, resultPageRects); -#endif // PLATFORM(MAC) +#endif // PLATFORM(COCOA) // If we're asked to print, we should actually print at least a blank page. if (resultPageRects.isEmpty()) resultPageRects.append(IntRect(0, 0, 1, 1)); - - send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID)); } -#if PLATFORM(MAC) +#if PLATFORM(COCOA) void WebPage::drawRectToImage(uint64_t frameID, const PrintInfo& printInfo, const IntRect& rect, const WebCore::IntSize& imageSize, uint64_t callbackID) { - WebFrame* frame = WebProcess::shared().webFrame(frameID); + WebFrame* frame = WebProcess::singleton().webFrame(frameID); Frame* coreFrame = frame ? frame->coreFrame() : 0; RefPtr<WebImage> image; @@ -3449,7 +4105,7 @@ void WebPage::drawRectToImage(uint64_t frameID, const PrintInfo& printInfo, cons #endif RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(imageSize, ShareableBitmap::SupportsAlpha); - OwnPtr<GraphicsContext> graphicsContext = bitmap->createGraphicsContext(); + auto graphicsContext = bitmap->createGraphicsContext(); float printingScale = static_cast<float>(imageSize.width()) / rect.width(); graphicsContext->scale(FloatSize(printingScale, printingScale)); @@ -3473,17 +4129,24 @@ void WebPage::drawRectToImage(uint64_t frameID, const PrintInfo& printInfo, cons ShareableBitmap::Handle handle; if (image) - image->bitmap()->createHandle(handle, SharedMemory::ReadOnly); + image->bitmap()->createHandle(handle, SharedMemory::Protection::ReadOnly); send(Messages::WebPageProxy::ImageCallback(handle, callbackID)); } void WebPage::drawPagesToPDF(uint64_t frameID, const PrintInfo& printInfo, uint32_t first, uint32_t count, uint64_t callbackID) { - WebFrame* frame = WebProcess::shared().webFrame(frameID); + RetainPtr<CFMutableDataRef> pdfPageData; + drawPagesToPDFImpl(frameID, printInfo, first, count, pdfPageData); + send(Messages::WebPageProxy::DataCallback(IPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID)); +} + +void WebPage::drawPagesToPDFImpl(uint64_t frameID, const PrintInfo& printInfo, uint32_t first, uint32_t count, RetainPtr<CFMutableDataRef>& pdfPageData) +{ + WebFrame* frame = WebProcess::singleton().webFrame(frameID); Frame* coreFrame = frame ? frame->coreFrame() : 0; - RetainPtr<CFMutableDataRef> pdfPageData = adoptCF(CFDataCreateMutable(0, 0)); + pdfPageData = adoptCF(CFDataCreateMutable(0, 0)); #if USE(CG) if (coreFrame) { @@ -3526,12 +4189,9 @@ void WebPage::drawPagesToPDF(uint64_t frameID, const PrintInfo& printInfo, uint3 CGPDFContextClose(context.get()); } #endif - - send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID)); } #elif PLATFORM(GTK) - void WebPage::drawPagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID) { beginPrinting(frameID, printInfo); @@ -3542,32 +4202,79 @@ void WebPage::drawPagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, send(Messages::WebPageProxy::VoidCallback(callbackID)); } + +void WebPage::didFinishPrintOperation(const WebCore::ResourceError& error, uint64_t callbackID) +{ + send(Messages::WebPageProxy::PrintFinishedCallback(error, callbackID)); + m_printOperation = nullptr; +} #endif void WebPage::savePDFToFileInDownloadsFolder(const String& suggestedFilename, const String& originatingURLString, const uint8_t* data, unsigned long size) { - send(Messages::WebPageProxy::SavePDFToFileInDownloadsFolder(suggestedFilename, originatingURLString, CoreIPC::DataReference(data, size))); + send(Messages::WebPageProxy::SavePDFToFileInDownloadsFolder(suggestedFilename, originatingURLString, IPC::DataReference(data, size))); } -#if PLATFORM(MAC) +#if PLATFORM(COCOA) void WebPage::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String& suggestedFilename, const String& originatingURLString, const uint8_t* data, unsigned long size, const String& pdfUUID) { - send(Messages::WebPageProxy::SavePDFToTemporaryFolderAndOpenWithNativeApplication(suggestedFilename, originatingURLString, CoreIPC::DataReference(data, size), pdfUUID)); + send(Messages::WebPageProxy::SavePDFToTemporaryFolderAndOpenWithNativeApplication(suggestedFilename, originatingURLString, IPC::DataReference(data, size), pdfUUID)); } #endif +void WebPage::addResourceRequest(unsigned long identifier, const WebCore::ResourceRequest& request) +{ + if (!request.url().protocolIsInHTTPFamily()) + return; + + if (m_mainFrameProgressCompleted && !ScriptController::processingUserGesture()) + return; + + ASSERT(!m_trackedNetworkResourceRequestIdentifiers.contains(identifier)); + bool wasEmpty = m_trackedNetworkResourceRequestIdentifiers.isEmpty(); + m_trackedNetworkResourceRequestIdentifiers.add(identifier); + if (wasEmpty) + send(Messages::WebPageProxy::SetNetworkRequestsInProgress(true)); +} + +void WebPage::removeResourceRequest(unsigned long identifier) +{ + if (!m_trackedNetworkResourceRequestIdentifiers.remove(identifier)) + return; + + if (m_trackedNetworkResourceRequestIdentifiers.isEmpty()) + send(Messages::WebPageProxy::SetNetworkRequestsInProgress(false)); +} + void WebPage::setMediaVolume(float volume) { m_page->setMediaVolume(volume); } +void WebPage::setMuted(bool muted) +{ + m_page->setMuted(muted); +} + +#if ENABLE(MEDIA_SESSION) +void WebPage::handleMediaEvent(uint32_t eventType) +{ + m_page->handleMediaEvent(static_cast<MediaEventType>(eventType)); +} + +void WebPage::setVolumeOfMediaElement(double volume, uint64_t elementID) +{ + m_page->setVolumeOfMediaElement(volume, elementID); +} +#endif + void WebPage::setMayStartMediaWhenInWindow(bool mayStartMedia) { if (mayStartMedia == m_mayStartMediaWhenInWindow) return; m_mayStartMediaWhenInWindow = mayStartMedia; - if (m_mayStartMediaWhenInWindow && m_page->isOnscreen()) + if (m_mayStartMediaWhenInWindow && m_page->isInWindow()) m_setCanStartMediaTimer.startOneShot(0); } @@ -3580,94 +4287,88 @@ void WebPage::runModal() m_isRunningModal = true; send(Messages::WebPageProxy::RunModal()); +#if !ASSERT_DISABLED + Ref<WebPage> protector(*this); +#endif RunLoop::run(); ASSERT(!m_isRunningModal); } -void WebPage::setMemoryCacheMessagesEnabled(bool memoryCacheMessagesEnabled) -{ - m_page->setMemoryCacheClientCallsEnabled(memoryCacheMessagesEnabled); -} - bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request) { if (SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(request.url().protocol())) return true; -#if ENABLE(BLOB) - if (request.url().protocolIs("blob")) + if (request.url().protocolIsBlob()) return true; -#endif return platformCanHandleRequest(request); } -#if USE(TILED_BACKING_STORE) +#if USE(COORDINATED_GRAPHICS_MULTIPROCESS) void WebPage::commitPageTransitionViewport() { m_drawingArea->setLayerTreeStateIsFrozen(false); } #endif -#if PLATFORM(MAC) +#if PLATFORM(COCOA) void WebPage::handleAlternativeTextUIResult(const String& result) { - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (!frame) - return; - frame->editor().handleAlternativeTextUIResult(result); + Frame& frame = m_page->focusController().focusedOrMainFrame(); + frame.editor().handleAlternativeTextUIResult(result); } #endif void WebPage::simulateMouseDown(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time) { - mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time)); + mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time, WebCore::ForceAtClick)); } void WebPage::simulateMouseUp(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time) { - mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time)); + mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time, WebCore::ForceAtClick)); } void WebPage::simulateMouseMotion(WebCore::IntPoint position, double time) { - mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time)); + mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time, 0)); } void WebPage::setCompositionForTesting(const String& compositionString, uint64_t from, uint64_t length) { - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (!frame || !frame->editor().canEdit()) + Frame& frame = m_page->focusController().focusedOrMainFrame(); + if (!frame.editor().canEdit()) return; Vector<CompositionUnderline> underlines; underlines.append(CompositionUnderline(0, compositionString.length(), Color(Color::black), false)); - frame->editor().setComposition(compositionString, underlines, from, from + length); + frame.editor().setComposition(compositionString, underlines, from, from + length); } bool WebPage::hasCompositionForTesting() { - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - return frame && frame->editor().hasComposition(); + Frame& frame = m_page->focusController().focusedOrMainFrame(); + return frame.editor().hasComposition(); } void WebPage::confirmCompositionForTesting(const String& compositionString) { - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (!frame || !frame->editor().canEdit()) + Frame& frame = m_page->focusController().focusedOrMainFrame(); + if (!frame.editor().canEdit()) return; if (compositionString.isNull()) - frame->editor().confirmComposition(); - frame->editor().confirmComposition(compositionString); + frame.editor().confirmComposition(); + frame.editor().confirmComposition(compositionString); } -void WebPage::numWheelEventHandlersChanged(unsigned numWheelEventHandlers) +void WebPage::wheelEventHandlersChanged(bool hasHandlers) { - if (m_numWheelEventHandlers == numWheelEventHandlers) + if (m_hasWheelEventHandlers == hasHandlers) return; - m_numWheelEventHandlers = numWheelEventHandlers; + m_hasWheelEventHandlers = hasHandlers; recomputeShortCircuitHorizontalWheelEventsState(); } @@ -3686,7 +4387,7 @@ static bool pageContainsAnyHorizontalScrollbars(Frame* mainFrame) return true; } - for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) { + for (Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) { FrameView* frameView = frame->view(); if (!frameView) continue; @@ -3710,7 +4411,7 @@ static bool pageContainsAnyHorizontalScrollbars(Frame* mainFrame) void WebPage::recomputeShortCircuitHorizontalWheelEventsState() { - bool canShortCircuitHorizontalWheelEvents = !m_numWheelEventHandlers; + bool canShortCircuitHorizontalWheelEvents = !m_hasWheelEventHandlers; if (canShortCircuitHorizontalWheelEvents) { // Check if we have any horizontal scroll bars on the page. @@ -3725,9 +4426,9 @@ void WebPage::recomputeShortCircuitHorizontalWheelEventsState() send(Messages::WebPageProxy::SetCanShortCircuitHorizontalWheelEvents(m_canShortCircuitHorizontalWheelEvents)); } -Frame* WebPage::mainFrame() const +MainFrame* WebPage::mainFrame() const { - return m_page ? m_page->mainFrame() : 0; + return m_page ? &m_page->mainFrame() : nullptr; } FrameView* WebPage::mainFrameView() const @@ -3735,49 +4436,7 @@ FrameView* WebPage::mainFrameView() const if (Frame* frame = mainFrame()) return frame->view(); - return 0; -} - -#if ENABLE(PAGE_VISIBILITY_API) || ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING) -void WebPage::setVisibilityState(uint32_t visibilityState, bool isInitialState) -{ - if (!m_page) - return; - - WebCore::PageVisibilityState state = static_cast<WebCore::PageVisibilityState>(visibilityState); - -#if ENABLE(PAGE_VISIBILITY_API) - if (m_visibilityState == state) - return; - - FrameView* view = m_page->mainFrame() ? m_page->mainFrame()->view() : 0; - - if (state == WebCore::PageVisibilityStateVisible) { - m_page->didMoveOnscreen(); - if (view) - view->show(); - } - - m_page->setVisibilityState(state, isInitialState); - m_visibilityState = state; - - if (state == WebCore::PageVisibilityStateHidden) { - m_page->willMoveOffscreen(); - if (view) - view->hide(); - } -#endif - -#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING) && !ENABLE(PAGE_VISIBILITY_API) - m_page->setVisibilityState(state, isInitialState); -#endif -} -#endif - -void WebPage::setThrottled(bool isThrottled) -{ - if (m_page) - m_page->setThrottled(isThrottled); + return nullptr; } void WebPage::setScrollingPerformanceLoggingEnabled(bool enabled) @@ -3795,7 +4454,7 @@ bool WebPage::canPluginHandleResponse(const ResourceResponse& response) { #if ENABLE(NETSCAPE_PLUGIN_API) uint32_t pluginLoadPolicy; - bool allowOnlyApplicationPlugins = !m_mainFrame->coreFrame()->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin); + bool allowOnlyApplicationPlugins = !m_mainFrame->coreFrame()->loader().subframeLoader().allowPlugins(); uint64_t pluginProcessToken; String newMIMEType; @@ -3803,36 +4462,152 @@ bool WebPage::canPluginHandleResponse(const ResourceResponse& response) 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))) return false; - return pluginLoadPolicy != PluginModuleBlocked && pluginProcessToken; + bool isBlockedPlugin = (pluginLoadPolicy == PluginModuleBlockedForSecurity) || (pluginLoadPolicy == PluginModuleBlockedForCompatibility); + return !isBlockedPlugin && pluginProcessToken; #else + UNUSED_PARAM(response); return false; #endif } +bool WebPage::shouldUseCustomContentProviderForResponse(const ResourceResponse& response) +{ + // If a plug-in exists that claims to support this response, it should take precedence over the custom content provider. + return m_mimeTypesWithCustomContentProviders.contains(response.mimeType()) && !canPluginHandleResponse(response); +} + +#if PLATFORM(COCOA) + +void WebPage::insertTextAsync(const String& text, const EditingRange& replacementEditingRange, bool registerUndoGroup, uint32_t editingRangeIsRelativeTo) +{ + Frame& frame = m_page->focusController().focusedOrMainFrame(); + + if (replacementEditingRange.location != notFound) { + RefPtr<Range> replacementRange = rangeFromEditingRange(frame, replacementEditingRange, static_cast<EditingRangeIsRelativeTo>(editingRangeIsRelativeTo)); + if (replacementRange) + frame.selection().setSelection(VisibleSelection(*replacementRange, SEL_DEFAULT_AFFINITY)); + } + + if (registerUndoGroup) + send(Messages::WebPageProxy::RegisterInsertionUndoGrouping()); + + if (!frame.editor().hasComposition()) { + // An insertText: might be handled by other responders in the chain if we don't handle it. + // One example is space bar that results in scrolling down the page. + frame.editor().insertText(text, nullptr); + } else + frame.editor().confirmComposition(text); +} + +void WebPage::getMarkedRangeAsync(uint64_t callbackID) +{ + Frame& frame = m_page->focusController().focusedOrMainFrame(); + + RefPtr<Range> range = frame.editor().compositionRange(); + size_t location; + size_t length; + if (!range || !TextIterator::getLocationAndLengthFromRange(frame.selection().rootEditableElementOrDocumentElement(), range.get(), location, length)) { + location = notFound; + length = 0; + } + + send(Messages::WebPageProxy::EditingRangeCallback(EditingRange(location, length), callbackID)); +} + +void WebPage::getSelectedRangeAsync(uint64_t callbackID) +{ + Frame& frame = m_page->focusController().focusedOrMainFrame(); + + size_t location; + size_t length; + RefPtr<Range> range = frame.selection().toNormalizedRange(); + if (!range || !TextIterator::getLocationAndLengthFromRange(frame.selection().rootEditableElementOrDocumentElement(), range.get(), location, length)) { + location = notFound; + length = 0; + } + + send(Messages::WebPageProxy::EditingRangeCallback(EditingRange(location, length), callbackID)); +} + +void WebPage::characterIndexForPointAsync(const WebCore::IntPoint& point, uint64_t callbackID) +{ + uint64_t index = notFound; + + HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(point); + Frame* frame = result.innerNonSharedNode() ? result.innerNodeFrame() : &m_page->focusController().focusedOrMainFrame(); + + RefPtr<Range> range = frame->rangeForPoint(result.roundedPointInInnerNodeFrame()); + if (range) { + size_t location; + size_t length; + if (TextIterator::getLocationAndLengthFromRange(frame->selection().rootEditableElementOrDocumentElement(), range.get(), location, length)) + index = static_cast<uint64_t>(location); + } + + send(Messages::WebPageProxy::UnsignedCallback(index, callbackID)); +} + +void WebPage::firstRectForCharacterRangeAsync(const EditingRange& editingRange, uint64_t callbackID) +{ + Frame& frame = m_page->focusController().focusedOrMainFrame(); + IntRect result(IntPoint(0, 0), IntSize(0, 0)); + + RefPtr<Range> range = rangeFromEditingRange(frame, editingRange); + if (!range) { + send(Messages::WebPageProxy::RectForCharacterRangeCallback(result, EditingRange(notFound, 0), callbackID)); + return; + } + + result = frame.view()->contentsToWindow(frame.editor().firstRectForRange(range.get())); + + // FIXME: Update actualRange to match the range of first rect. + send(Messages::WebPageProxy::RectForCharacterRangeCallback(result, editingRange, callbackID)); +} + +void WebPage::setCompositionAsync(const String& text, Vector<CompositionUnderline> underlines, const EditingRange& selection, const EditingRange& replacementEditingRange) +{ + Frame& frame = m_page->focusController().focusedOrMainFrame(); + + if (frame.selection().selection().isContentEditable()) { + RefPtr<Range> replacementRange; + if (replacementEditingRange.location != notFound) { + replacementRange = rangeFromEditingRange(frame, replacementEditingRange); + if (replacementRange) + frame.selection().setSelection(VisibleSelection(*replacementRange, SEL_DEFAULT_AFFINITY)); + } + + frame.editor().setComposition(text, underlines, selection.location, selection.location + selection.length); + } +} + +void WebPage::confirmCompositionAsync() +{ + Frame& frame = m_page->focusController().focusedOrMainFrame(); + frame.editor().confirmComposition(); +} + +#endif // PLATFORM(COCOA) + #if PLATFORM(QT) || PLATFORM(GTK) static Frame* targetFrameForEditing(WebPage* page) { - Frame* targetFrame = page->corePage()->focusController()->focusedOrMainFrame(); - - if (!targetFrame) - return 0; + Frame& targetFrame = page->corePage()->focusController().focusedOrMainFrame(); - Editor& editor = targetFrame->editor(); + Editor& editor = targetFrame.editor(); if (!editor.canEdit()) - return 0; + return nullptr; if (editor.hasComposition()) { // We should verify the parent node of this IME composition node are // editable because JavaScript may delete a parent node of the composition // node. In this case, WebKit crashes while deleting texts from the parent // node, which doesn't exist any longer. - if (PassRefPtr<Range> range = editor.compositionRange()) { - Node* node = range->startContainer(); - if (!node || !node->isContentEditable()) - return 0; + if (auto range = editor.compositionRange()) { + if (!range->startContainer().isContentEditable()) + return nullptr; } } - return targetFrame; + return &targetFrame; } void WebPage::confirmComposition(const String& compositionString, int64_t selectionStart, int64_t selectionLength) @@ -3850,21 +4625,21 @@ void WebPage::confirmComposition(const String& compositionString, int64_t select return; } - Element* scope = targetFrame->selection()->rootEditableElement(); + Element* scope = targetFrame->selection().selection().rootEditableElement(); RefPtr<Range> selectionRange = TextIterator::rangeFromLocationAndLength(scope, selectionStart, selectionLength); 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()); if (selectionRange) { - VisibleSelection selection(selectionRange.get(), SEL_DEFAULT_AFFINITY); - targetFrame->selection()->setSelection(selection); + VisibleSelection selection(*selectionRange, SEL_DEFAULT_AFFINITY); + targetFrame->selection().setSelection(selection); } send(Messages::WebPageProxy::EditorStateChanged(editorState())); } -void WebPage::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementStart, uint64_t replacementLength) +void WebPage::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, uint64_t selectionStart, uint64_t selectionLength, uint64_t replacementStart, uint64_t replacementLength) { Frame* targetFrame = targetFrameForEditing(this); - if (!targetFrame || !targetFrame->selection()->isContentEditable()) { + if (!targetFrame || !targetFrame->selection().selection().isContentEditable()) { send(Messages::WebPageProxy::EditorStateChanged(editorState())); return; } @@ -3873,14 +4648,14 @@ void WebPage::setComposition(const String& text, Vector<CompositionUnderline> un // The layout needs to be uptodate before setting a selection targetFrame->document()->updateLayout(); - Element* scope = targetFrame->selection()->rootEditableElement(); + Element* scope = targetFrame->selection().selection().rootEditableElement(); RefPtr<Range> replacementRange = TextIterator::rangeFromLocationAndLength(scope, replacementStart, replacementLength); targetFrame->editor().setIgnoreCompositionSelectionChange(true); - targetFrame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY)); + targetFrame->selection().setSelection(VisibleSelection(*replacementRange, SEL_DEFAULT_AFFINITY)); targetFrame->editor().setIgnoreCompositionSelectionChange(false); } - targetFrame->editor().setComposition(text, underlines, selectionStart, selectionEnd); + targetFrame->editor().setComposition(text, underlines, selectionStart, selectionStart + selectionLength); send(Messages::WebPageProxy::EditorStateChanged(editorState())); } @@ -3894,12 +4669,46 @@ void WebPage::cancelComposition() void WebPage::didChangeSelection() { - send(Messages::WebPageProxy::EditorStateChanged(editorState())); + Frame& frame = m_page->focusController().focusedOrMainFrame(); + FrameView* view = frame.view(); + + // If there is a layout pending, we should avoid populating EditorState that require layout to be done or it will + // trigger a synchronous layout every time the selection changes. sendPostLayoutEditorStateIfNeeded() will be called + // to send the full editor state after layout is done if we send a partial editor state here. + auto editorState = this->editorState(view && view->needsLayout() ? IncludePostLayoutDataHint::No : IncludePostLayoutDataHint::Yes); + m_isEditorStateMissingPostLayoutData = editorState.isMissingPostLayoutData; + +#if PLATFORM(MAC) + // Abandon the current inline input session if selection changed for any other reason but an input method direct action. + // FIXME: This logic should be in WebCore. + // 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. + // FIXME: We can't cancel composition when selection changes to NoSelection, but we probably should. + if (frame.editor().hasComposition() && !frame.editor().ignoreCompositionSelectionChange() && !frame.selection().isNone()) { + frame.editor().cancelComposition(); + send(Messages::WebPageProxy::CompositionWasCanceled(editorState)); + } else + send(Messages::WebPageProxy::EditorStateChanged(editorState)); +#else + send(Messages::WebPageProxy::EditorStateChanged(editorState), pageID(), IPC::DispatchMessageEvenWhenWaitingForSyncReply); +#endif + +#if PLATFORM(IOS) + m_drawingArea->scheduleCompositingLayerFlush(); +#endif } -void WebPage::setMainFrameInViewSourceMode(bool inViewSourceMode) +void WebPage::sendPostLayoutEditorStateIfNeeded() { - m_mainFrame->coreFrame()->setInViewSourceMode(inViewSourceMode); + if (!m_isEditorStateMissingPostLayoutData) + return; + + send(Messages::WebPageProxy::EditorStateChanged(editorState(IncludePostLayoutDataHint::Yes)), pageID(), IPC::DispatchMessageEvenWhenWaitingForSyncReply); + m_isEditorStateMissingPostLayoutData = false; +} + +void WebPage::discardedComposition() +{ + send(Messages::WebPageProxy::CompositionWasCanceled(editorState())); } void WebPage::setMinimumLayoutSize(const IntSize& minimumLayoutSize) @@ -3909,7 +4718,7 @@ void WebPage::setMinimumLayoutSize(const IntSize& minimumLayoutSize) m_minimumLayoutSize = minimumLayoutSize; if (minimumLayoutSize.width() <= 0) { - corePage()->mainFrame()->view()->enableAutoSizeMode(false, IntSize(), IntSize()); + corePage()->mainFrame().view()->enableAutoSizeMode(false, IntSize(), IntSize()); return; } @@ -3918,31 +4727,41 @@ void WebPage::setMinimumLayoutSize(const IntSize& minimumLayoutSize) int maximumSize = std::numeric_limits<int>::max(); - corePage()->mainFrame()->view()->enableAutoSizeMode(true, IntSize(minimumLayoutWidth, minimumLayoutHeight), IntSize(maximumSize, maximumSize)); + corePage()->mainFrame().view()->enableAutoSizeMode(true, IntSize(minimumLayoutWidth, minimumLayoutHeight), IntSize(maximumSize, maximumSize)); +} + +void WebPage::setAutoSizingShouldExpandToViewHeight(bool shouldExpand) +{ + if (m_autoSizingShouldExpandToViewHeight == shouldExpand) + return; + + m_autoSizingShouldExpandToViewHeight = shouldExpand; + + corePage()->mainFrame().view()->setAutoSizeFixedMinimumHeight(shouldExpand ? m_viewSize.height() : 0); } bool WebPage::isSmartInsertDeleteEnabled() { - return m_page->settings()->smartInsertDeleteEnabled(); + return m_page->settings().smartInsertDeleteEnabled(); } void WebPage::setSmartInsertDeleteEnabled(bool enabled) { - if (m_page->settings()->smartInsertDeleteEnabled() != enabled) { - m_page->settings()->setSmartInsertDeleteEnabled(enabled); + if (m_page->settings().smartInsertDeleteEnabled() != enabled) { + m_page->settings().setSmartInsertDeleteEnabled(enabled); setSelectTrailingWhitespaceEnabled(!enabled); } } bool WebPage::isSelectTrailingWhitespaceEnabled() { - return m_page->settings()->selectTrailingWhitespaceEnabled(); + return m_page->settings().selectTrailingWhitespaceEnabled(); } void WebPage::setSelectTrailingWhitespaceEnabled(bool enabled) { - if (m_page->settings()->selectTrailingWhitespaceEnabled() != enabled) { - m_page->settings()->setSelectTrailingWhitespaceEnabled(enabled); + if (m_page->settings().selectTrailingWhitespaceEnabled() != enabled) { + m_page->settings().setSelectTrailingWhitespaceEnabled(enabled); setSmartInsertDeleteEnabled(!enabled); } } @@ -3952,14 +4771,16 @@ bool WebPage::canShowMIMEType(const String& MIMEType) const if (MIMETypeRegistry::canShowMIMEType(MIMEType)) return true; - if (PluginData* pluginData = m_page->pluginData()) { - if (pluginData->supportsMimeType(MIMEType, PluginData::AllPlugins) && corePage()->mainFrame()->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin)) - return true; + if (m_mimeTypesWithCustomContentProviders.contains(MIMEType)) + return true; - // We can use application plugins even if plugins aren't enabled. - if (pluginData->supportsMimeType(MIMEType, PluginData::OnlyApplicationPlugins)) - return true; - } + const PluginData& pluginData = m_page->pluginData(); + if (pluginData.supportsWebVisibleMimeType(MIMEType, PluginData::AllPlugins) && corePage()->mainFrame().loader().subframeLoader().allowPlugins()) + return true; + + // We can use application plugins even if plugins aren't enabled. + if (pluginData.supportsWebVisibleMimeType(MIMEType, PluginData::OnlyApplicationPlugins)) + return true; return false; } @@ -3971,46 +4792,109 @@ void WebPage::addTextCheckingRequest(uint64_t requestID, PassRefPtr<TextChecking void WebPage::didFinishCheckingText(uint64_t requestID, const Vector<TextCheckingResult>& result) { - TextCheckingRequest* request = m_pendingTextCheckingRequestMap.get(requestID); + RefPtr<TextCheckingRequest> request = m_pendingTextCheckingRequestMap.take(requestID); if (!request) return; request->didSucceed(result); - m_pendingTextCheckingRequestMap.remove(requestID); } void WebPage::didCancelCheckingText(uint64_t requestID) { - TextCheckingRequest* request = m_pendingTextCheckingRequestMap.get(requestID); + RefPtr<TextCheckingRequest> request = m_pendingTextCheckingRequestMap.take(requestID); if (!request) return; request->didCancel(); - m_pendingTextCheckingRequestMap.remove(requestID); +} + +void WebPage::willReplaceMultipartContent(const WebFrame& frame) +{ +#if PLATFORM(IOS) + if (!frame.isMainFrame()) + return; + + m_previousExposedContentRect = m_drawingArea->exposedContentRect(); +#endif +} + +void WebPage::didReplaceMultipartContent(const WebFrame& frame) +{ +#if PLATFORM(IOS) + if (!frame.isMainFrame()) + return; + + // Restore the previous exposed content rect so that it remains fixed when replacing content + // from multipart/x-mixed-replace streams. + m_drawingArea->setExposedContentRect(m_previousExposedContentRect); +#endif } void WebPage::didCommitLoad(WebFrame* frame) { +#if PLATFORM(IOS) + frame->setFirstLayerTreeTransactionIDAfterDidCommitLoad(downcast<RemoteLayerTreeDrawingArea>(*m_drawingArea).nextTransactionID()); + cancelPotentialTapInFrame(*frame); + resetAssistedNodeForFrame(frame); +#endif + if (!frame->isMainFrame()) return; // If previous URL is invalid, then it's not a real page that's being navigated away from. // Most likely, this is actually the first load to be committed in this page. - if (frame->coreFrame()->loader()->previousURL().isValid()) + if (frame->coreFrame()->loader().previousURL().isValid()) reportUsedFeatures(); // Only restore the scale factor for standard frame loads (of the main frame). - if (frame->coreFrame()->loader()->loadType() == FrameLoadTypeStandard) { + if (frame->coreFrame()->loader().loadType() == FrameLoadType::Standard) { Page* page = frame->coreFrame()->page(); + +#if PLATFORM(MAC) + // As a very special case, we disable non-default layout modes in WKView for main-frame PluginDocuments. + // Ideally we would only worry about this in WKView or the WKViewLayoutStrategies, but if we allow + // a round-trip to the UI process, you'll see the wrong scale temporarily. So, we reset it here, and then + // again later from the UI process. + if (frame->coreFrame()->document()->isPluginDocument()) { + scaleView(1); + setUseFixedLayout(false); + } +#endif + if (page && page->pageScaleFactor() != 1) scalePage(1, IntPoint()); } +#if PLATFORM(IOS) + m_hasReceivedVisibleContentRectsAfterDidCommitLoad = false; + m_scaleWasSetByUIProcess = false; + m_userHasChangedPageScaleFactor = false; + m_estimatedLatency = std::chrono::milliseconds(1000 / 60); + +#if ENABLE(IOS_TOUCH_EVENTS) + WebProcess::singleton().eventDispatcher().clearQueuedTouchEventsForPage(*this); +#endif + + resetViewportDefaultConfiguration(frame); + const Frame* coreFrame = frame->coreFrame(); + + bool viewportChanged = false; + if (m_viewportConfiguration.setContentsSize(coreFrame->view()->contentsSize())) + viewportChanged = true; + + if (m_viewportConfiguration.setViewportArguments(coreFrame->document()->viewportArguments())) + viewportChanged = true; + + if (viewportChanged) + viewportConfigurationChanged(); +#endif #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) resetPrimarySnapshottedPlugIn(); #endif - WebProcess::shared().updateActivePages(); + WebProcess::singleton().updateActivePages(); + + updateMainFrameScrollOffsetPinning(); } void WebPage::didFinishLoad(WebFrame* frame) @@ -4020,6 +4904,7 @@ void WebPage::didFinishLoad(WebFrame* frame) return; m_readyToFindPrimarySnapshottedPlugin = true; + LOG(Plugins, "Primary Plug-In Detection: triggering detection from didFinishLoad (marking as ready to detect)."); m_determinePrimarySnapshottedPlugInTimer.startOneShot(0); #else UNUSED_PARAM(frame); @@ -4027,11 +4912,14 @@ void WebPage::didFinishLoad(WebFrame* frame) } #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) -static int primarySnapshottedPlugInSearchLimit = 3000; -static int primarySnapshottedPlugInSearchGap = 200; -static float primarySnapshottedPlugInSearchBucketSize = 1.1; -static int primarySnapshottedPlugInMinimumWidth = 400; -static int primarySnapshottedPlugInMinimumHeight = 300; +static const int primarySnapshottedPlugInSearchLimit = 3000; +static const float primarySnapshottedPlugInSearchBucketSize = 1.1; +static const int primarySnapshottedPlugInMinimumWidth = 400; +static const int primarySnapshottedPlugInMinimumHeight = 300; +static const unsigned maxPrimarySnapshottedPlugInDetectionAttempts = 2; +static const int deferredPrimarySnapshottedPlugInDetectionDelay = 3; +static const float overlappingImageBoundsScale = 1.1; +static const float minimumOverlappingImageToPluginDimensionScale = .9; #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) void WebPage::determinePrimarySnapshottedPlugInTimerFired() @@ -4039,84 +4927,113 @@ void WebPage::determinePrimarySnapshottedPlugInTimerFired() if (!m_page) return; - Settings* settings = m_page->settings(); - if (!settings->snapshotAllPlugIns() && settings->primaryPlugInSnapshotDetectionEnabled()) + Settings& settings = m_page->settings(); + if (!settings.snapshotAllPlugIns() && settings.primaryPlugInSnapshotDetectionEnabled()) determinePrimarySnapshottedPlugIn(); } #endif void WebPage::determinePrimarySnapshottedPlugIn() { - if (!m_page->settings()->plugInSnapshottingEnabled()) + if (!m_page->settings().plugInSnapshottingEnabled()) return; - if (!m_readyToFindPrimarySnapshottedPlugin) + LOG(Plugins, "Primary Plug-In Detection: began."); + + if (!m_readyToFindPrimarySnapshottedPlugin) { + LOG(Plugins, "Primary Plug-In Detection: exiting - not ready to find plugins."); return; + } - if (m_pluginViews.isEmpty()) + if (!m_hasSeenPlugin) { + LOG(Plugins, "Primary Plug-In Detection: exiting - we never saw a plug-in get added to the page."); return; + } - if (m_didFindPrimarySnapshottedPlugin) + if (m_didFindPrimarySnapshottedPlugin) { + LOG(Plugins, "Primary Plug-In Detection: exiting - we've already found a primary plug-in."); return; + } + + ++m_numberOfPrimarySnapshotDetectionAttempts; - RenderView* renderView = corePage()->mainFrame()->view()->renderView(); + layoutIfNeeded(); - IntRect searchRect = IntRect(IntPoint(), corePage()->mainFrame()->view()->contentsSize()); + MainFrame& mainFrame = corePage()->mainFrame(); + if (!mainFrame.view()) + return; + if (!mainFrame.view()->renderView()) + return; + RenderView& mainRenderView = *mainFrame.view()->renderView(); + + IntRect searchRect = IntRect(IntPoint(), corePage()->mainFrame().view()->contentsSize()); searchRect.intersect(IntRect(IntPoint(), IntSize(primarySnapshottedPlugInSearchLimit, primarySnapshottedPlugInSearchLimit))); HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); - HashSet<RenderObject*> seenRenderers; - HTMLPlugInImageElement* candidatePlugIn = 0; + HTMLPlugInImageElement* candidatePlugIn = nullptr; unsigned candidatePlugInArea = 0; - for (int x = searchRect.x(); x <= searchRect.width(); x += primarySnapshottedPlugInSearchGap) { - for (int y = searchRect.y(); y <= searchRect.height(); y += primarySnapshottedPlugInSearchGap) { - HitTestResult hitTestResult = HitTestResult(LayoutPoint(x, y)); - renderView->hitTest(request, hitTestResult); - - Element* element = hitTestResult.innerElement(); - if (!element) - continue; - - RenderObject* renderer = element->renderer(); - if (!renderer || !renderer->isBox()) - continue; - - RenderBox* renderBox = toRenderBox(renderer); - - if (!seenRenderers.add(renderer).isNewEntry) + for (Frame* frame = &mainFrame; frame; frame = frame->tree().traverseNextRendered()) { + if (!frame->loader().subframeLoader().containsPlugins()) + continue; + if (!frame->document() || !frame->view()) + continue; + for (auto& plugInImageElement : descendantsOfType<HTMLPlugInImageElement>(*frame->document())) { + if (plugInImageElement.displayState() == HTMLPlugInElement::Playing) continue; - if (!element->isPluginElement()) + auto pluginRenderer = plugInImageElement.renderer(); + if (!pluginRenderer || !pluginRenderer->isBox()) continue; - - HTMLPlugInElement* plugInElement = toHTMLPlugInElement(element); - if (!plugInElement->isPlugInImageElement()) + auto& pluginRenderBox = downcast<RenderBox>(*pluginRenderer); + if (!plugInIntersectsSearchRect(plugInImageElement)) continue; - HTMLPlugInImageElement* plugInImageElement = toHTMLPlugInImageElement(plugInElement); - - if (plugInElement->displayState() == HTMLPlugInElement::Playing) - continue; + IntRect plugInRectRelativeToView = plugInImageElement.clientRect(); + ScrollPosition scrollPosition = mainFrame.view()->documentScrollPositionRelativeToViewOrigin(); + IntRect plugInRectRelativeToTopDocument(plugInRectRelativeToView.location() + scrollPosition, plugInRectRelativeToView.size()); + HitTestResult hitTestResult(plugInRectRelativeToTopDocument.center()); + mainRenderView.hitTest(request, hitTestResult); - if (renderBox->contentWidth() < primarySnapshottedPlugInMinimumWidth || renderBox->contentHeight() < primarySnapshottedPlugInMinimumHeight) + Element* element = hitTestResult.innerElement(); + if (!element) continue; - LayoutUnit contentArea = renderBox->contentWidth() * renderBox->contentHeight(); - - if (contentArea > candidatePlugInArea * primarySnapshottedPlugInSearchBucketSize) { - candidatePlugIn = plugInImageElement; - candidatePlugInArea = contentArea; + IntRect elementRectRelativeToView = element->clientRect(); + IntRect elementRectRelativeToTopDocument(elementRectRelativeToView.location() + scrollPosition, elementRectRelativeToView.size()); + LayoutRect inflatedPluginRect = plugInRectRelativeToTopDocument; + LayoutUnit xOffset = (inflatedPluginRect.width() * overlappingImageBoundsScale - inflatedPluginRect.width()) / 2; + LayoutUnit yOffset = (inflatedPluginRect.height() * overlappingImageBoundsScale - inflatedPluginRect.height()) / 2; + inflatedPluginRect.inflateX(xOffset); + inflatedPluginRect.inflateY(yOffset); + + if (element != &plugInImageElement) { + if (!(is<HTMLImageElement>(*element) + && inflatedPluginRect.contains(elementRectRelativeToTopDocument) + && elementRectRelativeToTopDocument.width() > pluginRenderBox.width() * minimumOverlappingImageToPluginDimensionScale + && elementRectRelativeToTopDocument.height() > pluginRenderBox.height() * minimumOverlappingImageToPluginDimensionScale)) + continue; + 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."); + plugInImageElement.restartSnapshottedPlugIn(); } + + if (plugInIsPrimarySize(plugInImageElement, candidatePlugInArea)) + candidatePlugIn = &plugInImageElement; } } - - if (!candidatePlugIn) + if (!candidatePlugIn) { + LOG(Plugins, "Primary Plug-In Detection: fail - did not find a candidate plug-in."); + if (m_numberOfPrimarySnapshotDetectionAttempts < maxPrimarySnapshottedPlugInDetectionAttempts) { + LOG(Plugins, "Primary Plug-In Detection: will attempt again in %ds.", deferredPrimarySnapshottedPlugInDetectionDelay); + m_determinePrimarySnapshottedPlugInTimer.startOneShot(deferredPrimarySnapshottedPlugInDetectionDelay); + } return; + } + LOG(Plugins, "Primary Plug-In Detection: success - found a candidate plug-in - inform it."); m_didFindPrimarySnapshottedPlugin = true; - m_primaryPlugInPageOrigin = m_page->mainFrame()->document()->baseURL().host(); + m_primaryPlugInPageOrigin = m_page->mainFrame().document()->baseURL().host(); m_primaryPlugInOrigin = candidatePlugIn->loadedUrl().host(); m_primaryPlugInMimeType = candidatePlugIn->loadedMimeType(); @@ -4127,6 +5044,8 @@ void WebPage::resetPrimarySnapshottedPlugIn() { m_readyToFindPrimarySnapshottedPlugin = false; m_didFindPrimarySnapshottedPlugin = false; + m_numberOfPrimarySnapshotDetectionAttempts = 0; + m_hasSeenPlugin = false; } bool WebPage::matchesPrimaryPlugIn(const String& pageOrigin, const String& pluginOrigin, const String& mimeType) const @@ -4136,6 +5055,40 @@ bool WebPage::matchesPrimaryPlugIn(const String& pageOrigin, const String& plugi return (pageOrigin == m_primaryPlugInPageOrigin && pluginOrigin == m_primaryPlugInOrigin && mimeType == m_primaryPlugInMimeType); } + +bool WebPage::plugInIntersectsSearchRect(HTMLPlugInImageElement& plugInImageElement) +{ + MainFrame& mainFrame = corePage()->mainFrame(); + if (!mainFrame.view()) + return false; + if (!mainFrame.view()->renderView()) + return false; + + IntRect searchRect = IntRect(IntPoint(), corePage()->mainFrame().view()->contentsSize()); + searchRect.intersect(IntRect(IntPoint(), IntSize(primarySnapshottedPlugInSearchLimit, primarySnapshottedPlugInSearchLimit))); + + IntRect plugInRectRelativeToView = plugInImageElement.clientRect(); + if (plugInRectRelativeToView.isEmpty()) + return false; + ScrollPosition scrollPosition = mainFrame.view()->documentScrollPositionRelativeToViewOrigin(); + IntRect plugInRectRelativeToTopDocument(plugInRectRelativeToView.location() + toIntSize(scrollPosition), plugInRectRelativeToView.size()); + + return plugInRectRelativeToTopDocument.intersects(searchRect); +} + +bool WebPage::plugInIsPrimarySize(WebCore::HTMLPlugInImageElement& plugInImageElement, unsigned& candidatePlugInArea) +{ + auto& pluginRenderBox = downcast<RenderBox>(*plugInImageElement.renderer()); + if (pluginRenderBox.contentWidth() < primarySnapshottedPlugInMinimumWidth || pluginRenderBox.contentHeight() < primarySnapshottedPlugInMinimumHeight) + return false; + + LayoutUnit contentArea = pluginRenderBox.contentWidth() * pluginRenderBox.contentHeight(); + if (contentArea > candidatePlugInArea * primarySnapshottedPlugInSearchBucketSize) { + candidatePlugInArea = contentArea; + return true; + } + return false; +} #endif // ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) PassRefPtr<Range> WebPage::currentSelectionAsRange() @@ -4144,17 +5097,12 @@ PassRefPtr<Range> WebPage::currentSelectionAsRange() if (!frame) return 0; - return frame->selection()->toNormalizedRange(); + return frame->selection().toNormalizedRange(); } void WebPage::reportUsedFeatures() { - // FIXME: Feature names should not be hardcoded. - const BitVector* features = m_page->featureObserver()->accumulatedFeatureBits(); Vector<String> namedFeatures; - if (features && features->quickGet(FeatureObserver::SharedWorkerStart)) - namedFeatures.append("SharedWorker"); - m_loaderClient.featuresUsedInPage(this, namedFeatures); } @@ -4165,7 +5113,7 @@ unsigned WebPage::extendIncrementalRenderingSuppression() token++; m_activeRenderingSuppressionTokens.add(token); - m_page->mainFrame()->view()->setVisualUpdatesAllowedByClient(false); + m_page->mainFrame().view()->setVisualUpdatesAllowedByClient(false); m_maximumRenderingSuppressionToken = token; @@ -4174,17 +5122,194 @@ unsigned WebPage::extendIncrementalRenderingSuppression() void WebPage::stopExtendingIncrementalRenderingSuppression(unsigned token) { - if (!m_activeRenderingSuppressionTokens.contains(token)) + if (!m_activeRenderingSuppressionTokens.remove(token)) return; - m_activeRenderingSuppressionTokens.remove(token); - m_page->mainFrame()->view()->setVisualUpdatesAllowedByClient(!shouldExtendIncrementalRenderingSuppression()); + m_page->mainFrame().view()->setVisualUpdatesAllowedByClient(!shouldExtendIncrementalRenderingSuppression()); } void WebPage::setScrollPinningBehavior(uint32_t pinning) { m_scrollPinningBehavior = static_cast<ScrollPinningBehavior>(pinning); - m_page->mainFrame()->view()->setScrollPinningBehavior(m_scrollPinningBehavior); + m_page->mainFrame().view()->setScrollPinningBehavior(m_scrollPinningBehavior); +} + +void WebPage::setScrollbarOverlayStyle(WTF::Optional<uint32_t> scrollbarStyle) +{ + if (scrollbarStyle) + m_scrollbarOverlayStyle = static_cast<ScrollbarOverlayStyle>(scrollbarStyle.value()); + else + m_scrollbarOverlayStyle = WTF::Optional<ScrollbarOverlayStyle>(); + m_page->mainFrame().view()->recalculateScrollbarOverlayStyle(); +} + +Ref<DocumentLoader> WebPage::createDocumentLoader(Frame& frame, const ResourceRequest& request, const SubstituteData& substituteData) +{ + Ref<WebDocumentLoader> documentLoader = WebDocumentLoader::create(request, substituteData); + + if (frame.isMainFrame()) { + if (m_pendingNavigationID) { + documentLoader->setNavigationID(m_pendingNavigationID); + m_pendingNavigationID = 0; + } + } + + return WTFMove(documentLoader); +} + +void WebPage::updateCachedDocumentLoader(WebDocumentLoader& documentLoader, Frame& frame) +{ + if (m_pendingNavigationID && frame.isMainFrame()) { + documentLoader.setNavigationID(m_pendingNavigationID); + m_pendingNavigationID = 0; + } +} + +void WebPage::getBytecodeProfile(uint64_t callbackID) +{ + if (!JSDOMWindow::commonVM().m_perBytecodeProfiler) { + send(Messages::WebPageProxy::StringCallback(String(), callbackID)); + return; + } + + String result = JSDOMWindow::commonVM().m_perBytecodeProfiler->toJSON(); + ASSERT(result.length()); + send(Messages::WebPageProxy::StringCallback(result, callbackID)); +} + +PassRefPtr<WebCore::Range> WebPage::rangeFromEditingRange(WebCore::Frame& frame, const EditingRange& range, EditingRangeIsRelativeTo editingRangeIsRelativeTo) +{ + ASSERT(range.location != notFound); + + // Sanitize the input, because TextIterator::rangeFromLocationAndLength takes signed integers. + if (range.location > INT_MAX) + return 0; + int length; + if (range.length <= INT_MAX && range.location + range.length <= INT_MAX) + length = static_cast<int>(range.length); + else + length = INT_MAX - range.location; + + if (editingRangeIsRelativeTo == EditingRangeIsRelativeTo::EditableRoot) { + // Our critical assumption is that this code path is called by input methods that + // concentrate on a given area containing the selection. + // We have to do this because of text fields and textareas. The DOM for those is not + // directly in the document DOM, so serialization is problematic. Our solution is + // to use the root editable element of the selection start as the positional base. + // That fits with AppKit's idea of an input context. + return TextIterator::rangeFromLocationAndLength(frame.selection().rootEditableElementOrDocumentElement(), static_cast<int>(range.location), length); + } + + ASSERT(editingRangeIsRelativeTo == EditingRangeIsRelativeTo::Paragraph); + + const VisibleSelection& selection = frame.selection().selection(); + RefPtr<Range> selectedRange = selection.toNormalizedRange(); + if (!selectedRange) + return 0; + + RefPtr<Range> paragraphRange = makeRange(startOfParagraph(selection.visibleStart()), selection.visibleEnd()); + if (!paragraphRange) + return 0; + + ContainerNode& rootNode = paragraphRange.get()->startContainer().treeScope().rootNode(); + int paragraphStartIndex = TextIterator::rangeLength(Range::create(rootNode.document(), &rootNode, 0, ¶graphRange->startContainer(), paragraphRange->startOffset()).ptr()); + return TextIterator::rangeFromLocationAndLength(&rootNode, paragraphStartIndex + static_cast<int>(range.location), length); +} + +void WebPage::didChangeScrollOffsetForFrame(Frame* frame) +{ + if (!frame->isMainFrame()) + return; + + // If this is called when tearing down a FrameView, the WebCore::Frame's + // current FrameView will be null. + if (!frame->view()) + return; + + updateMainFrameScrollOffsetPinning(); +} + +void WebPage::postMessage(const String& messageName, API::Object* messageBody) +{ + send(Messages::WebPageProxy::HandleMessage(messageName, UserData(WebProcess::singleton().transformObjectsToHandles(messageBody)))); +} + +void WebPage::postSynchronousMessageForTesting(const String& messageName, API::Object* messageBody, RefPtr<API::Object>& returnData) +{ + UserData returnUserData; + + auto& webProcess = WebProcess::singleton(); + if (!sendSync(Messages::WebPageProxy::HandleSynchronousMessage(messageName, UserData(webProcess.transformObjectsToHandles(messageBody))), Messages::WebPageProxy::HandleSynchronousMessage::Reply(returnUserData), std::chrono::milliseconds::max(), IPC::SyncMessageSendFlags::UseFullySynchronousModeForTesting)) + returnData = nullptr; + else + returnData = webProcess.transformHandlesToObjects(returnUserData.object()); +} + +void WebPage::clearWheelEventTestTrigger() +{ + if (!m_page) + return; + + m_page->clearTrigger(); +} + +void WebPage::setShouldScaleViewToFitDocument(bool shouldScaleViewToFitDocument) +{ + if (!m_drawingArea) + return; + + m_drawingArea->setShouldScaleViewToFitDocument(shouldScaleViewToFitDocument); +} + +void WebPage::imageOrMediaDocumentSizeChanged(const IntSize& newSize) +{ + send(Messages::WebPageProxy::ImageOrMediaDocumentSizeChanged(newSize)); +} + +void WebPage::addUserScript(const String& source, WebCore::UserContentInjectedFrames injectedFrames, WebCore::UserScriptInjectionTime injectionTime) +{ + ASSERT(m_userContentController); + + WebCore::UserScript userScript(source, WebCore::blankURL(), Vector<String>(), Vector<String>(), injectionTime, injectedFrames); + + m_userContentController->userContentController().addUserScript(mainThreadNormalWorld(), std::make_unique<WebCore::UserScript>(userScript)); +} + +void WebPage::addUserStyleSheet(const String& source, WebCore::UserContentInjectedFrames injectedFrames) +{ + ASSERT(m_userContentController); + + WebCore::UserStyleSheet userStyleSheet(source, WebCore::blankURL(), Vector<String>(), Vector<String>(), injectedFrames, UserStyleUserLevel); + + m_userContentController->userContentController().addUserStyleSheet(mainThreadNormalWorld(), std::make_unique<WebCore::UserStyleSheet>(userStyleSheet), InjectInExistingDocuments); +} + +void WebPage::removeAllUserContent() +{ + if (!m_userContentController) + return; + + m_userContentController->userContentController().removeAllUserContent(); +} + +void WebPage::dispatchDidLayout(WebCore::LayoutMilestones milestones) +{ + RefPtr<API::Object> userData; + injectedBundleLoaderClient().didLayout(this, milestones, userData); + + // Clients should not set userData for this message, and it won't be passed through. + ASSERT(!userData); + + // The drawing area might want to defer dispatch of didLayout to the UI process. + if (m_drawingArea && m_drawingArea->dispatchDidLayout(milestones)) + return; + + send(Messages::WebPageProxy::DidLayout(milestones)); +} + +void WebPage::didRestoreScrollPosition() +{ + send(Messages::WebPageProxy::DidRestoreScrollPosition()); } } // namespace WebKit |