Title: [220388] trunk/Source/WebDriver
Revision
220388
Author
carlo...@webkit.org
Date
2017-08-07 23:43:25 -0700 (Mon, 07 Aug 2017)

Log Message

WebDriver: implement unhandled prompt behavior
https://bugs.webkit.org/show_bug.cgi?id=175184

Reviewed by Brian Burg.

Handle user prompts before running some of the commands according to the specification.

* Capabilities.h: Add UnhandledPromptBehavior capability.
* CommandResult.cpp:
(WebDriver::CommandResult::httpStatusCode const): Add UnexpectedAlertOpen error.
(WebDriver::CommandResult::errorString const): Ditto.
* CommandResult.h:
(WebDriver::CommandResult::setAdditonalErrorData): New method to set an additional data object that will be sent
as part of the result error message.
(WebDriver::CommandResult::additionalErrorData const): Return the additional data object.
* Session.cpp:
(WebDriver::Session::handleUserPrompts): Check if there's an active _javascript_ dialog and deal with it depeding
on the unhandled prompt behavior.
(WebDriver::Session::reportUnexpectedAlertOpen): Generate an error message with UnexpectedAlertOpen error and
including the alert text as additional error data.
(WebDriver::Session::go): Handle user prompts before running the command.
(WebDriver::Session::getCurrentURL): Ditto.
(WebDriver::Session::back): Ditto.
(WebDriver::Session::forward): Ditto.
(WebDriver::Session::refresh): Ditto.
(WebDriver::Session::getTitle): Ditto.
(WebDriver::Session::closeWindow): Ditto.
(WebDriver::Session::switchToFrame): Ditto.
(WebDriver::Session::switchToParentFrame): Ditto.
(WebDriver::Session::isElementSelected): Ditto.
(WebDriver::Session::getElementText): Ditto.
(WebDriver::Session::getElementTagName): Ditto.
(WebDriver::Session::getElementRect): Ditto.
(WebDriver::Session::isElementEnabled): Ditto.
(WebDriver::Session::isElementDisplayed): Ditto.
(WebDriver::Session::getElementAttribute): Ditto.
(WebDriver::Session::elementSendKeys): Ditto.
(WebDriver::Session::elementSubmit): Ditto.
(WebDriver::Session::executeScript): Ditto.
* Session.h:
* WebDriverService.cpp:
(WebDriver::WebDriverService::sendResponse const): Send data object as part of the result error message if present.
(WebDriver::deserializeUnhandledPromptBehavior):
(WebDriver::WebDriverService::parseCapabilities const):
(WebDriver::WebDriverService::validatedCapabilities const):
(WebDriver::WebDriverService::newSession):

Modified Paths

Diff

Modified: trunk/Source/WebDriver/Capabilities.h (220387 => 220388)


--- trunk/Source/WebDriver/Capabilities.h	2017-08-08 06:25:23 UTC (rev 220387)
+++ trunk/Source/WebDriver/Capabilities.h	2017-08-08 06:43:25 UTC (rev 220388)
@@ -44,6 +44,12 @@
     Eager
 };
 
+enum class UnhandledPromptBehavior {
+    Dismiss,
+    Accept,
+    Ignore
+};
+
 struct Capabilities {
     std::optional<String> browserName;
     std::optional<String> browserVersion;
@@ -51,6 +57,7 @@
     std::optional<bool> acceptInsecureCerts;
     std::optional<Timeouts> timeouts;
     std::optional<PageLoadStrategy> pageLoadStrategy;
+    std::optional<UnhandledPromptBehavior> unhandledPromptBehavior;
 #if PLATFORM(GTK)
     std::optional<String> browserBinary;
     std::optional<Vector<String>> browserArguments;

Modified: trunk/Source/WebDriver/ChangeLog (220387 => 220388)


--- trunk/Source/WebDriver/ChangeLog	2017-08-08 06:25:23 UTC (rev 220387)
+++ trunk/Source/WebDriver/ChangeLog	2017-08-08 06:43:25 UTC (rev 220388)
@@ -1,5 +1,54 @@
 2017-08-07  Carlos Garcia Campos  <cgar...@igalia.com>
 
+        WebDriver: implement unhandled prompt behavior
+        https://bugs.webkit.org/show_bug.cgi?id=175184
+
+        Reviewed by Brian Burg.
+
+        Handle user prompts before running some of the commands according to the specification.
+
+        * Capabilities.h: Add UnhandledPromptBehavior capability.
+        * CommandResult.cpp:
+        (WebDriver::CommandResult::httpStatusCode const): Add UnexpectedAlertOpen error.
+        (WebDriver::CommandResult::errorString const): Ditto.
+        * CommandResult.h:
+        (WebDriver::CommandResult::setAdditonalErrorData): New method to set an additional data object that will be sent
+        as part of the result error message.
+        (WebDriver::CommandResult::additionalErrorData const): Return the additional data object.
+        * Session.cpp:
+        (WebDriver::Session::handleUserPrompts): Check if there's an active _javascript_ dialog and deal with it depeding
+        on the unhandled prompt behavior.
+        (WebDriver::Session::reportUnexpectedAlertOpen): Generate an error message with UnexpectedAlertOpen error and
+        including the alert text as additional error data.
+        (WebDriver::Session::go): Handle user prompts before running the command.
+        (WebDriver::Session::getCurrentURL): Ditto.
+        (WebDriver::Session::back): Ditto.
+        (WebDriver::Session::forward): Ditto.
+        (WebDriver::Session::refresh): Ditto.
+        (WebDriver::Session::getTitle): Ditto.
+        (WebDriver::Session::closeWindow): Ditto.
+        (WebDriver::Session::switchToFrame): Ditto.
+        (WebDriver::Session::switchToParentFrame): Ditto.
+        (WebDriver::Session::isElementSelected): Ditto.
+        (WebDriver::Session::getElementText): Ditto.
+        (WebDriver::Session::getElementTagName): Ditto.
+        (WebDriver::Session::getElementRect): Ditto.
+        (WebDriver::Session::isElementEnabled): Ditto.
+        (WebDriver::Session::isElementDisplayed): Ditto.
+        (WebDriver::Session::getElementAttribute): Ditto.
+        (WebDriver::Session::elementSendKeys): Ditto.
+        (WebDriver::Session::elementSubmit): Ditto.
+        (WebDriver::Session::executeScript): Ditto.
+        * Session.h:
+        * WebDriverService.cpp:
+        (WebDriver::WebDriverService::sendResponse const): Send data object as part of the result error message if present.
+        (WebDriver::deserializeUnhandledPromptBehavior):
+        (WebDriver::WebDriverService::parseCapabilities const):
+        (WebDriver::WebDriverService::validatedCapabilities const):
+        (WebDriver::WebDriverService::newSession):
+
+2017-08-07  Carlos Garcia Campos  <cgar...@igalia.com>
+
         WebDriver: implement user prompt commands
         https://bugs.webkit.org/show_bug.cgi?id=174614
 

Modified: trunk/Source/WebDriver/CommandResult.cpp (220387 => 220388)


--- trunk/Source/WebDriver/CommandResult.cpp	2017-08-08 06:25:23 UTC (rev 220387)
+++ trunk/Source/WebDriver/CommandResult.cpp	2017-08-08 06:43:25 UTC (rev 220388)
@@ -143,6 +143,7 @@
         return 408;
     case ErrorCode::_javascript_Error:
     case ErrorCode::SessionNotCreated:
+    case ErrorCode::UnexpectedAlertOpen:
     case ErrorCode::UnknownError:
     case ErrorCode::UnsupportedOperation:
         return 500;
@@ -187,6 +188,8 @@
         return ASCIILiteral("stale element reference");
     case ErrorCode::Timeout:
         return ASCIILiteral("timeout");
+    case ErrorCode::UnexpectedAlertOpen:
+        return ASCIILiteral("unexpected alert open");
     case ErrorCode::UnknownCommand:
         return ASCIILiteral("unknown command");
     case ErrorCode::UnknownError:

Modified: trunk/Source/WebDriver/CommandResult.h (220387 => 220388)


--- trunk/Source/WebDriver/CommandResult.h	2017-08-08 06:25:23 UTC (rev 220387)
+++ trunk/Source/WebDriver/CommandResult.h	2017-08-08 06:43:25 UTC (rev 220388)
@@ -29,6 +29,7 @@
 #include <wtf/text/WTFString.h>
 
 namespace Inspector {
+class InspectorObject;
 class InspectorValue;
 }
 
@@ -54,6 +55,7 @@
         SessionNotCreated,
         StaleElementReference,
         Timeout,
+        UnexpectedAlertOpen,
         UnknownCommand,
         UnknownError,
         UnsupportedOperation,
@@ -76,10 +78,12 @@
 
     unsigned httpStatusCode() const;
     const RefPtr<Inspector::InspectorValue>& result() const { return m_result; };
+    void setAdditionalErrorData(RefPtr<Inspector::InspectorObject>&& errorData) { m_errorAdditionalData = WTFMove(errorData); }
     bool isError() const { return !!m_errorCode; }
     ErrorCode errorCode() const { ASSERT(isError()); return m_errorCode.value(); }
     String errorString() const;
     std::optional<String> errorMessage() const { ASSERT(isError()); return m_errorMessage; }
+    const RefPtr<Inspector::InspectorObject>& additionalErrorData() const { return m_errorAdditionalData; }
 
 private:
     explicit CommandResult(RefPtr<Inspector::InspectorValue>&&, std::optional<ErrorCode> = std::nullopt);
@@ -88,6 +92,7 @@
     RefPtr<Inspector::InspectorValue> m_result;
     std::optional<ErrorCode> m_errorCode;
     std::optional<String> m_errorMessage;
+    RefPtr<Inspector::InspectorObject> m_errorAdditionalData;
 };
 
 } // namespace WebDriver

Modified: trunk/Source/WebDriver/Session.cpp (220387 => 220388)


--- trunk/Source/WebDriver/Session.cpp	2017-08-08 06:25:23 UTC (rev 220387)
+++ trunk/Source/WebDriver/Session.cpp	2017-08-08 06:43:25 UTC (rev 220388)
@@ -143,6 +143,72 @@
     });
 }
 
