Port DOMTimer from std::chrono::milliseconds to WTF::Seconds type
[WebKit-https.git] / Source / WebKit / win / WebView.cpp
index 71587b0..3175be3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2015 Apple, Inc.  All rights reserved.
+ * Copyright (C) 2006-2016 Apple, Inc.  All rights reserved.
  * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
  * Copyright (C) 2011 Brent Fulgham. All rights reserved.
  *
 
 #include "WebView.h"
 
-#include "BackForwardController.h"
+#include "BackForwardList.h"
 #include "COMVariantSetter.h"
 #include "DOMCoreClasses.h"
 #include "FullscreenVideoController.h"
 #include "MarshallingHelpers.h"
 #include "PluginDatabase.h"
 #include "PluginView.h"
-#include "ResourceLoadScheduler.h"
+#include "SocketProvider.h"
 #include "SoftLinking.h"
 #include "SubframeLoader.h"
 #include "TextIterator.h"
+#include "WebApplicationCache.h"
 #include "WebBackForwardList.h"
 #include "WebChromeClient.h"
 #include "WebContextMenuClient.h"
@@ -66,7 +67,9 @@
 #include "WebMutableURLRequest.h"
 #include "WebNotificationCenter.h"
 #include "WebPlatformStrategies.h"
+#include "WebPluginInfoProvider.h"
 #include "WebPreferences.h"
+#include "WebResourceLoadScheduler.h"
 #include "WebScriptWorld.h"
 #include "WebStorageNamespaceProvider.h"
 #include "WebViewGroup.h"
 #include <JavaScriptCore/InitializeThreading.h>
 #include <JavaScriptCore/JSCJSValue.h>
 #include <JavaScriptCore/JSLock.h>
-#include <JavaScriptCore/Profile.h>
 #include <WebCore/AXObjectCache.h>
 #include <WebCore/ApplicationCacheStorage.h>
 #include <WebCore/BString.h>
 #include <WebCore/BackForwardController.h>
-#include <WebCore/BackForwardList.h>
 #include <WebCore/BitmapInfo.h>
 #include <WebCore/Chrome.h>
 #include <WebCore/ContextMenu.h>
 #include <WebCore/HitTestResult.h>
 #include <WebCore/IntRect.h>
 #include <WebCore/JSElement.h>
-#include <WebCore/JSScriptProfile.h>
 #include <WebCore/KeyboardEvent.h>
+#include <WebCore/LibWebRTCProvider.h>
+#include <WebCore/LogInitialization.h>
 #include <WebCore/Logging.h>
 #include <WebCore/MIMETypeRegistry.h>
 #include <WebCore/MainFrame.h>
 #include <WebCore/MemoryCache.h>
-#include <WebCore/MemoryPressureHandler.h>
+#include <WebCore/MemoryRelease.h>
 #include <WebCore/NotImplemented.h>
 #include <WebCore/Page.h>
 #include <WebCore/PageCache.h>
 #include <WebCore/WindowMessageBroadcaster.h>
 #include <WebCore/WindowsTouch.h>
 #include <bindings/ScriptValue.h>
+#include <comdef.h>
+#include <d2d1.h>
 #include <wtf/MainThread.h>
 #include <wtf/RAMSize.h>
+#include <wtf/UniqueRef.h>
 
 #if USE(CG)
 #include <CoreGraphics/CGContext.h>
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
-#if USE(CFNETWORK)
+#if USE(CFURLCONNECTION)
 #include <CFNetwork/CFURLCachePriv.h>
 #include <CFNetwork/CFURLProtocolPriv.h>
 #include <WebKitSystemInterface/WebKitSystemInterface.h>
 #include <wtf/text/StringConcatenate.h>
 #include <wtf/win/GDIObject.h>
 
+#define WEBKIT_DRAWING 4
+
 // Soft link functions for gestures and panning feedback
 SOFT_LINK_LIBRARY(USER32);
 SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO));
@@ -402,7 +409,7 @@ bool WebView::s_allowSiteSpecificHacks = false;
 WebView::WebView()
 {
     JSC::initializeThreading();
-    WTF::initializeMainThread();
+    RunLoop::initializeMainRunLoop();
 
     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
 
@@ -490,11 +497,11 @@ void WebView::setCacheModel(WebCacheModel cacheModel)
 
     String cacheDirectory;
 
-#if USE(CFNETWORK)
+#if USE(CFURLCONNECTION)
     RetainPtr<CFURLCacheRef> cfurlCache = adoptCF(CFURLCacheCopySharedURLCache());
     RetainPtr<CFStringRef> cfurlCacheDirectory = adoptCF(wkCopyFoundationCacheDirectory(0));
     if (!cfurlCacheDirectory) {
-        RetainPtr<CFPropertyListRef> preference = adoptCF(CFPreferencesCopyAppValue(WebKitLocalCacheDefaultsKey, kCFPreferencesCurrentApplication));
+        RetainPtr<CFPropertyListRef> preference = adoptCF(CFPreferencesCopyAppValue(WebKitLocalCacheDefaultsKey, WebPreferences::applicationId()));
         if (preference && (CFStringGetTypeID() == CFGetTypeID(preference.get())))
             cfurlCacheDirectory = adoptCF(static_cast<CFStringRef>(preference.leakRef()));
         else
@@ -544,7 +551,7 @@ void WebView::setCacheModel(WebCacheModel cacheModel)
         // Memory cache capacity (in bytes)
         cacheMemoryCapacity = 0;
 
-#if USE(CFNETWORK)
+#if USE(CFURLCONNECTION)
         // Foundation disk cache capacity (in bytes)
         cacheDiskCapacity = CFURLCacheDiskCapacity(cfurlCache.get());
 #endif
@@ -668,7 +675,7 @@ void WebView::setCacheModel(WebCacheModel cacheModel)
     memoryCache.setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
     PageCache::singleton().setMaxSize(pageCacheSize);
 
-#if USE(CFNETWORK)
+#if USE(CFURLCONNECTION)
     // Don't shrink a big disk cache, since that would cause churn.
     cacheDiskCapacity = max(cacheDiskCapacity, CFURLCacheDiskCapacity(cfurlCache.get()));
 
@@ -762,12 +769,14 @@ HRESULT WebView::close()
     setUIDelegate(0);
     setFormDelegate(0);
 
-    m_inspectorClient = 0;
+    m_inspectorClient = nullptr;
     if (m_webInspector)
-        m_webInspector->webViewClosed();
+        m_webInspector->inspectedWebViewClosed();
 
     delete m_page;
-    m_page = 0;
+    m_page = nullptr;
+
+    m_mainFrame = nullptr;
 
     registerForIconNotification(false);
     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
@@ -826,6 +835,11 @@ void WebView::deleteBackingStore()
         m_deleteBackingStoreTimerActive = false;
     }
     m_backingStoreBitmap = nullptr;
+#if USE(DIRECT2D)
+    m_backingStoreD2DBitmap = nullptr;
+    m_backingStoreGdiInterop = nullptr;
+    m_backingStoreRenderTarget = nullptr;
+#endif
     m_backingStoreDirtyRegion = nullptr;
     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
 }
