Web Inspector: Avoid using Runtime.executionContextCreated to figure out the iframe's contentDocument node.
https://bugs.webkit.org/show_bug.cgi?id=122764
<rdar://problem/15222136>

Reviewed by Devin Rousso.

Source/WebCore:

Force execution context creation on frame navigation similar to what inspector already
does for all known contexts when Runtime.enable is called. This is a prerequisite for
the injected script to work.

Test: inspector/runtime/execution-context-in-scriptless-page.html

* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::didCommitLoadImpl):
* inspector/agents/page/PageRuntimeAgent.cpp:
(WebCore::PageRuntimeAgent::frameNavigated):
* inspector/agents/page/PageRuntimeAgent.h:

LayoutTests:

Test that execution context is created and reported for pages without JavaScript.

* inspector/runtime/execution-context-in-scriptless-page-expected.txt: Added.
* inspector/runtime/execution-context-in-scriptless-page.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@253166 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 0fc6016..d3a4f71 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,16 @@
+2019-12-05  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: Avoid using Runtime.executionContextCreated to figure out the iframe's contentDocument node.
+        https://bugs.webkit.org/show_bug.cgi?id=122764
+        <rdar://problem/15222136>
+
+        Reviewed by Devin Rousso.
+
+        Test that execution context is created and reported for pages without JavaScript.
+
+        * inspector/runtime/execution-context-in-scriptless-page-expected.txt: Added.
+        * inspector/runtime/execution-context-in-scriptless-page.html: Added.
+
 2019-12-05  youenn fablet  <youenn@apple.com>
 
         maplike should define a set method
diff --git a/LayoutTests/inspector/runtime/execution-context-in-scriptless-page-expected.txt b/LayoutTests/inspector/runtime/execution-context-in-scriptless-page-expected.txt
new file mode 100644
index 0000000..5a3a311
--- /dev/null
+++ b/LayoutTests/inspector/runtime/execution-context-in-scriptless-page-expected.txt
@@ -0,0 +1,8 @@
+Test that Runtime.executionContextCreated event is fired even for pages without JavaScript.
+
+
+== Running test suite: Runtime.executionContextCreated.ContextWithoutScript
+-- Running test case: Runtime.executionContextCreated.ContextWithoutScript.SubFrame
+PASS: Should receive Runtime.executionContextCreated notification.
+PASS: Should be able to evaluate in subframe.
+
diff --git a/LayoutTests/inspector/runtime/execution-context-in-scriptless-page.html b/LayoutTests/inspector/runtime/execution-context-in-scriptless-page.html
new file mode 100644
index 0000000..149c63d
--- /dev/null
+++ b/LayoutTests/inspector/runtime/execution-context-in-scriptless-page.html
@@ -0,0 +1,53 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/protocol-test.js"></script>
+<script>
+
+function createFrame()
+{
+  let iframe = document.createElement("iframe");
+  iframe.src = "data:text/html,<p>No JavaScript.</p>";
+  document.body.appendChild(iframe);
+}
+
+function test()
+{
+    let suite = ProtocolTest.createAsyncSuite("Runtime.executionContextCreated.ContextWithoutScript");
+
+    suite.addTestCase({
+        name: "Runtime.executionContextCreated.ContextWithoutScript.SubFrame",
+        description: "Test that Runtime.executionContextCreated event is fired when a new iframe is added to the page and its document doesn't have any JavaScript.",
+        async test() {
+            await InspectorProtocol.awaitCommand({method: "Page.enable"});
+            await InspectorProtocol.awaitCommand({method: "Runtime.enable"});
+
+            let [executionContextCreatedEvent] = await Promise.all([
+                InspectorProtocol.awaitEvent({event: "Runtime.executionContextCreated"}),
+                InspectorProtocol.awaitCommand({
+                    method: "Runtime.evaluate",
+                    params: {expression: `createFrame()`}
+                })
+            ]);
+
+            ProtocolTest.pass("Should receive Runtime.executionContextCreated notification.");
+
+            let evaluateResult = await InspectorProtocol.awaitCommand({
+                method: "Runtime.evaluate",
+                params: {
+                    contextId: executionContextCreatedEvent.params.context.id,
+                    expression: `document.body.textContent`
+                }
+            });
+
+            ProtocolTest.expectEqual(evaluateResult.result.value, "No JavaScript.", "Should be able to evaluate in subframe.");
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Test that Runtime.executionContextCreated event is fired even for pages without JavaScript.</p>
+</body>
+</html>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 0e1edd4..4cf26da 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,23 @@
+2019-12-05  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: Avoid using Runtime.executionContextCreated to figure out the iframe's contentDocument node.
+        https://bugs.webkit.org/show_bug.cgi?id=122764
+        <rdar://problem/15222136>
+
+        Reviewed by Devin Rousso.
+
+        Force execution context creation on frame navigation similar to what inspector already
+        does for all known contexts when Runtime.enable is called. This is a prerequisite for
+        the injected script to work.
+
+        Test: inspector/runtime/execution-context-in-scriptless-page.html
+
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::didCommitLoadImpl):
+        * inspector/agents/page/PageRuntimeAgent.cpp:
+        (WebCore::PageRuntimeAgent::frameNavigated):
+        * inspector/agents/page/PageRuntimeAgent.h:
+
 2019-12-05  Chris Dumez  <cdumez@apple.com>
 
         MESSAGE_CHECK BackForwardItemIdentifier on incoming IPC from the WebProcess
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp
index cb6ed9f..0ad193c 100644
--- a/Source/WebCore/inspector/InspectorInstrumentation.cpp
+++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp
@@ -717,6 +717,9 @@
             pageHeapAgent->mainFrameNavigated();
     }
 
+    if (auto* pageRuntimeAgent = instrumentingAgents.pageRuntimeAgent())
+        pageRuntimeAgent->frameNavigated(frame);
+
     if (InspectorCanvasAgent* canvasAgent = instrumentingAgents.inspectorCanvasAgent())
         canvasAgent->frameNavigated(frame);
 
diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
index 8c4a104..b4b9d5c 100644
--- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
+++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
@@ -87,6 +87,12 @@
     InspectorRuntimeAgent::disable(errorString);
 }
 
+void PageRuntimeAgent::frameNavigated(Frame& frame)
+{
+    // Ensure execution context is created for the frame even if it doesn't have scripts.
+    mainWorldExecState(&frame);
+}
+
 void PageRuntimeAgent::didClearWindowObjectInWorld(Frame& frame)
 {
     auto* pageAgent = m_instrumentingAgents.inspectorPageAgent();
diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
index f388280..54a00e0 100644
--- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
+++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h
@@ -60,6 +60,7 @@
     void callFunctionOn(ErrorString&, const String& objectId, const String& expression, const JSON::Array* optionalArguments, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* emulateUserGesture, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown) override;
 
     // InspectorInstrumentation
+    void frameNavigated(Frame&);
     void didClearWindowObjectInWorld(Frame&);
 
 private: