Web Inspector: user gesture toggle should also force user interaction flag
https://bugs.webkit.org/show_bug.cgi?id=197269

Reviewed by Joseph Pecoraro.

Source/WebCore:

Test: inspector/runtime/evaluate-userGestureEmulation-userIsInteracting.html

* inspector/agents/page/PageRuntimeAgent.cpp:
(WebCore::PageRuntimeAgent::evaluate):

* page/ChromeClient.h:
(WebCore::ChromeClient::userIsInteracting const): Added.
(WebCore::ChromeClient::setUserIsInteracting): Added.

* testing/Internals.idl:
* testing/Internals.h:
* testing/Internals.cpp:
(WebCore::Internals::userIsInteracting): Added.

Source/WebKit:

* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::userIsInteracting const): Added.
(WebKit::WebChromeClient::setUserIsInteracting): Added.

* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::userIsInteracting const): Added.
(WebKit::WebPage::setUserIsInteracting): Added.

LayoutTests:

* inspector/runtime/evaluate-userGestureEmulation-userIsInteracting.html: Added.
* inspector/runtime/evaluate-userGestureEmulation-userIsInteracting-expected.txt: Added.

* TestExpectations:
* platform/wk2/TestExpectations:
Only enable the above test on WK2, as the user interaction state is only supported by WK2.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@245366 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 8a6fb5f..ab3bd9d 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,5 +1,19 @@
 2019-05-15  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: user gesture toggle should also force user interaction flag
+        https://bugs.webkit.org/show_bug.cgi?id=197269
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/runtime/evaluate-userGestureEmulation-userIsInteracting.html: Added.
+        * inspector/runtime/evaluate-userGestureEmulation-userIsInteracting-expected.txt: Added.
+
+        * TestExpectations:
+        * platform/wk2/TestExpectations:
+        Only enable the above test on WK2, as the user interaction state is only supported by WK2.
+
+2019-05-15  Devin Rousso  <drousso@apple.com>
+
         REGRESSION (r240644): Layout Test inspector/page/overrideSetting-ICECandidateFilteringEnabled.html is a flaky timeout
         https://bugs.webkit.org/show_bug.cgi?id=194437
         <rdar://problem/48008005>
diff --git a/LayoutTests/TestExpectations b/LayoutTests/TestExpectations
index bc1ce8b..78f1ba6 100644
--- a/LayoutTests/TestExpectations
+++ b/LayoutTests/TestExpectations
@@ -543,6 +543,9 @@
 # Debugger stepping tests can timeout if they run slowly due to a short timer scheduled in the frontend.
 webkit.org/b/161951 [ Debug ] inspector/debugger/paused-scopes.html [ Skip ]
 
