Web Inspector: notify inspector when provisional page is created, committed and destroyed
authoryurys@chromium.org <yurys@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Oct 2019 20:16:00 +0000 (20:16 +0000)
committeryurys@chromium.org <yurys@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Oct 2019 20:16:00 +0000 (20:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=202704

Reviewed by Devin Rousso.

Source/JavaScriptCore:

* inspector/InspectorTarget.h: changed InspectorTarget to not require FrontendChannel as
all messages are routed by means of the owning InspectorTargetAgent.
* inspector/agents/InspectorTargetAgent.cpp:
(Inspector::InspectorTargetAgent::InspectorTargetAgent):
(Inspector::buildTargetInfoObject):
(Inspector::InspectorTargetAgent::targetCreated):
(Inspector::InspectorTargetAgent::targetDestroyed):
(Inspector::InspectorTargetAgent::didCommitProvisionalTarget): this method is used to
notify frontend that corresponding provisional target has committed and replaced previous
target.
(Inspector::InspectorTargetAgent::connectionType const):
(Inspector::InspectorTargetAgent::connectToTargets):
(Inspector::InspectorTargetAgent::disconnectFromTargets):
* inspector/agents/InspectorTargetAgent.h:
* inspector/protocol/Target.json: extended TargetInfo with provisional page details and
added event which is fired when provisional page gets committed. If provisional
load fails there will be targetDestroyed event without corresponding commit.

Source/WebCore:

Test: http/tests/inspector/target/target-events-for-proisional-page.html

* inspector/InspectorController.cpp:
(WebCore::InspectorController::setIsUnderTest): This method may be called several times
when reloading inspected page with opened frontend so the assumption that there are no
connected frontends when this method is called from tests doesn't hold anymore.

Source/WebInspectorUI:

Updated frontend code to understand provisional targets. For now there are
no changes frontend behavior, it will wait for the provisional target to commit
and will not send any commands to it before that.

* UserInterface/Base/Main.js: Moved a bunch of methods shared between Main.js and Test.js
to TargetManager.js to keep them in sync.
* UserInterface/Controllers/TargetManager.js:
(WI.TargetManager):
(WI.TargetManager.prototype.removeTarget):
(WI.TargetManager.prototype.createMultiplexingBackendTarget):
(WI.TargetManager.prototype.createDirectBackendTarget):
(WI.TargetManager.prototype.targetCreated):
(WI.TargetManager.prototype.didCommitProvisionalTarget):
(WI.TargetManager.prototype.targetDestroyed):
(WI.TargetManager.prototype.dispatchMessageFromTarget):
(WI.TargetManager.prototype._checkAndHandlePageTargetTransition):
(WI.TargetManager.prototype._checkAndHandlePageTargetTermination):
(WI.TargetManager.prototype._initializeBackendTarget):
(WI.TargetManager.prototype._initializePageTarget):
(WI.TargetManager.prototype._transitionPageTarget):
(WI.TargetManager.prototype._terminatePageTarget):
(WI.TargetManager.prototype._resetMainExecutionContext):
(WI.TargetManager.prototype._redirectGlobalAgentsToConnection):
* UserInterface/Protocol/Connection.js:
(InspectorBackend.WorkerConnection.sendMessageToBackend):
(InspectorBackend.WorkerConnection):
(InspectorBackend.TargetConnection.sendMessageToBackend):
(InspectorBackend.TargetConnection):
* UserInterface/Protocol/Target.js:
(WI.Target.prototype.destroy): Mark target as destroyed to distinguish expected command errors from
genuine failures.

(WI.Target.prototype.isDestroyed):
* UserInterface/Protocol/TargetObserver.js: Since the front-end doesn't
send commands to the provisional targets yet, it has to ignore all activities
related to provisional pages. For that reason we need two sets to keep track of
- provisional pages that were destroyed and never committed
- old pages which were replaced by committed page and for which following targetDestroyed
event should be ignored
Better support for provisional targets will be added to frontend in a separate change.
(WI.TargetObserver):
(WI.TargetObserver.prototype.targetCreated):
(WI.TargetObserver.prototype.didCommitProvisionalTarget): For now convert the event into a subsequence
of targetDestroyed/targetCreated events which matches previous behavior.

(WI.TargetObserver.prototype.targetDestroyed):
(WI.TargetObserver.prototype.dispatchMessageFromTarget):
* UserInterface/Test/Test.js:
(WI.transitionPageTarget):
(WI.terminatePageTarget):

Source/WebKit:

Target.targetCreated event is now generated for provisional pages as well as for regular
ones. This is the first step toward reattaching inspector earlier during PSON. In the future
if debugging is in progress the provisional target (page) will be paused until a signal from
inspector frontend. This will enable the frontend configure all agents before navigation starts.

* Sources.txt:
* UIProcess/API/APIWebAuthenticationPanel.cpp:
(API::WebAuthenticationPanel::WebAuthenticationPanel): Added explicit namespace specifier
to the constructor's argument as otherwise compilation fails due to conflict between API::String
and WTF::String.

* UIProcess/InspectorTargetProxy.cpp:
(WebKit::InspectorTargetProxy::create):
(WebKit::InspectorTargetProxy::connect):
(WebKit::InspectorTargetProxy::disconnect):
(WebKit::InspectorTargetProxy::sendMessageToTargetBackend):
(WebKit::InspectorTargetProxy::didCommitProvisionalTarget):
(WebKit::InspectorTargetProxy::isProvisional const):
(WebKit::InspectorTargetProxy::previousTargetID const):
* UIProcess/InspectorTargetProxy.h: Target proxy can start as a provisional target (with a pointer to
ProvisionalPageProxy) and later either be committed or destroyed.

* UIProcess/ProvisionalPageProxy.cpp:
(WebKit::ProvisionalPageProxy::ProvisionalPageProxy):
(WebKit::ProvisionalPageProxy::~ProvisionalPageProxy):
(WebKit::ProvisionalPageProxy::didReceiveMessage): Forward inspector messages to parent page's WebPageInspectorController.
Since each WebPage has a unique identifier the target ids will be globally unique and there is no risk of collisions.

* UIProcess/ProvisionalPageProxy.h:
(WebKit::ProvisionalPageProxy::page const):
* UIProcess/WebPageInspectorController.cpp:
(WebKit::getTargetID):
(WebKit::WebPageInspectorController::WebPageInspectorController):
(WebKit::WebPageInspectorController::clearTargets):
(WebKit::WebPageInspectorController::createInspectorTarget):
(WebKit::WebPageInspectorController::destroyInspectorTarget):
(WebKit::WebPageInspectorController::didCreateProvisionalPage):
(WebKit::WebPageInspectorController::didDestroyProvisionalPage):
(WebKit::WebPageInspectorController::didCommitProvisionalPage):
(WebKit::WebPageInspectorController::addTarget):
* UIProcess/WebPageInspectorController.h:
* UIProcess/WebPageInspectorTargetAgent.cpp: Removed. Merged this agent into InspectorTargetAgent.
* UIProcess/WebPageInspectorTargetAgent.h: Removed.
* UIProcess/WebPageProxy.cpp:
(WebKit::m_resetRecentCrashCountTimer):
(WebKit::WebPageProxy::finishAttachingToWebProcess):
(WebKit::WebPageProxy::commitProvisionalPage):
* UIProcess/WebPageProxy.h: Moved the target management logic into WebPageInspectorController.
WebPageProxy/ProvisionalPageProxy are expected to notifiy it about key lifecycle events and also
forward to it messages from inspector in the inspected WebProcess. How it translates to Target
events is inspector's business.

* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPageInspectorTarget.cpp:
(WebKit::WebPageInspectorTarget::identifier const):
(WebKit::WebPageInspectorTarget::connect):
(WebKit::WebPageInspectorTarget::disconnect):
(WebKit::WebPageInspectorTarget::toTargetID):
* WebProcess/WebPage/WebPageInspectorTarget.h: Made the target own frontend channel instance as it's the
only place where the page specific channel is used.

* WebProcess/WebPage/WebPageInspectorTargetController.cpp:
(WebKit::WebPageInspectorTargetController::removeTarget):
(WebKit::WebPageInspectorTargetController::connectInspector):
(WebKit::WebPageInspectorTargetController::disconnectInspector):
* WebProcess/WebPage/WebPageInspectorTargetController.h:
* WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.cpp:
(WebKit::WebPageInspectorTargetFrontendChannel::WebPageInspectorTargetFrontendChannel):
(WebKit::WebPageInspectorTargetFrontendChannel::sendMessageToFrontend):
* WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.h: The channel's lifetime is managed by owning
target. No need to reference count it.

LayoutTests:

Added new test for Target events during PSON. It is only enabled on WebKit2 as there is
no Target agent in WebKit1.

* TestExpectations:
* http/tests/inspector/target/target-events-for-provisional-page-expected.txt: Added.
* http/tests/inspector/target/target-events-for-provisional-page.html: Added.
* platform/wk2/TestExpectations:

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

42 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/http/tests/inspector/target/target-events-for-provisional-page-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html [new file with mode: 0644]
LayoutTests/platform/wk2/TestExpectations
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/InspectorTarget.h
Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp
Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h
Source/JavaScriptCore/inspector/protocol/Target.json
Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorController.cpp
Source/WebCore/inspector/InspectorController.h
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Base/Main.js
Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js
Source/WebInspectorUI/UserInterface/Protocol/Connection.js
Source/WebInspectorUI/UserInterface/Protocol/Target.js
Source/WebInspectorUI/UserInterface/Protocol/TargetObserver.js
Source/WebInspectorUI/UserInterface/Test/Test.js
Source/WebInspectorUI/UserInterface/Views/QuickConsole.js
Source/WebKit/ChangeLog
Source/WebKit/Sources.txt
Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp
Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.h
Source/WebKit/UIProcess/InspectorTargetProxy.cpp
Source/WebKit/UIProcess/InspectorTargetProxy.h
Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
Source/WebKit/UIProcess/ProvisionalPageProxy.h
Source/WebKit/UIProcess/WebPageInspectorController.cpp
Source/WebKit/UIProcess/WebPageInspectorController.h
Source/WebKit/UIProcess/WebPageInspectorTargetAgent.cpp [deleted file]
Source/WebKit/UIProcess/WebPageInspectorTargetAgent.h [deleted file]
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.cpp
Source/WebKit/WebProcess/WebPage/WebPageInspectorTarget.h
Source/WebKit/WebProcess/WebPage/WebPageInspectorTargetController.cpp
Source/WebKit/WebProcess/WebPage/WebPageInspectorTargetController.h
Source/WebKit/WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.cpp
Source/WebKit/WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.h

index 639a6fa..de13811 100644 (file)
@@ -1,3 +1,18 @@
+2019-10-23  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: notify inspector when provisional page is created, committed and destroyed
+        https://bugs.webkit.org/show_bug.cgi?id=202704
+
+        Reviewed by Devin Rousso.
+
+        Added new test for Target events during PSON. It is only enabled on WebKit2 as there is
+        no Target agent in WebKit1.
+
+        * TestExpectations:
+        * http/tests/inspector/target/target-events-for-provisional-page-expected.txt: Added.
+        * http/tests/inspector/target/target-events-for-provisional-page.html: Added.
+        * platform/wk2/TestExpectations:
+
 2019-10-23  Rob Buis  <rbuis@igalia.com>
 
         Be strict on request's Content-Type
index 9cd1634..826d98e 100644 (file)
@@ -912,6 +912,9 @@ webkit.org/b/161951 [ Debug ] inspector/debugger/paused-scopes.html [ Skip ]
 inspector/debugger/evaluateOnCallFrame-emulateUserGesture-userIsInteracting.html [ Skip ]
 inspector/runtime/evaluate-emulateUserGesture-userIsInteracting.html [ Skip ]
 
+# Target domain is only present in WK2.
+http/tests/inspector/target [ Skip ]
+
 # These conformance tests are no longer in sync with the latest specification
 # and expect compareDocumentPosition() to return:
 # DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_DISCONNECTED
diff --git a/LayoutTests/http/tests/inspector/target/target-events-for-provisional-page-expected.txt b/LayoutTests/http/tests/inspector/target/target-events-for-provisional-page-expected.txt
new file mode 100644 (file)
index 0000000..6def7e0
--- /dev/null
@@ -0,0 +1,16 @@
+Test that cross domain navigation results in the following sequence of events in Target domain: 
+1. Target.targetCreated for provisional page. 
+2. Target.didCommitProvisionalTarget when provisional load is committed. 
+3. Target.targetDestroyed for the old target after the navigation request is committed.
+
+
+== Running test suite: Target.PSON
+-- Running test case: ProvisionalPageTarget
+PASS: Should receive targetCreated event.
+PASS: Target should be provisional.
+PASS: Should receive didCommitProvisionalTarget event.
+PASS: Previous target should be the current one.
+PASS: Committed target should match provisional target.
+PASS: Should receive targetDestroyed event.
+PASS: Destroyed target should be previous target.
+
diff --git a/LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html b/LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html
new file mode 100644 (file)
index 0000000..e739513
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../resources/inspector-test.js"></script>
+<script>
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("Target.PSON");
+
+    suite.addTestCase({
+        name: "ProvisionalPageTarget",
+        description: "Check that a new target will be created for provisional page.",
+        test(resolve, reject) {
+            const mainTargetId = WI.mainTarget.identifier;
+            let newTargetId;
+            InspectorTest.assert(mainTargetId);
+            let reloadPromise = InspectorTest.awaitEvent(FrontendTestHarness.Event.TestPageDidLoad);
+
+            WI.targetManager.addEventListener(WI.TargetManager.Event.TargetCreated, (event) => {
+                let {targetInfo} = event.data;
+                newTargetId = targetInfo.targetId;
+                InspectorTest.pass(`Should receive targetCreated event.`);
+                InspectorTest.expectTrue(targetInfo.isProvisional, "Target should be provisional.");
+            });
+
+            WI.targetManager.addEventListener(WI.TargetManager.Event.DidCommitProvisionalTarget, (event) => {
+                let {previousTargetId, targetInfo} = event.data;
+                InspectorTest.pass(`Should receive didCommitProvisionalTarget event.`);
+                InspectorTest.expectEqual(previousTargetId, mainTargetId, "Previous target should be the current one.");
+                InspectorTest.expectEqual(targetInfo.targetId, newTargetId, "Committed target should match provisional target.");
+            });
+
+            WI.targetManager.addEventListener(WI.TargetManager.Event.TargetDestroyed, (event) =>{
+                let {targetId} = event.data;
+                InspectorTest.pass(`Should receive targetDestroyed event.`);
+                InspectorTest.expectEqual(targetId, mainTargetId, "Destroyed target should be previous target.");
+
+                // Wait for page reload event to avoid race between test results flushing and the test completion.
+                reloadPromise.then(resolve);
+            });
+
+            WI.mainTarget.RuntimeAgent.evaluate("location.hostname='localhost'");
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Test that cross domain navigation results in the following sequence of events in Target domain:
+<br>1. Target.targetCreated for provisional page.
+<br>2. Target.didCommitProvisionalTarget when provisional load is committed.
+<br>3. Target.targetDestroyed for the old target after the navigation request is committed.
+</p>
+</body>
+</html>
index 02d6898..7d4fb66 100644 (file)
@@ -764,6 +764,9 @@ http/tests/adClickAttribution [ Pass ]
 inspector/debugger/evaluateOnCallFrame-emulateUserGesture-userIsInteracting.html [ Pass ]
 inspector/runtime/evaluate-emulateUserGesture-userIsInteracting.html [ Pass ]
 
+# Target domain is only present in WebKit2.
+http/tests/inspector/target [ Pass ]
+
 ### END OF (5) Progressions, expected successes that are expected failures in WebKit1.
 ########################################
 
index 3f4e85f..4be87bf 100644 (file)
@@ -1,3 +1,28 @@
+2019-10-23  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: notify inspector when provisional page is created, committed and destroyed
+        https://bugs.webkit.org/show_bug.cgi?id=202704
+
+        Reviewed by Devin Rousso.
+
+        * inspector/InspectorTarget.h: changed InspectorTarget to not require FrontendChannel as
+        all messages are routed by means of the owning InspectorTargetAgent.
+        * inspector/agents/InspectorTargetAgent.cpp:
+        (Inspector::InspectorTargetAgent::InspectorTargetAgent):
+        (Inspector::buildTargetInfoObject):
+        (Inspector::InspectorTargetAgent::targetCreated):
+        (Inspector::InspectorTargetAgent::targetDestroyed):
+        (Inspector::InspectorTargetAgent::didCommitProvisionalTarget): this method is used to
+        notify frontend that corresponding provisional target has committed and replaced previous
+        target.
+        (Inspector::InspectorTargetAgent::connectionType const):
+        (Inspector::InspectorTargetAgent::connectToTargets):
+        (Inspector::InspectorTargetAgent::disconnectFromTargets):
+        * inspector/agents/InspectorTargetAgent.h:
+        * inspector/protocol/Target.json: extended TargetInfo with provisional page details and
+        added event which is fired when provisional page gets committed. If provisional
+        load fails there will be targetDestroyed event without corresponding commit.
+
 2019-10-23  Ross Kirsling  <ross.kirsling@sony.com>
 
         String.prototype.matchAll should throw on non-global regex
index be11ce3..a9f04b8 100644 (file)
@@ -46,9 +46,11 @@ public:
     virtual String identifier() const = 0;
     virtual InspectorTargetType type() const = 0;
 
+    virtual bool isProvisional() const { return false; }
+
     // Connection management.
-    virtual void connect(FrontendChannel&) = 0;
-    virtual void disconnect(FrontendChannel&) = 0;
+    virtual void connect(FrontendChannel::ConnectionType) = 0;
+    virtual void disconnect() = 0;
     virtual void sendMessageToTargetBackend(const String&) = 0;
 };
 
index c809606..1177090 100644 (file)
@@ -32,6 +32,7 @@ namespace Inspector {
 
 InspectorTargetAgent::InspectorTargetAgent(FrontendRouter& frontendRouter, BackendDispatcher& backendDispatcher)
     : InspectorAgentBase("Target"_s)
+    , m_router(frontendRouter)
     , m_frontendDispatcher(makeUnique<TargetFrontendDispatcher>(frontendRouter))
     , m_backendDispatcher(TargetBackendDispatcher::create(backendDispatcher, this))
 {
@@ -88,10 +89,13 @@ static Protocol::Target::TargetInfo::Type targetTypeToProtocolType(InspectorTarg
 
 static Ref<Protocol::Target::TargetInfo> buildTargetInfoObject(const InspectorTarget& target)
 {
-    return Protocol::Target::TargetInfo::create()
+    auto result = Protocol::Target::TargetInfo::create()
         .setTargetId(target.identifier())
         .setType(targetTypeToProtocolType(target.type()))
         .release();
+    if (target.isProvisional())
+        result->setIsProvisional(true);
+    return result;
 }
 
 void InspectorTargetAgent::targetCreated(InspectorTarget& target)
@@ -102,7 +106,7 @@ void InspectorTargetAgent::targetCreated(InspectorTarget& target)
     if (!m_isConnected)
         return;
 
-    target.connect(frontendChannel());
+    target.connect(connectionType());
 
     m_frontendDispatcher->targetCreated(buildTargetInfoObject(target));
 }
@@ -114,27 +118,40 @@ void InspectorTargetAgent::targetDestroyed(InspectorTarget& target)
     if (!m_isConnected)
         return;
 
-    target.disconnect(frontendChannel());
+    target.disconnect();
 
     m_frontendDispatcher->targetDestroyed(target.identifier());
 }
 
-void InspectorTargetAgent::connectToTargets()
+void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID)
 {
-    auto& channel = frontendChannel();
+    if (!m_isConnected)
+        return;
+
+    auto* target = m_targets.get(committedTargetID);
+    if (!target)
+        return;
+
+    m_frontendDispatcher->didCommitProvisionalTarget(oldTargetID, committedTargetID);
+}
 
+FrontendChannel::ConnectionType InspectorTargetAgent::connectionType() const
+{
+    return m_router.hasLocalFrontend() ? Inspector::FrontendChannel::ConnectionType::Local : Inspector::FrontendChannel::ConnectionType::Remote;
+}
+
+void InspectorTargetAgent::connectToTargets()
+{
     for (InspectorTarget* target : m_targets.values()) {
-        target->connect(channel);
+        target->connect(connectionType());
         m_frontendDispatcher->targetCreated(buildTargetInfoObject(*target));
     }
 }
 
 void InspectorTargetAgent::disconnectFromTargets()
 {
-    auto& channel = frontendChannel();
-
     for (InspectorTarget* target : m_targets.values())
-        target->disconnect(channel);
+        target->disconnect();
 }
 
 } // namespace Inspector
index 0b1a04e..38cb318 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "InspectorAgentBase.h"
 #include "InspectorBackendDispatchers.h"
+#include "InspectorFrontendChannel.h"
 #include "InspectorFrontendDispatchers.h"
 #include <wtf/Forward.h>
 
@@ -40,6 +41,7 @@ class JS_EXPORT_PRIVATE InspectorTargetAgent : public InspectorAgentBase, public
     WTF_MAKE_NONCOPYABLE(InspectorTargetAgent);
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    InspectorTargetAgent(FrontendRouter&, BackendDispatcher&);
     ~InspectorTargetAgent() override;
 
     // InspectorAgentBase
@@ -52,19 +54,18 @@ public:
     // Target lifecycle.
     void targetCreated(InspectorTarget&);
     void targetDestroyed(InspectorTarget&);
+    void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID);
 
     // Target messages.
     void sendMessageFromTargetToFrontend(const String& targetId, const String& message);
 
-protected:
-    InspectorTargetAgent(FrontendRouter&, BackendDispatcher&);
-
-    virtual FrontendChannel& frontendChannel() = 0;
-
 private:
+    // FrontendChannel
+    FrontendChannel::ConnectionType connectionType() const;
     void connectToTargets();
     void disconnectFromTargets();
 
+    Inspector::FrontendRouter& m_router;
     std::unique_ptr<TargetFrontendDispatcher> m_frontendDispatcher;
     Ref<TargetBackendDispatcher> m_backendDispatcher;
     HashMap<String, InspectorTarget*> m_targets;
index 394fedd..240cd42 100644 (file)
@@ -9,7 +9,8 @@
             "description": "Description of a target.",
             "properties": [
                 { "name": "targetId", "type": "string", "description": "Unique identifier for the target." },
-                { "name": "type", "type": "string", "enum": ["page", "service-worker", "worker"] }
+                { "name": "type", "type": "string", "enum": ["page", "service-worker", "worker"] },
+                { "name": "isProvisional", "type": "boolean", "optional": true, "description": "True value indicates that this is a provisional page target i.e. Such target may be created when current page starts cross-origin navigation. Eventually each provisional target is either committed and swaps with the current target or gets destroyed, e.g. in case of load request failure." }
             ]
         }
     ],
             ]
         },
         {
+            "name": "didCommitProvisionalTarget",
+            "description": "This event is fired when provisional load is committed. Provisional target swaps with the current target.",
+            "parameters": [
+                { "name": "oldTargetId", "type": "string", "description": "ID of the old target that is swapped with the committed one." },
+                { "name": "newTargetId", "type": "string", "description": "ID of the committed target." }
+            ]
+        },
+        {
             "name": "dispatchMessageFromTarget",
             "parameters": [
                 { "name": "targetId", "type": "string" },
index b585984..4ba002e 100644 (file)
@@ -1,3 +1,17 @@
+2019-10-23  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: notify inspector when provisional page is created, committed and destroyed
+        https://bugs.webkit.org/show_bug.cgi?id=202704
+
+        Reviewed by Devin Rousso.
+
+        Test: http/tests/inspector/target/target-events-for-proisional-page.html
+
+        * inspector/InspectorController.cpp:
+        (WebCore::InspectorController::setIsUnderTest): This method may be called several times
+        when reloading inspected page with opened frontend so the assumption that there are no
+        connected frontends when this method is called from tests doesn't hold anymore.
+
 2019-10-23  Rob Buis  <rbuis@igalia.com>
 
         Be strict on request's Content-Type
index 4c04fbb..81093d3 100644 (file)
@@ -344,17 +344,6 @@ void InspectorController::show()
         connectFrontend(*frontendChannel);
 }
 
-void InspectorController::setIsUnderTest(bool value)
-{
-    if (value == m_isUnderTest)
-        return;
-
-    m_isUnderTest = value;
-
-    // <rdar://problem/26768628> Try to catch suspicious scenarios where we may have a dangling frontend while running tests.
-    RELEASE_ASSERT(!m_isUnderTest || !m_frontendRouter->hasFrontends());
-}
-
 void InspectorController::evaluateForTestInFrontend(const String& script)
 {
     ensureInspectorAgent().evaluateForTestInFrontend(script);
index e6388ac..cd4497c 100644 (file)
@@ -101,7 +101,7 @@ public:
     WEBCORE_EXPORT void didComposite(Frame&);
 
     bool isUnderTest() const { return m_isUnderTest; }
-    WEBCORE_EXPORT void setIsUnderTest(bool);
+    void setIsUnderTest(bool isUnderTest) { m_isUnderTest = isUnderTest; }
     WEBCORE_EXPORT void evaluateForTestInFrontend(const String& script);
 
     InspectorClient* inspectorClient() const { return m_inspectorClient; }
index 3ad3193..6aee5bb 100644 (file)
@@ -1,3 +1,61 @@
+2019-10-23  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: notify inspector when provisional page is created, committed and destroyed
+        https://bugs.webkit.org/show_bug.cgi?id=202704
+
+        Reviewed by Devin Rousso.
+
+        Updated frontend code to understand provisional targets. For now there are
+        no changes frontend behavior, it will wait for the provisional target to commit
+        and will not send any commands to it before that.
+
+        * UserInterface/Base/Main.js: Moved a bunch of methods shared between Main.js and Test.js
+        to TargetManager.js to keep them in sync.
+        * UserInterface/Controllers/TargetManager.js:
+        (WI.TargetManager):
+        (WI.TargetManager.prototype.removeTarget):
+        (WI.TargetManager.prototype.createMultiplexingBackendTarget):
+        (WI.TargetManager.prototype.createDirectBackendTarget):
+        (WI.TargetManager.prototype.targetCreated):
+        (WI.TargetManager.prototype.didCommitProvisionalTarget):
+        (WI.TargetManager.prototype.targetDestroyed):
+        (WI.TargetManager.prototype.dispatchMessageFromTarget):
+        (WI.TargetManager.prototype._checkAndHandlePageTargetTransition):
+        (WI.TargetManager.prototype._checkAndHandlePageTargetTermination):
+        (WI.TargetManager.prototype._initializeBackendTarget):
+        (WI.TargetManager.prototype._initializePageTarget):
+        (WI.TargetManager.prototype._transitionPageTarget):
+        (WI.TargetManager.prototype._terminatePageTarget):
+        (WI.TargetManager.prototype._resetMainExecutionContext):
+        (WI.TargetManager.prototype._redirectGlobalAgentsToConnection):
+        * UserInterface/Protocol/Connection.js:
+        (InspectorBackend.WorkerConnection.sendMessageToBackend):
+        (InspectorBackend.WorkerConnection):
+        (InspectorBackend.TargetConnection.sendMessageToBackend):
+        (InspectorBackend.TargetConnection):
+        * UserInterface/Protocol/Target.js:
+        (WI.Target.prototype.destroy): Mark target as destroyed to distinguish expected command errors from
+        genuine failures.
+
+        (WI.Target.prototype.isDestroyed):
+        * UserInterface/Protocol/TargetObserver.js: Since the front-end doesn't
+        send commands to the provisional targets yet, it has to ignore all activities
+        related to provisional pages. For that reason we need two sets to keep track of
+        - provisional pages that were destroyed and never committed
+        - old pages which were replaced by committed page and for which following targetDestroyed
+        event should be ignored
+        Better support for provisional targets will be added to frontend in a separate change.
+        (WI.TargetObserver):
+        (WI.TargetObserver.prototype.targetCreated):
+        (WI.TargetObserver.prototype.didCommitProvisionalTarget): For now convert the event into a subsequence
+        of targetDestroyed/targetCreated events which matches previous behavior.
+
+        (WI.TargetObserver.prototype.targetDestroyed):
+        (WI.TargetObserver.prototype.dispatchMessageFromTarget):
+        * UserInterface/Test/Test.js:
+        (WI.transitionPageTarget):
+        (WI.terminatePageTarget):
+
 2019-10-23  Nikita Vasilyev  <nvasilyev@apple.com>
 
         Web Inspector: Replace color wheel with square HSB color picker
index b8b3a7a..6fb49c4 100644 (file)
@@ -183,70 +183,6 @@ WI.loaded = function()
         WI.targetManager.createDirectBackendTarget();
 };
 
-WI.initializeBackendTarget = function(target)
-{
-    console.assert(!WI.mainTarget);
-
-    WI.backendTarget = target;
-
-    WI.resetMainExecutionContext();
-
-    WI._targetsAvailablePromise.resolve();
-};
-
-WI.initializePageTarget = function(target)
-{
-    console.assert(WI.sharedApp.isWebDebuggable());
-    console.assert(target.type === WI.TargetType.Page || target instanceof WI.DirectBackendTarget);
-
-    WI.pageTarget = target;
-
-    WI.resetMainExecutionContext();
-};
-
-WI.transitionPageTarget = function(target)
-{
-    console.assert(!WI.pageTarget);
-    console.assert(WI.sharedApp.debuggableType === WI.DebuggableType.WebPage);
-    console.assert(target.type === WI.TargetType.Page);
-
-    WI.pageTarget = target;
-
-    WI.resetMainExecutionContext();
-
-    // Actions to transition the page target.
-    WI.notifications.dispatchEventToListeners(WI.Notification.TransitionPageTarget);
-    WI.domManager.transitionPageTarget();
-    WI.networkManager.transitionPageTarget();
-    WI.timelineManager.transitionPageTarget();
-};
-
-WI.terminatePageTarget = function(target)
-{
-    console.assert(WI.pageTarget);
-    console.assert(WI.pageTarget === target);
-    console.assert(WI.sharedApp.debuggableType === WI.DebuggableType.WebPage);
-
-    // Remove any Worker targets associated with this page.
-    let workerTargets = WI.targets.filter((x) => x.type === WI.TargetType.Worker);
-    for (let workerTarget of workerTargets)
-        WI.workerManager.workerTerminated(workerTarget.identifier);
-
-    WI.pageTarget = null;
-};
-
-WI.resetMainExecutionContext = function()
-{
-    if (WI.mainTarget instanceof WI.MultiplexingBackendTarget)
-        return;
-
-    if (WI.mainTarget.executionContext) {
-        WI.runtimeManager.activeExecutionContext = WI.mainTarget.executionContext;
-        if (WI.quickConsole)
-            WI.quickConsole.initializeMainExecutionContextPathComponent();
-    }
-};
-
 WI.contentLoaded = function()
 {
     // If there was an uncaught exception earlier during loading, then
index c244f38..bd72979 100644 (file)
@@ -33,6 +33,9 @@ WI.TargetManager = class TargetManager extends WI.Object
         this._cachedTargetsList = null;
         this._seenPageTarget = false;
         this._transitionTimeoutIdentifier = undefined;
+
+        this._provisionalTargetInfos = new Map;
+        this._swappedTargetIds = new Set;
     }
 
     // Public
@@ -80,6 +83,7 @@ WI.TargetManager = class TargetManager extends WI.Object
 
         this._cachedTargetsList = null;
         this._targets.delete(target.identifier);
+        target.destroy();
 
         this.dispatchEventToListeners(WI.TargetManager.Event.TargetRemoved, {target});
     }