@@ -839,12 +853,50 @@ bool WebView::ensureBackingStore()
     if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) {
         deleteBackingStore();
 
+#if USE(DIRECT2D)
+        auto bitmapSize = D2D1::SizeF(width, height);
+        auto pixelSize = D2D1::SizeU(width, height);
+
+        if (!m_renderTarget) {
+            // Create a Direct2D render target.
+            auto renderTargetProperties = D2D1::RenderTargetProperties();
+            renderTargetProperties.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
+            auto hwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(m_viewWindow, pixelSize);
+            HRESULT hr = GraphicsContext::systemFactory()->CreateHwndRenderTarget(&renderTargetProperties, &hwndRenderTargetProperties, &m_renderTarget);
+            if (!SUCCEEDED(hr))
+                return false;
+        }
+
+        COMPtr<ID2D1SolidColorBrush> brush;
+        m_renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::BlueViolet), &brush);
+
+        m_renderTarget->BeginDraw();
+        m_renderTarget->FillRoundedRectangle(D2D1::RoundedRect(D2D1::RectF(100.0f, 100.0f, 300.0f, 200.0f), 20.0f, 20.0f), brush.get());
+        m_renderTarget->EndDraw();
+#endif
         m_backingStoreSize.cx = width;
         m_backingStoreSize.cy = height;
         BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(m_backingStoreSize));
 
         void* pixels = NULL;
         m_backingStoreBitmap = SharedGDIObject<HBITMAP>::create(adoptGDIObject(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0)));
+
+#if USE(DIRECT2D)
+        HRESULT hr = m_renderTarget->CreateCompatibleRenderTarget(&bitmapSize, &pixelSize, nullptr, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, &m_backingStoreRenderTarget);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+
+        hr = m_backingStoreRenderTarget->GetBitmap(&m_backingStoreD2DBitmap);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+
+        hr = m_backingStoreRenderTarget->QueryInterface(__uuidof(ID2D1GdiInteropRenderTarget), (void**)&m_backingStoreGdiInterop);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+
+        COMPtr<ID2D1SolidColorBrush> brush2;
+        m_backingStoreRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::SeaGreen), &brush2);
+        m_backingStoreRenderTarget->BeginDraw();
+        m_renderTarget->FillRoundedRectangle(D2D1::RoundedRect(D2D1::RectF(100.0f, 100.0f, 300.0f, 200.0f), 20.0f, 20.0f), brush2.get());
+        m_renderTarget->EndDraw();
+#endif
         return true;
     }
 
@@ -870,7 +922,7 @@ void WebView::addToDirtyRegion(const IntRect& dirtyRect)
 
     auto newRegion = adoptGDIObject(::CreateRectRgn(dirtyRect.x(), dirtyRect.y(),
         dirtyRect.maxX(), dirtyRect.maxY()));
-    addToDirtyRegion(WTF::move(newRegion));
+    addToDirtyRegion(WTFMove(newRegion));
 }
 
 void WebView::addToDirtyRegion(GDIObject<HRGN> newRegion)
@@ -884,9 +936,9 @@ void WebView::addToDirtyRegion(GDIObject<HRGN> newRegion)
     if (m_backingStoreDirtyRegion) {
         auto combinedRegion = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
         ::CombineRgn(combinedRegion.get(), m_backingStoreDirtyRegion->get(), newRegion.get(), RGN_OR);
-        m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTF::move(combinedRegion));
+        m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTFMove(combinedRegion));
     } else
-        m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTF::move(newRegion));
+        m_backingStoreDirtyRegion = SharedGDIObject<HRGN>::create(WTFMove(newRegion));
 
     if (m_uiDelegatePrivate)
         m_uiDelegatePrivate->webViewDidInvalidate(this);
@@ -906,6 +958,16 @@ void WebView::scrollBackingStore(FrameView* frameView, int logicalDx, int logica
     FloatRect clipRect(logicalClipRect);
     clipRect.scale(scaleFactor);
 
+#if USE(DIRECT2D)
+    RECT scrollRectWin(scrollViewRect);
+    RECT clipRectWin(enclosingIntRect(clipRect));
+    RECT updateRect;
+    ::ScrollWindowEx(m_viewWindow, dx, dy, &scrollRectWin, &clipRectWin, nullptr, &updateRect, 0);
+    ::InvalidateRect(m_viewWindow, &updateRect, FALSE);
+
+    if (m_uiDelegatePrivate)
+        m_uiDelegatePrivate->webViewScrolled(this);
+#else
     if (isAcceleratedCompositing()) {
         // FIXME: We should be doing something smarter here, like moving tiles around and painting
         // any newly-exposed tiles. <http://webkit.org/b/52714>
@@ -934,6 +996,15 @@ void WebView::scrollBackingStore(FrameView* frameView, int logicalDx, int logica
     HWndDC windowDC(m_viewWindow);
     auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(windowDC));
     HGDIOBJ oldBitmap = ::SelectObject(bitmapDC.get(), m_backingStoreBitmap->get());
+    if (!oldBitmap) {
+        // The ::SelectObject call will fail if m_backingStoreBitmap is already selected into a device context.
+        // This happens when this method is called indirectly from WebView::updateBackingStore during normal WM_PAINT handling.
+        // There is no point continuing, since we would just be scrolling a 1x1 bitmap which is selected into the device context by default.
+        // We can just scroll by repainting the scroll rectangle.
+        RECT scrollRect(scrollViewRect);
+        ::InvalidateRect(m_viewWindow, &scrollRect, FALSE);
+        return;
+    }
 
     // Scroll the bitmap.
     RECT scrollRectWin(scrollViewRect);
@@ -946,7 +1017,7 @@ void WebView::scrollBackingStore(FrameView* frameView, int logicalDx, int logica
     GdiFlush();
 
     // Add the dirty region to the backing store's dirty region.
-    addToDirtyRegion(WTF::move(updateRegion));
+    addToDirtyRegion(WTFMove(updateRegion));
 
     if (m_uiDelegatePrivate)
         m_uiDelegatePrivate->webViewScrolled(this);
@@ -956,6 +1027,7 @@ void WebView::scrollBackingStore(FrameView* frameView, int logicalDx, int logica
 
     // Clean up.
     ::SelectObject(bitmapDC.get(), oldBitmap);
+#endif // USE(DIRECT2D)
 }
 
 void WebView::sizeChanged(const IntSize& newSize)
@@ -982,6 +1054,20 @@ void WebView::sizeChanged(const IntSize& newSize)
     if (m_acceleratedCompositingContext)
         m_acceleratedCompositingContext->resizeRootLayer(newSize);
 #endif
+
+#if USE(DIRECT2D)
+    if (m_renderTarget) {
+        m_renderTarget->Resize(newSize);
+        return;
+    }
+
+    // Create a Direct2D render target.
+    auto renderTargetProperties = D2D1::RenderTargetProperties();
+    renderTargetProperties.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
+    auto hwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(m_viewWindow, newSize, D2D1_PRESENT_OPTIONS_IMMEDIATELY);
+    HRESULT hr = GraphicsContext::systemFactory()->CreateHwndRenderTarget(&renderTargetProperties, &hwndRenderTargetProperties, &m_renderTarget);
+    ASSERT(SUCCEEDED(hr));
+#endif
 }
 
 bool WebView::dpiChanged(float, const WebCore::IntSize& newSize)
@@ -1042,6 +1128,13 @@ void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStore
 
     LOCAL_GDI_COUNTER(0, __FUNCTION__);
 
+#if USE(DIRECT2D)
+    if (!m_backingStoreGdiInterop) {
+        HRESULT hr = m_backingStoreRenderTarget->QueryInterface(__uuidof(ID2D1GdiInteropRenderTarget), (void**)&m_backingStoreGdiInterop);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+    }
+#endif
+
     GDIObject<HDC> bitmapDCObject;
 
     HDC bitmapDC = dc;
@@ -1051,6 +1144,10 @@ void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStore
         bitmapDCObject = adoptGDIObject(::CreateCompatibleDC(windowDC));
         bitmapDC = bitmapDCObject.get();
         oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->get());
+#if USE(DIRECT2D)
+        HRESULT hr = m_backingStoreGdiInterop->GetDC(D2D1_DC_INITIALIZE_MODE_COPY, &bitmapDC);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+#endif
     }
 
     if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
@@ -1079,8 +1176,12 @@ void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStore
         m_backingStoreDirtyRegion = nullptr;
     }
 
