Web Inspector: consolidate code that hosts the Inspector page inside a WKWebView
authorbburg@apple.com <bburg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Oct 2017 17:30:04 +0000 (17:30 +0000)
committerbburg@apple.com <bburg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Oct 2017 17:30:04 +0000 (17:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=177661
<rdar://problem/34740286>

Reviewed by Joseph Pecoraro.

Move setup and delegates of the inspector frontend page into implementations of
WebInspectorProxy::platformCreateFrontendPage. The Mac implementation
will be subsumed by WKInspectorViewController, while the GTK implementation
is inherited from the cross-platform version that uses C API. Eventually the
GTK version should use GTK API rather than the soon to be deprecated C API.

* UIProcess/WebInspectorProxy.cpp:
(WebKit::WebInspectorProxy::createFrontendPage):
(WebKit::webProcessDidCrash): Deleted.
(WebKit::decidePolicyForNavigationAction): Deleted.
(WebKit::getContextMenuFromProposedMenu): Deleted.
* UIProcess/gtk/WebInspectorProxyGtk.cpp:
(WebKit::exceededDatabaseQuota):
(WebKit::webProcessDidCrash):
(WebKit::decidePolicyForNavigationAction):
(WebKit::getContextMenuFromProposedMenu):
(WebKit::WebInspectorProxy::platformCreateFrontendPage):
* UIProcess/mac/WebInspectorProxyMac.mm:
(WebKit::exceededDatabaseQuota):
(WebKit::webProcessDidCrash):
(WebKit::decidePolicyForNavigationAction):
(WebKit::getContextMenuFromProposedMenu):
(WebKit::WebInspectorProxy::platformCreateFrontendPage):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@223774 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/WebInspectorProxy.cpp
Source/WebKit/UIProcess/WebInspectorProxy.h
Source/WebKit/UIProcess/gtk/WebInspectorProxyGtk.cpp
Source/WebKit/UIProcess/mac/WKInspectorViewController.h
Source/WebKit/UIProcess/mac/WKInspectorViewController.mm
Source/WebKit/UIProcess/mac/WebInspectorProxyMac.mm

index 18d7b4c..2bbe2e1 100644 (file)
@@ -6,6 +6,92 @@
 
         Reviewed by Joseph Pecoraro.
 
+        Move setup and delegates of the inspector frontend page into implementations of
+        WebInspectorProxy::platformCreateFrontendPage. The Mac implementation
+        will be subsumed by WKInspectorViewController, while the GTK implementation
+        is inherited from the cross-platform version that uses C API. Eventually the
+        GTK version should use GTK API rather than the soon to be deprecated C API.
+
+        * UIProcess/WebInspectorProxy.cpp:
+        (WebKit::WebInspectorProxy::createFrontendPage):
+        (WebKit::webProcessDidCrash): Deleted.
+        (WebKit::decidePolicyForNavigationAction): Deleted.
+        (WebKit::getContextMenuFromProposedMenu): Deleted.
+        * UIProcess/gtk/WebInspectorProxyGtk.cpp:
+        (WebKit::exceededDatabaseQuota):
+        (WebKit::webProcessDidCrash):
+        (WebKit::decidePolicyForNavigationAction):
+        (WebKit::getContextMenuFromProposedMenu):
+        (WebKit::WebInspectorProxy::platformCreateFrontendPage):
+        * UIProcess/mac/WebInspectorProxyMac.mm:
+        (WebKit::exceededDatabaseQuota):
+        (WebKit::webProcessDidCrash):
+        (WebKit::decidePolicyForNavigationAction):
+        (WebKit::getContextMenuFromProposedMenu):
+        (WebKit::WebInspectorProxy::platformCreateFrontendPage):
+
+2017-10-02  Brian Burg  <bburg@apple.com>
+
+        Web Inspector: consolidate code that hosts the Inspector page inside a WKWebView
+        https://bugs.webkit.org/show_bug.cgi?id=177661
+        <rdar://problem/34740286>
+
+        Reviewed by Joseph Pecoraro.
+
+        Adopt WKInspectorViewController in WebInspectorProxyMac to set up the
+        frontend's web view.
+
+        * UIProcess/WebInspectorProxy.cpp:
+        (WebKit::WebInspectorProxy::invalidate):
+        (WebKit::WebInspectorProxy::close):
+        (WebKit::WebInspectorProxy::didClose):
+        (WebKit::WebInspectorProxy::closeFrontendPageAndWindow):
+        Make closeFrontendPageAndWindow into the method that does work.
+        Only use didClose() as the IPC message entry point.
+
+        * UIProcess/WebInspectorProxy.h:
+        (WebKit::WebInspectorProxy::isUnderTest const): Make public.
+
+        * UIProcess/mac/WKInspectorViewController.h:
+        * UIProcess/mac/WKInspectorViewController.mm:
+        (+[WKInspectorViewController viewIsInspectorWebView:]):
+        Abstract away the -isInstanceOfClass: check for WKInspectorWKWebView.
+        Clients shouldn't need to know whether we use a subclass or what its name is.
+
+        * UIProcess/mac/WebInspectorProxyMac.mm:
+        (-[WKWebInspectorProxyObjCAdapter inspectorViewControllerInspectorDidCrash:]):
+        (-[WKWebInspectorProxyObjCAdapter inspectorViewControllerInspectorIsUnderTest:]):
+        Hook up view controller delegates.
+
+        (WebKit::WebInspectorProxy::platformCreateFrontendPage):
+        (WebKit::WebInspectorProxy::platformCreateFrontendWindow):
+        (WebKit::WebInspectorProxy::closeFrontendPage):
+        New implementation based on the view controller.
+
+        (WebKit::WebInspectorProxy::platformBringToFront):
+        (WebKit::WebInspectorProxy::platformIsFront):
+        (WebKit::WebInspectorProxy::platformCanAttach):
+        (WebKit::WebInspectorProxy::inspectedViewFrameDidChange):
+        (WebKit::WebInspectorProxy::platformAttach):
+        (WebKit::WebInspectorProxy::platformDetach):
+        (WebKit::WebInspectorProxy::platformStartWindowDrag):
+        Adjust to get the WKWebView out of the view controller for code that needs
+        to do something with the NSView, such as get/set the frame.
+
+        (WebKit::WebInspectorProxy::createFrontendConfiguration): Deleted.
+        (WebKit::exceededDatabaseQuota): Deleted.
+        (WebKit::webProcessDidCrash): Deleted.
+        (WebKit::decidePolicyForNavigationAction): Deleted.
+        (WebKit::getContextMenuFromProposedMenu): Deleted.
+
+2017-10-02  Brian Burg  <bburg@apple.com>
+
+        Web Inspector: consolidate code that hosts the Inspector page inside a WKWebView
+        https://bugs.webkit.org/show_bug.cgi?id=177661
+        <rdar://problem/34740286>
+
+        Reviewed by Joseph Pecoraro.
+
         Introduce new platform methods to open and close the frontend page and window.
         This matches how RemoteWebInspectorProxy divides work up into platform methods.
         Move existing code from platformDidClose, platformOpen, and other methods into
index 694762c..8d909cd 100644 (file)
 #include "config.h"
 #include "WebInspectorProxy.h"
 
-#include "APINavigationAction.h"
 #include "APIProcessPoolConfiguration.h"
-#include "WKArray.h"
-#include "WKContextMenuItem.h"
-#include "WKMutableArray.h"
 #include "WebAutomationSession.h"
-#include "WebFramePolicyListenerProxy.h"
 #include "WebFrameProxy.h"
 #include "WebInspectorInterruptDispatcherMessages.h"
 #include "WebInspectorMessages.h"
@@ -88,7 +83,7 @@ void WebInspectorProxy::invalidate()
 {
     m_inspectedPage->process().removeMessageReceiver(Messages::WebInspectorProxy::messageReceiverName(), m_inspectedPage->pageID());
 
-    didClose();
+    closeFrontendPageAndWindow();
     platformInvalidate();
 
     m_inspectedPage = nullptr;
@@ -153,7 +148,7 @@ void WebInspectorProxy::close()
 
     m_inspectedPage->process().send(Messages::WebInspector::Close(), m_inspectedPage->pageID());
 
-    didClose();
+    closeFrontendPageAndWindow();
 }
 
 void WebInspectorProxy::closeForCrash()
@@ -327,64 +322,6 @@ bool WebInspectorProxy::isMainOrTestInspectorPage(const URL& url)
     return url.protocol() == testPageURL.protocol() && decodeURLEscapeSequences(url.path()) == decodeURLEscapeSequences(testPageURL.path());
 }
 
-static void webProcessDidCrash(WKPageRef, const void* clientInfo)
-{
-    WebInspectorProxy* webInspectorProxy = static_cast<WebInspectorProxy*>(const_cast<void*>(clientInfo));
-    ASSERT(webInspectorProxy);
-    webInspectorProxy->closeForCrash();
-}
-
-static void decidePolicyForNavigationAction(WKPageRef pageRef, WKNavigationActionRef navigationActionRef, WKFramePolicyListenerRef listenerRef, WKTypeRef, const void* clientInfo)
-{
-    // Allow non-main frames to navigate anywhere.
-    API::FrameInfo* sourceFrame = toImpl(navigationActionRef)->sourceFrame();
-    if (sourceFrame && !sourceFrame->isMainFrame()) {
-        toImpl(listenerRef)->use({ });
-        return;
-    }
-
-    const WebInspectorProxy* webInspectorProxy = static_cast<const WebInspectorProxy*>(clientInfo);
-    ASSERT(webInspectorProxy);
-
-    WebCore::ResourceRequest request = toImpl(navigationActionRef)->request();
-
-    // Allow loading of the main inspector file.
-    if (WebInspectorProxy::isMainOrTestInspectorPage(request.url())) {
-        toImpl(listenerRef)->use({ });
-        return;
-    }
-
-    // Prevent everything else from loading in the inspector's page.
-    toImpl(listenerRef)->ignore();
-
-    // And instead load it in the inspected page.
-    webInspectorProxy->inspectedPage()->loadRequest(WTFMove(request));
-}
-
-static void getContextMenuFromProposedMenu(WKPageRef pageRef, WKArrayRef proposedMenuRef, WKArrayRef* newMenuRef, WKHitTestResultRef, WKTypeRef, const void*)
-{
-    WKMutableArrayRef menuItems = WKMutableArrayCreate();
-
-    size_t count = WKArrayGetSize(proposedMenuRef);
-    for (size_t i = 0; i < count; ++i) {
-        WKContextMenuItemRef contextMenuItem = static_cast<WKContextMenuItemRef>(WKArrayGetItemAtIndex(proposedMenuRef, i));
-        switch (WKContextMenuItemGetTag(contextMenuItem)) {
-        case kWKContextMenuItemTagOpenLinkInNewWindow:
-        case kWKContextMenuItemTagOpenImageInNewWindow:
-        case kWKContextMenuItemTagOpenFrameInNewWindow:
-        case kWKContextMenuItemTagOpenMediaInNewWindow:
-        case kWKContextMenuItemTagDownloadLinkToDisk:
-        case kWKContextMenuItemTagDownloadImageToDisk:
-            break;
-        default:
-            WKArrayAppendItem(menuItems, contextMenuItem);
-            break;
-        }
-    }
-
-    *newMenuRef = menuItems;
-}
-
 void WebInspectorProxy::createFrontendPage()
 {
     if (m_inspectorPage)
@@ -397,45 +334,6 @@ void WebInspectorProxy::createFrontendPage()
 
     trackInspectorPage(m_inspectorPage);
 
-    WKPageNavigationClientV0 navigationClient = {
-        { 0, this },
-        decidePolicyForNavigationAction,
-        nullptr, // decidePolicyForNavigationResponse
-        nullptr, // decidePolicyForPluginLoad
-        nullptr, // didStartProvisionalNavigation
-        nullptr, // didReceiveServerRedirectForProvisionalNavigation
-        nullptr, // didFailProvisionalNavigation
-        nullptr, // didCommitNavigation
-        nullptr, // didFinishNavigation
-        nullptr, // didFailNavigation
-        nullptr, // didFailProvisionalLoadInSubframe
-        nullptr, // didFinishDocumentLoad
-        nullptr, // didSameDocumentNavigation
-        nullptr, // renderingProgressDidChange
-        nullptr, // canAuthenticateAgainstProtectionSpace
-        nullptr, // didReceiveAuthenticationChallenge
-        webProcessDidCrash,
-        nullptr, // copyWebCryptoMasterKey
-
-        nullptr, // didBeginNavigationGesture
-        nullptr, // willEndNavigationGesture
-        nullptr, // didEndNavigationGesture
-        nullptr, // didRemoveNavigationGestureSnapshot
-    };
-
-    WKPageContextMenuClientV3 contextMenuClient = {
-        { 3, this },
-        nullptr, // getContextMenuFromProposedMenu_deprecatedForUseWithV0
-        nullptr, // customContextMenuItemSelected
-        nullptr, // contextMenuDismissed
-        getContextMenuFromProposedMenu,
-        nullptr, // showContextMenu
-        nullptr, // hideContextMenu
-    };
-
-    WKPageSetPageNavigationClient(toAPI(m_inspectorPage), &navigationClient.base);
-    WKPageSetPageContextMenuClient(toAPI(m_inspectorPage), &contextMenuClient.base);
-
     m_inspectorPage->process().addMessageReceiver(Messages::WebInspectorProxy::messageReceiverName(), m_inspectedPage->pageID(), *this);
     m_inspectorPage->process().assumeReadAccessToBaseURL(WebInspectorProxy::inspectorBaseURL());
 }
@@ -508,6 +406,11 @@ void WebInspectorProxy::open()
 
 void WebInspectorProxy::didClose()
 {
+    closeFrontendPageAndWindow();
+}
+
+void WebInspectorProxy::closeFrontendPageAndWindow()
+{
     if (!m_inspectorPage)
         return;
 
index da825a1..c1d2e27 100644 (file)
@@ -45,8 +45,7 @@ OBJC_CLASS NSURL;
 OBJC_CLASS NSView;
 OBJC_CLASS NSWindow;
 OBJC_CLASS WKWebInspectorProxyObjCAdapter;
-OBJC_CLASS WKWebInspectorWKWebView;
-OBJC_CLASS WKWebViewConfiguration;
+OBJC_CLASS WKInspectorViewController;
 #endif
 
 namespace WebCore {
@@ -92,7 +91,6 @@ public:
     void closeForCrash();
 
 #if PLATFORM(MAC) && WK_API_ENABLED
-    static RetainPtr<WKWebViewConfiguration> createFrontendConfiguration(WebPageProxy*, bool underTest);
     static RetainPtr<NSWindow> createFrontendWindow(NSRect savedWindowFrame);
 
     void updateInspectorWindowTitle() const;
@@ -139,6 +137,8 @@ public:
     bool isElementSelectionActive() const { return m_elementSelectionActive; }
     void toggleElementSelection();
 
+    bool isUnderTest() const { return m_underTest; }
+
     // Provided by platform WebInspectorProxy implementations.
     static String inspectorPageURL();
     static String inspectorTestPageURL();
@@ -155,6 +155,7 @@ private:
     explicit WebInspectorProxy(WebPageProxy*);
 
     void createFrontendPage();
+    void closeFrontendPageAndWindow();
 
     // IPC::MessageReceiver
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
@@ -202,8 +203,6 @@ private:
     bool canAttach() const { return m_canAttach; }
     bool shouldOpenAttached();
 
-    bool isUnderTest() const { return m_underTest; }
-
     void open();
 
     unsigned inspectionLevel() const;
@@ -232,7 +231,7 @@ private:
     AttachmentSide m_attachmentSide {AttachmentSide::Bottom};
 
 #if PLATFORM(MAC) && WK_API_ENABLED
-    RetainPtr<WKWebInspectorWKWebView> m_inspectorView;
+    RetainPtr<WKInspectorViewController> m_inspectorViewController;
     RetainPtr<NSWindow> m_inspectorWindow;
     RetainPtr<WKWebInspectorProxyObjCAdapter> m_objCAdapter;
     HashMap<String, RetainPtr<NSURL>> m_suggestedToActualURLMap;
index a785eff..865b393 100644 (file)
 #include "config.h"
 #include "WebInspectorProxy.h"
 
+#include "APINavigationAction.h"
+#include "WKArray.h"
+#include "WKContextMenuItem.h"
+#include "WKMutableArray.h"
+#include "WebFramePolicyListenerProxy.h"
 #include "WebInspectorProxyClient.h"
 #include "WebKitInspectorWindow.h"
 #include "WebKitWebViewBasePrivate.h"
@@ -52,11 +57,6 @@ static void inspectorViewDestroyed(GtkWidget*, gpointer userData)
     inspectorProxy->close();
 }
 
-static unsigned long long exceededDatabaseQuota(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKStringRef, WKStringRef, unsigned long long, unsigned long long, unsigned long long currentDatabaseUsage, unsigned long long expectedUsage, const void*)
-{
-    return std::max<unsigned long long>(expectedUsage, currentDatabaseUsage * 1.25);
-}
-
 void WebInspectorProxy::setClient(std::unique_ptr<WebInspectorProxyClient>&& client)
 {
     m_client = WTFMove(client);
@@ -68,6 +68,69 @@ void WebInspectorProxy::updateInspectorWindowTitle() const
     webkitInspectorWindowSetSubtitle(WEBKIT_INSPECTOR_WINDOW(m_inspectorWindow), !m_inspectedURLString.isEmpty() ? m_inspectedURLString.utf8().data() : nullptr);
 }
 
+static unsigned long long exceededDatabaseQuota(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKStringRef, WKStringRef, unsigned long long, unsigned long long, unsigned long long currentDatabaseUsage, unsigned long long expectedUsage, const void*)
+{
+    return std::max<unsigned long long>(expectedUsage, currentDatabaseUsage * 1.25);
+}
+
+static void webProcessDidCrash(WKPageRef, const void* clientInfo)
+{
+    WebInspectorProxy* webInspectorProxy = static_cast<WebInspectorProxy*>(const_cast<void*>(clientInfo));
+    ASSERT(webInspectorProxy);
+    webInspectorProxy->closeForCrash();
+}
+
+static void decidePolicyForNavigationAction(WKPageRef pageRef, WKNavigationActionRef navigationActionRef, WKFramePolicyListenerRef listenerRef, WKTypeRef, const void* clientInfo)
+{
+    // Allow non-main frames to navigate anywhere.
+    API::FrameInfo* sourceFrame = toImpl(navigationActionRef)->sourceFrame();
+    if (sourceFrame && !sourceFrame->isMainFrame()) {
+        toImpl(listenerRef)->use({ });
+        return;
+    }
+
+    const WebInspectorProxy* webInspectorProxy = static_cast<const WebInspectorProxy*>(clientInfo);
+    ASSERT(webInspectorProxy);
+
+    WebCore::ResourceRequest request = toImpl(navigationActionRef)->request();
+
+    // Allow loading of the main inspector file.
+    if (WebInspectorProxy::isMainOrTestInspectorPage(request.url())) {
+        toImpl(listenerRef)->use({ });
+        return;
+    }
+
+    // Prevent everything else from loading in the inspector's page.
+    toImpl(listenerRef)->ignore();
+
+    // And instead load it in the inspected page.
+    webInspectorProxy->inspectedPage()->loadRequest(WTFMove(request));
+}
+
+static void getContextMenuFromProposedMenu(WKPageRef pageRef, WKArrayRef proposedMenuRef, WKArrayRef* newMenuRef, WKHitTestResultRef, WKTypeRef, const void*)
+{
+    WKMutableArrayRef menuItems = WKMutableArrayCreate();
+
+    size_t count = WKArrayGetSize(proposedMenuRef);
+    for (size_t i = 0; i < count; ++i) {
+        WKContextMenuItemRef contextMenuItem = static_cast<WKContextMenuItemRef>(WKArrayGetItemAtIndex(proposedMenuRef, i));
+        switch (WKContextMenuItemGetTag(contextMenuItem)) {
+        case kWKContextMenuItemTagOpenLinkInNewWindow:
+        case kWKContextMenuItemTagOpenImageInNewWindow:
+        case kWKContextMenuItemTagOpenFrameInNewWindow:
+        case kWKContextMenuItemTagOpenMediaInNewWindow:
+        case kWKContextMenuItemTagDownloadLinkToDisk:
+        case kWKContextMenuItemTagDownloadImageToDisk:
+            break;
+        default:
+            WKArrayAppendItem(menuItems, contextMenuItem);
+            break;
+        }
+    }
+
+    *newMenuRef = menuItems;
+}
+
 WebPageProxy* WebInspectorProxy::platformCreateFrontendPage()
 {
     ASSERT(inspectedPage());
@@ -141,9 +204,48 @@ WebPageProxy* WebInspectorProxy::platformCreateFrontendPage()
         nullptr, // unavailablePluginButtonClicked
     };
 
+    WKPageNavigationClientV0 navigationClient = {
+        { 0, this },
+        decidePolicyForNavigationAction,
+        nullptr, // decidePolicyForNavigationResponse
+        nullptr, // decidePolicyForPluginLoad
+        nullptr, // didStartProvisionalNavigation
+        nullptr, // didReceiveServerRedirectForProvisionalNavigation
+        nullptr, // didFailProvisionalNavigation
+        nullptr, // didCommitNavigation
+        nullptr, // didFinishNavigation
+        nullptr, // didFailNavigation
+        nullptr, // didFailProvisionalLoadInSubframe
+        nullptr, // didFinishDocumentLoad
+        nullptr, // didSameDocumentNavigation
+        nullptr, // renderingProgressDidChange
+        nullptr, // canAuthenticateAgainstProtectionSpace
+        nullptr, // didReceiveAuthenticationChallenge
+        webProcessDidCrash,
+        nullptr, // copyWebCryptoMasterKey
+
+        nullptr, // didBeginNavigationGesture
+        nullptr, // willEndNavigationGesture
+        nullptr, // didEndNavigationGesture
+        nullptr, // didRemoveNavigationGestureSnapshot
+    };
+
+    WKPageContextMenuClientV3 contextMenuClient = {
+        { 3, this },
+        nullptr, // getContextMenuFromProposedMenu_deprecatedForUseWithV0
+        nullptr, // customContextMenuItemSelected
+        nullptr, // contextMenuDismissed
+        getContextMenuFromProposedMenu,
+        nullptr, // showContextMenu
+        nullptr, // hideContextMenu
+    };
+
     WebPageProxy* inspectorPage = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_inspectorView));
     ASSERT(inspectorPage);