@@ -91,7 +95,7 @@ WI.TargetManager = class TargetManager extends WI.Object
         let target = new WI.MultiplexingBackendTarget;
         target.initialize();
 
-        WI.initializeBackendTarget(target);
+        this._initializeBackendTarget(target);
 
         // Add the target without dispatching an event.
         this._targets.set(target.identifier, target);
@@ -104,19 +108,55 @@ WI.TargetManager = class TargetManager extends WI.Object
         let target = new WI.DirectBackendTarget;
         target.initialize();
 
-        WI.initializeBackendTarget(target);
+        this._initializeBackendTarget(target);
 
         if (WI.sharedApp.debuggableType === WI.DebuggableType.Page)
-            WI.initializePageTarget(target);
+            this._initializePageTarget(target);
 
         this.addTarget(target);
     }
 
     // TargetObserver
 
-    targetCreated(target, targetInfo)
+    targetCreated(parentTarget, targetInfo)
+    {
+        this._targetCreated(parentTarget, targetInfo);
+
+        this.dispatchEventToListeners(WI.TargetManager.Event.TargetCreated, {targetInfo});
+    }
+
+    didCommitProvisionalTarget(parentTarget, previousTargetId, newTargetId)
+    {
+        this._targetDestroyed(previousTargetId);
+        let targetInfo = this._provisionalTargetInfos.get(newTargetId);
+        console.assert(targetInfo);
+        targetInfo.isProvisional = false;
+        this._provisionalTargetInfos.delete(newTargetId);
+        this._targetCreated(parentTarget, targetInfo);
+        console.assert(!this._swappedTargetIds.has(previousTargetId));
+        this._swappedTargetIds.add(previousTargetId);
+
+        this.dispatchEventToListeners(WI.TargetManager.Event.DidCommitProvisionalTarget, {previousTargetId, targetInfo});
+    }
+
+    targetDestroyed(targetId)
     {
-        let connection = new InspectorBackend.TargetConnection(target, targetInfo.targetId);
+        this._targetDestroyed(targetId);
+
+        this.dispatchEventToListeners(WI.TargetManager.Event.TargetDestroyed, {targetId});
+    }
+
+    _targetCreated(parentTarget, targetInfo)
+    {
+        console.assert(!this._provisionalTargetInfos.has(targetInfo.targetId));
+
+        // COMPATIBILITY (iOS 13.0): `Target.TargetInfo.isProvisional` did not exist yet.
+        if (targetInfo.isProvisional) {
+            this._provisionalTargetInfos.set(targetInfo.targetId, targetInfo);
+            return;
+        }
+
+        let connection = new InspectorBackend.TargetConnection(parentTarget, targetInfo.targetId);
         let subTarget = this._createTarget(targetInfo, connection);
         this._checkAndHandlePageTargetTransition(subTarget);
         subTarget.initialize();
@@ -124,8 +164,14 @@ WI.TargetManager = class TargetManager extends WI.Object
         this.addTarget(subTarget);
     }
 