-    if (!dc)
+    if (!dc) {
         ::SelectObject(bitmapDC, oldBitmap);
+#if USE(DIRECT2D)
+        m_backingStoreGdiInterop->ReleaseDC(nullptr);
+#endif
+    }
 
     GdiFlush();
 
@@ -1115,27 +1216,77 @@ void WebView::performLayeredWindowUpdate()
     m_needsDisplay = false;
 }
 
-void WebView::paint(HDC dc, LPARAM options)
+void WebView::paintWithDirect2D()
 {
-    LOCAL_GDI_COUNTER(0, __FUNCTION__);
+#if USE(DIRECT2D)
+    Frame* coreFrame = core(m_mainFrame);
+    if (!coreFrame)
+        return;
+    FrameView* frameView = coreFrame->view();
+    frameView->updateLayoutAndStyleIfNeededRecursive();
 
-    if (isAcceleratedCompositing() && !usesLayeredWindow()) {
-#if USE(CA)
-        m_layerTreeHost->flushPendingLayerChangesNow();
-#elif USE(TEXTURE_MAPPER_GL)
-        m_acceleratedCompositingContext->flushAndRenderLayers();
-#endif
-        // Flushing might have taken us out of compositing mode.
-        if (isAcceleratedCompositing()) {
-#if USE(CA)
-            // FIXME: We need to paint into dc (if provided). <http://webkit.org/b/52578>
-            m_layerTreeHost->paint();
-#endif
-            ::ValidateRect(m_viewWindow, 0);
+    if (!m_renderTarget) {
+        // Create a Direct2D render target.
+        auto renderTargetProperties = D2D1::RenderTargetProperties();
+        renderTargetProperties.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
+
+        RECT rect;
+        ::GetClientRect(m_viewWindow, &rect);
+
+        IntRect clientRect(rect);
+
+        auto pixelSize = D2D1::SizeU(clientRect.width(), clientRect.height());
+
+        auto hwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(m_viewWindow, pixelSize, D2D1_PRESENT_OPTIONS_IMMEDIATELY);
+        HRESULT hr = GraphicsContext::systemFactory()->CreateHwndRenderTarget(&renderTargetProperties, &hwndRenderTargetProperties, &m_renderTarget);
+        if (!SUCCEEDED(hr))
             return;
+    }
+
+    RECT clientRect = {};
+    GraphicsContext gc(m_renderTarget.get());
+
+    {
+        m_renderTarget->SetTags(WEBKIT_DRAWING, __LINE__);
+        m_renderTarget->Clear();
+
+        // Direct2D honors the scale factor natively.
+        float scaleFactor = 1.0f;
+        float inverseScaleFactor = 1.0f / scaleFactor;
+
+        GetClientRect(m_viewWindow, &clientRect);
+
+        IntRect dirtyRectPixels(0, 0, clientRect.right, clientRect.bottom);
+        FloatRect logicalDirtyRectFloat = dirtyRectPixels;
+        logicalDirtyRectFloat.scale(inverseScaleFactor);
+        IntRect logicalDirtyRect(enclosingIntRect(logicalDirtyRectFloat));
+
+        if (frameView && frameView->frame().contentRenderer()) {
+            gc.save();
+            gc.scale(FloatSize(scaleFactor, scaleFactor));
+            gc.clip(logicalDirtyRect);
+            frameView->paint(gc, logicalDirtyRect);
+            gc.restore();
+            if (m_shouldInvertColors)
+                gc.fillRect(logicalDirtyRect, Color::white, CompositeDifference);
         }
     }
 
+    ::ValidateRect(m_viewWindow, &clientRect);
+#else
+    ASSERT_NOT_REACHED();
+#endif
+}
+
+void WebView::paint(HDC dc, LPARAM options)
+{
+    LOCAL_GDI_COUNTER(0, __FUNCTION__);
+
+    if (paintCompositedContentToHDC(dc)) {
+        ::ValidateRect(m_viewWindow, nullptr);
+        return;
+    }
+
     Frame* coreFrame = core(m_mainFrame);
     if (!coreFrame)
         return;
@@ -1195,8 +1346,18 @@ void WebView::paint(HDC dc, LPARAM options)
 
     ::SelectObject(bitmapDC.get(), oldBitmap);
 
-    if (!dc)
+    if (!dc) {
         EndPaint(m_viewWindow, &ps);
+#if USE(DIRECT2D)
+        HRESULT hr = m_backingStoreRenderTarget->EndDraw();
+        // FIXME: Recognize and recover from error state:
+        RELEASE_ASSERT(SUCCEEDED(hr));
+#endif
+    }
+
+#if USE(DIRECT2D)
+    m_backingStoreGdiInterop->ReleaseDC(nullptr);
+#endif
 
     m_paintCount--;
 
@@ -1238,6 +1399,10 @@ void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const In
     logicalDirtyRectFloat.scale(inverseScaleFactor);    
     IntRect logicalDirtyRect(enclosingIntRect(logicalDirtyRectFloat));
 
+#if USE(DIRECT2D)
+    m_backingStoreRenderTarget = nullptr;
+#endif
+
     GraphicsContext gc(bitmapDC, m_transparent);
     gc.setShouldIncludeChildWindows(windowsToPaint == PaintWebViewAndChildren);
     gc.save();
@@ -1254,10 +1419,10 @@ void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const In
         gc.save();
         gc.scale(FloatSize(scaleFactor, scaleFactor));
         gc.clip(logicalDirtyRect);
-        frameView->paint(&gc, logicalDirtyRect);
+        frameView->paint(gc, logicalDirtyRect);
         gc.restore();
         if (m_shouldInvertColors)
-            gc.fillRect(logicalDirtyRect, Color::white, ColorSpaceDeviceRGB, CompositeDifference);
+            gc.fillRect(logicalDirtyRect, Color::white, CompositeDifference);
     }
     gc.restore();
 }
@@ -1377,16 +1542,12 @@ void WebView::closeWindow()
 
 bool WebView::canHandleRequest(const WebCore::ResourceRequest& request)
 {
-    // On the mac there's an about url protocol implementation but CFNetwork doesn't have that.
-    if (equalIgnoringCase(String(request.url().protocol()), "about"))
+#if USE(CFURLCONNECTION)
+    // On the Mac there's an about URL protocol implementation but Windows CFNetwork doesn't have that.
+    if (request.url().protocolIs("about"))
         return true;
 
-#if USE(CFNETWORK)
-    if (CFURLProtocolCanHandleRequest(request.cfURLRequest(UpdateHTTPBody)))
-        return true;
-
-    // FIXME: Mac WebKit calls _representationExistsForURLScheme here
-    return false;
+    return CFURLProtocolCanHandleRequest(request.cfURLRequest(UpdateHTTPBody));
 #else
     return true;
 #endif
@@ -1405,6 +1566,63 @@ Page* WebView::page()
     return m_page;
 }
 
+static HMENU createContextMenuFromItems(const Vector<ContextMenuItem>& items)
+{
+    HMENU menu = ::CreatePopupMenu();
+
+    for (auto& item : items) {
+        UINT flags = 0;
+
+        flags |= item.enabled() ? MF_ENABLED : MF_DISABLED;
+        flags |= item.checked() ? MF_CHECKED : MF_UNCHECKED;
+
+        switch (item.type()) {
+        case ActionType:
+        case CheckableActionType:
+            ::AppendMenu(menu, flags | MF_STRING, item.action(), item.title().charactersWithNullTermination().data());
+            break;
+        case SeparatorType:
+            ::AppendMenu(menu, flags | MF_SEPARATOR, item.action(), nullptr);
+            break;
+        case SubmenuType:
+            ::AppendMenu(menu, flags | MF_POPUP, (UINT_PTR)createContextMenuFromItems(item.subMenuItems()), item.title().charactersWithNullTermination().data());
+            break;
+        }
+    }
+
+    return menu;
+}
+
+HMENU WebView::createContextMenu()
+{
+    auto& contextMenuController = m_page->contextMenuController();
+
+    ContextMenu* coreMenu = contextMenuController.contextMenu();
+    if (!coreMenu)
+        return nullptr;
+
+    HMENU contextMenu = createContextMenuFromItems(coreMenu->items());
+
+    COMPtr<IWebUIDelegate> uiDelegate;
+    if (SUCCEEDED(this->uiDelegate(&uiDelegate))) {
+        ASSERT(uiDelegate);
+
+        COMPtr<WebElementPropertyBag> propertyBag;
+        propertyBag.adoptRef(WebElementPropertyBag::createInstance(contextMenuController.hitTestResult()));
+
+        HMENU newMenu = nullptr;
+        if (SUCCEEDED(uiDelegate->contextMenuItemsForElement(this, propertyBag.get(), contextMenu, &newMenu))) {
+            // Make sure to delete the old menu if the delegate returned a new menu.
+            if (newMenu != contextMenu) {
+                ::DestroyMenu(contextMenu);
+                contextMenu = newMenu;
+            }
+        }
+    }
+
+    return contextMenu;
+}
+
 bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
 {
     // Translate the screen coordinates into window coordinates
@@ -1440,7 +1658,7 @@ bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
     Frame* targetFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document().frame() : &m_page->focusController().focusedOrMainFrame();
 
     targetFrame->view()->setCursor(pointerCursor());
-    PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam);
+    PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, makeScaledPoint(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)), deviceScaleFactor()));
     bool handledEvent = targetFrame->eventHandler().sendContextMenuEvent(mouseEvent);
     if (!handledEvent)
         return false;