+
     WKPageSetPageUIClient(toAPI(inspectorPage), &uiClient.base);
+    WKPageSetPageNavigationClient(toAPI(inspectorPage), &navigationClient.base);
+    WKPageSetPageContextMenuClient(toAPI(inspectorPage), &contextMenuClient.base);
 
     return inspectorPage;
 }
index 8b932ca..377b373 100644 (file)
@@ -46,6 +46,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 - (instancetype)initWithInspectedPage:(WebKit::WebPageProxy* _Nullable)inspectedPage;
 
++ (BOOL)viewIsInspectorWebView:(NSView *)view;
+
 @end
 
 @protocol WKInspectorViewControllerDelegate <NSObject>
index 465df1c..fe12b1a 100644 (file)
@@ -143,6 +143,11 @@ using namespace WebKit;
     return configuration.autorelease();
 }
 
++ (BOOL)viewIsInspectorWebView:(NSView *)view
+{
+    return [view isKindOfClass:[WKInspectorWKWebView class]];
+}
+
 // MARK: WKUIDelegate methods
 
 - (void)_webView:(WKWebView *)webView getWindowFrameWithCompletionHandler:(void (^)(CGRect))completionHandler
index 9cbff79..e46a787 100644 (file)
 #if PLATFORM(MAC) && WK_API_ENABLED
 
 #import "WKInspectorPrivateMac.h"