-    targetDestroyed(targetId)
+    _targetDestroyed(targetId)
     {
+        if (this._provisionalTargetInfos.delete(targetId))
+            return;
+
+        if (this._swappedTargetIds.delete(targetId))
+            return;
+
         let target = this._targets.get(targetId);
         this._checkAndHandlePageTargetTermination(target);
         this.removeTarget(target);
@@ -133,6 +179,9 @@ WI.TargetManager = class TargetManager extends WI.Object
 
     dispatchMessageFromTarget(targetId, message)
     {
+        if (this._provisionalTargetInfos.has(targetId))
+            return;
+
         let target = this._targets.get(targetId);
         console.assert(target);
         if (!target)
@@ -168,12 +217,12 @@ WI.TargetManager = class TargetManager extends WI.Object
         // First page target.
         if (!WI.pageTarget && !this._seenPageTarget) {
             this._seenPageTarget = true;
-            WI.initializePageTarget(target);
+            this._initializePageTarget(target);
             return;
         }
 
         // Transitioning page target.
-        WI.transitionPageTarget(target);
+        this._transitionPageTarget(target);
     }
 
     _checkAndHandlePageTargetTermination(target)
@@ -185,7 +234,7 @@ WI.TargetManager = class TargetManager extends WI.Object
         console.assert(this._seenPageTarget);
 
         // Terminating the page target.
-        WI.terminatePageTarget(target);
+        this._terminatePageTarget(target);
 
         // Ensure we transition in a reasonable amount of time, otherwise close.
         const timeToTransition = 2000;
@@ -199,9 +248,74 @@ WI.TargetManager = class TargetManager extends WI.Object
             WI.close();
         }, timeToTransition);
     }