+void Session::handleUserPrompts(Function<void (CommandResult&&)>&& completionHandler)
+{
+    RefPtr<InspectorObject> parameters = InspectorObject::create();
+    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+    m_host->sendCommandToBackend(ASCIILiteral("isShowingJavaScriptDialog"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) mutable {
+        if (response.isError || !response.responseObject) {
+            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+            return;
+        }
+        bool isShowingJavaScriptDialog;
+        if (!response.responseObject->getBoolean("result", isShowingJavaScriptDialog)) {
+            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+            return;
+        }
+
+        if (!isShowingJavaScriptDialog) {
+            completionHandler(CommandResult::success());
+            return;
+        }
+
+        if (!capabilities().unhandledPromptBehavior) {
+            reportUnexpectedAlertOpen([this, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+                dismissAlert([this, errorResult = WTFMove(result), completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+                    if (result.isError()) {
+                        completionHandler(WTFMove(result));
+                        return;
+                    }
+                    completionHandler(WTFMove(errorResult));
+                });
+            });
+            return;
+        }
+
+        switch (capabilities().unhandledPromptBehavior.value()) {
+        case UnhandledPromptBehavior::Dismiss:
+            dismissAlert(WTFMove(completionHandler));
+            break;
+        case UnhandledPromptBehavior::Accept:
+            acceptAlert(WTFMove(completionHandler));
+            break;
+        case UnhandledPromptBehavior::Ignore:
+            reportUnexpectedAlertOpen(WTFMove(completionHandler));
+            break;
+        }
+    });
+}
+
+void Session::reportUnexpectedAlertOpen(Function<void (CommandResult&&)>&& completionHandler)
+{
+    getAlertText([this, completionHandler = WTFMove(completionHandler)](CommandResult&& result) {
+        std::optional<String> alertText;
+        if (!result.isError()) {
+            String valueString;
+            if (result.result()->asString(valueString))
+                alertText = valueString;
+        }
+        auto errorResult = CommandResult::fail(CommandResult::ErrorCode::UnexpectedAlertOpen);
+        if (alertText) {
+            RefPtr<InspectorObject> additonalData = InspectorObject::create();
+            additonalData->setString(ASCIILiteral("text"), alertText.value());
+            errorResult.setAdditionalErrorData(WTFMove(additonalData));
+        }
+        completionHandler(WTFMove(errorResult));
+    });
+}
+
 void Session::go(const String& url, Function<void (CommandResult&&)>&& completionHandler)
 {
     if (!m_toplevelBrowsingContext) {
@@ -150,20 +216,27 @@
         return;
     }
 
-    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>());
-    if (auto pageLoadStrategy = pageLoadStrategyString())
-        parameters->setString(ASCIILiteral("pageLoadStrategy"), pageLoadStrategy.value());
-    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)));
+    handleUserPrompts([this, url, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        switchToBrowsingContext(std::nullopt);
-        completionHandler(CommandResult::success());
+
+        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>());
+        if (auto pageLoadStrategy = pageLoadStrategyString())
+            parameters->setString(ASCIILiteral("pageLoadStrategy"), pageLoadStrategy.value());
+        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)));
+                return;
+            }
+            switchToBrowsingContext(std::nullopt);
+            completionHandler(CommandResult::success());
+        });
     });
 }
 
@@ -174,24 +247,31 @@
         return;
     }
 
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("handle"), m_toplevelBrowsingContext.value());
-    m_host->sendCommandToBackend(ASCIILiteral("getBrowsingContext"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        RefPtr<InspectorObject> browsingContext;
-        if (!response.responseObject->getObject("context", browsingContext)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        String url;
-        if (!browsingContext->getString("url", url)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        completionHandler(CommandResult::success(InspectorValue::create(url)));
+
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("handle"), m_toplevelBrowsingContext.value());
+        m_host->sendCommandToBackend(ASCIILiteral("getBrowsingContext"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            RefPtr<InspectorObject> browsingContext;
+            if (!response.responseObject->getObject("context", browsingContext)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            String url;
+            if (!browsingContext->getString("url", url)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            completionHandler(CommandResult::success(InspectorValue::create(url)));
+        });
     });
 }
 
@@ -202,19 +282,25 @@
         return;
     }
 
-    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>());
-    if (auto pageLoadStrategy = pageLoadStrategyString())
-        parameters->setString(ASCIILiteral("pageLoadStrategy"), pageLoadStrategy.value());
-    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)));
+    handleUserPrompts([this, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        switchToBrowsingContext(std::nullopt);
-        completionHandler(CommandResult::success());
+        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>());
+        if (auto pageLoadStrategy = pageLoadStrategyString())
+            parameters->setString(ASCIILiteral("pageLoadStrategy"), pageLoadStrategy.value());
+        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)));
+                return;
+            }
+            switchToBrowsingContext(std::nullopt);
+            completionHandler(CommandResult::success());
+        });
     });
 }
 
@@ -225,19 +311,25 @@
         return;
     }
 
-    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>());
-    if (auto pageLoadStrategy = pageLoadStrategyString())
-        parameters->setString(ASCIILiteral("pageLoadStrategy"), pageLoadStrategy.value());
-    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)));
+    handleUserPrompts([this, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        switchToBrowsingContext(std::nullopt);
-        completionHandler(CommandResult::success());
+        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>());
+        if (auto pageLoadStrategy = pageLoadStrategyString())
+            parameters->setString(ASCIILiteral("pageLoadStrategy"), pageLoadStrategy.value());
+        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)));
+                return;
+            }
+            switchToBrowsingContext(std::nullopt);
+            completionHandler(CommandResult::success());
+        });
     });
 }
 
@@ -248,19 +340,25 @@
         return;
     }
 
-    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>());
-    if (auto pageLoadStrategy = pageLoadStrategyString())
-        parameters->setString(ASCIILiteral("pageLoadStrategy"), pageLoadStrategy.value());
-    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)));
+    handleUserPrompts([this, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        switchToBrowsingContext(std::nullopt);
-        completionHandler(CommandResult::success());
+        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>());
+        if (auto pageLoadStrategy = pageLoadStrategyString())
+            parameters->setString(ASCIILiteral("pageLoadStrategy"), pageLoadStrategy.value());
+        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)));
+                return;
+            }
+            switchToBrowsingContext(std::nullopt);
+            completionHandler(CommandResult::success());
+        });
     });
 }
 
@@ -271,26 +369,32 @@
         return;
     }
 
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    parameters->setString(ASCIILiteral("function"), ASCIILiteral("function() { return document.title; }"));
-    parameters->setArray(ASCIILiteral("arguments"), InspectorArray::create());
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        String valueString;
-        if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        RefPtr<InspectorValue> resultValue;
-        if (!InspectorValue::parseJSON(valueString, resultValue)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        completionHandler(CommandResult::success(WTFMove(resultValue)));
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        parameters->setString(ASCIILiteral("function"), ASCIILiteral("function() { return document.title; }"));
+        parameters->setArray(ASCIILiteral("arguments"), InspectorArray::create());
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String valueString;
+            if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            RefPtr<InspectorValue> resultValue;
+            if (!InspectorValue::parseJSON(valueString, resultValue)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            completionHandler(CommandResult::success(WTFMove(resultValue)));
+        });
     });
 }
 
@@ -329,7 +433,13 @@
         return;
     }
 
-    close(WTFMove(completionHandler));
+    handleUserPrompts([this, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
+            return;
+        }
+        close(WTFMove(completionHandler));
+    });
 }
 
 void Session::switchToWindow(const String& windowHandle, Function<void (CommandResult&&)>&& completionHandler)
@@ -397,44 +507,50 @@
         return;
     }
 
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-
-    int frameIndex;
-    if (frameID->asInteger(frameIndex)) {
-        if (frameIndex < 0 || frameIndex > USHRT_MAX) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::NoSuchFrame));
+    handleUserPrompts([this, frameID = WTFMove(frameID), completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        parameters->setInteger(ASCIILiteral("ordinal"), frameIndex);
-    } else {
-        String frameElementID = extractElementID(*frameID);
-        if (!frameElementID.isEmpty())
-            parameters->setString(ASCIILiteral("nodeHandle"), frameElementID);
-        else {
-            String frameName;
-            if (!frameID->asString(frameName)) {
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+
+        int frameIndex;
+        if (frameID->asInteger(frameIndex)) {
+            if (frameIndex < 0 || frameIndex > USHRT_MAX) {
                 completionHandler(CommandResult::fail(CommandResult::ErrorCode::NoSuchFrame));
                 return;
             }
-            parameters->setString(ASCIILiteral("name"), frameName);
+            parameters->setInteger(ASCIILiteral("ordinal"), frameIndex);
+        } else {
+            String frameElementID = extractElementID(*frameID);
+            if (!frameElementID.isEmpty())
+                parameters->setString(ASCIILiteral("nodeHandle"), frameElementID);
+            else {
+                String frameName;
+                if (!frameID->asString(frameName)) {
+                    completionHandler(CommandResult::fail(CommandResult::ErrorCode::NoSuchFrame));
+                    return;
+                }
+                parameters->setString(ASCIILiteral("name"), frameName);
+            }
         }
-    }
 
-    m_host->sendCommandToBackend(ASCIILiteral("resolveChildFrameHandle"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
-            return;
-        }
-        String frameHandle;
-        if (!response.responseObject->getString(ASCIILiteral("result"), frameHandle)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        switchToBrowsingContext(frameHandle);
-        completionHandler(CommandResult::success());
+        m_host->sendCommandToBackend(ASCIILiteral("resolveChildFrameHandle"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String frameHandle;
+            if (!response.responseObject->getString(ASCIILiteral("result"), frameHandle)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            switchToBrowsingContext(frameHandle);
+            completionHandler(CommandResult::success());
+        });
     });
 }
 
@@ -450,21 +566,27 @@
         return;
     }
 
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    m_host->sendCommandToBackend(ASCIILiteral("resolveParentFrameHandle"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        String frameHandle;
-        if (!response.responseObject->getString(ASCIILiteral("result"), frameHandle)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        switchToBrowsingContext(frameHandle);
-        completionHandler(CommandResult::success());
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        m_host->sendCommandToBackend(ASCIILiteral("resolveParentFrameHandle"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String frameHandle;
+            if (!response.responseObject->getString(ASCIILiteral("result"), frameHandle)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            switchToBrowsingContext(frameHandle);
+            completionHandler(CommandResult::success());
+        });
     });
 }
 
@@ -761,41 +883,47 @@
         return;
     }
 
-    RefPtr<InspectorArray> arguments = InspectorArray::create();
-    arguments->pushString(createElement(elementID)->toJSONString());
-    arguments->pushString(InspectorValue::create("selected")->toJSONString());
-
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    parameters->setString(ASCIILiteral("function"), ElementAttributeJavaScript);
-    parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, elementID, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        String valueString;
-        if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        RefPtr<InspectorValue> resultValue;
-        if (!InspectorValue::parseJSON(valueString, resultValue)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        if (resultValue->isNull()) {
-            completionHandler(CommandResult::success(InspectorValue::create(false)));
-            return;
-        }
-        String booleanResult;
-        if (!resultValue->asString(booleanResult) || booleanResult != "true") {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        completionHandler(CommandResult::success(InspectorValue::create(true)));
+        RefPtr<InspectorArray> arguments = InspectorArray::create();
+        arguments->pushString(createElement(elementID)->toJSONString());
+        arguments->pushString(InspectorValue::create("selected")->toJSONString());
+
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        parameters->setString(ASCIILiteral("function"), ElementAttributeJavaScript);
+        parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String valueString;
+            if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            RefPtr<InspectorValue> resultValue;
+            if (!InspectorValue::parseJSON(valueString, resultValue)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            if (resultValue->isNull()) {
+                completionHandler(CommandResult::success(InspectorValue::create(false)));
+                return;
+            }
+            String booleanResult;
+            if (!resultValue->asString(booleanResult) || booleanResult != "true") {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            completionHandler(CommandResult::success(InspectorValue::create(true)));
+        });
     });
 }
 
@@ -806,32 +934,38 @@
         return;
     }
 