+# User interaction is a WK2 concept.
+inspector/runtime/evaluate-userGestureEmulation-userIsInteracting.html [ 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/inspector/runtime/evaluate-userGestureEmulation-userIsInteracting-expected.txt b/LayoutTests/inspector/runtime/evaluate-userGestureEmulation-userIsInteracting-expected.txt
new file mode 100644
index 0000000..de8d12b
--- /dev/null
+++ b/LayoutTests/inspector/runtime/evaluate-userGestureEmulation-userIsInteracting-expected.txt
@@ -0,0 +1,9 @@
+Tests for Runtime emulateUserGesture option.
+
+
+== Running test suite: Runtime.evaluateUserGestureEmulation.userIsInteracting
+-- Running test case: EvaluateWithoutEmulatingUserGesture.userIsInteracting
+User is NOT Interacting
+-- Running test case: EvaluateWithEmulatingUserGesture.userIsInteracting
+User is Interacting
+
diff --git a/LayoutTests/inspector/runtime/evaluate-userGestureEmulation-userIsInteracting.html b/LayoutTests/inspector/runtime/evaluate-userGestureEmulation-userIsInteracting.html
new file mode 100644
index 0000000..007f1f2
--- /dev/null
+++ b/LayoutTests/inspector/runtime/evaluate-userGestureEmulation-userIsInteracting.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script>
+
+function load() {
+    document.getElementById("test").addEventListener("click", (event) => {
+        if (!window.internals)
+            return;
+
+        TestPage.addResult(window.internals.userIsInteracting() ? "User is Interacting" : "User is NOT Interacting");
+    });
+
+    runTest();
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("Runtime.evaluateUserGestureEmulation.userIsInteracting");
+
+    suite.addTestCase({
+        name: "EvaluateWithoutEmulatingUserGesture.userIsInteracting",
+        description: "Check that the evaluation is not considered a user interaction when emulateUserGesture is false.",
+        async test() {
+            await RuntimeAgent.evaluate.invoke({expression: `document.getElementById("test").click()`, emulateUserGesture: false});
+        },
+    });
+
+    suite.addTestCase({
+        name: "EvaluateWithEmulatingUserGesture.userIsInteracting",
+        description: "Check that the evaluation is considered a user interaction when emulateUserGesture is true.",
+        async test() {
+            await RuntimeAgent.evaluate.invoke({expression: `document.getElementById("test").click()`, emulateUserGesture: true});
+        },
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="load()">
+    <p>Tests for Runtime emulateUserGesture option.</p>
+    <a id="test"></a>
+</body>
+</html>
diff --git a/LayoutTests/platform/wk2/TestExpectations b/LayoutTests/platform/wk2/TestExpectations
index c8e80de..0c30604 100644
--- a/LayoutTests/platform/wk2/TestExpectations
+++ b/LayoutTests/platform/wk2/TestExpectations
@@ -502,6 +502,9 @@
 # First two lines are reversed when test is flaky.
 fast/preloader/document-write-2.html [ Pass Failure ]
 
+# User interaction is a WK2 concept.
+inspector/runtime/evaluate-userGestureEmulation-userIsInteracting.html [ Skip ]
+
 ### END OF (3) Unclassified failures
 ########################################
 
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 9ed9c6c..bda82a3 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,24 @@
+2019-05-15  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: user gesture toggle should also force user interaction flag
+        https://bugs.webkit.org/show_bug.cgi?id=197269
+
+        Reviewed by Joseph Pecoraro.
+
+        Test: inspector/runtime/evaluate-userGestureEmulation-userIsInteracting.html
+
+        * inspector/agents/page/PageRuntimeAgent.cpp:
+        (WebCore::PageRuntimeAgent::evaluate):
+
+        * page/ChromeClient.h:
+        (WebCore::ChromeClient::userIsInteracting const): Added.
+        (WebCore::ChromeClient::setUserIsInteracting): Added.
+
+        * testing/Internals.idl:
+        * testing/Internals.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::userIsInteracting): Added.
+
 2019-05-15  Zalan Bujtas  <zalan@apple.com>
 
         Do not create a shape object outside of the layout context
diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
index 82d87dc..33d7a12 100644
--- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
+++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp
@@ -32,6 +32,8 @@
 #include "config.h"
 #include "PageRuntimeAgent.h"
 
+#include "Chrome.h"
+#include "ChromeClient.h"
 #include "Document.h"
 #include "Frame.h"
 #include "InspectorPageAgent.h"
@@ -161,9 +163,24 @@
 
 void PageRuntimeAgent::evaluate(ErrorString& errorString, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, const bool* emulateUserGesture, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown, Optional<int>& savedResultIndex)
 {
-    Optional<ProcessingUserGestureState> userGestureState = (emulateUserGesture && *emulateUserGesture) ? Optional<ProcessingUserGestureState>(ProcessingUserGesture) : WTF::nullopt;
+    auto& pageChromeClient = m_inspectedPage.chrome().client();
+
+    auto shouldEmulateUserGesture = emulateUserGesture && *emulateUserGesture;
+
+    Optional<ProcessingUserGestureState> userGestureState = shouldEmulateUserGesture ? Optional<ProcessingUserGestureState>(ProcessingUserGesture) : WTF::nullopt;
     UserGestureIndicator gestureIndicator(userGestureState);
+
+    bool userWasInteracting = false;
+    if (shouldEmulateUserGesture) {
+        userWasInteracting = pageChromeClient.userIsInteracting();
+        if (!userWasInteracting)
+            pageChromeClient.setUserIsInteracting(true);
+    }
+
     InspectorRuntimeAgent::evaluate(errorString, expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, executionContextId, returnByValue, generatePreview, saveResult, emulateUserGesture, result, wasThrown, savedResultIndex);
+
+    if (shouldEmulateUserGesture && !userWasInteracting && pageChromeClient.userIsInteracting())
+        pageChromeClient.setUserIsInteracting(false);
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h
index 340a6af..f35390c 100644
--- a/Source/WebCore/page/ChromeClient.h
+++ b/Source/WebCore/page/ChromeClient.h
@@ -507,6 +507,9 @@
 
     virtual void configureLoggingChannel(const String&, WTFLogChannelState, WTFLogLevel) { }
 
+    virtual bool userIsInteracting() const { return false; }
+    virtual void setUserIsInteracting(bool) { }
+
 protected:
     virtual ~ChromeClient() = default;
 };
diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp
index eb94fed..ff682f7 100644
--- a/Source/WebCore/testing/Internals.cpp
+++ b/Source/WebCore/testing/Internals.cpp
@@ -47,6 +47,7 @@
 #include "CachedResourceLoader.h"
 #include "CertificateInfo.h"
 #include "Chrome.h"
+#include "ChromeClient.h"
 #include "ClientOrigin.h"
 #include "ComposedTreeIterator.h"
 #include "CookieJar.h"
@@ -4423,6 +4424,15 @@
     callback->handleEvent();
 }
 
+bool Internals::userIsInteracting()
+{
+    if (auto* document = contextDocument()) {
+        if (auto* page = document->page())
+            return page->chrome().client().userIsInteracting();
+    }
+    return false;
+}
+
 double Internals::lastHandledUserGestureTimestamp()
 {
     Document* document = contextDocument();
diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h
index 3342351..3ac66f7 100644
--- a/Source/WebCore/testing/Internals.h
+++ b/Source/WebCore/testing/Internals.h
@@ -655,6 +655,8 @@
 
     void withUserGesture(RefPtr<VoidCallback>&&);
 
+    bool userIsInteracting();
+
     RefPtr<GCObservation> observeGC(JSC::JSValue);
 
     enum class UserInterfaceLayoutDirection : uint8_t { LTR, RTL };
diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl
index d749e7e..ca2bc54 100644
--- a/Source/WebCore/testing/Internals.idl
+++ b/Source/WebCore/testing/Internals.idl
@@ -638,6 +638,8 @@
 
     void withUserGesture(VoidCallback callback);
 
+    boolean userIsInteracting();
+
     GCObservation? observeGC(any observed);
 
     void setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection userInterfaceLayoutDirection);
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 80bf8a3..f9ab477 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,19 @@
+2019-05-15  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: user gesture toggle should also force user interaction flag
+        https://bugs.webkit.org/show_bug.cgi?id=197269
+
+        Reviewed by Joseph Pecoraro.
+
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::userIsInteracting const): Added.
+        (WebKit::WebChromeClient::setUserIsInteracting): Added.
+
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::userIsInteracting const): Added.
+        (WebKit::WebPage::setUserIsInteracting): Added.
+
 2019-05-15  Brent Fulgham  <bfulgham@apple.com>
 
         Revise sandbox to allow IOKit properties needed by Metal and LaunchServices
diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
index 66e53a2..26900b5 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
@@ -1340,4 +1340,14 @@
     m_page.configureLoggingChannel(channelName, state, level);
 }
 
+bool WebChromeClient::userIsInteracting() const
+{
+    return m_page.userIsInteracting();
+}
+
+void WebChromeClient::setUserIsInteracting(bool userIsInteracting)
+{
+    m_page.setUserIsInteracting(userIsInteracting);
+}
+
 } // namespace WebKit
diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h
index 1121215..dd3b225 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h
@@ -379,6 +379,9 @@
 
     void configureLoggingChannel(const String&, WTFLogChannelState, WTFLogLevel) final;
 
+    bool userIsInteracting() const final;
+    void setUserIsInteracting(bool) final;
+
     String m_cachedToolTip;
     mutable RefPtr<WebFrame> m_cachedFrameSetLargestFrame;
     mutable bool m_cachedMainFrameHasHorizontalScrollbar { false };
diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h
index 1c9b99b..732890c 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h
@@ -1193,6 +1193,9 @@
     void scheduleFullEditorStateUpdate();
     bool isThrottleable() const;
 
+    bool userIsInteracting() const { return m_userIsInteracting; }
+    void setUserIsInteracting(bool userIsInteracting) { m_userIsInteracting = userIsInteracting; }
+
 private:
     WebPage(uint64_t pageID, WebPageCreationParameters&&);