+
+    _initializeBackendTarget(target)
+    {
+        console.assert(!WI.mainTarget);
+
+        WI.backendTarget = target;
+
+        this._resetMainExecutionContext();
+
+        WI._targetsAvailablePromise.resolve();
+    }
+
+    _initializePageTarget(target)
+    {
+        console.assert(WI.sharedApp.isWebDebuggable());
+        console.assert(target.type === WI.TargetType.Page || target instanceof WI.DirectBackendTarget);
+
+        WI.pageTarget = target;
+
+        this._resetMainExecutionContext();
+    }
+
+    _transitionPageTarget(target)
+    {
+        console.assert(!WI.pageTarget);
+        console.assert(WI.sharedApp.debuggableType === WI.DebuggableType.WebPage);
+        console.assert(target.type === WI.TargetType.Page);
+
+        WI.pageTarget = target;
+
+        this._resetMainExecutionContext();
+
+        // Actions to transition the page target.
+        WI.notifications.dispatchEventToListeners(WI.Notification.TransitionPageTarget);
+        WI.domManager.transitionPageTarget();
+        WI.networkManager.transitionPageTarget();
+        WI.timelineManager.transitionPageTarget();
+    }
+
+    _terminatePageTarget(target)
+    {
+        console.assert(WI.pageTarget);
+        console.assert(WI.pageTarget === target);
+        console.assert(WI.sharedApp.debuggableType === WI.DebuggableType.WebPage);
+
+        // Remove any Worker targets associated with this page.
+        let workerTargets = WI.targets.filter((x) => x.type === WI.TargetType.Worker);
+        for (let workerTarget of workerTargets)
+            WI.workerManager.workerTerminated(workerTarget.identifier);
+
+        WI.pageTarget = null;
+    }
+
+    _resetMainExecutionContext()
+    {
+        if (WI.mainTarget instanceof WI.MultiplexingBackendTarget)
+            return;
+
+        if (WI.mainTarget.executionContext)
+            WI.runtimeManager.activeExecutionContext = WI.mainTarget.executionContext;
+    }
 };
 
 WI.TargetManager.Event = {
     TargetAdded: Symbol("target-manager-target-added"),
     TargetRemoved: Symbol("target-manager-target-removed"),
+
+    TargetCreated: "target-manager-target-created",
+    DidCommitProvisionalTarget: "target-manager-provisional-target-committed",
+    TargetDestroyed: "target-manager-target-detroyed",
 };
index 71c206b..f258c57 100644 (file)
@@ -296,8 +296,12 @@ InspectorBackend.WorkerConnection = class InspectorBackendWorkerConnection exten
 
     sendMessageToBackend(message)
     {
-        // Ignore errors if a worker went away quickly.
-        this._parentTarget.WorkerAgent.sendMessageToWorker(this._workerId, message).catch(function(){});
+        this._parentTarget.WorkerAgent.sendMessageToWorker(this._workerId, message).catch((error) => {
+            // Ignore errors if a worker went away quickly.
+            if (this.target.isDestroyed)
+                return;
+            WI.reportInternalError(error);
+        });
     }
 };
 
@@ -315,7 +319,12 @@ InspectorBackend.TargetConnection = class InspectorBackendTargetConnection exten
 
     sendMessageToBackend(message)
     {
-        this._parentTarget.TargetAgent.sendMessageToTarget(this._targetId, message);
+        this._parentTarget.TargetAgent.sendMessageToTarget(this._targetId, message).catch((error) => {
+            // Ignore errors if the target was destroyed after the command was dispatched.
+            if (this.target.isDestroyed)
+                return;
+            WI.reportInternalError(error);
+        });
     }
 };
 
index 677079e..b5fc41b 100644 (file)
@@ -162,6 +162,8 @@ WI.Target = class Target extends WI.Object
     get resourceCollection() { return this._resourceCollection; }
     get extraScriptCollection() { return this._extraScriptCollection; }
 
+    get isDestroyed() { return this._isDestroyed; }
+
     get displayName() { return this._name; }
 
     get mainResource()
@@ -199,10 +201,14 @@ WI.Target = class Target extends WI.Object
         this.dispatchEventToListeners(WI.Target.Event.ScriptAdded, {script});
     }
 
+    destroy()
+    {
+        this._isDestroyed = true;
+    }
+
     hasDomain(domainName)
     {
         console.assert(!domainName.includes(".") && !domainName.endsWith("Agent"));
-
         return domainName in this._agents;
     }
 
index 8eb1205..08aee9d 100644 (file)
@@ -32,6 +32,11 @@ WI.TargetObserver = class TargetObserver extends InspectorBackend.Dispatcher
         WI.targetManager.targetCreated(this._target, targetInfo);
     }
 
+    didCommitProvisionalTarget(oldTargetId, newTargetId)
+    {
+        WI.targetManager.didCommitProvisionalTarget(this._target, oldTargetId, newTargetId);
+    }
+
     targetDestroyed(targetId)
     {
         WI.targetManager.targetDestroyed(targetId);
index c234220..8eead55 100644 (file)
@@ -85,41 +85,6 @@ WI.loaded = function()
         WI.targetManager.createDirectBackendTarget();
 };
 