-    RefPtr<InspectorArray> arguments = InspectorArray::create();
-    arguments->pushString(createElement(elementID)->toJSONString());
-
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    // FIXME: Add an atom to properly implement this instead of just using innerText.
-    parameters->setString(ASCIILiteral("function"), ASCIILiteral("function(element) { return element.innerText.replace(/^[^\\S\\xa0]+|[^\\S\\xa0]+$/g, '') }"));
-    parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, elementID, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        String valueString;
-        if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        RefPtr<InspectorValue> resultValue;
-        if (!InspectorValue::parseJSON(valueString, resultValue)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        completionHandler(CommandResult::success(WTFMove(resultValue)));
+        RefPtr<InspectorArray> arguments = InspectorArray::create();
+        arguments->pushString(createElement(elementID)->toJSONString());
+
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        // FIXME: Add an atom to properly implement this instead of just using innerText.
+        parameters->setString(ASCIILiteral("function"), ASCIILiteral("function(element) { return element.innerText.replace(/^[^\\S\\xa0]+|[^\\S\\xa0]+$/g, '') }"));
+        parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String valueString;
+            if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            RefPtr<InspectorValue> resultValue;
+            if (!InspectorValue::parseJSON(valueString, resultValue)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            completionHandler(CommandResult::success(WTFMove(resultValue)));
+        });
     });
 }
 
@@ -842,31 +976,37 @@
         return;
     }
 
-    RefPtr<InspectorArray> arguments = InspectorArray::create();
-    arguments->pushString(createElement(elementID)->toJSONString());
-
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    parameters->setString(ASCIILiteral("function"), ASCIILiteral("function(element) { return element.tagName.toLowerCase() }"));
-    parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, elementID, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        String valueString;
-        if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        RefPtr<InspectorValue> resultValue;
-        if (!InspectorValue::parseJSON(valueString, resultValue)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        completionHandler(CommandResult::success(WTFMove(resultValue)));
+        RefPtr<InspectorArray> arguments = InspectorArray::create();
+        arguments->pushString(createElement(elementID)->toJSONString());
+
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        parameters->setString(ASCIILiteral("function"), ASCIILiteral("function(element) { return element.tagName.toLowerCase() }"));
+        parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String valueString;
+            if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            RefPtr<InspectorValue> resultValue;
+            if (!InspectorValue::parseJSON(valueString, resultValue)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            completionHandler(CommandResult::success(WTFMove(resultValue)));
+        });
     });
 }
 
@@ -877,17 +1017,23 @@
         return;
     }
 
-    computeElementLayout(elementID, { }, [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](std::optional<Rect>&& rect, std::optional<Point>&&, bool, RefPtr<InspectorObject>&& error) {
-        if (!rect || error) {
-            completionHandler(CommandResult::fail(WTFMove(error)));
+    handleUserPrompts([this, elementID, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        RefPtr<InspectorObject> rectObject = InspectorObject::create();
-        rectObject->setInteger(ASCIILiteral("x"), rect.value().origin.x);
-        rectObject->setInteger(ASCIILiteral("y"), rect.value().origin.y);
-        rectObject->setInteger(ASCIILiteral("width"), rect.value().size.width);
-        rectObject->setInteger(ASCIILiteral("height"), rect.value().size.height);
-        completionHandler(CommandResult::success(WTFMove(rectObject)));
+        computeElementLayout(elementID, { }, [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](std::optional<Rect>&& rect, std::optional<Point>&&, bool, RefPtr<InspectorObject>&& error) {
+            if (!rect || error) {
+                completionHandler(CommandResult::fail(WTFMove(error)));
+                return;
+            }
+            RefPtr<InspectorObject> rectObject = InspectorObject::create();
+            rectObject->setInteger(ASCIILiteral("x"), rect.value().origin.x);
+            rectObject->setInteger(ASCIILiteral("y"), rect.value().origin.y);
+            rectObject->setInteger(ASCIILiteral("width"), rect.value().size.width);
+            rectObject->setInteger(ASCIILiteral("height"), rect.value().size.height);
+            completionHandler(CommandResult::success(WTFMove(rectObject)));
+        });
     });
 }
 
@@ -898,31 +1044,37 @@
         return;
     }
 
-    RefPtr<InspectorArray> arguments = InspectorArray::create();
-    arguments->pushString(createElement(elementID)->toJSONString());
-
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    parameters->setString(ASCIILiteral("function"), ASCIILiteral("function(element) { return element.disabled === undefined ? true : !element.disabled }"));
-    parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, elementID, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        String valueString;
-        if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        RefPtr<InspectorValue> resultValue;
-        if (!InspectorValue::parseJSON(valueString, resultValue)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        completionHandler(CommandResult::success(WTFMove(resultValue)));
+        RefPtr<InspectorArray> arguments = InspectorArray::create();
+        arguments->pushString(createElement(elementID)->toJSONString());
+
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        parameters->setString(ASCIILiteral("function"), ASCIILiteral("function(element) { return element.disabled === undefined ? true : !element.disabled }"));
+        parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String valueString;
+            if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            RefPtr<InspectorValue> resultValue;
+            if (!InspectorValue::parseJSON(valueString, resultValue)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            completionHandler(CommandResult::success(WTFMove(resultValue)));
+        });
     });
 }
 
@@ -933,31 +1085,37 @@
         return;
     }
 