@@ -1468,17 +1686,26 @@ bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
     if (!::ClientToScreen(m_viewWindow, &point))
         return false;
 
+    if (m_currentContextMenu)
+        ::DestroyMenu(m_currentContextMenu);
+    m_currentContextMenu = createContextMenu();
+
+    MENUINFO menuInfo;
+    menuInfo.cbSize = sizeof(menuInfo);
+    menuInfo.fMask = MIM_STYLE;
+    menuInfo.dwStyle = MNS_NOTIFYBYPOS;
+    ::SetMenuInfo(m_currentContextMenu, &menuInfo);
+
     BOOL hasCustomMenus = false;
     if (m_uiDelegate)
         m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
 
     if (hasCustomMenus)
-        m_uiDelegate->trackCustomPopupMenu((IWebView*)this, coreMenu->platformContextMenu(), &point);
+        m_uiDelegate->trackCustomPopupMenu((IWebView*)this, m_currentContextMenu, &point);
     else {
         // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button
-        UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL
-            | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
-        ::TrackPopupMenuEx(coreMenu->platformContextMenu(), flags, point.x, point.y, m_viewWindow, 0);
+        UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
+        ::TrackPopupMenuEx(m_currentContextMenu, flags, point.x, point.y, m_viewWindow, 0);
     }
 
     return true;
@@ -1548,15 +1775,40 @@ bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
     return true;
 }
 
-void WebView::performContextMenuAction(WPARAM wParam, LPARAM lParam, bool byPosition)
+void WebView::onMenuCommand(WPARAM wParam, LPARAM lParam)
 {
-    ContextMenu* menu = m_page->contextMenuController().contextMenu();
-    ASSERT(menu);
+    HMENU hMenu = reinterpret_cast<HMENU>(lParam);
+    unsigned index = static_cast<unsigned>(wParam);
 
-    ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam) : menu->itemWithAction((ContextMenuAction)wParam);
-    if (!item)
+    MENUITEMINFO menuItemInfo = { 0 };
+    menuItemInfo.cbSize = sizeof(menuItemInfo);
+    menuItemInfo.fMask = MIIM_STRING;
+    ::GetMenuItemInfo(hMenu, index, true, &menuItemInfo);
+
+    auto buffer = std::make_unique<WCHAR[]>(menuItemInfo.cch + 1);
+    menuItemInfo.dwTypeData = buffer.get();
+    menuItemInfo.cch++;
+    menuItemInfo.fMask |= MIIM_ID;
+
+    ::GetMenuItemInfo(hMenu, index, true, &menuItemInfo);
+
+    ::DestroyMenu(m_currentContextMenu);
+    m_currentContextMenu = nullptr;
+
+    String title(buffer.get(), menuItemInfo.cch);
+    ContextMenuAction action = static_cast<ContextMenuAction>(menuItemInfo.wID);
+
+    if (action >= ContextMenuItemBaseApplicationTag) {
+        if (m_uiDelegate) {
+            COMPtr<WebElementPropertyBag> propertyBag;
+            propertyBag.adoptRef(WebElementPropertyBag::createInstance(m_page->contextMenuController().hitTestResult()));
+
+            m_uiDelegate->contextMenuItemSelected(this, &menuItemInfo, propertyBag.get());
+        }
         return;
-    m_page->contextMenuController().contextMenuItemSelected(item);
+    }
+
+    m_page->contextMenuController().contextMenuItemSelected(action, title);
 }
 
 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
@@ -1574,7 +1826,7 @@ bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
     // Create our event.
     // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position
     // of the event to be at (MINSHORT, MINSHORT).
-    LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : lParam;
+    LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : makeScaledPoint(IntPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)), deviceScaleFactor());
     PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, position, m_mouseActivated);
 
     setMouseActivated(false);
@@ -1663,7 +1915,7 @@ bool WebView::gestureNotify(WPARAM wParam, LPARAM lParam)
     IntPoint logicalGestureBeginPoint(gestureBeginPoint);
     logicalGestureBeginPoint.scale(inverseScaleFactor, inverseScaleFactor);
 
-    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent);
+    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowUserAgentShadowContent);
     for (Frame* childFrame = &m_page->mainFrame(); childFrame; childFrame = EventHandler::subframeForTargetNode(m_gestureTargetNode.get())) {
         FrameView* frameView = childFrame->view();
         if (!frameView)
@@ -1687,8 +1939,8 @@ bool WebView::gestureNotify(WPARAM wParam, LPARAM lParam)
         // The hit testing above won't detect if we've hit the main frame's vertical scrollbar. Check that manually now.
         RECT webViewRect;
         GetWindowRect(m_viewWindow, &webViewRect);
-        hitScrollbar = (view->verticalScrollbar() && (gestureBeginPoint.x > (webViewRect.right - view->verticalScrollbar()->theme()->scrollbarThickness()))) 
-            || (view->horizontalScrollbar() && (gestureBeginPoint.y > (webViewRect.bottom - view->horizontalScrollbar()->theme()->scrollbarThickness())));  
+        hitScrollbar = (view->verticalScrollbar() && (gestureBeginPoint.x > (webViewRect.right - view->verticalScrollbar()->theme().scrollbarThickness()))) 
+            || (view->horizontalScrollbar() && (gestureBeginPoint.y > (webViewRect.bottom - view->horizontalScrollbar()->theme().scrollbarThickness())));  
     }
 
     bool canBeScrolled = false;
@@ -1783,12 +2035,16 @@ bool WebView::gesture(WPARAM wParam, LPARAM lParam)
         float scaleFactor = deviceScaleFactor();
         IntSize logicalScrollDelta(-deltaX * scaleFactor, -deltaY * scaleFactor);
 