-WI.initializeBackendTarget = function(target)
-{
-    WI.backendTarget = target;
-
-    WI.resetMainExecutionContext();
-
-    WI._targetsAvailablePromise.resolve();
-};
-
-WI.initializePageTarget = function(target)
-{
-    WI.pageTarget = target;
-
-    WI.resetMainExecutionContext();
-};
-
-WI.transitionPageTarget = function(target)
-{
-    console.error("WI.transitionPageTarget should not be reached in tests.");
-};
-
-WI.terminatePageTarget = function(target)
-{
-    console.error("WI.terminatePageTarget should not be reached in tests.");
-};
-
-WI.resetMainExecutionContext = function()
-{
-    if (WI.mainTarget instanceof WI.MultiplexingBackendTarget)
-        return;
-
-    if (WI.mainTarget.executionContext)
-        WI.runtimeManager.activeExecutionContext = WI.mainTarget.executionContext;
-};
-
 WI.contentLoaded = function()
 {
     // Things that would normally get called by the UI, that we still want to do in tests.
index 1797abf..a2f9836 100644 (file)
@@ -69,7 +69,7 @@ WI.QuickConsole = class QuickConsole extends WI.View
         this._executionContextSelectorDivider = new WI.DividerNavigationItem;
         this._navigationBar.addNavigationItem(this._executionContextSelectorDivider);
 
-        this.initializeMainExecutionContextPathComponent();
+        this._initializeMainExecutionContextPathComponent();
 
         WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, this._updateAutomaticExecutionContextPathComponentTooltip, this);
 
@@ -82,6 +82,7 @@ WI.QuickConsole = class QuickConsole extends WI.View
         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._debuggerActiveCallFrameDidChange, this);
 
         WI.runtimeManager.addEventListener(WI.RuntimeManager.Event.ActiveExecutionContextChanged, this._activeExecutionContextChanged, this);
+        WI.notifications.addEventListener(WI.Notification.TransitionPageTarget, this._pageTargetTransitioned, this);
 
         WI.targetManager.addEventListener(WI.TargetManager.Event.TargetAdded, this._targetAdded, this);
         WI.targetManager.addEventListener(WI.TargetManager.Event.TargetRemoved, this._targetRemoved, this);
@@ -111,7 +112,14 @@ WI.QuickConsole = class QuickConsole extends WI.View
         super.closed();
     }
 
-    initializeMainExecutionContextPathComponent()
+    _pageTargetTransitioned()
+    {
+        if (WI.mainTarget instanceof WI.MultiplexingBackendTarget)
+            return;
+        this._initializeMainExecutionContextPathComponent();
+    }
+
+    _initializeMainExecutionContextPathComponent()
     {
         if (!WI.mainTarget || WI.mainTarget instanceof WI.MultiplexingBackendTarget)
             return;
index 41f2129..c97d0b2 100644 (file)
@@ -1,3 +1,82 @@
+2019-10-23  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: notify inspector when provisional page is created, committed and destroyed
+        https://bugs.webkit.org/show_bug.cgi?id=202704
+
+        Reviewed by Devin Rousso.
+
+        Target.targetCreated event is now generated for provisional pages as well as for regular
+        ones. This is the first step toward reattaching inspector earlier during PSON. In the future
+        if debugging is in progress the provisional target (page) will be paused until a signal from
+        inspector frontend. This will enable the frontend configure all agents before navigation starts.
+
+        * Sources.txt:
+        * UIProcess/API/APIWebAuthenticationPanel.cpp:
+        (API::WebAuthenticationPanel::WebAuthenticationPanel): Added explicit namespace specifier
+        to the constructor's argument as otherwise compilation fails due to conflict between API::String
+        and WTF::String.
+
+        * UIProcess/InspectorTargetProxy.cpp:
+        (WebKit::InspectorTargetProxy::create):
+        (WebKit::InspectorTargetProxy::connect):
+        (WebKit::InspectorTargetProxy::disconnect):
+        (WebKit::InspectorTargetProxy::sendMessageToTargetBackend):
+        (WebKit::InspectorTargetProxy::didCommitProvisionalTarget):
+        (WebKit::InspectorTargetProxy::isProvisional const):
+        (WebKit::InspectorTargetProxy::previousTargetID const):
+        * UIProcess/InspectorTargetProxy.h: Target proxy can start as a provisional target (with a pointer to
+        ProvisionalPageProxy) and later either be committed or destroyed.
+
+        * UIProcess/ProvisionalPageProxy.cpp:
+        (WebKit::ProvisionalPageProxy::ProvisionalPageProxy):
+        (WebKit::ProvisionalPageProxy::~ProvisionalPageProxy):
+        (WebKit::ProvisionalPageProxy::didReceiveMessage): Forward inspector messages to parent page's WebPageInspectorController.
+        Since each WebPage has a unique identifier the target ids will be globally unique and there is no risk of collisions.
+
+        * UIProcess/ProvisionalPageProxy.h:
+        (WebKit::ProvisionalPageProxy::page const):
+        * UIProcess/WebPageInspectorController.cpp:
+        (WebKit::getTargetID):
+        (WebKit::WebPageInspectorController::WebPageInspectorController):
+        (WebKit::WebPageInspectorController::clearTargets):
+        (WebKit::WebPageInspectorController::createInspectorTarget):
+        (WebKit::WebPageInspectorController::destroyInspectorTarget):
+        (WebKit::WebPageInspectorController::didCreateProvisionalPage):
+        (WebKit::WebPageInspectorController::didDestroyProvisionalPage):
+        (WebKit::WebPageInspectorController::didCommitProvisionalPage):
+        (WebKit::WebPageInspectorController::addTarget):
+        * UIProcess/WebPageInspectorController.h:
+        * UIProcess/WebPageInspectorTargetAgent.cpp: Removed. Merged this agent into InspectorTargetAgent.
+        * UIProcess/WebPageInspectorTargetAgent.h: Removed.
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::m_resetRecentCrashCountTimer):
+        (WebKit::WebPageProxy::finishAttachingToWebProcess):
+        (WebKit::WebPageProxy::commitProvisionalPage):
+        * UIProcess/WebPageProxy.h: Moved the target management logic into WebPageInspectorController.
+        WebPageProxy/ProvisionalPageProxy are expected to notifiy it about key lifecycle events and also
+        forward to it messages from inspector in the inspected WebProcess. How it translates to Target
+        events is inspector's business.
+
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPageInspectorTarget.cpp:
+        (WebKit::WebPageInspectorTarget::identifier const):
+        (WebKit::WebPageInspectorTarget::connect):
+        (WebKit::WebPageInspectorTarget::disconnect):
+        (WebKit::WebPageInspectorTarget::toTargetID):
+        * WebProcess/WebPage/WebPageInspectorTarget.h: Made the target own frontend channel instance as it's the
+        only place where the page specific channel is used.
+
+        * WebProcess/WebPage/WebPageInspectorTargetController.cpp:
+        (WebKit::WebPageInspectorTargetController::removeTarget):
+        (WebKit::WebPageInspectorTargetController::connectInspector):
+        (WebKit::WebPageInspectorTargetController::disconnectInspector):
+        * WebProcess/WebPage/WebPageInspectorTargetController.h:
+        * WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.cpp:
+        (WebKit::WebPageInspectorTargetFrontendChannel::WebPageInspectorTargetFrontendChannel):
+        (WebKit::WebPageInspectorTargetFrontendChannel::sendMessageToFrontend):
+        * WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.h: The channel's lifetime is managed by owning
+        target. No need to reference count it.
+
 2019-10-22  Jiewen Tan  <jiewen_tan@apple.com>
 
         [WebAuthn] Supply FrameInfo in -[WKUIDelegatePrivate _webView:runWebAuthenticationPanel:initiatedByFrame:completionHandler:]
index 1675275..d2a31cc 100644 (file)
@@ -289,7 +289,6 @@ UIProcess/WebPageDiagnosticLoggingClient.cpp
 UIProcess/WebPageGroup.cpp
 UIProcess/WebPageInjectedBundleClient.cpp
 UIProcess/WebPageInspectorController.cpp
-UIProcess/WebPageInspectorTargetAgent.cpp
 UIProcess/WebPageProxy.cpp
 UIProcess/WebPasteboardProxy.cpp
 UIProcess/WebPreferences.cpp