-    RefPtr<InspectorArray> arguments = InspectorArray::create();
-    arguments->pushString(createElement(elementID)->toJSONString());
-
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    parameters->setString(ASCIILiteral("function"), ElementDisplayedJavaScript);
-    parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, elementID, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        String valueString;
-        if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        RefPtr<InspectorValue> resultValue;
-        if (!InspectorValue::parseJSON(valueString, resultValue)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        completionHandler(CommandResult::success(WTFMove(resultValue)));
+        RefPtr<InspectorArray> arguments = InspectorArray::create();
+        arguments->pushString(createElement(elementID)->toJSONString());
+
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        parameters->setString(ASCIILiteral("function"), ElementDisplayedJavaScript);
+        parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String valueString;
+            if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            RefPtr<InspectorValue> resultValue;
+            if (!InspectorValue::parseJSON(valueString, resultValue)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            completionHandler(CommandResult::success(WTFMove(resultValue)));
+        });
     });
 }
 
@@ -968,32 +1126,38 @@
         return;
     }
 
-    RefPtr<InspectorArray> arguments = InspectorArray::create();
-    arguments->pushString(createElement(elementID)->toJSONString());
-    arguments->pushString(InspectorValue::create(attribute)->toJSONString());
-
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    parameters->setString(ASCIILiteral("function"), ElementAttributeJavaScript);
-    parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, elementID, attribute, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        String valueString;
-        if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        RefPtr<InspectorValue> resultValue;
-        if (!InspectorValue::parseJSON(valueString, resultValue)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        completionHandler(CommandResult::success(WTFMove(resultValue)));
+        RefPtr<InspectorArray> arguments = InspectorArray::create();
+        arguments->pushString(createElement(elementID)->toJSONString());
+        arguments->pushString(InspectorValue::create(attribute)->toJSONString());
+
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        parameters->setString(ASCIILiteral("function"), ElementAttributeJavaScript);
+        parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String valueString;
+            if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            RefPtr<InspectorValue> resultValue;
+            if (!InspectorValue::parseJSON(valueString, resultValue)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            completionHandler(CommandResult::success(WTFMove(resultValue)));
+        });
     });
 }
 
@@ -1212,68 +1376,74 @@
         return;
     }
 
-    // FIXME: move this to an atom.
-    static const char focusScript[] =
-        "function focus(element) {"
-        "    var doc = element.ownerDocument || element;"
-        "    var prevActiveElement = doc.activeElement;"
-        "    if (element != prevActiveElement && prevActiveElement)"
-        "        prevActiveElement.blur();"
-        "    element.focus();"
-        "    if (element != prevActiveElement && element.value && element.value.length && element.setSelectionRange)"
-        "        element.setSelectionRange(element.value.length, element.value.length);"
-        "    if (element != doc.activeElement)"
-        "        throw new Error('cannot focus element');"
-        "}";
-
-    RefPtr<InspectorArray> arguments = InspectorArray::create();
-    arguments->pushString(createElement(elementID)->toJSONString());
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    parameters->setString(ASCIILiteral("function"), focusScript);
-    parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), keys = WTFMove(keys), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) mutable {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, elementID, keys = WTFMove(keys), completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
+        // FIXME: move this to an atom.
+        static const char focusScript[] =
+            "function focus(element) {"
+            "    var doc = element.ownerDocument || element;"
+            "    var prevActiveElement = doc.activeElement;"
+            "    if (element != prevActiveElement && prevActiveElement)"
+            "        prevActiveElement.blur();"
+            "    element.focus();"
+            "    if (element != prevActiveElement && element.value && element.value.length && element.setSelectionRange)"
+            "        element.setSelectionRange(element.value.length, element.value.length);"
+            "    if (element != doc.activeElement)"
+            "        throw new Error('cannot focus element');"
+            "}";
 
-        unsigned stickyModifiers = 0;
-        Vector<KeyboardInteraction> interactions;
-        interactions.reserveInitialCapacity(keys.size());
-        for (const auto& key : keys) {
-            KeyboardInteraction interaction;
-            KeyModifier modifier;
-            auto virtualKey = virtualKeyForKeySequence(key, modifier);
-            if (!virtualKey.isNull()) {
-                interaction.key = virtualKey;
-                if (modifier != KeyModifier::None) {
-                    stickyModifiers ^= modifier;
-                    if (stickyModifiers & modifier)
-                        interaction.type = KeyboardInteractionType::KeyPress;
-                    else
-                        interaction.type = KeyboardInteractionType::KeyRelease;
-                }
-            } else
-                interaction.text = key;
-            interactions.uncheckedAppend(WTFMove(interaction));
-        }
+        RefPtr<InspectorArray> arguments = InspectorArray::create();
+        arguments->pushString(createElement(elementID)->toJSONString());
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        parameters->setString(ASCIILiteral("function"), focusScript);
+        parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), keys = WTFMove(keys), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) mutable {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
 
-        // Reset sticky modifiers if needed.
-        if (stickyModifiers) {
-            if (stickyModifiers & KeyModifier::Shift)
-                interactions.append({ KeyboardInteractionType::KeyRelease, std::nullopt, std::optional<String>(ASCIILiteral("Shift")) });
-            if (stickyModifiers & KeyModifier::Control)
-                interactions.append({ KeyboardInteractionType::KeyRelease, std::nullopt, std::optional<String>(ASCIILiteral("Control")) });
-            if (stickyModifiers & KeyModifier::Alternate)
-                interactions.append({ KeyboardInteractionType::KeyRelease, std::nullopt, std::optional<String>(ASCIILiteral("Alternate")) });
-            if (stickyModifiers & KeyModifier::Meta)
-                interactions.append({ KeyboardInteractionType::KeyRelease, std::nullopt, std::optional<String>(ASCIILiteral("Meta")) });
-        }
+            unsigned stickyModifiers = 0;
+            Vector<KeyboardInteraction> interactions;
+            interactions.reserveInitialCapacity(keys.size());
+            for (const auto& key : keys) {
+                KeyboardInteraction interaction;
+                KeyModifier modifier;
+                auto virtualKey = virtualKeyForKeySequence(key, modifier);
+                if (!virtualKey.isNull()) {
+                    interaction.key = virtualKey;
+                    if (modifier != KeyModifier::None) {
+                        stickyModifiers ^= modifier;
+                        if (stickyModifiers & modifier)
+                            interaction.type = KeyboardInteractionType::KeyPress;
+                        else
+                            interaction.type = KeyboardInteractionType::KeyRelease;
+                    }
+                } else
+                    interaction.text = key;
+                interactions.uncheckedAppend(WTFMove(interaction));
+            }
 
-        performKeyboardInteractions(WTFMove(interactions), WTFMove(completionHandler));
+            // Reset sticky modifiers if needed.
+            if (stickyModifiers) {
+                if (stickyModifiers & KeyModifier::Shift)
+                    interactions.append({ KeyboardInteractionType::KeyRelease, std::nullopt, std::optional<String>(ASCIILiteral("Shift")) });
+                if (stickyModifiers & KeyModifier::Control)
+                    interactions.append({ KeyboardInteractionType::KeyRelease, std::nullopt, std::optional<String>(ASCIILiteral("Control")) });
+                if (stickyModifiers & KeyModifier::Alternate)
+                    interactions.append({ KeyboardInteractionType::KeyRelease, std::nullopt, std::optional<String>(ASCIILiteral("Alternate")) });
+                if (stickyModifiers & KeyModifier::Meta)
+                    interactions.append({ KeyboardInteractionType::KeyRelease, std::nullopt, std::optional<String>(ASCIILiteral("Meta")) });
+            }
+
+            performKeyboardInteractions(WTFMove(interactions), WTFMove(completionHandler));
+        });
     });
 }
 
