WebDriver: implement page load timeout
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 24 Jul 2017 05:58:46 +0000 (05:58 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 24 Jul 2017 05:58:46 +0000 (05:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=174672

Reviewed by Brian Burg.

Source/WebDriver:

Handle timeout errors and pass the page load timeout to waitForNavigationToComplete and all other navigation
commands. Also fix the setTimeouts command that was still using the legacy name of the page load timeout,
instead of the one in the spec.

8. Sessions
https://www.w3.org/TR/webdriver/#dfn-session-page-load-timeout

* CommandResult.cpp:
(WebDriver::CommandResult::CommandResult):
(WebDriver::CommandResult::httpStatusCode):
(WebDriver::CommandResult::errorString):
* CommandResult.h:
* Session.cpp:
(WebDriver::Session::go):
(WebDriver::Session::back):
(WebDriver::Session::forward):
(WebDriver::Session::refresh):
(WebDriver::Session::waitForNavigationToComplete):
* WebDriverService.cpp:
(WebDriver::WebDriverService::setTimeouts):

Source/WebKit:

Always start a timer when waiting for a navigation to complete. When the timer fires, pending callbacks for
navigations are removed and invoked with a timeout error. If navigation completes before the timer is fired,
then the timer is stopped. All navigation commands now receive the page load strategy and timeout as optional
parameters, when not provided the default timeout (300 seconds) is used.

* UIProcess/Automation/Automation.json:
* UIProcess/Automation/WebAutomationSession.cpp:
(WebKit::WebAutomationSession::WebAutomationSession):
(WebKit::WebAutomationSession::waitForNavigationToComplete):
(WebKit::WebAutomationSession::waitForNavigationToCompleteOnPage):
(WebKit::WebAutomationSession::waitForNavigationToCompleteOnFrame):
(WebKit::WebAutomationSession::loadTimerFired):
(WebKit::WebAutomationSession::navigateBrowsingContext):
(WebKit::WebAutomationSession::goBackInBrowsingContext):
(WebKit::WebAutomationSession::goForwardInBrowsingContext):
(WebKit::WebAutomationSession::reloadBrowsingContext):
(WebKit::WebAutomationSession::navigationOccurredForFrame):
* UIProcess/Automation/WebAutomationSession.h:

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

Source/WebDriver/ChangeLog
Source/WebDriver/CommandResult.cpp
Source/WebDriver/CommandResult.h
Source/WebDriver/Session.cpp
Source/WebDriver/WebDriverService.cpp
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/Automation/Automation.json
Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp
Source/WebKit/UIProcess/Automation/WebAutomationSession.h

index a2f68841a37f0e199039d7dd54d30deb81bc34a3..138a4c3d3eeb1c4959bd7a75ce5b17c3c3e06ad6 100644 (file)
@@ -1,3 +1,31 @@
+2017-07-20  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        WebDriver: implement page load timeout
+        https://bugs.webkit.org/show_bug.cgi?id=174672
+
+        Reviewed by Brian Burg.
+
+        Handle timeout errors and pass the page load timeout to waitForNavigationToComplete and all other navigation
+        commands. Also fix the setTimeouts command that was still using the legacy name of the page load timeout,
+        instead of the one in the spec.
+
+        8. Sessions
+        https://www.w3.org/TR/webdriver/#dfn-session-page-load-timeout
+
+        * CommandResult.cpp:
+        (WebDriver::CommandResult::CommandResult):
+        (WebDriver::CommandResult::httpStatusCode):
+        (WebDriver::CommandResult::errorString):
+        * CommandResult.h:
+        * Session.cpp:
+        (WebDriver::Session::go):
+        (WebDriver::Session::back):
+        (WebDriver::Session::forward):
+        (WebDriver::Session::refresh):
+        (WebDriver::Session::waitForNavigationToComplete):
+        * WebDriverService.cpp:
+        (WebDriver::WebDriverService::setTimeouts):
+
 2017-07-21  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         WebDriver: wait until navigation is complete before running new commands and after a click
index ded1cc984a76292a3bc9a61a436caa84d84c3194..3798a1812b1580f00f9c166b938e33c64f6a6f04 100644 (file)
@@ -100,6 +100,8 @@ CommandResult::CommandResult(RefPtr<InspectorValue>&& result, std::optional<Erro
             m_errorCode = ErrorCode::InvalidElementState;
         else if (errorName == "InvalidSelector")
             m_errorCode = ErrorCode::InvalidSelector;
+        else if (errorName == "Timeout")
+            m_errorCode = ErrorCode::Timeout;
 
         break;
     }
@@ -132,6 +134,7 @@ unsigned CommandResult::httpStatusCode() const
     case ErrorCode::UnknownCommand:
         return 404;
     case ErrorCode::ScriptTimeout:
+    case ErrorCode::Timeout:
         return 408;
     case ErrorCode::JavascriptError:
     case ErrorCode::SessionNotCreated:
@@ -171,6 +174,8 @@ String CommandResult::errorString() const
         return ASCIILiteral("session not created");
     case ErrorCode::StaleElementReference:
         return ASCIILiteral("stale element reference");
+    case ErrorCode::Timeout:
+        return ASCIILiteral("timeout");
     case ErrorCode::UnknownCommand:
         return ASCIILiteral("unknown command");
     case ErrorCode::UnknownError:
index f4a2f4b271b06a1ba2257148a923a3b1d1705af4..296e4b71119c8d9057b0637de0e3e53efa73172e 100644 (file)
@@ -50,6 +50,7 @@ public:
         ScriptTimeout,
         SessionNotCreated,
         StaleElementReference,
+        Timeout,
         UnknownCommand,
         UnknownError,
         UnsupportedOperation,
index cfbbbeffcea7ad10d660fa417ddc94ade8de9159..68e2fd7e6f6451abd6abb650469ae323a4950e14 100644 (file)
@@ -132,6 +132,8 @@ void Session::go(const String& url, Function<void (CommandResult&&)>&& completio
     RefPtr<InspectorObject> parameters = InspectorObject::create();
     parameters->setString(ASCIILiteral("handle"), m_toplevelBrowsingContext.value());
     parameters->setString(ASCIILiteral("url"), url);
+    if (m_timeouts.pageLoad)
+        parameters->setInteger(ASCIILiteral("pageLoadTimeout"), m_timeouts.pageLoad.value().millisecondsAs<int>());
     m_host->sendCommandToBackend(ASCIILiteral("navigateBrowsingContext"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
         if (response.isError) {
             completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
@@ -179,6 +181,8 @@ void Session::back(Function<void (CommandResult&&)>&& completionHandler)
 
     RefPtr<InspectorObject> parameters = InspectorObject::create();
     parameters->setString(ASCIILiteral("handle"), m_toplevelBrowsingContext.value());
+    if (m_timeouts.pageLoad)
+        parameters->setInteger(ASCIILiteral("pageLoadTimeout"), m_timeouts.pageLoad.value().millisecondsAs<int>());
     m_host->sendCommandToBackend(ASCIILiteral("goBackInBrowsingContext"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
         if (response.isError) {
             completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
@@ -198,6 +202,8 @@ void Session::forward(Function<void (CommandResult&&)>&& completionHandler)
 
     RefPtr<InspectorObject> parameters = InspectorObject::create();
     parameters->setString(ASCIILiteral("handle"), m_toplevelBrowsingContext.value());
+    if (m_timeouts.pageLoad)
+        parameters->setInteger(ASCIILiteral("pageLoadTimeout"), m_timeouts.pageLoad.value().millisecondsAs<int>());
     m_host->sendCommandToBackend(ASCIILiteral("goForwardInBrowsingContext"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
         if (response.isError) {
             completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
@@ -217,6 +223,8 @@ void Session::refresh(Function<void (CommandResult&&)>&& completionHandler)
 
     RefPtr<InspectorObject> parameters = InspectorObject::create();
     parameters->setString(ASCIILiteral("handle"), m_toplevelBrowsingContext.value());
+    if (m_timeouts.pageLoad)
+        parameters->setInteger(ASCIILiteral("pageLoadTimeout"), m_timeouts.pageLoad.value().millisecondsAs<int>());
     m_host->sendCommandToBackend(ASCIILiteral("reloadBrowsingContext"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
         if (response.isError) {
             completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
@@ -953,6 +961,8 @@ void Session::waitForNavigationToComplete(Function<void (CommandResult&&)>&& com
     parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
     if (m_browsingContext)
         parameters->setString(ASCIILiteral("frameHandle"), m_browsingContext.value());
+    if (m_timeouts.pageLoad)
+        parameters->setInteger(ASCIILiteral("pageLoadTimeout"), m_timeouts.pageLoad.value().millisecondsAs<int>());
     m_host->sendCommandToBackend(ASCIILiteral("waitForNavigationToComplete"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
         if (response.isError) {
             auto result = CommandResult::fail(WTFMove(response.responseObject));
index f82044d0329c1df511ce03ba25460e804075f2e7..ec1013cb9d309e0e913f8653451715b1c62df584 100644 (file)
@@ -383,7 +383,7 @@ void WebDriverService::setTimeouts(RefPtr<InspectorObject>&& parameters, Functio
 
         if (it->key == "script")
             timeouts.script = Seconds::fromMilliseconds(timeoutMS);
-        else if (it->key == "page load")
+        else if (it->key == "pageLoad")
             timeouts.pageLoad = Seconds::fromMilliseconds(timeoutMS);
         else if (it->key == "implicit")
             timeouts.implicit = Seconds::fromMilliseconds(timeoutMS);
index 71dfa95fa435db9e24f26f6d823be263f94de7f5..b97c1f34381fe5672318c3b21609b2ebc2dc95ad 100644 (file)
@@ -1,3 +1,29 @@
+2017-07-20  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        WebDriver: implement page load timeout
+        https://bugs.webkit.org/show_bug.cgi?id=174672
+
+        Reviewed by Brian Burg.
+
+        Always start a timer when waiting for a navigation to complete. When the timer fires, pending callbacks for
+        navigations are removed and invoked with a timeout error. If navigation completes before the timer is fired,
+        then the timer is stopped. All navigation commands now receive the page load strategy and timeout as optional
+        parameters, when not provided the default timeout (300 seconds) is used.
+
+        * UIProcess/Automation/Automation.json:
+        * UIProcess/Automation/WebAutomationSession.cpp:
+        (WebKit::WebAutomationSession::WebAutomationSession):
+        (WebKit::WebAutomationSession::waitForNavigationToComplete):
+        (WebKit::WebAutomationSession::waitForNavigationToCompleteOnPage):
+        (WebKit::WebAutomationSession::waitForNavigationToCompleteOnFrame):
+        (WebKit::WebAutomationSession::loadTimerFired):
+        (WebKit::WebAutomationSession::navigateBrowsingContext):
+        (WebKit::WebAutomationSession::goBackInBrowsingContext):
+        (WebKit::WebAutomationSession::goForwardInBrowsingContext):
+        (WebKit::WebAutomationSession::reloadBrowsingContext):
+        (WebKit::WebAutomationSession::navigationOccurredForFrame):
+        * UIProcess/Automation/WebAutomationSession.h:
+
 2017-07-23  Takuro Ashie  <ashie@clear-code.com>
 
         [GTK] Correct a typo in the reference manual of WebKitWebInspector
index 37ea8787cb8ba3ae8cd4e52074664584e82dee53..08133689230d52ca5f356540baaf2533d1e6a49d 100644 (file)
             "description": "Navigates a browsing context to a specified URL.",
             "parameters": [
                 { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context that should be navigated." },
-                { "name": "url", "type": "string", "description": "The URL to load in the browsing context." }
+                { "name": "url", "type": "string", "description": "The URL to load in the browsing context." },
+                { "name": "pageLoadStrategy", "$ref": "PageLoadStrategy", "optional": true, "description": "The page load strategy to use when determining when navigation is complete." },
+                { "name": "pageLoadTimeout", "type": "integer", "optional": true, "description": "The timeout in milliseconds that the navigation is expected to be completed in, otherwise a <code>Timeout</code> error is returned." }
             ],
             "async": true
         },
             "name": "goBackInBrowsingContext",
             "description": "Navigates a browsing context to go back one page in history.",
             "parameters": [
-                { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context that should be navigated." }
+                { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context that should be navigated." },
+                { "name": "pageLoadStrategy", "$ref": "PageLoadStrategy", "optional": true, "description": "The page load strategy to use when determining when navigation is complete." },
+                { "name": "pageLoadTimeout", "type": "integer", "optional": true, "description": "The timeout in milliseconds that the navigation is expected to be completed in, otherwise a <code>Timeout</code> error is returned." }
             ],
             "async": true
         },
             "name": "goForwardInBrowsingContext",
             "description": "Navigates a browsing context to got forward one page in history.",
             "parameters": [
-                { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context that should be navigated." }
+                { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context that should be navigated." },
+                { "name": "pageLoadStrategy", "$ref": "PageLoadStrategy", "optional": true, "description": "The page load strategy to use when determining when navigation is complete." },
+                { "name": "pageLoadTimeout", "type": "integer", "optional": true, "description": "The timeout in milliseconds that the navigation is expected to be completed in, otherwise a <code>Timeout</code> error is returned." }
             ],
             "async": true
         },
             "name": "reloadBrowsingContext",
             "description": "Reloads the current page in a browsing context.",
             "parameters": [
-                { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context that should be reloaded." }
+                { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context that should be reloaded." },
+                { "name": "pageLoadStrategy", "$ref": "PageLoadStrategy", "optional": true, "description": "The page load strategy to use when determining when navigation is complete." },
+                { "name": "pageLoadTimeout", "type": "integer", "optional": true, "description": "The timeout in milliseconds that the navigation is expected to be completed in, otherwise a <code>Timeout</code> error is returned." }
             ],
             "async": true
         },
index d8bb1af5bfe945a3978c049c90a10d46d81070b2..58de22ac17e46ffa4bd261e948816c2875ac97b2 100644 (file)
@@ -47,11 +47,16 @@ using namespace Inspector;
 
 namespace WebKit {
 
+// ยง8. Sessions
+// https://www.w3.org/TR/webdriver/#dfn-session-page-load-timeout
+static const Seconds defaultPageLoadTimeout = 300_s;
+
 WebAutomationSession::WebAutomationSession()
     : m_client(std::make_unique<API::AutomationSessionClient>())
     , m_frontendRouter(FrontendRouter::create())
     , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef()))
     , m_domainDispatcher(AutomationBackendDispatcher::create(m_backendDispatcher, this))
+    , m_loadTimer(RunLoop::main(), this, &WebAutomationSession::loadTimerFired)
 {
 }
 
@@ -381,7 +386,9 @@ void WebAutomationSession::waitForNavigationToComplete(Inspector::ErrorString& e
     if (!page)
         FAIL_WITH_PREDEFINED_ERROR(WindowNotFound);
 
-    // FIXME: Implement page load strategy and timeout.
+    // FIXME: Implement page load strategy.
+
+    Seconds pageLoadTimeout = optionalPageLoadTimeout ? Seconds::fromMilliseconds(*optionalPageLoadTimeout) : defaultPageLoadTimeout;
 
     if (optionalFrameHandle && !optionalFrameHandle->isEmpty()) {
         std::optional<uint64_t> frameID = webFrameIDForHandle(*optionalFrameHandle);
@@ -390,75 +397,93 @@ void WebAutomationSession::waitForNavigationToComplete(Inspector::ErrorString& e
         WebFrameProxy* frame = page->process().webFrame(frameID.value());
         if (!frame)
             FAIL_WITH_PREDEFINED_ERROR(FrameNotFound);
-        waitForNavigationToCompleteOnFrame(*frame, WTFMove(callback));
+        waitForNavigationToCompleteOnFrame(*frame, pageLoadTimeout, WTFMove(callback));
     } else
-        waitForNavigationToCompleteOnPage(*page, WTFMove(callback));
+        waitForNavigationToCompleteOnPage(*page, pageLoadTimeout, WTFMove(callback));
 }
 
-void WebAutomationSession::waitForNavigationToCompleteOnPage(WebPageProxy& page, Ref<Inspector::BackendDispatcher::CallbackBase>&& callback)
+void WebAutomationSession::waitForNavigationToCompleteOnPage(WebPageProxy& page, Seconds timeout, Ref<Inspector::BackendDispatcher::CallbackBase>&& callback)
 {
-    if (auto callback = m_pendingNavigationInBrowsingContextCallbacksPerPage.take(page.pageID()))
-        callback->sendFailure(STRING_FOR_PREDEFINED_ERROR_NAME(Timeout));
-
+    ASSERT(!m_loadTimer.isActive());
     if (!page.pageLoadState().isLoading()) {
         callback->sendSuccess(InspectorObject::create());
         return;
     }
 
+    m_loadTimer.startOneShot(timeout);
     m_pendingNavigationInBrowsingContextCallbacksPerPage.set(page.pageID(), WTFMove(callback));
 }
 
-void WebAutomationSession::waitForNavigationToCompleteOnFrame(WebFrameProxy& frame, Ref<Inspector::BackendDispatcher::CallbackBase>&& callback)
+void WebAutomationSession::waitForNavigationToCompleteOnFrame(WebFrameProxy& frame, Seconds timeout, Ref<Inspector::BackendDispatcher::CallbackBase>&& callback)
 {
-    if (auto callback = m_pendingNavigationInBrowsingContextCallbacksPerFrame.take(frame.frameID()))
-        callback->sendFailure(STRING_FOR_PREDEFINED_ERROR_NAME(Timeout));
-
+    ASSERT(!m_loadTimer.isActive());
     if (frame.frameLoadState().state() == FrameLoadState::State::Finished) {
         callback->sendSuccess(InspectorObject::create());
         return;
     }
 
+    m_loadTimer.startOneShot(timeout);
     m_pendingNavigationInBrowsingContextCallbacksPerFrame.set(frame.frameID(), WTFMove(callback));
 }
 
-void WebAutomationSession::navigateBrowsingContext(Inspector::ErrorString& errorString, const String& handle, const String& url, Ref<NavigateBrowsingContextCallback>&& callback)
+void WebAutomationSession::loadTimerFired()
+{
+    for (auto frameID : m_pendingNavigationInBrowsingContextCallbacksPerFrame.keys()) {
+        auto callback = m_pendingNavigationInBrowsingContextCallbacksPerFrame.take(frameID);
+        callback->sendFailure(STRING_FOR_PREDEFINED_ERROR_NAME(Timeout));
+    }
+    for (auto pageID : m_pendingNavigationInBrowsingContextCallbacksPerPage.keys()) {
+        auto callback = m_pendingNavigationInBrowsingContextCallbacksPerPage.take(pageID);
+        callback->sendFailure(STRING_FOR_PREDEFINED_ERROR_NAME(Timeout));
+    }
+}
+
+void WebAutomationSession::navigateBrowsingContext(Inspector::ErrorString& errorString, const String& handle, const String& url, const String* optionalPageLoadStrategyString, const int* optionalPageLoadTimeout, Ref<NavigateBrowsingContextCallback>&& callback)
 {
     WebPageProxy* page = webPageProxyForHandle(handle);
     if (!page)
         FAIL_WITH_PREDEFINED_ERROR(WindowNotFound);
 
+    // FIXME: Implement page load strategy.
+
     page->loadRequest(WebCore::URL(WebCore::URL(), url));
-    waitForNavigationToCompleteOnPage(*page, WTFMove(callback));
+    waitForNavigationToCompleteOnPage(*page, optionalPageLoadTimeout ? Seconds::fromMilliseconds(*optionalPageLoadTimeout) : defaultPageLoadTimeout, WTFMove(callback));
 }
 
-void WebAutomationSession::goBackInBrowsingContext(Inspector::ErrorString& errorString, const String& handle, Ref<GoBackInBrowsingContextCallback>&& callback)
+void WebAutomationSession::goBackInBrowsingContext(Inspector::ErrorString& errorString, const String& handle, const String* optionalPageLoadStrategyString, const int* optionalPageLoadTimeout, Ref<GoBackInBrowsingContextCallback>&& callback)
 {
     WebPageProxy* page = webPageProxyForHandle(handle);
     if (!page)
         FAIL_WITH_PREDEFINED_ERROR(WindowNotFound);
 
+    // FIXME: Implement page load strategy.
+
     page->goBack();
-    waitForNavigationToCompleteOnPage(*page, WTFMove(callback));
+    waitForNavigationToCompleteOnPage(*page, optionalPageLoadTimeout ? Seconds::fromMilliseconds(*optionalPageLoadTimeout) : defaultPageLoadTimeout, WTFMove(callback));
 }
 
-void WebAutomationSession::goForwardInBrowsingContext(Inspector::ErrorString& errorString, const String& handle, Ref<GoForwardInBrowsingContextCallback>&& callback)
+void WebAutomationSession::goForwardInBrowsingContext(Inspector::ErrorString& errorString, const String& handle, const String* optionalPageLoadStrategyString, const int* optionalPageLoadTimeout, Ref<GoForwardInBrowsingContextCallback>&& callback)
 {
     WebPageProxy* page = webPageProxyForHandle(handle);
     if (!page)
         FAIL_WITH_PREDEFINED_ERROR(WindowNotFound);
 
+    // FIXME: Implement page load strategy.
+
     page->goForward();
-    waitForNavigationToCompleteOnPage(*page, WTFMove(callback));
+    waitForNavigationToCompleteOnPage(*page, optionalPageLoadTimeout ? Seconds::fromMilliseconds(*optionalPageLoadTimeout) : defaultPageLoadTimeout, WTFMove(callback));
 }
 
-void WebAutomationSession::reloadBrowsingContext(Inspector::ErrorString& errorString, const String& handle, Ref<ReloadBrowsingContextCallback>&& callback)
+void WebAutomationSession::reloadBrowsingContext(Inspector::ErrorString& errorString, const String& handle, const String* optionalPageLoadStrategyString, const int* optionalPageLoadTimeout, Ref<ReloadBrowsingContextCallback>&& callback)
 {
     WebPageProxy* page = webPageProxyForHandle(handle);
     if (!page)
         FAIL_WITH_PREDEFINED_ERROR(WindowNotFound);
 
+    // FIXME: Implement page load strategy.
+
     page->reload({ });
-    waitForNavigationToCompleteOnPage(*page, WTFMove(callback));
+    waitForNavigationToCompleteOnPage(*page, optionalPageLoadTimeout ? Seconds::fromMilliseconds(*optionalPageLoadTimeout) : defaultPageLoadTimeout, WTFMove(callback));
 }
 
 void WebAutomationSession::navigationOccurredForFrame(const WebFrameProxy& frame)
@@ -467,11 +492,15 @@ void WebAutomationSession::navigationOccurredForFrame(const WebFrameProxy& frame
         // New page loaded, clear frame handles previously cached.
         m_handleWebFrameMap.clear();
         m_webFrameHandleMap.clear();
-        if (auto callback = m_pendingNavigationInBrowsingContextCallbacksPerPage.take(frame.page()->pageID()))
+        if (auto callback = m_pendingNavigationInBrowsingContextCallbacksPerPage.take(frame.page()->pageID())) {
+            m_loadTimer.stop();
             callback->sendSuccess(InspectorObject::create());
+        }
     } else {
-        if (auto callback = m_pendingNavigationInBrowsingContextCallbacksPerFrame.take(frame.frameID()))
+        if (auto callback = m_pendingNavigationInBrowsingContextCallbacksPerFrame.take(frame.frameID())) {
+            m_loadTimer.stop();
             callback->sendSuccess(InspectorObject::create());
+        }
     }
 }
 
index cac6ccd1a48fd843b0dc47a5b424c0e545260b35..0f24c7362f461436fabb565df1b569653a0b5b67 100644 (file)
@@ -31,6 +31,7 @@
 #include "ShareableBitmap.h"
 #include "WebEvent.h"
 #include <wtf/Forward.h>
+#include <wtf/RunLoop.h>
 
 #if ENABLE(REMOTE_INSPECTOR)
 #include <JavaScriptCore/RemoteAutomationTarget.h>
@@ -111,10 +112,10 @@ public:
     void switchToBrowsingContext(Inspector::ErrorString&, const String& browsingContextHandle, const String* optionalFrameHandle) override;
     void resizeWindowOfBrowsingContext(Inspector::ErrorString&, const String& handle, const Inspector::InspectorObject& size) override;
     void moveWindowOfBrowsingContext(Inspector::ErrorString&, const String& handle, const Inspector::InspectorObject& position) override;
-    void navigateBrowsingContext(Inspector::ErrorString&, const String& handle, const String& url, Ref<NavigateBrowsingContextCallback>&&) override;
-    void goBackInBrowsingContext(Inspector::ErrorString&, const String&, Ref<GoBackInBrowsingContextCallback>&&) override;
-    void goForwardInBrowsingContext(Inspector::ErrorString&, const String&, Ref<GoForwardInBrowsingContextCallback>&&) override;
-    void reloadBrowsingContext(Inspector::ErrorString&, const String&, Ref<ReloadBrowsingContextCallback>&&) override;
+    void navigateBrowsingContext(Inspector::ErrorString&, const String& handle, const String& url, const String* optionalPageLoadStrategyString, const int* optionalPageLoadTimeout, Ref<NavigateBrowsingContextCallback>&&) override;
+    void goBackInBrowsingContext(Inspector::ErrorString&, const String&, const String* optionalPageLoadStrategyString, const int* optionalPageLoadTimeout, Ref<GoBackInBrowsingContextCallback>&&) override;
+    void goForwardInBrowsingContext(Inspector::ErrorString&, const String&, const String* optionalPageLoadStrategyString, const int* optionalPageLoadTimeout, Ref<GoForwardInBrowsingContextCallback>&&) override;
+    void reloadBrowsingContext(Inspector::ErrorString&, const String&, const String* optionalPageLoadStrategyString, const int* optionalPageLoadTimeout, Ref<ReloadBrowsingContextCallback>&&) override;
     void waitForNavigationToComplete(Inspector::ErrorString&, const String& browsingContextHandle, const String* optionalFrameHandle, const String* optionalPageLoadStrategyString, const int* optionalPageLoadTimeout, Ref<WaitForNavigationToCompleteCallback>&&) override;
     void evaluateJavaScriptFunction(Inspector::ErrorString&, const String& browsingContextHandle, const String* optionalFrameHandle, const String& function, const Inspector::InspectorArray& arguments, const bool* optionalExpectsImplicitCallbackArgument, const int* optionalCallbackTimeout, Ref<Inspector::AutomationBackendDispatcherHandler::EvaluateJavaScriptFunctionCallback>&&) override;
     void performMouseInteraction(Inspector::ErrorString&, const String& handle, const Inspector::InspectorObject& requestedPosition, const String& mouseButton, const String& mouseInteraction, const Inspector::InspectorArray& keyModifiers, RefPtr<Inspector::Protocol::Automation::Point>& updatedPosition) override;
@@ -153,8 +154,9 @@ private:
     String handleForWebFrameID(uint64_t frameID);
     String handleForWebFrameProxy(const WebFrameProxy&);
 
-    void waitForNavigationToCompleteOnPage(WebPageProxy&, Ref<Inspector::BackendDispatcher::CallbackBase>&&);
-    void waitForNavigationToCompleteOnFrame(WebFrameProxy&, Ref<Inspector::BackendDispatcher::CallbackBase>&&);
+    void waitForNavigationToCompleteOnPage(WebPageProxy&, Seconds, Ref<Inspector::BackendDispatcher::CallbackBase>&&);
+    void waitForNavigationToCompleteOnFrame(WebFrameProxy&, Seconds, Ref<Inspector::BackendDispatcher::CallbackBase>&&);
+    void loadTimerFired();
 
     // Implemented in generated WebAutomationSessionMessageReceiver.cpp.
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
@@ -226,6 +228,8 @@ private:
     uint64_t m_nextDeleteCookieCallbackID { 1 };
     HashMap<uint64_t, RefPtr<Inspector::AutomationBackendDispatcherHandler::DeleteSingleCookieCallback>> m_deleteCookieCallbacks;
 
+    RunLoop::Timer<WebAutomationSession> m_loadTimer;
+
 #if ENABLE(REMOTE_INSPECTOR)
     Inspector::FrontendChannel* m_remoteChannel { nullptr };
 #endif