index 87a2f06..a5c0e30 100644 (file)
 namespace API {
 using namespace WebKit;
 
-Ref<WebAuthenticationPanel> WebAuthenticationPanel::create(const AuthenticatorManager& manager, const String& rpId)
+Ref<WebAuthenticationPanel> WebAuthenticationPanel::create(const AuthenticatorManager& manager, const WTF::String& rpId)
 {
     return adoptRef(*new WebAuthenticationPanel(manager, rpId));
 }
 
-WebAuthenticationPanel::WebAuthenticationPanel(const AuthenticatorManager& manager, const String& rpId)
+WebAuthenticationPanel::WebAuthenticationPanel(const AuthenticatorManager& manager, const WTF::String& rpId)
     : m_manager(makeWeakPtr(manager))
     , m_rpId(rpId)
     , m_client(WTF::makeUniqueRef<WebAuthenticationPanelClient>())
index 78e7ee9..c3f403f 100644 (file)
@@ -42,7 +42,7 @@ class WebAuthenticationPanelClient;
 
 class WebAuthenticationPanel final : public ObjectImpl<Object::Type::WebAuthenticationPanel>, public CanMakeWeakPtr<WebAuthenticationPanel> {
 public:
-    static Ref<WebAuthenticationPanel> create(const WebKit::AuthenticatorManager&, const String& rpId);
+    static Ref<WebAuthenticationPanel> create(const WebKit::AuthenticatorManager&, const WTF::String& rpId);
     ~WebAuthenticationPanel();
 
     WTF::String rpId() const { return m_rpId; }
@@ -52,7 +52,7 @@ public:
     void setClient(UniqueRef<WebAuthenticationPanelClient>&&);
 
 private:
-    WebAuthenticationPanel(const WebKit::AuthenticatorManager&, const String& rpId);
+    WebAuthenticationPanel(const WebKit::AuthenticatorManager&, const WTF::String& rpId);
 
     WeakPtr<WebKit::AuthenticatorManager> m_manager;
     WTF::String m_rpId;
index 61b8f36..1b37c1e 100644 (file)
@@ -26,7 +26,9 @@
 #include "config.h"
 #include "InspectorTargetProxy.h"
 
+#include "ProvisionalPageProxy.h"
 #include "WebFrameProxy.h"
+#include "WebPageInspectorTarget.h"
 #include "WebPageMessages.h"
 #include "WebPageProxy.h"
 #include "WebProcessProxy.h"
@@ -35,9 +37,16 @@ namespace WebKit {
 
 using namespace Inspector;
 
-Ref<InspectorTargetProxy> InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
+std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
 {
-    return adoptRef(*new InspectorTargetProxy(page, targetId, type));
+    return makeUnique<InspectorTargetProxy>(page, targetId, type);
+}
+
+std::unique_ptr<InspectorTargetProxy> InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId, Inspector::InspectorTargetType type)
+{
+    auto target = InspectorTargetProxy::create(provisionalPage.page(), targetId, type);
+    target->m_provisionalPage = makeWeakPtr(provisionalPage);
+    return target;
 }
 
 InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type)
@@ -47,22 +56,48 @@ InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, const String& tar
 {
 }
 
-void InspectorTargetProxy::connect(Inspector::FrontendChannel& channel)
+void InspectorTargetProxy::connect(Inspector::FrontendChannel::ConnectionType connectionType)
 {
+    if (m_provisionalPage) {
+        m_provisionalPage->process().send(Messages::WebPage::ConnectInspector(identifier(), connectionType), m_provisionalPage->webPageID());
+        return;
+    }
+
     if (m_page.hasRunningProcess())
-        m_page.process().send(Messages::WebPage::ConnectInspector(identifier(), channel.connectionType()), m_page.webPageID());
+        m_page.process().send(Messages::WebPage::ConnectInspector(identifier(), connectionType), m_page.webPageID());
 }
 
-void InspectorTargetProxy::disconnect(Inspector::FrontendChannel&)
+void InspectorTargetProxy::disconnect()
 {
+    if (m_provisionalPage) {
+        m_provisionalPage->process().send(Messages::WebPage::DisconnectInspector(identifier()), m_provisionalPage->webPageID());
+        return;
+    }
+
     if (m_page.hasRunningProcess())
         m_page.process().send(Messages::WebPage::DisconnectInspector(identifier()), m_page.webPageID());
 }
 
 void InspectorTargetProxy::sendMessageToTargetBackend(const String& message)
 {
+    if (m_provisionalPage) {
+        m_provisionalPage->process().send(Messages::WebPage::SendMessageToTargetBackend(identifier(), message), m_provisionalPage->webPageID());
+        return;
+    }
+
     if (m_page.hasRunningProcess())
         m_page.process().send(Messages::WebPage::SendMessageToTargetBackend(identifier(), message), m_page.webPageID());
 }
 
+void InspectorTargetProxy::didCommitProvisionalTarget()
+{
+    ASSERT(isProvisional());
+    m_provisionalPage = nullptr;
+}
+
+bool InspectorTargetProxy::isProvisional() const
+{
+    return !!m_provisionalPage;
+}
+
 } // namespace WebKit