-#import "WKPreferencesInternal.h"
-#import "WKProcessPoolInternal.h"
+#import "WKInspectorViewController.h"
 #import "WKViewInternal.h"
-#import "WKWebInspectorWKWebView.h"
-#import "WKWebViewConfigurationPrivate.h"
 #import "WKWebViewInternal.h"
 #import "WebInspectorUIMessages.h"
 #import "WebPageGroup.h"
@@ -43,6 +40,7 @@
 #import <wtf/SoftLinking.h>
 #import <wtf/text/Base64.h>
 
+
 SOFT_LINK_STAGED_FRAMEWORK(WebInspectorUI, PrivateFrameworks, A)
 
 using namespace WebCore;
@@ -54,10 +52,7 @@ static const NSUInteger windowStyleMask = NSWindowStyleMaskTitled | NSWindowStyl
 // Reusing the WebView improves start up time for people that jump in and out of the Inspector.
 static const Seconds webViewCloseTimeout { 1_min };
 
-// WKWebInspectorProxyObjCAdapter is a helper ObjC object used as a delegate or notification observer
-// for the sole purpose of getting back into the C++ code from an ObjC caller.
-
-@interface WKWebInspectorProxyObjCAdapter ()
+@interface WKWebInspectorProxyObjCAdapter () <WKInspectorViewControllerDelegate>
 
 - (instancetype)initWithWebInspectorProxy:(WebInspectorProxy*)inspectorProxy;
 - (void)invalidate;
@@ -134,6 +129,19 @@ static const Seconds webViewCloseTimeout { 1_min };
     });
 }
 
+// MARK: WKInspectorViewControllerDelegate methods
+
+- (void)inspectorViewControllerInspectorDidCrash:(WKInspectorViewController *)inspectorViewController
+{
+    if (_inspectorProxy)
+        _inspectorProxy->closeForCrash();
+}
+
+- (BOOL)inspectorViewControllerInspectorIsUnderTest:(WKInspectorViewController *)inspectorViewController
+{
+    return _inspectorProxy ? _inspectorProxy->isUnderTest() : false;
+}
+
 @end
 
 namespace WebKit {
@@ -179,34 +187,6 @@ void WebInspectorProxy::updateInspectorWindowTitle() const
     }
 }
 
-RetainPtr<WKWebViewConfiguration> WebInspectorProxy::createFrontendConfiguration(WebPageProxy* page, bool underTest)
-{
-    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-
-    WKPreferences *preferences = [configuration preferences];
-    preferences._allowFileAccessFromFileURLs = YES;
-    [configuration _setAllowUniversalAccessFromFileURLs:YES];
-    preferences._storageBlockingPolicy = _WKStorageBlockingPolicyAllowAll;
-    preferences._javaScriptRuntimeFlags = 0;
-
-#ifndef NDEBUG
-    // Allow developers to inspect the Web Inspector in debug builds without changing settings.
-    preferences._developerExtrasEnabled = YES;
-    preferences._logsPageMessagesToSystemConsoleEnabled = YES;
-#endif
-
-    if (underTest) {
-        preferences._hiddenPageDOMTimerThrottlingEnabled = NO;
-        preferences._pageVisibilityBasedProcessSuppressionEnabled = NO;
-    }
-
-    unsigned inspectorLevel = inspectorLevelForPage(page);
-    [configuration setProcessPool: ::WebKit::wrapper(inspectorProcessPool(inspectorLevel))];
-    [configuration _setGroupIdentifier:inspectorPageGroupIdentifierForPage(page)];
-
-    return configuration;
-}
-
 RetainPtr<NSWindow> WebInspectorProxy::createFrontendWindow(NSRect savedWindowFrame)
 {
     NSRect windowFrame = !NSIsEmptyRect(savedWindowFrame) ? savedWindowFrame : NSMakeRect(0, 0, initialWindowWidth, initialWindowHeight);
@@ -232,52 +212,21 @@ RetainPtr<NSWindow> WebInspectorProxy::createFrontendWindow(NSRect savedWindowFr
 WebPageProxy* WebInspectorProxy::platformCreateFrontendPage()
 {
     ASSERT(inspectedPage());
+    ASSERT(!m_inspectorPage);
 
     m_closeFrontendAfterInactivityTimer.stop();
 
-    if (m_inspectorView) {
-        ASSERT(m_objCAdapter);
-        return m_inspectorView->_page.get();
-    }
-
-    ASSERT(!m_inspectorView);
-    ASSERT(!m_objCAdapter);
-
-    NSView *inspectedView = inspectedPage()->inspectorAttachmentView();
-
-    NSRect initialRect;
-    if (m_isAttached) {
-        NSRect inspectedViewFrame = inspectedView.frame;
-
-        switch (m_attachmentSide) {
-        case AttachmentSide::Bottom:
-            initialRect = NSMakeRect(0, 0, NSWidth(inspectedViewFrame), inspectorPagePreferences().inspectorAttachedHeight());
-            break;
-        case AttachmentSide::Right:
-            initialRect = NSMakeRect(0, 0, inspectorPagePreferences().inspectorAttachedWidth(), NSHeight(inspectedViewFrame));
-            break;
-        case AttachmentSide::Left:
-            initialRect = NSMakeRect(0, 0, NSWidth(inspectedViewFrame) - inspectorPagePreferences().inspectorAttachedWidth(), NSHeight(inspectedViewFrame));
-            break;
-        }
-    } else {
-        initialRect = NSMakeRect(0, 0, initialWindowWidth, initialWindowHeight);
-
-        NSString *windowFrameString = inspectedPage()->pageGroup().preferences().inspectorWindowFrame();
-        NSRect windowFrame = NSRectFromString(windowFrameString);
-        if (!NSIsEmptyRect(windowFrame))
-            initialRect = [NSWindow contentRectForFrameRect:windowFrame styleMask:windowStyleMask];
-    }
-
     m_objCAdapter = adoptNS([[WKWebInspectorProxyObjCAdapter alloc] initWithWebInspectorProxy:this]);
-    ASSERT(m_objCAdapter);
-
+    NSView *inspectedView = inspectedPage()->inspectorAttachmentView();
     [[NSNotificationCenter defaultCenter] addObserver:m_objCAdapter.get() selector:@selector(inspectedViewFrameDidChange:) name:NSViewFrameDidChangeNotification object:inspectedView];
 
-    auto configuration = WebInspectorProxy::createFrontendConfiguration(inspectedPage(), isUnderTest());
-    m_inspectorView = adoptNS([[WKWebInspectorWKWebView alloc] initWithFrame:initialRect configuration:configuration.get()]);
+    m_inspectorViewController = adoptNS([[WKInspectorViewController alloc] initWithInspectedPage:inspectedPage()]);
+    [m_inspectorViewController.get() setDelegate:m_objCAdapter.get()];
+
+    WebPageProxy *inspectorPage = [m_inspectorViewController webView]->_page.get();
+    ASSERT(inspectorPage);
 
-    return m_inspectorView->_page.get();
+    return inspectorPage;
 }
 
 void WebInspectorProxy::platformCreateFrontendWindow()
@@ -290,10 +239,10 @@ void WebInspectorProxy::platformCreateFrontendWindow()
     m_inspectorWindow = WebInspectorProxy::createFrontendWindow(savedWindowFrame);
     [m_inspectorWindow setDelegate:m_objCAdapter.get()];
 
+    WKWebView *inspectorView = [m_inspectorViewController webView];
     NSView *contentView = [m_inspectorWindow contentView];
-    [m_inspectorView setFrame:[contentView bounds]];
-    [m_inspectorView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
-    [contentView addSubview:m_inspectorView.get()];
+    inspectorView.frame = [contentView bounds];
+    [contentView addSubview:inspectorView];
 
     updateInspectorWindowTitle();
 }
@@ -301,9 +250,10 @@ void WebInspectorProxy::platformCreateFrontendWindow()
 void WebInspectorProxy::closeFrontendPage()
 {
     ASSERT(!m_isAttached || !m_inspectorWindow);
-    if (m_inspectorView) {
-        m_inspectorView->_page->close();
-        m_inspectorView = nil;
+
+    if (m_inspectorViewController) {
+        [m_inspectorViewController.get() setDelegate:nil];
+        m_inspectorViewController = nil;
     }
 
     if (m_objCAdapter) {
@@ -363,14 +313,14 @@ void WebInspectorProxy::platformBringToFront()
     // If the Web Inspector is no longer in the same window as the inspected view,
     // then we need to reopen the Inspector to get it attached to the right window.
     // This can happen when dragging tabs to another window in Safari.
-    if (m_isAttached && m_inspectorView.get().window != inspectedPage()->platformWindow()) {
+    if (m_isAttached && [m_inspectorViewController webView].window != inspectedPage()->platformWindow()) {
         open();
         return;
     }
 
     // FIXME <rdar://problem/10937688>: this will not bring a background tab in Safari to the front, only its window.
-    [m_inspectorView.get().window makeKeyAndOrderFront:nil];
-    [m_inspectorView.get().window makeFirstResponder:m_inspectorView.get()];
+    [[m_inspectorViewController webView].window makeKeyAndOrderFront:nil];
+    [[m_inspectorViewController webView].window makeFirstResponder:[m_inspectorViewController webView]];
 }
 
 void WebInspectorProxy::platformBringInspectedPageToFront()
@@ -381,7 +331,7 @@ void WebInspectorProxy::platformBringInspectedPageToFront()
 bool WebInspectorProxy::platformIsFront()
 {
     // FIXME <rdar://problem/10937688>: this will not return false for a background tab in Safari, only a background window.
-    return m_isVisible && [m_inspectorView.get().window isMainWindow];
+    return m_isVisible && [m_inspectorViewController webView].window.isMainWindow;
 }
 
 bool WebInspectorProxy::platformCanAttach(bool webProcessCanAttach)
@@ -390,7 +340,7 @@ bool WebInspectorProxy::platformCanAttach(bool webProcessCanAttach)
         return false;
 
     NSView *inspectedView = inspectedPage()->inspectorAttachmentView();
-    if ([inspectedView isKindOfClass:[WKWebInspectorWKWebView class]])
+    if ([WKInspectorViewController viewIsInspectorWebView:inspectedView])
         return webProcessCanAttach;
 
     static const float minimumAttachedHeight = 250;
@@ -533,28 +483,31 @@ void WebInspectorProxy::inspectedViewFrameDidChange(CGFloat currentDimension)
     }
 
     NSView *inspectedView = inspectedPage()->inspectorAttachmentView();
-    NSRect inspectedViewFrame = [inspectedView frame];
-    NSRect inspectorFrame = NSZeroRect;
-    NSRect parentBounds = [[inspectedView superview] bounds];
+    WKWebView *inspectorView = [m_inspectorViewController webView];
+
+    NSRect inspectedViewFrame = inspectedView.frame;
+    NSRect oldInspectorViewFrame = inspectorView.frame;
+    NSRect newInspectorViewFrame = NSZeroRect;
+    NSRect parentBounds = inspectedView.superview.bounds;
     CGFloat inspectedViewTop = NSMaxY(inspectedViewFrame);
 
     switch (m_attachmentSide) {
     case AttachmentSide::Bottom: {
         if (!currentDimension)
-            currentDimension = NSHeight([m_inspectorView frame]);
+            currentDimension = NSHeight(oldInspectorViewFrame);
 
         CGFloat parentHeight = NSHeight(parentBounds);
         CGFloat inspectorHeight = InspectorFrontendClientLocal::constrainedAttachedWindowHeight(currentDimension, parentHeight);
 
         // Preserve the top position of the inspected view so banners in Safari still work.
         inspectedViewFrame = NSMakeRect(0, inspectorHeight, NSWidth(parentBounds), inspectedViewTop - inspectorHeight);
-        inspectorFrame = NSMakeRect(0, 0, NSWidth(inspectedViewFrame), inspectorHeight);
+        newInspectorViewFrame = NSMakeRect(0, 0, NSWidth(inspectedViewFrame), inspectorHeight);
         break;
     }
 
     case AttachmentSide::Right: {
         if (!currentDimension)
-            currentDimension = NSWidth([m_inspectorView frame]);
+            currentDimension = NSWidth(oldInspectorViewFrame);
 
         CGFloat parentWidth = NSWidth(parentBounds);
         CGFloat inspectorWidth = InspectorFrontendClientLocal::constrainedAttachedWindowWidth(currentDimension, parentWidth);
@@ -565,13 +518,13 @@ void WebInspectorProxy::inspectedViewFrameDidChange(CGFloat currentDimension)
         CGFloat insetExcludingBanners = 0;
         if ([inspectedView isKindOfClass:[WKView class]])
             insetExcludingBanners = ((WKView *)inspectedView)._topContentInset - ((WKView *)inspectedView)._totalHeightOfBanners;
-        inspectorFrame = NSMakeRect(parentWidth - inspectorWidth, 0, inspectorWidth, NSHeight(parentBounds) - insetExcludingBanners);
+        newInspectorViewFrame = NSMakeRect(parentWidth - inspectorWidth, 0, inspectorWidth, NSHeight(parentBounds) - insetExcludingBanners);
         break;
     }
 
     case AttachmentSide::Left: {
         if (!currentDimension)
-            currentDimension = NSWidth([m_inspectorView frame]);
+            currentDimension = NSWidth(oldInspectorViewFrame);
 
         CGFloat parentWidth = NSWidth(parentBounds);
         CGFloat inspectorWidth = InspectorFrontendClientLocal::constrainedAttachedWindowWidth(currentDimension, parentWidth);
@@ -582,18 +535,18 @@ void WebInspectorProxy::inspectedViewFrameDidChange(CGFloat currentDimension)
         CGFloat insetExcludingBanners = 0;
         if ([inspectedView isKindOfClass:[WKView class]])
             insetExcludingBanners = ((WKView *)inspectedView)._topContentInset - ((WKView *)inspectedView)._totalHeightOfBanners;
-        inspectorFrame = NSMakeRect(0, 0, inspectorWidth, NSHeight(parentBounds) - insetExcludingBanners);
+        newInspectorViewFrame = NSMakeRect(0, 0, inspectorWidth, NSHeight(parentBounds) - insetExcludingBanners);
         break;
     }
     }
 
-    if (NSEqualRects([m_inspectorView frame], inspectorFrame) && NSEqualRects([inspectedView frame], inspectedViewFrame))
+    if (NSEqualRects(oldInspectorViewFrame, newInspectorViewFrame) && NSEqualRects([inspectedView frame], inspectedViewFrame))
         return;
 
     // Disable screen updates to make sure the layers for both views resize in sync.
-    [[m_inspectorView window] disableScreenUpdatesUntilFlush];
+    [inspectorView.window disableScreenUpdatesUntilFlush];
 
-    [m_inspectorView setFrame:inspectorFrame];
+    [inspectorView setFrame:newInspectorViewFrame];
     [inspectedView setFrame:inspectedViewFrame];
 }
 
@@ -614,6 +567,7 @@ unsigned WebInspectorProxy::platformInspectedWindowWidth()
 void WebInspectorProxy::platformAttach()
 {
     NSView *inspectedView = inspectedPage()->inspectorAttachmentView();
+    WKWebView *inspectorView = [m_inspectorViewController webView];
 
     if (m_inspectorWindow) {
         [m_inspectorWindow setDelegate:nil];
@@ -621,36 +575,36 @@ void WebInspectorProxy::platformAttach()
         m_inspectorWindow = nil;
     }
 
-    [m_inspectorView removeFromSuperview];
+    [inspectorView removeFromSuperview];
 
     CGFloat currentDimension;
-
     switch (m_attachmentSide) {
     case AttachmentSide::Bottom:
-        [m_inspectorView setAutoresizingMask:NSViewWidthSizable | NSViewMaxYMargin];
+        [inspectorView setAutoresizingMask:NSViewWidthSizable | NSViewMaxYMargin];
         currentDimension = inspectorPagePreferences().inspectorAttachedHeight();
         break;
     case AttachmentSide::Right:
-        [m_inspectorView setAutoresizingMask:NSViewHeightSizable | NSViewMinXMargin];
+        [inspectorView setAutoresizingMask:NSViewHeightSizable | NSViewMinXMargin];
         currentDimension = inspectorPagePreferences().inspectorAttachedWidth();
         break;
     case AttachmentSide::Left:
-        [m_inspectorView setAutoresizingMask:NSViewHeightSizable | NSViewMaxXMargin];
+        [inspectorView setAutoresizingMask:NSViewHeightSizable | NSViewMaxXMargin];
         currentDimension = inspectorPagePreferences().inspectorAttachedWidth();
         break;
     }
 
     inspectedViewFrameDidChange(currentDimension);
 
-    [[inspectedView superview] addSubview:m_inspectorView.get() positioned:NSWindowBelow relativeTo:inspectedView];
-    [m_inspectorView.get().window makeFirstResponder:m_inspectorView.get()];
+    [inspectedView.superview addSubview:inspectorView positioned:NSWindowBelow relativeTo:inspectedView];
+    [inspectorView.window makeFirstResponder:inspectorView];
 }
 
 void WebInspectorProxy::platformDetach()
 {
     NSView *inspectedView = inspectedPage()->inspectorAttachmentView();
+    WKWebView *inspectorView = [m_inspectorViewController webView];
 
-    [m_inspectorView removeFromSuperview];
+    [inspectorView removeFromSuperview];
 
     // Make sure that we size the inspected view's frame after detaching so that it takes up the space that the
     // attached inspector used to. Preserve the top position of the inspected view so banners in Safari still work.
@@ -683,7 +637,7 @@ void WebInspectorProxy::platformSetAttachedWindowWidth(unsigned width)
 
 void WebInspectorProxy::platformStartWindowDrag()
 {
-    m_inspectorView->_page->startWindowDrag();
+    [m_inspectorViewController webView]->_page->startWindowDrag();
 }
 
 String WebInspectorProxy::inspectorPageURL()