@@ -1284,21 +1454,27 @@
         return;
     }
 
-    RefPtr<InspectorArray> arguments = InspectorArray::create();
-    arguments->pushString(createElement(elementID)->toJSONString());
-
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    parameters->setString(ASCIILiteral("function"), FormSubmitJavaScript);
-    parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, elementID, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        completionHandler(CommandResult::success());
+        RefPtr<InspectorArray> arguments = InspectorArray::create();
+        arguments->pushString(createElement(elementID)->toJSONString());
+
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        parameters->setString(ASCIILiteral("function"), FormSubmitJavaScript);
+        parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            completionHandler(CommandResult::success());
+        });
     });
 }
 
@@ -1335,48 +1511,54 @@
         return;
     }
 
-    RefPtr<InspectorArray> arguments = InspectorArray::create();
-    unsigned argumentsLength = argumentsArray->length();
-    for (unsigned i = 0; i < argumentsLength; ++i) {
-        if (auto argument = argumentsArray->get(i)) {
-            if (auto element = extractElement(*argument))
-                arguments->pushString(element->toJSONString());
-            else
-                arguments->pushString(argument->toJSONString());
-        }
-    }
-
-    RefPtr<InspectorObject> parameters = InspectorObject::create();
-    parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
-    if (m_currentBrowsingContext)
-        parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
-    parameters->setString(ASCIILiteral("function"), "function(){" + script + '}');
-    parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
-    if (mode == ExecuteScriptMode::Async) {
-        parameters->setBoolean(ASCIILiteral("expectsImplicitCallbackArgument"), true);
-        if (m_timeouts.script)
-            parameters->setInteger(ASCIILiteral("callbackTimeout"), m_timeouts.script.value().millisecondsAs<int>());
-    }
-    m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
-        if (response.isError || !response.responseObject) {
-            completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+    handleUserPrompts([this, script, argumentsArray = WTFMove(argumentsArray), mode, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+        if (result.isError()) {
+            completionHandler(WTFMove(result));
             return;
         }
-        String valueString;
-        if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
+        RefPtr<InspectorArray> arguments = InspectorArray::create();
+        unsigned argumentsLength = argumentsArray->length();
+        for (unsigned i = 0; i < argumentsLength; ++i) {
+            if (auto argument = argumentsArray->get(i)) {
+                if (auto element = extractElement(*argument))
+                    arguments->pushString(element->toJSONString());
+                else
+                    arguments->pushString(argument->toJSONString());
+            }
         }
-        if (valueString.isEmpty()) {
-            completionHandler(CommandResult::success());
-            return;
+
+        RefPtr<InspectorObject> parameters = InspectorObject::create();
+        parameters->setString(ASCIILiteral("browsingContextHandle"), m_toplevelBrowsingContext.value());
+        if (m_currentBrowsingContext)
+            parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+        parameters->setString(ASCIILiteral("function"), "function(){" + script + '}');
+        parameters->setArray(ASCIILiteral("arguments"), WTFMove(arguments));
+        if (mode == ExecuteScriptMode::Async) {
+            parameters->setBoolean(ASCIILiteral("expectsImplicitCallbackArgument"), true);
+            if (m_timeouts.script)
+                parameters->setInteger(ASCIILiteral("callbackTimeout"), m_timeouts.script.value().millisecondsAs<int>());
         }
-        RefPtr<InspectorValue> resultValue;
-        if (!InspectorValue::parseJSON(valueString, resultValue)) {
-            completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
-            return;
-        }
-        completionHandler(CommandResult::success(handleScriptResult(WTFMove(resultValue))));
+        m_host->sendCommandToBackend(ASCIILiteral("evaluateJavaScriptFunction"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
+            if (response.isError || !response.responseObject) {
+                completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+                return;
+            }
+            String valueString;
+            if (!response.responseObject->getString(ASCIILiteral("result"), valueString)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            if (valueString.isEmpty()) {
+                completionHandler(CommandResult::success());
+                return;
+            }
+            RefPtr<InspectorValue> resultValue;
+            if (!InspectorValue::parseJSON(valueString, resultValue)) {
+                completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+                return;
+            }
+            completionHandler(CommandResult::success(handleScriptResult(WTFMove(resultValue))));
+        });
     });
 }
 

Modified: trunk/Source/WebDriver/Session.h (220387 => 220388)


--- trunk/Source/WebDriver/Session.h	2017-08-08 06:25:23 UTC (rev 220387)
+++ trunk/Source/WebDriver/Session.h	2017-08-08 06:43:25 UTC (rev 220388)
@@ -107,6 +107,9 @@
 
     std::optional<String> pageLoadStrategyString() const;
 
+    void handleUserPrompts(Function<void (CommandResult&&)>&&);
+    void reportUnexpectedAlertOpen(Function<void (CommandResult&&)>&&);
+
     RefPtr<Inspector::InspectorObject> createElement(RefPtr<Inspector::InspectorValue>&&);
     RefPtr<Inspector::InspectorObject> createElement(const String& elementID);
     RefPtr<Inspector::InspectorObject> extractElement(Inspector::InspectorValue&);

Modified: trunk/Source/WebDriver/WebDriverService.cpp (220387 => 220388)


--- trunk/Source/WebDriver/WebDriverService.cpp	2017-08-08 06:25:23 UTC (rev 220387)
+++ trunk/Source/WebDriver/WebDriverService.cpp	2017-08-08 06:43:25 UTC (rev 220388)
@@ -248,6 +248,8 @@
         responseObject->setString(ASCIILiteral("error"), result.errorString());
         responseObject->setString(ASCIILiteral("message"), result.errorMessage().value_or(emptyString()));
         responseObject->setString(ASCIILiteral("stacktrace"), emptyString());
+        if (auto& additionalData = result.additionalErrorData())
+            responseObject->setObject(ASCIILiteral("data"), RefPtr<InspectorObject> { additionalData });
     } else {
         responseObject = InspectorObject::create();
         auto resultValue = result.result();
@@ -293,6 +295,17 @@
     return std::nullopt;
 }
 
+static std::optional<UnhandledPromptBehavior> deserializeUnhandledPromptBehavior(const String& unhandledPromptBehavior)
+{
+    if (unhandledPromptBehavior == "dismiss")
+        return UnhandledPromptBehavior::Dismiss;
+    if (unhandledPromptBehavior == "accept")
+        return UnhandledPromptBehavior::Accept;
+    if (unhandledPromptBehavior == "ignore")
+        return UnhandledPromptBehavior::Ignore;
+    return std::nullopt;
+}
+
 void WebDriverService::parseCapabilities(const InspectorObject& matchedCapabilities, Capabilities& capabilities) const
 {
     // Matched capabilities have already been validated.
@@ -314,6 +327,9 @@
     String pageLoadStrategy;
     if (matchedCapabilities.getString(ASCIILiteral("pageLoadStrategy"), pageLoadStrategy))
         capabilities.pageLoadStrategy = deserializePageLoadStrategy(pageLoadStrategy);
+    String unhandledPromptBehavior;
+    if (matchedCapabilities.getString(ASCIILiteral("unhandledPromptBehavior"), unhandledPromptBehavior))
+        capabilities.unhandledPromptBehavior = deserializeUnhandledPromptBehavior(unhandledPromptBehavior);
     platformParseCapabilities(matchedCapabilities, capabilities);
 }
 
@@ -367,9 +383,8 @@
             result->setValue(it->key, RefPtr<InspectorValue>(it->value));
         } else if (it->key == "unhandledPromptBehavior") {
             String unhandledPromptBehavior;
-            if (!it->value->asString(unhandledPromptBehavior))
+            if (!it->value->asString(unhandledPromptBehavior) || !deserializeUnhandledPromptBehavior(unhandledPromptBehavior))
                 return nullptr;
-            // FIXME: implement prompts support.
             result->setString(it->key, unhandledPromptBehavior);
         } else if (it->key.find(":") != notFound) {
             if (!platformValidateCapability(it->key, it->value))
@@ -591,6 +606,19 @@
                     break;
                 }
             }
+            if (capabilities.unhandledPromptBehavior) {
+                switch (capabilities.unhandledPromptBehavior.value()) {
+                case UnhandledPromptBehavior::Dismiss:
+                    capabilitiesObject->setString(ASCIILiteral("unhandledPromptBehavior"), "dismiss");
+                    break;
+                case UnhandledPromptBehavior::Accept:
+                    capabilitiesObject->setString(ASCIILiteral("unhandledPromptBehavior"), "accept");
+                    break;
+                case UnhandledPromptBehavior::Ignore:
+                    capabilitiesObject->setString(ASCIILiteral("unhandledPromptBehavior"), "ignore");
+                    break;
+                }
+            }
             resultObject->setObject(ASCIILiteral("value"), WTFMove(capabilitiesObject));
             completionHandler(CommandResult::success(WTFMove(resultObject)));
         });
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to