index d382b02..dc30a06 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <JavaScriptCore/InspectorTarget.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebKit {
 
@@ -35,25 +36,30 @@ class WebPageProxy;
 // NOTE: This UIProcess side InspectorTarget doesn't care about the frontend channel, since
 // any target -> frontend messages will be routed to the WebPageProxy with a targetId.
 
-class InspectorTargetProxy final : public Inspector::InspectorTarget, public RefCounted<InspectorTargetProxy> {
+class InspectorTargetProxy final : public Inspector::InspectorTarget {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(InspectorTargetProxy);
 public:
-    static Ref<InspectorTargetProxy> create(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
+    static std::unique_ptr<InspectorTargetProxy> create(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
+    static std::unique_ptr<InspectorTargetProxy> create(ProvisionalPageProxy&, const String& targetId, Inspector::InspectorTargetType);
     InspectorTargetProxy(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType);
     ~InspectorTargetProxy() = default;
 
     Inspector::InspectorTargetType type() const final { return m_type; }
     String identifier() const final { return m_identifier; }
 
-    void connect(Inspector::FrontendChannel&);
-    void disconnect(Inspector::FrontendChannel&);
-    void sendMessageToTargetBackend(const String&);
+    void didCommitProvisionalTarget();
+    bool isProvisional() const override;
+
+    void connect(Inspector::FrontendChannel::ConnectionType) override;
+    void disconnect() override;
+    void sendMessageToTargetBackend(const String&) override;
 
 private:
     WebPageProxy& m_page;
     String m_identifier;
     Inspector::InspectorTargetType m_type;
+    WeakPtr<ProvisionalPageProxy> m_provisionalPage;
 };
 
 } // namespace WebKit
index 8b0b430..8cceb09 100644 (file)
@@ -38,6 +38,7 @@
 #include "WebErrors.h"
 #include "WebNavigationDataStore.h"
 #include "WebNavigationState.h"
+#include "WebPageInspectorController.h"
 #include "WebPageMessages.h"
 #include "WebPageProxy.h"
 #include "WebPageProxyMessages.h"
@@ -85,11 +86,15 @@ ProvisionalPageProxy::ProvisionalPageProxy(WebPageProxy& page, Ref<WebProcessPro
     }
 
     initializeWebPage();
+
+    m_page.inspectorController().didCreateProvisionalPage(*this);
 }
 
 ProvisionalPageProxy::~ProvisionalPageProxy()
 {
     if (!m_wasCommitted) {
+        m_page.inspectorController().willDestroyProvisionalPage(*this);
+
         if (&m_process->websiteDataStore() != &m_page.websiteDataStore())
             m_process->processPool().pageEndUsingWebsiteDataStore(m_page.identifier(), m_process->websiteDataStore());
 
@@ -387,6 +392,9 @@ void ProvisionalPageProxy::didReceiveMessage(IPC::Connection& connection, IPC::D
         || decoder.messageName() == Messages::WebPageProxy::DidStartLoadForQuickLookDocumentInMainFrame::name()
         || decoder.messageName() == Messages::WebPageProxy::DidFinishLoadForQuickLookDocumentInMainFrame::name()
 #endif
+        || decoder.messageName() == Messages::WebPageProxy::CreateInspectorTarget::name()
+        || decoder.messageName() == Messages::WebPageProxy::DestroyInspectorTarget::name()
+        || decoder.messageName() == Messages::WebPageProxy::SendMessageToInspectorFrontend::name()
         )
     {
         m_page.didReceiveMessage(connection, decoder);
index 6d9379c..634fb75 100644 (file)
@@ -65,7 +65,7 @@ public:
     ProvisionalPageProxy(WebPageProxy&, Ref<WebProcessProxy>&&, std::unique_ptr<SuspendedPageProxy>, uint64_t navigationID, bool isServerRedirect, const WebCore::ResourceRequest&, ProcessSwapRequestedByClient);
     ~ProvisionalPageProxy();
 
-    WebPageProxy& page() { return m_page; }
+    WebPageProxy& page() const { return m_page; }
     WebCore::PageIdentifier webPageID() const { return m_webPageID; }
     WebFrameProxy* mainFrame() const { return m_mainFrame.get(); }
     WebProcessProxy& process() { return m_process.get(); }
index bda59cd..b9a9469 100644 (file)
 #include "config.h"
 #include "WebPageInspectorController.h"
 
+#include "ProvisionalPageProxy.h"
 #include "WebFrameProxy.h"
-#include "WebPageInspectorTargetAgent.h"
+#include "WebPageInspectorTarget.h"
 #include "WebPageProxy.h"
 #include <JavaScriptCore/InspectorAgentBase.h>
 #include <JavaScriptCore/InspectorBackendDispatcher.h>
 #include <JavaScriptCore/InspectorBackendDispatchers.h>
 #include <JavaScriptCore/InspectorFrontendRouter.h>
+#include <JavaScriptCore/InspectorTargetAgent.h>
+#include <wtf/HashMap.h>
 
 namespace WebKit {
 
 using namespace Inspector;
 
+static String getTargetID(const ProvisionalPageProxy& provisionalPage)
+{
+    return WebPageInspectorTarget::toTargetID(provisionalPage.webPageID());
+}
+
 WebPageInspectorController::WebPageInspectorController(WebPageProxy& page)
     : m_page(page)
     , m_frontendRouter(FrontendRouter::create())
     , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
 {
-    auto targetAgent = makeUnique<WebPageInspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
+    auto targetAgent = makeUnique<InspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
 
     m_targetAgent = targetAgent.get();
 
     m_agents.append(WTFMove(targetAgent));
 }
 
+void WebPageInspectorController::init()
+{
+    String pageTargetId = WebPageInspectorTarget::toTargetID(m_page.webPageID());
+    createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
+}
+
 void WebPageInspectorController::pageClosed()
 {
     disconnectAllFrontends();
@@ -134,37 +148,57 @@ void WebPageInspectorController::setIndicating(bool indicating)
 }
 #endif
 
-void WebPageInspectorController::clearTargets()
+void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
 {
-    for (auto& target : m_targets)
-        m_targetAgent->targetDestroyed(*target.get());
-
-    m_targets.clear();
+    addTarget(InspectorTargetProxy::create(m_page, targetId, type));
 }
 
-void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
+void WebPageInspectorController::destroyInspectorTarget(const String& targetId)
 {
-    auto target = InspectorTargetProxy::create(m_page, targetId, type);
-    m_targets.append(target.copyRef());
+    auto it = m_targets.find(targetId);
+    if (it == m_targets.end())
+        return;
+    m_targetAgent->targetDestroyed(*it->value);
+    m_targets.remove(it);
+}
 
-    m_targetAgent->targetCreated(target.get());
+void WebPageInspectorController::sendMessageToInspectorFrontend(const String& targetId, const String& message)
+{
+    m_targetAgent->sendMessageFromTargetToFrontend(targetId, message);
 }
 
-void WebPageInspectorController::destroyInspectorTarget(const String& targetId)
+void WebPageInspectorController::didCreateProvisionalPage(ProvisionalPageProxy& provisionalPage)
 {
-    auto position = m_targets.findMatching([&](const auto& item) { return item->identifier() == targetId; });
-    if (position == notFound)
-        return;
+    addTarget(InspectorTargetProxy::create(provisionalPage, getTargetID(provisionalPage), Inspector::InspectorTargetType::Page));
+}
 
-    auto& target = m_targets[position];
-    m_targetAgent->targetDestroyed(*target.get());
+void WebPageInspectorController::willDestroyProvisionalPage(const ProvisionalPageProxy& provisionalPage)
+{
+    destroyInspectorTarget(getTargetID(provisionalPage));
+}
 
-    m_targets.remove(position);
+void WebPageInspectorController::didCommitProvisionalPage(WebCore::PageIdentifier oldWebPageID, WebCore::PageIdentifier newWebPageID)
+{
+    String oldID = WebPageInspectorTarget::toTargetID(oldWebPageID);
+    String newID = WebPageInspectorTarget::toTargetID(newWebPageID);
+    auto newTarget = m_targets.take(newID);
+    ASSERT(newTarget);
+    newTarget->didCommitProvisionalTarget();
+    m_targetAgent->didCommitProvisionalTarget(oldID, newID);
+
+    // We've disconnected from the old page and will not receive any message from it, so
+    // we destroy everything but the new target here.
+    // FIXME: <https://webkit.org/b/202937> do not destroy targets that belong to the committed page.
+    for (auto& target : m_targets.values())
+        m_targetAgent->targetDestroyed(*target);
+    m_targets.clear();
+    m_targets.set(newTarget->identifier(), WTFMove(newTarget));
 }
 
-void WebPageInspectorController::sendMessageToInspectorFrontend(const String& targetId, const String& message)
+void WebPageInspectorController::addTarget(std::unique_ptr<InspectorTargetProxy>&& target)
 {
-    m_targetAgent->sendMessageFromTargetToFrontend(targetId, message);
+    m_targetAgent->targetCreated(*target);
+    m_targets.set(target->identifier(), WTFMove(target));
 }
 
 } // namespace WebKit
index 0caf6a1..a70dce7 100644 (file)
@@ -46,6 +46,7 @@ class WebPageInspectorController {
 public:
     WebPageInspectorController(WebPageProxy&);
 
+    void init();
     void pageClosed();
 
     bool hasLocalFrontend() const;
@@ -60,18 +61,23 @@ public:
     void setIndicating(bool);
 #endif
 
-    void clearTargets();
     void createInspectorTarget(const String& targetId, Inspector::InspectorTargetType);
     void destroyInspectorTarget(const String& targetId);
     void sendMessageToInspectorFrontend(const String& targetId, const String& message);
 
+    void didCreateProvisionalPage(ProvisionalPageProxy&);
+    void willDestroyProvisionalPage(const ProvisionalPageProxy&);
+    void didCommitProvisionalPage(WebCore::PageIdentifier oldWebPageID, WebCore::PageIdentifier newWebPageID);
+
 private:
+    void addTarget(std::unique_ptr<InspectorTargetProxy>&&);
+
     WebPageProxy& m_page;
     Ref<Inspector::FrontendRouter> m_frontendRouter;
     Ref<Inspector::BackendDispatcher> m_backendDispatcher;
     Inspector::AgentRegistry m_agents;
     Inspector::InspectorTargetAgent* m_targetAgent;
-    Vector<RefPtr<InspectorTargetProxy>> m_targets;
+    HashMap<String, std::unique_ptr<InspectorTargetProxy>> m_targets;
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorTargetAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorTargetAgent.cpp
deleted file mode 100644 (file)
index ba001c0..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "WebPageInspectorTargetAgent.h"
-
-namespace WebKit {
-
-WebPageInspectorTargetAgent::WebPageInspectorTargetAgent(Inspector::FrontendRouter& frontendRouter, Inspector::BackendDispatcher& backendDispatcher)
-    : Inspector::InspectorTargetAgent(frontendRouter, backendDispatcher)
-    , m_router(frontendRouter)
-{
-}
-
-WebPageInspectorTargetAgent::~WebPageInspectorTargetAgent() = default;
-
-Inspector::FrontendChannel& WebPageInspectorTargetAgent::frontendChannel()
-{
-    return *this;
-}
-
-Inspector::FrontendChannel::ConnectionType WebPageInspectorTargetAgent::connectionType() const
-{
-    return m_router.hasLocalFrontend() ? Inspector::FrontendChannel::ConnectionType::Local : Inspector::FrontendChannel::ConnectionType::Remote;
-}
-
-void WebPageInspectorTargetAgent::sendMessageToFrontend(const String&)
-{
-    // Intentionally ignored, this channel is not actually used to send messages.
-    ASSERT_NOT_REACHED();
-}
-
-} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/WebPageInspectorTargetAgent.h b/Source/WebKit/UIProcess/WebPageInspectorTargetAgent.h
deleted file mode 100644 (file)
index 963f9c3..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <JavaScriptCore/InspectorFrontendChannel.h>
-#include <JavaScriptCore/InspectorTargetAgent.h>
-
-namespace WebKit {
-
-class WebPageInspectorTargetAgent final : public Inspector::InspectorTargetAgent, public Inspector::FrontendChannel {
-public:
-    WebPageInspectorTargetAgent(Inspector::FrontendRouter&, Inspector::BackendDispatcher&);
-    virtual ~WebPageInspectorTargetAgent();
-
-    // InspectorTargetAgent
-    Inspector::FrontendChannel& frontendChannel();
-
-    // FrontendChannel
-    Inspector::FrontendChannel::ConnectionType connectionType() const;
-    void sendMessageToFrontend(const String&);
-
-private:
-    Inspector::FrontendRouter& m_router;
-};
-
-} // namespace WebKit
index 35f49ff..3bdf2e3 100644 (file)
@@ -492,8 +492,7 @@ WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, Ref
     m_inspectorDebuggable->setRemoteDebuggingAllowed(true);
     m_inspectorDebuggable->init();
 #endif
-
-    createInspectorTargets();
+    m_inspectorController->init();
 }
 
 WebPageProxy::~WebPageProxy()
@@ -862,9 +861,6 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason)
     remoteInspectorInformationDidChange();
 #endif
 
-    clearInspectorTargets();
-    createInspectorTargets();
-
     pageClient().didRelaunchProcess();
     m_pageLoadState.didSwapWebProcesses();
     if (reason != ProcessLaunchReason::InitialProcess)
@@ -1667,17 +1663,6 @@ void WebPageProxy::remoteInspectorInformationDidChange()
 }
 #endif
 
-void WebPageProxy::clearInspectorTargets()
-{
-    m_inspectorController->clearTargets();
-}
-
-void WebPageProxy::createInspectorTargets()
-{
-    String pageTargetId = makeString("page-", m_webPageID.toUInt64());
-    m_inspectorController->createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
-}
-
 void WebPageProxy::setBackgroundColor(const Optional<Color>& color)
 {
     if (m_backgroundColor == color)
@@ -3041,6 +3026,7 @@ void WebPageProxy::commitProvisionalPage(FrameIdentifier frameID, uint64_t navig
     if (!didSuspendPreviousPage)
         m_process->send(Messages::WebPage::Close(), m_webPageID);
 
+    const auto oldWebPageID = m_webPageID;
     swapToWebProcess(m_provisionalPage->process(), m_provisionalPage->webPageID(), m_provisionalPage->takeDrawingArea(), m_provisionalPage->mainFrame());
 
 #if PLATFORM(COCOA)
@@ -3051,6 +3037,7 @@ void WebPageProxy::commitProvisionalPage(FrameIdentifier frameID, uint64_t navig
 
     didCommitLoadForFrame(frameID, navigationID, mimeType, frameHasCustomContentProvider, frameLoadType, certificateInfo, containsPluginDocument, forcedHasInsecureContent, userData);
 
+    m_inspectorController->didCommitProvisionalPage(oldWebPageID, m_webPageID);
     m_provisionalPage = nullptr;
 }
 
index 45817d7..a5a3454 100644 (file)
@@ -2092,9 +2092,6 @@ private:
 
     void stopAllURLSchemeTasks(WebProcessProxy* = nullptr);
 
-    void clearInspectorTargets();
-    void createInspectorTargets();
-
 #if ENABLE(ATTACHMENT_ELEMENT)
     void registerAttachmentIdentifierFromData(const String&, const String& contentType, const String& preferredFileName, const IPC::DataReference&);
     void registerAttachmentIdentifierFromFilePath(const String&, const String& contentType, const String& filePath);
index d424fc1..2bbde9c 100644 (file)
                A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = A543E305215AD12D00279CD9 /* WebPageInspectorTargetFrontendChannel.h */; };
                A543E30C215C8A8D00279CD9 /* WebPageInspectorTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = A543E308215C8A8300279CD9 /* WebPageInspectorTarget.h */; };
                A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */ = {isa = PBXBuildFile; fileRef = A543E30B215C8A8400279CD9 /* WebPageInspectorTargetController.h */; };
-               A543E310215D8CE600279CD9 /* WebPageInspectorTargetAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A543E30E215D8CE200279CD9 /* WebPageInspectorTargetAgent.h */; };
                A55BA8101BA1317E007CD33D /* _WKRemoteWebInspectorViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = A55BA80C1BA12BE1007CD33D /* _WKRemoteWebInspectorViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A55BA8171BA23E12007CD33D /* RemoteWebInspectorUI.h in Headers */ = {isa = PBXBuildFile; fileRef = A55BA8131BA23E05007CD33D /* RemoteWebInspectorUI.h */; };
                A55BA81F1BA25B27007CD33D /* RemoteWebInspectorProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = A55BA8191BA25B1E007CD33D /* RemoteWebInspectorProxy.h */; };
                A543E309215C8A8300279CD9 /* WebPageInspectorTargetController.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageInspectorTargetController.cpp; sourceTree = "<group>"; };
                A543E30A215C8A8400279CD9 /* WebPageInspectorTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageInspectorTarget.cpp; sourceTree = "<group>"; };
                A543E30B215C8A8400279CD9 /* WebPageInspectorTargetController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorTargetController.h; sourceTree = "<group>"; };
-               A543E30E215D8CE200279CD9 /* WebPageInspectorTargetAgent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorTargetAgent.h; sourceTree = "<group>"; };
-               A543E30F215D8CE200279CD9 /* WebPageInspectorTargetAgent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageInspectorTargetAgent.cpp; sourceTree = "<group>"; };
                A55BA80C1BA12BE1007CD33D /* _WKRemoteWebInspectorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKRemoteWebInspectorViewController.h; sourceTree = "<group>"; };
                A55BA80D1BA12BE1007CD33D /* _WKRemoteWebInspectorViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKRemoteWebInspectorViewController.mm; sourceTree = "<group>"; };
                A55BA8121BA23E05007CD33D /* RemoteWebInspectorUI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteWebInspectorUI.cpp; sourceTree = "<group>"; };
                                2D9EA30E1A96CBFF002D2807 /* WebPageInjectedBundleClient.h */,
                                A513F53F2154A5CD00662841 /* WebPageInspectorController.cpp */,
                                A513F53E2154A5CC00662841 /* WebPageInspectorController.h */,
-                               A543E30F215D8CE200279CD9 /* WebPageInspectorTargetAgent.cpp */,
-                               A543E30E215D8CE200279CD9 /* WebPageInspectorTargetAgent.h */,
                                BC111B0B112F5E4F00337BAB /* WebPageProxy.cpp */,
                                BC032DCB10F4389F0058C15A /* WebPageProxy.h */,
                                BCBD38FA125BAB9A00D2C29F /* WebPageProxy.messages.in */,
                                2D9EA30F1A96CBFF002D2807 /* WebPageInjectedBundleClient.h in Headers */,
                                A513F5402154A5D700662841 /* WebPageInspectorController.h in Headers */,
                                A543E30C215C8A8D00279CD9 /* WebPageInspectorTarget.h in Headers */,
-                               A543E310215D8CE600279CD9 /* WebPageInspectorTargetAgent.h in Headers */,
                                A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */,
                                A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */,
                                C0CE72A11247E71D00BC0EC4 /* WebPageMessages.h in Headers */,
index 56b0d52..a70f6fd 100644 (file)
@@ -27,6 +27,7 @@
 #include "WebPageInspectorTarget.h"
 
 #include "WebPage.h"
+#include "WebPageInspectorTargetFrontendChannel.h"
 #include <WebCore/InspectorController.h>
 #include <WebCore/Page.h>
 
@@ -41,19 +42,25 @@ WebPageInspectorTarget::WebPageInspectorTarget(WebPage& page)
 
 String WebPageInspectorTarget::identifier() const
 {
-    return makeString("page-", m_page.identifier().toUInt64());
+    return toTargetID(m_page.identifier());
 }
 
-void WebPageInspectorTarget::connect(Inspector::FrontendChannel& channel)
+void WebPageInspectorTarget::connect(Inspector::FrontendChannel::ConnectionType connectionType)
 {
+    if (m_channel)
+        return;
+    m_channel = makeUnique<WebPageInspectorTargetFrontendChannel>(m_page, identifier(), connectionType);
     if (m_page.corePage())
-        m_page.corePage()->inspectorController().connectFrontend(channel);
+        m_page.corePage()->inspectorController().connectFrontend(*m_channel);
 }
 
-void WebPageInspectorTarget::disconnect(Inspector::FrontendChannel& channel)
+void WebPageInspectorTarget::disconnect()
 {
+    if (!m_channel)
+        return;
     if (m_page.corePage())
-        m_page.corePage()->inspectorController().disconnectFrontend(channel);
+        m_page.corePage()->inspectorController().disconnectFrontend(*m_channel);
+    m_channel.reset();
 }
 
 void WebPageInspectorTarget::sendMessageToTargetBackend(const String& message)
@@ -62,4 +69,10 @@ void WebPageInspectorTarget::sendMessageToTargetBackend(const String& message)
         m_page.corePage()->inspectorController().dispatchMessageFromFrontend(message);
 }
 