-        if (!m_gestureTargetNode || !m_gestureTargetNode->renderer()) {
+        RenderLayer* scrollableLayer = nullptr;
+        if (m_gestureTargetNode && m_gestureTargetNode->renderer() && m_gestureTargetNode->renderer()->enclosingLayer())
+            scrollableLayer = m_gestureTargetNode->renderer()->enclosingLayer()->enclosingScrollableLayer();
+
+        if (!scrollableLayer) {
             // We might directly hit the document without hitting any nodes
             coreFrame->view()->scrollBy(logicalScrollDelta);
             scrolledArea = coreFrame->view();
         } else
-            m_gestureTargetNode->renderer()->enclosingLayer()->enclosingScrollableLayer()->scrollByRecursively(logicalScrollDelta, WebCore::RenderLayer::ScrollOffsetClamped, &scrolledArea);
+            scrollableLayer->scrollByRecursively(logicalScrollDelta, WebCore::RenderLayer::ScrollOffsetClamped, &scrolledArea);
 
         if (!(UpdatePanningFeedbackPtr() && BeginPanningFeedbackPtr() && EndPanningFeedbackPtr())) {
             CloseGestureInfoHandlePtr()(gestureHandle);
@@ -2306,7 +2562,11 @@ LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam,
 
     switch (message) {
         case WM_PAINT: {
+#if USE(DIRECT2D)
+            webView->paintWithDirect2D();
+#else
             webView->paint(0, 0);
+#endif
             if (webView->usesLayeredWindow())
                 webView->performLayeredWindowUpdate();
             break;
@@ -2442,11 +2702,9 @@ LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam,
         case WM_COMMAND:
             if (HIWORD(wParam))
                 handled = webView->execCommand(wParam, lParam);
-            else // If the high word of wParam is 0, the message is from a menu
-                webView->performContextMenuAction(wParam, lParam, false);
             break;
         case WM_MENUCOMMAND:
-            webView->performContextMenuAction(wParam, lParam, true);
+            webView->onMenuCommand(wParam, lParam);
             break;
         case WM_CONTEXTMENU:
             handled = webView->handleContextMenuEvent(wParam, lParam);
@@ -2467,7 +2725,7 @@ LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam,
             if (Frame* coreFrame = core(mainFrameImpl)) {
                 webView->deleteBackingStore();
                 coreFrame->page()->theme().themeChanged();
-                ScrollbarTheme::theme()->themeChanged();
+                ScrollbarTheme::theme().themeChanged();
                 RECT windowRect;
                 ::GetClientRect(hWnd, &windowRect);
                 ::InvalidateRect(hWnd, &windowRect, false);
@@ -2627,6 +2885,10 @@ HRESULT WebView::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
         *ppvObject = static_cast<IWebViewPrivate*>(this);
     else if (IsEqualGUID(riid, IID_IWebViewPrivate2))
         *ppvObject = static_cast<IWebViewPrivate2*>(this);
+    else if (IsEqualGUID(riid, IID_IWebViewPrivate3))
+        *ppvObject = static_cast<IWebViewPrivate3*>(this);
+    else if (IsEqualGUID(riid, IID_IWebViewPrivate4))
+        *ppvObject = static_cast<IWebViewPrivate4*>(this);
     else if (IsEqualGUID(riid, IID_IWebIBActions))
         *ppvObject = static_cast<IWebIBActions*>(this);
     else if (IsEqualGUID(riid, IID_IWebViewCSS))
@@ -2753,26 +3015,6 @@ HRESULT WebView::URLTitleFromPasteboard(_In_opt_ IDataObject* /*pasteboard*/, _D
     return E_NOTIMPL;
 }
 
-static void WebKitSetApplicationCachePathIfNecessary()
-{
-    static bool initialized = false;
-    if (initialized)
-        return;
-
-    String path = localUserSpecificStorageDirectory();
-
-#if USE(CF)
-    RetainPtr<CFPropertyListRef> cacheDirectoryPreference = adoptCF(CFPreferencesCopyAppValue(WebKitLocalCacheDefaultsKey, kCFPreferencesCurrentApplication));
-    if (cacheDirectoryPreference && (CFStringGetTypeID() == CFGetTypeID(cacheDirectoryPreference.get())))
-        path = static_cast<CFStringRef>(cacheDirectoryPreference.get());
-#endif
-
-    if (!path.isNull())
-        ApplicationCacheStorage::singleton().setCacheDirectory(path);
-
-    initialized = true;
-}
-
 bool WebView::shouldInitializeTrackPointHack()
 {
     static bool shouldCreateScrollbars;
@@ -2832,18 +3074,21 @@ HRESULT WebView::initWithFrame(RECT frame, _In_ BSTR frameName, _In_ BSTR groupN
 
     static bool didOneTimeInitialization;
     if (!didOneTimeInitialization) {
-#if !LOG_DISABLED
-        initializeLoggingChannelsIfNecessary();
-#endif // !LOG_DISABLED
+#if !LOG_DISABLED || !RELEASE_LOG_DISABLED
+        initializeLogChannelsIfNecessary();
+#endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
 
         // Initialize our platform strategies first before invoking the rest
         // of the initialization code which may depend on the strategies.
         WebPlatformStrategies::initialize();
 
         WebKitInitializeWebDatabasesIfNecessary();
-        WebKitSetApplicationCachePathIfNecessary();
 
-        MemoryPressureHandler::singleton().install();
+        auto& memoryPressureHandler = MemoryPressureHandler::singleton();
+        memoryPressureHandler.setLowMemoryHandler([] (Critical critical, Synchronous synchronous) {
+            WebCore::releaseMemory(critical, synchronous);
+        });
+        memoryPressureHandler.install();
 
         didOneTimeInitialization = true;
      }
@@ -2854,20 +3099,26 @@ HRESULT WebView::initWithFrame(RECT frame, _In_ BSTR frameName, _In_ BSTR groupN
 
     m_inspectorClient = new WebInspectorClient(this);
 
-    PageConfiguration configuration;
+    PageConfiguration configuration(
+        makeUniqueRef<WebEditorClient>(this),
+        SocketProvider::create(),
+        makeUniqueRef<LibWebRTCProvider>()
+    );
+    configuration.backForwardClient = BackForwardList::create();
     configuration.chromeClient = new WebChromeClient(this);
     configuration.contextMenuClient = new WebContextMenuClient(this);
-    configuration.editorClient = new WebEditorClient(this);
     configuration.dragClient = new WebDragClient(this);
     configuration.inspectorClient = m_inspectorClient;
     configuration.loaderClientForMainFrame = new WebFrameLoaderClient;
+    configuration.applicationCacheStorage = &WebApplicationCache::storage();
     configuration.databaseProvider = &WebDatabaseProvider::singleton();
     configuration.storageNamespaceProvider = &m_webViewGroup->storageNamespaceProvider();
     configuration.progressTrackerClient = static_cast<WebFrameLoaderClient*>(configuration.loaderClientForMainFrame);
-    configuration.userContentController = &m_webViewGroup->userContentController();
+    configuration.userContentProvider = &m_webViewGroup->userContentController();
     configuration.visitedLinkStore = &m_webViewGroup->visitedLinkStore();
+    configuration.pluginInfoProvider = &WebPluginInfoProvider::singleton();
 
-    m_page = new Page(configuration);
+    m_page = new Page(WTFMove(configuration));
     provideGeolocationTo(m_page, new WebGeolocationClient(this));
 
     unsigned layoutMilestones = DidFirstLayout | DidFirstVisuallyNonEmptyLayout;
@@ -2906,6 +3157,7 @@ HRESULT WebView::initWithFrame(RECT frame, _In_ BSTR frameName, _In_ BSTR groupN
     m_page->setDeviceScaleFactor(deviceScaleFactor());
 
     setSmartInsertDeleteEnabled(TRUE);
+
     return hr;
 }
 
@@ -3185,7 +3437,7 @@ HRESULT WebView::backForwardList(_COM_Outptr_opt_ IWebBackForwardList** list)
     if (!m_useBackForwardList)
         return E_FAIL;
  
-    *list = WebBackForwardList::createInstance(static_cast<WebCore::BackForwardList*>(m_page->backForward().client()));
+    *list = WebBackForwardList::createInstance(static_cast<BackForwardList*>(m_page->backForward().client()));
 
     return S_OK;
 }
@@ -3430,7 +3682,7 @@ HRESULT WebView::stringByEvaluatingJavaScriptFromString(_In_ BSTR script, // ass
     if (!coreFrame)
         return E_UNEXPECTED;
 
-    JSC::JSValue scriptExecutionResult = coreFrame->script().executeScript(WTF::String(script), true).jsValue();
+    auto scriptExecutionResult = coreFrame->script().executeScript(WTF::String(script), true);
     if (!scriptExecutionResult)
         return E_FAIL;
     else if (scriptExecutionResult.isString()) {
@@ -3709,15 +3961,15 @@ HRESULT WebView::rectsForTextMatches(_COM_Outptr_opt_ IEnumTextMatches** pmatche
     do {
         if (Document* document = frame->document()) {
             IntRect visibleRect = frame->view()->visibleContentRect();
-            Vector<IntRect> frameRects = document->markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
-            IntPoint frameOffset(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
+            Vector<FloatRect> frameRects = document->markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
+            IntPoint frameOffset = -frame->view()->scrollPosition();
             frameOffset = frame->view()->convertToContainingWindow(frameOffset);
 
-            Vector<IntRect>::iterator end = frameRects.end();
-            for (Vector<IntRect>::iterator it = frameRects.begin(); it < end; it++) {
+            Vector<FloatRect>::iterator end = frameRects.end();
+            for (Vector<FloatRect>::iterator it = frameRects.begin(); it < end; it++) {
                 it->intersect(visibleRect);
                 it->move(frameOffset.x(), frameOffset.y());
-                allRects.append(*it);
+                allRects.append(enclosingIntRect(*it));
             }
         }
         frame = incrementFrame(frame, true, false);
@@ -3756,7 +4008,7 @@ HRESULT WebView::selectionRect(_Inout_ RECT* rc)
 
     IntRect ir = enclosingIntRect(frame.selection().selectionBounds());
     ir = frame.view()->convertToContainingWindow(ir);
-    ir.move(-frame.view()->scrollOffset().width(), -frame.view()->scrollOffset().height());
+    ir.moveBy(-frame.view()->scrollPosition());
 
     float scaleFactor = deviceScaleFactor();
     rc->left = ir.x() * scaleFactor;
@@ -3784,7 +4036,7 @@ HRESULT WebView::setGroupName(_In_ BSTR groupName)
     if (!m_page)
         return S_OK;
 
-    m_page->setUserContentController(&m_webViewGroup->userContentController());
+    m_page->setUserContentProvider(m_webViewGroup->userContentController());
     m_page->setVisitedLinkStore(m_webViewGroup->visitedLinkStore());
     m_page->setGroupName(toString(groupName));
     return S_OK;
@@ -3916,7 +4168,7 @@ HRESULT WebView::centerSelectionInVisibleArea(_In_opt_ IUnknown* /* sender */)
     if (!coreFrame)
         return E_UNEXPECTED;
 
-    coreFrame->selection().revealSelection(ScrollAlignment::alignCenterAlways);
+    coreFrame->selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignCenterAlways);
     return S_OK;
 }
 
@@ -4933,7 +5185,7 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
     settings.setShouldDisplayTextDescriptions(enabled);
 #endif
 
-    COMPtr<IWebPreferencesPrivate2> prefsPrivate(Query, preferences);
+    COMPtr<IWebPreferencesPrivate4> prefsPrivate(Query, preferences);
     if (prefsPrivate) {
         hr = prefsPrivate->localStorageDatabasePath(&str);
         if (FAILED(hr))
@@ -4978,15 +5230,56 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
         return hr;
     settings.setPluginsEnabled(!!enabled);
 
-    hr = preferences->isCSSRegionsEnabled(&enabled);
+    // FIXME: Add preferences for the runtime enabled features.
+
+#if ENABLE(FETCH_API)
+    hr = prefsPrivate->fetchAPIEnabled(&enabled);
+    if (FAILED(hr))
+        return hr;
+    RuntimeEnabledFeatures::sharedFeatures().setFetchAPIEnabled(!!enabled);
+#endif
+
+    hr = prefsPrivate->shadowDOMEnabled(&enabled);
+    if (FAILED(hr))
+        return hr;
+    RuntimeEnabledFeatures::sharedFeatures().setShadowDOMEnabled(!!enabled);
+
+    hr = prefsPrivate->customElementsEnabled(&enabled);
+    if (FAILED(hr))
+        return hr;
+    RuntimeEnabledFeatures::sharedFeatures().setCustomElementsEnabled(!!enabled);
+
+    hr = prefsPrivate->modernMediaControlsEnabled(&enabled);
     if (FAILED(hr))
         return hr;
-    RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled(!!enabled);
+    RuntimeEnabledFeatures::sharedFeatures().setModernMediaControlsEnabled(!!enabled);
+
+#if ENABLE(WEB_ANIMATIONS)
+    hr = prefsPrivate->webAnimationsEnabled(&enabled);
+    if (FAILED(hr))
+        return hr;
+    RuntimeEnabledFeatures::sharedFeatures().setWebAnimationsEnabled(!!enabled);
+#endif
+
+    hr = prefsPrivate->userTimingEnabled(&enabled);
+    if (FAILED(hr))
+        return hr;
+    RuntimeEnabledFeatures::sharedFeatures().setUserTimingEnabled(!!enabled);
+
+    hr = prefsPrivate->resourceTimingEnabled(&enabled);
+    if (FAILED(hr))
+        return hr;
+    RuntimeEnabledFeatures::sharedFeatures().setResourceTimingEnabled(!!enabled);
+
+    hr = prefsPrivate->linkPreloadEnabled(&enabled);
+    if (FAILED(hr))
+        return hr;
+    RuntimeEnabledFeatures::sharedFeatures().setLinkPreloadEnabled(!!enabled);
 
     hr = preferences->privateBrowsingEnabled(&enabled);
     if (FAILED(hr))
         return hr;
-#if PLATFORM(WIN) || USE(CFNETWORK)
+#if PLATFORM(WIN) || USE(CFURLCONNECTION)
     if (enabled)
         WebFrameNetworkingContext::ensurePrivateBrowsingSession();
     else
@@ -5089,7 +5382,7 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
     hr = preferences->fontSmoothing(&smoothingType);
     if (FAILED(hr))
         return hr;
-    settings.setFontRenderingMode(smoothingType != FontSmoothingTypeWindows ? NormalRenderingMode : AlternateRenderingMode);
+    settings.setFontRenderingMode(smoothingType != FontSmoothingTypeWindows ? FontRenderingMode::Normal : FontRenderingMode::Alternate);
 
 #if USE(AVFOUNDATION)
     hr = preferences->avFoundationEnabled(&enabled);
@@ -5166,6 +5459,9 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
 #if USE(TEXTURE_MAPPER_GL)
     static bool acceleratedCompositingAvailable = AcceleratedCompositingContext::acceleratedCompositingAvailable();
     enabled = enabled && acceleratedCompositingAvailable;
+#elif USE(DIRECT2D)
+    // Disable accelerated compositing for now.
+    enabled = false;
 #endif
     settings.setAcceleratedCompositingEnabled(enabled);
 
@@ -5179,6 +5475,11 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
         return hr;
     settings.setShowRepaintCounter(enabled);
 
+    hr = prefsPrivate->showTiledScrollingIndicator(&enabled);
+    if (FAILED(hr))
+        return hr;
+    settings.setShowTiledScrollingIndicator(!!enabled);
+
 #if ENABLE(WEB_AUDIO)
     settings.setWebAudioEnabled(true);
 #endif // ENABLE(WEB_AUDIO)
@@ -5225,7 +5526,8 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
     hr = prefsPrivate->mediaPlaybackRequiresUserGesture(&enabled);
     if (FAILED(hr))
         return hr;
-    settings.setRequiresUserGestureForMediaPlayback(enabled);
+    settings.setVideoPlaybackRequiresUserGesture(enabled);
+    settings.setAudioPlaybackRequiresUserGesture(enabled);
 
     hr = prefsPrivate->mediaPlaybackAllowsInline(&enabled);
     if (FAILED(hr))
@@ -5276,7 +5578,7 @@ HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences* preferences
     if (FAILED(hr))
         return hr;
 
-#if USE(CFNETWORK)
+#if USE(CFURLCONNECTION)
     WebFrameNetworkingContext::setCookieAcceptPolicyForAllContexts(acceptPolicy);
 #endif
 
@@ -5387,12 +5689,16 @@ HRESULT WebView::scrollOffset(_Out_ LPPOINT offset)
 {
     if (!offset)
         return E_POINTER;
-    IntSize offsetIntSize = m_page->mainFrame().view()->scrollOffset();
 
-    offsetIntSize.scale(deviceScaleFactor());
+    if (!m_page || !m_page->mainFrame().view())
+        return E_FAIL;
+
+    IntPoint scrollPosition = m_page->mainFrame().view()->scrollPosition();
+    float scaleFactor = deviceScaleFactor();
+    scrollPosition.scale(scaleFactor, scaleFactor);
 
-    offset->x = offsetIntSize.width();
-    offset->y = offsetIntSize.height();
+    offset->x = scrollPosition.x();
+    offset->y = scrollPosition.y();
     return S_OK;
 }
 
@@ -5401,6 +5707,9 @@ HRESULT WebView::scrollBy(_In_ LPPOINT offset)
     if (!offset)
         return E_POINTER;
 
+    if (!m_page || !m_page->mainFrame().view())
+        return E_FAIL;
+
     IntSize scrollDelta(offset->x, offset->y);
     scrollDelta.scale(1.0f / deviceScaleFactor());
     m_page->mainFrame().view()->scrollBy(scrollDelta);
@@ -5412,6 +5721,9 @@ HRESULT WebView::visibleContentRect(_Out_ LPRECT rect)
     if (!rect)
         return E_POINTER;
 
+    if (!m_page || !m_page->mainFrame().view())
+        return E_FAIL;
+
     FloatRect visibleContent = m_page->mainFrame().view()->visibleContentRect();
     visibleContent.scale(deviceScaleFactor());
     rect->left = (LONG) visibleContent.x();
@@ -5560,7 +5872,7 @@ HRESULT WebView::standardUserAgentWithApplicationName(_In_ BSTR applicationName,
 HRESULT WebView::clearFocusNode()
 {
     if (m_page)
-        m_page->focusController().setFocusedElement(0, 0);
+        m_page->focusController().setFocusedElement(nullptr, m_page->focusController().focusedOrMainFrame());
     return S_OK;
 }
 
@@ -5641,7 +5953,7 @@ HRESULT WebView::loadBackForwardListFromOtherView(_In_opt_ IWebView* otherView)
         Ref<HistoryItem> newItem = otherBackForward.itemAtIndex(i)->copy();
         if (!i) 
             newItemToGoTo = newItem.ptr();
-        backForward.client()->addItem(WTF::move(newItem));
+        backForward.client()->addItem(WTFMove(newItem));
     }
     
     ASSERT(newItemToGoTo);
@@ -5771,7 +6083,7 @@ void WebView::prepareCandidateWindow(Frame* targetFrame, HIMC hInputContext)
     IntRect caret;
     if (RefPtr<Range> range = targetFrame->selection().selection().toNormalizedRange()) {
         ExceptionCode ec = 0;
-        RefPtr<Range> tempRange = range->cloneRange(ec);
+        RefPtr<Range> tempRange = range->cloneRange();
         caret = targetFrame->editor().firstRectForRange(tempRange.get());
     }
     caret = targetFrame->view()->contentsToWindow(caret);
@@ -6030,9 +6342,8 @@ LRESULT WebView::onIMERequestCharPosition(Frame* targetFrame, IMECHARPOSITION* c
         return 0;
     IntRect caret;
     if (RefPtr<Range> range = targetFrame->editor().hasComposition() ? targetFrame->editor().compositionRange() : targetFrame->selection().selection().toNormalizedRange()) {
-        ExceptionCode ec = 0;
-        RefPtr<Range> tempRange = range->cloneRange(ec);
-        tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + charPos->dwCharPos, ec);
+        RefPtr<Range> tempRange = range->cloneRange();
+        tempRange->setStart(tempRange->startContainer(), tempRange->startOffset() + charPos->dwCharPos);
         caret = targetFrame->editor().firstRectForRange(tempRange.get());
     }
     caret = targetFrame->view()->contentsToWindow(caret);
@@ -6136,6 +6447,28 @@ HRESULT WebView::windowAncestryDidChange()
     return S_OK;
 }
 
+bool WebView::paintCompositedContentToHDC(HDC deviceContext)
+{
+    if (!isAcceleratedCompositing() || usesLayeredWindow())
+        return false;
+
+#if USE(CA)
+    m_layerTreeHost->flushPendingLayerChangesNow();
+#elif USE(TEXTURE_MAPPER_GL)
+    m_acceleratedCompositingContext->flushAndRenderLayers();
+#endif
+
+    // Flushing might have taken us out of compositing mode.
+    if (!isAcceleratedCompositing())
+        return false;
+
+#if USE(CA)
+    m_layerTreeHost->paint(deviceContext);
+#endif
+
+    return true;
+}
+
 HRESULT WebView::paintDocumentRectToContext(RECT rect, _In_ HDC deviceContext)
 {
     if (!deviceContext)
@@ -6144,6 +6477,9 @@ HRESULT WebView::paintDocumentRectToContext(RECT rect, _In_ HDC deviceContext)
     if (!m_mainFrame)
         return E_UNEXPECTED;
 
+    if (paintCompositedContentToHDC(deviceContext))
+        return S_OK;
+
     return m_mainFrame->paintDocumentRectToContext(rect, deviceContext);
 }
 
@@ -6155,6 +6491,9 @@ HRESULT WebView::paintScrollViewRectToContextAtPoint(RECT rect, POINT pt, _In_ H
     if (!m_mainFrame)
         return E_UNEXPECTED;
 
+    if (paintCompositedContentToHDC(deviceContext))
+        return S_OK;
+
     return m_mainFrame->paintScrollViewRectToContextAtPoint(rect, pt, deviceContext);
 }
 
@@ -6167,7 +6506,7 @@ HRESULT WebView::reportException(_In_ JSContextRef context, _In_ JSValueRef exce
     JSC::JSLockHolder lock(execState);
 
     // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView.
-    if (!toJSDOMWindow(execState->lexicalGlobalObject()))
+    if (!toJSDOMWindow(execState->vm(), execState->lexicalGlobalObject()))
         return E_FAIL;
 
     WebCore::reportException(execState, toJS(execState, exception));
@@ -6186,7 +6525,7 @@ HRESULT WebView::elementFromJS(_In_ JSContextRef context, _In_ JSValueRef nodeOb
 
     JSC::ExecState* exec = toJS(context);
     JSC::JSLockHolder lock(exec);
-    Element* elt = JSElement::toWrapped(toJS(exec, nodeObject));
+    Element* elt = JSElement::toWrapped(exec->vm(), toJS(exec, nodeObject));
     if (!elt)
         return E_FAIL;
 
@@ -6576,7 +6915,7 @@ HRESULT WebView::addUserScriptToGroup(_In_ BSTR groupName, _In_opt_ IWebScriptWo
     auto userScript = std::make_unique<UserScript>(source, toURL(url), toStringVector(whitelist, whitelistCount),
         toStringVector(blacklist, blacklistCount), injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd,
         injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
-    viewGroup->userContentController().addUserScript(world->world(), WTF::move(userScript));
+    viewGroup->userContentController().addUserScript(world->world(), WTFMove(userScript));
     return S_OK;
 }
 
@@ -6604,7 +6943,7 @@ HRESULT WebView::addUserStyleSheetToGroup(_In_ BSTR groupName, _In_opt_ IWebScri
     WebScriptWorld* world = reinterpret_cast<WebScriptWorld*>(iWorld);
     auto styleSheet = std::make_unique<UserStyleSheet>(source, toURL(url), toStringVector(whitelist, whitelistCount), toStringVector(blacklist, blacklistCount),
         injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly, UserStyleUserLevel);
-    viewGroup->userContentController().addUserStyleSheet(world->world(), WTF::move(styleSheet), InjectInExistingDocuments);
+    viewGroup->userContentController().addUserStyleSheet(world->world(), WTFMove(styleSheet), InjectInExistingDocuments);
     return S_OK;
 }
 
@@ -6682,7 +7021,16 @@ HRESULT WebView::removeUserStyleSheetsFromGroup(_In_ BSTR groupName, _In_opt_ IW
 
 HRESULT WebView::removeAllUserContentFromGroup(_In_ BSTR groupName)
 {
-    return E_NOTIMPL;
+    String group = toString(groupName);
+    if (group.isEmpty())
+        return E_FAIL;
+
+    auto viewGroup = WebViewGroup::get(group);
+    if (!viewGroup)
+        return S_OK;
+
+    viewGroup->userContentController().removeAllUserContent();
+    return S_OK;
 }
 
 HRESULT WebView::invalidateBackingStore(_In_ const RECT* rect)
@@ -6815,6 +7163,8 @@ void WebView::setAcceleratedCompositing(bool accelerated)
             m_layerTreeHost->setClient(this);
             ASSERT(m_viewWindow);
             m_layerTreeHost->setWindow(m_viewWindow);
+            m_layerTreeHost->setPage(page());
+            m_layerTreeHost->setScaleFactor(deviceScaleFactor());
 
             // FIXME: We could perhaps get better performance by never allowing this layer to
             // become tiled (or choosing a higher-than-normal tiling threshold).
@@ -6828,6 +7178,13 @@ void WebView::setAcceleratedCompositing(bool accelerated)
             m_backingLayer->setNeedsDisplay();
             m_layerTreeHost->setRootChildLayer(PlatformCALayer::platformCALayer(m_backingLayer->platformLayer()));
 
+#if !HAVE(CACFLAYER_SETCONTENTSSCALE)
+            TransformationMatrix m;
+            m.scale(deviceScaleFactor());
+            m_backingLayer->setAnchorPoint(FloatPoint3D());
+            m_backingLayer->setTransform(m);
+#endif
+
             // We aren't going to be using our backing store while we're in accelerated compositing
             // mode. But don't delete it immediately, in case we switch out of accelerated
             // compositing mode soon (e.g., if we're only compositing for a :hover animation).
@@ -6989,7 +7346,7 @@ void WebView::paintContents(const GraphicsLayer*, GraphicsContext& context, Grap
     context.save();
     context.scale(FloatSize(scaleFactor, scaleFactor));
     context.clip(logicalClip);
-    frame->view()->paint(&context, enclosingIntRect(logicalClip));
+    frame->view()->paint(context, enclosingIntRect(logicalClip));
     context.restore();
 }
 
@@ -7010,7 +7367,7 @@ void WebView::flushPendingGraphicsLayerChanges()
 #if USE(CA)
     // Updating layout might have taken us out of compositing mode.
     if (m_backingLayer)
-        m_backingLayer->flushCompositingStateForThisLayerOnly(view->viewportIsStable());
+        m_backingLayer->flushCompositingStateForThisLayerOnly();
 
     view->flushCompositingStateIncludingSubframes();
 #elif USE(TEXTURE_MAPPER_GL)
@@ -7110,7 +7467,7 @@ HRESULT WebView::defaultMinimumTimerInterval(_Out_ double* interval)
 {
     if (!interval)
         return E_POINTER;
-    *interval = DOMTimer::defaultMinimumInterval();
+    *interval = DOMTimer::defaultMinimumInterval().seconds();
     return S_OK;
 }
 
@@ -7119,7 +7476,7 @@ HRESULT WebView::setMinimumTimerInterval(double interval)
     if (!m_page)
         return E_FAIL;
 
-    page()->settings().setMinimumDOMTimerInterval(interval);
+    page()->settings().setMinimumDOMTimerInterval(Seconds { interval });
     return S_OK;
 }
 
@@ -7331,9 +7688,6 @@ HRESULT WebView::firstRectForCharacterRangeForTesting(UINT location, UINT length
 
     if (!range)
         return E_FAIL;
-    
-    ASSERT(range->startContainer());
-    ASSERT(range->endContainer());
      
     IntRect rect = frame.editor().firstRectForRange(range.get());
     resultIntRect = frame.view()->contentsToWindow(rect);
@@ -7377,7 +7731,7 @@ HRESULT WebView::selectedRangeForTesting(_Out_ UINT* location, _Out_ UINT* lengt
 HRESULT WebView::setLoadResourcesSerially(BOOL serialize)
 {
     WebPlatformStrategies::initialize();
-    resourceLoadScheduler()->setSerialLoadingEnabled(serialize);
+    webResourceLoadScheduler().setSerialLoadingEnabled(serialize);
     return S_OK;
 }
 
@@ -7393,7 +7747,7 @@ HRESULT WebView::scaleWebView(double scale, POINT origin)
 
 HRESULT WebView::dispatchPendingLoadRequests()
 {
-    resourceLoadScheduler()->servePendingRequests();
+    webResourceLoadScheduler().servePendingRequests();
     return S_OK;
 }
 
@@ -7419,7 +7773,7 @@ HRESULT WebView::setCustomBackingScaleFactor(double customScaleFactor)
 
     m_customDeviceScaleFactor = customScaleFactor;
 
-    if (oldScaleFactor != deviceScaleFactor())
+    if (m_page && oldScaleFactor != deviceScaleFactor())
         m_page->setDeviceScaleFactor(deviceScaleFactor());
 
     return S_OK;
@@ -7434,3 +7788,46 @@ HRESULT WebView::backingScaleFactor(_Out_ double* factor)
 
     return S_OK;
 }
+
+HRESULT WebView::layerTreeAsString(_Deref_opt_out_ BSTR* treeBstr)
+{
+    if (!treeBstr)
+        return E_POINTER;
+
+    *treeBstr = nullptr;
+
+#if USE(CA)
+    if (!m_layerTreeHost)
+        return S_OK;
+
+    String tree = m_layerTreeHost->layerTreeAsString();
+
+    *treeBstr = BString(tree).release();
+    if (!*treeBstr && tree.length())
+        return E_OUTOFMEMORY;
+#endif
+
+    return S_OK;
+}
+
+HRESULT WebView::findString(_In_ BSTR string, WebFindOptions options, _Deref_opt_out_ BOOL* found)
+{
+    if (!found)
+        return E_POINTER;
+
+    *found = m_page->findString(toString(string), options);
+    return S_OK;
+}
+
+HRESULT WebView::setVisibilityState(WebPageVisibilityState visibilityState)
+{
+    if (!m_page)
+        return E_FAIL;
+    
+    m_page->setIsVisible(visibilityState == WebPageVisibilityStateVisible);
+
+    if (visibilityState == WebPageVisibilityStatePrerender)
+        m_page->setIsPrerender();
+
+    return S_OK;
+}