+String WebPageInspectorTarget::toTargetID(WebCore::PageIdentifier pageID)
+{
+    return makeString("page-", pageID.toUInt64());
+}
+
+
 } // namespace WebKit
index b70e31c..6cbd7fa 100644 (file)
 #pragma once
 
 #include <JavaScriptCore/InspectorTarget.h>
+#include <WebCore/PageIdentifier.h>
 #include <wtf/Noncopyable.h>
 
 namespace WebKit {
 
 class WebPage;
+class WebPageInspectorTargetFrontendChannel;
 
 class WebPageInspectorTarget final : public Inspector::InspectorTarget {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(WebPageInspectorTarget);
 public:
-    WebPageInspectorTarget(WebPage&);
+    explicit WebPageInspectorTarget(WebPage&);
     ~WebPageInspectorTarget() = default;
 
     Inspector::InspectorTargetType type() const final { return Inspector::InspectorTargetType::Page; }
 
     String identifier() const final;
 
-    void connect(Inspector::FrontendChannel&);
-    void disconnect(Inspector::FrontendChannel&);
-    void sendMessageToTargetBackend(const String&);
+    void connect(Inspector::FrontendChannel::ConnectionType) override;
+    void disconnect() override;
+    void sendMessageToTargetBackend(const String&) override;
+
+    static String toTargetID(WebCore::PageIdentifier);
 
 private:
     WebPage& m_page;
+    std::unique_ptr<WebPageInspectorTargetFrontendChannel> m_channel;
 };
 
 } // namespace WebKit
index 5254896..cda4f1e 100644 (file)
@@ -58,7 +58,6 @@ void WebPageInspectorTargetController::removeTarget(Inspector::InspectorTarget&
     m_page.send(Messages::WebPageProxy::DestroyInspectorTarget(target.identifier()));
 
     m_targets.remove(target.identifier());
-    m_targetFrontendChannels.remove(target.identifier());
 }
 
 void WebPageInspectorTargetController::connectInspector(const String& targetId, Inspector::FrontendChannel::ConnectionType connectionType)
@@ -67,13 +66,7 @@ void WebPageInspectorTargetController::connectInspector(const String& targetId,
     if (!target)
         return;
 
-    RefPtr<WebPageInspectorTargetFrontendChannel> channel = m_targetFrontendChannels.get(targetId);
-    if (!channel) {
-        channel = WebPageInspectorTargetFrontendChannel::create(*this, targetId, connectionType);
-        m_targetFrontendChannels.set(target->identifier(), channel);
-    }
-
-    target->connect(*channel.get());
+    target->connect(connectionType);
 }
 
 void WebPageInspectorTargetController::disconnectInspector(const String& targetId)
@@ -82,11 +75,7 @@ void WebPageInspectorTargetController::disconnectInspector(const String& targetI
     if (!target)
         return;
 
-    RefPtr<WebPageInspectorTargetFrontendChannel> channel = m_targetFrontendChannels.take(targetId);
-    if (!channel)
-        return;
-
-    target->disconnect(*channel.get());
+    target->disconnect();
 }
 
 void WebPageInspectorTargetController::sendMessageToTargetBackend(const String& targetId, const String& message)
@@ -98,9 +87,4 @@ void WebPageInspectorTargetController::sendMessageToTargetBackend(const String&
     target->sendMessageToTargetBackend(message);
 }
 
-void WebPageInspectorTargetController::sendMessageToTargetFrontend(const String& targetId, const String& message)
-{
-    m_page.send(Messages::WebPageProxy::SendMessageToInspectorFrontend(targetId, message));
-}
-
 } // namespace WebKit
index 3e92b7a..7c931da 100644 (file)
@@ -26,7 +26,6 @@
 #pragma once
 
 #include "WebPageInspectorTarget.h"
-#include "WebPageInspectorTargetFrontendChannel.h"
 #include <wtf/HashMap.h>
 #include <wtf/text/WTFString.h>
 
@@ -50,13 +49,11 @@ public:
     void connectInspector(const String& targetId, Inspector::FrontendChannel::ConnectionType);
     void disconnectInspector(const String& targetId);
     void sendMessageToTargetBackend(const String& targetId, const String& message);
-    void sendMessageToTargetFrontend(const String& targetId, const String& message);
 
 private:
     WebPage& m_page;
     WebPageInspectorTarget m_pageTarget;
     HashMap<String, Inspector::InspectorTarget*> m_targets;
-    HashMap<String, RefPtr<WebPageInspectorTargetFrontendChannel>> m_targetFrontendChannels;
 };
 
 } // namespace WebKit
index 8d78807..e1b5f71 100644 (file)
 #include "config.h"
 #include "WebPageInspectorTargetFrontendChannel.h"
 
-#include "WebPageInspectorTargetController.h"
+#include "WebPage.h"
+#include "WebPageProxyMessages.h"
 
 namespace WebKit {
 
-Ref<WebPageInspectorTargetFrontendChannel> WebPageInspectorTargetFrontendChannel::create(WebPageInspectorTargetController& targetController, const String& targetId, Inspector::FrontendChannel::ConnectionType connectionType)
-{
-    return adoptRef(*new WebPageInspectorTargetFrontendChannel(targetController, targetId, connectionType));
-}
-
-WebPageInspectorTargetFrontendChannel::WebPageInspectorTargetFrontendChannel(WebPageInspectorTargetController& targetController, const String& targetId, Inspector::FrontendChannel::ConnectionType connectionType)
-    : m_targetController(targetController)
+WebPageInspectorTargetFrontendChannel::WebPageInspectorTargetFrontendChannel(WebPage& page, const String& targetId, Inspector::FrontendChannel::ConnectionType connectionType)
+    : m_page(page)
     , m_targetId(targetId)
     , m_connectionType(connectionType)
 {
@@ -44,7 +40,7 @@ WebPageInspectorTargetFrontendChannel::WebPageInspectorTargetFrontendChannel(Web
 
 void WebPageInspectorTargetFrontendChannel::sendMessageToFrontend(const String& message)
 {
-    m_targetController.sendMessageToTargetFrontend(m_targetId, message);
+    m_page.send(Messages::WebPageProxy::SendMessageToInspectorFrontend(m_targetId, message));
 }
 
 } // namespace WebKit
index 76af62a..8184ac5 100644 (file)
 
 namespace WebKit {
 
-class WebPageInspectorTargetController;
+class WebPage;
 
-class WebPageInspectorTargetFrontendChannel final : public RefCounted<WebPageInspectorTargetFrontendChannel>, public Inspector::FrontendChannel {
+class WebPageInspectorTargetFrontendChannel final : public Inspector::FrontendChannel {
     WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(WebPageInspectorTargetFrontendChannel);
 public:
-    static Ref<WebPageInspectorTargetFrontendChannel> create(WebPageInspectorTargetController&, const String& targetId, Inspector::FrontendChannel::ConnectionType);
+    WebPageInspectorTargetFrontendChannel(WebPage&, const String& targetId, Inspector::FrontendChannel::ConnectionType);
     virtual ~WebPageInspectorTargetFrontendChannel() = default;
 
 private:
-    WebPageInspectorTargetFrontendChannel(WebPageInspectorTargetController&, const String& targetId, Inspector::FrontendChannel::ConnectionType);
-
     ConnectionType connectionType() const override { return m_connectionType; }
     void sendMessageToFrontend(const String& message) override;
 
-private:
-    WebPageInspectorTargetController& m_targetController;
+    WebPage& m_page;
     String m_targetId;
     Inspector::FrontendChannel::ConnectionType m_connectionType { Inspector::FrontendChannel::ConnectionType::Remote };
 };