WebDriverConnection.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright (c) 2022, Florent Castelli <florent.castelli@gmail.com>
  3. * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
  4. * Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
  5. * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
  6. * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
  7. *
  8. * SPDX-License-Identifier: BSD-2-Clause
  9. */
  10. #include <AK/JsonObject.h>
  11. #include <AK/JsonValue.h>
  12. #include <AK/Vector.h>
  13. #include <LibWeb/DOM/Document.h>
  14. #include <LibWeb/HTML/BrowsingContext.h>
  15. #include <LibWeb/Page/Page.h>
  16. #include <LibWeb/Platform/Timer.h>
  17. #include <WebContent/PageHost.h>
  18. #include <WebContent/WebDriverConnection.h>
  19. namespace WebContent {
  20. static JsonValue make_success_response(JsonValue value)
  21. {
  22. JsonObject result;
  23. result.set("value", move(value));
  24. return result;
  25. }
  26. ErrorOr<NonnullRefPtr<WebDriverConnection>> WebDriverConnection::connect(PageHost& page_host, String const& webdriver_ipc_path)
  27. {
  28. dbgln_if(WEBDRIVER_DEBUG, "Trying to connect to {}", webdriver_ipc_path);
  29. auto socket = TRY(Core::Stream::LocalSocket::connect(webdriver_ipc_path));
  30. dbgln_if(WEBDRIVER_DEBUG, "Connected to WebDriver");
  31. return adopt_nonnull_ref_or_enomem(new (nothrow) WebDriverConnection(move(socket), page_host));
  32. }
  33. WebDriverConnection::WebDriverConnection(NonnullOwnPtr<Core::Stream::LocalSocket> socket, PageHost& page_host)
  34. : IPC::ConnectionToServer<WebDriverClientEndpoint, WebDriverServerEndpoint>(*this, move(socket))
  35. , m_page_host(page_host)
  36. {
  37. }
  38. // https://w3c.github.io/webdriver/#dfn-close-the-session
  39. void WebDriverConnection::close_session()
  40. {
  41. // 1. Set the webdriver-active flag to false.
  42. set_is_webdriver_active(false);
  43. // 2. An endpoint node must close any top-level browsing contexts associated with the session, without prompting to unload.
  44. m_page_host.page().top_level_browsing_context().close();
  45. }
  46. void WebDriverConnection::set_is_webdriver_active(bool is_webdriver_active)
  47. {
  48. m_page_host.set_is_webdriver_active(is_webdriver_active);
  49. }
  50. // 10.1 Navigate To, https://w3c.github.io/webdriver/#navigate-to
  51. Messages::WebDriverClient::NavigateToResponse WebDriverConnection::navigate_to(JsonValue const& payload)
  52. {
  53. dbgln_if(WEBDRIVER_DEBUG, "WebDriverConnection::navigate_to {}", payload);
  54. // 1. If the current top-level browsing context is no longer open, return error with error code no such window.
  55. TRY(ensure_open_top_level_browsing_context());
  56. // 2. Let url be the result of getting the property url from the parameters argument.
  57. if (!payload.is_object() || !payload.as_object().has_string("url"sv))
  58. return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload doesn't have a string `url`"sv);
  59. URL url(payload.as_object().get_ptr("url"sv)->as_string());
  60. // FIXME: 3. If url is not an absolute URL or is not an absolute URL with fragment or not a local scheme, return error with error code invalid argument.
  61. // FIXME: 4. Handle any user prompts and return its value if it is an error.
  62. // FIXME: 5. Let current URL be the current top-level browsing context’s active document’s URL.
  63. // FIXME: 6. If current URL and url do not have the same absolute URL:
  64. // FIXME: a. If timer has not been started, start a timer. If this algorithm has not completed before timer reaches the session’s session page load timeout in milliseconds, return an error with error code timeout.
  65. // 7. Navigate the current top-level browsing context to url.
  66. m_page_host.page().load(url);
  67. // FIXME: 8. If url is special except for file and current URL and URL do not have the same absolute URL:
  68. // FIXME: a. Try to wait for navigation to complete.
  69. // FIXME: b. Try to run the post-navigation checks.
  70. // FIXME: 9. Set the current browsing context with the current top-level browsing context.
  71. // FIXME: 10. If the current top-level browsing context contains a refresh state pragma directive of time 1 second or less, wait until the refresh timeout has elapsed, a new navigate has begun, and return to the first step of this algorithm.
  72. // 11. Return success with data null.
  73. return make_success_response({});
  74. }
  75. // 10.2 Get Current URL, https://w3c.github.io/webdriver/#get-current-url
  76. Messages::WebDriverClient::GetCurrentUrlResponse WebDriverConnection::get_current_url()
  77. {
  78. dbgln_if(WEBDRIVER_DEBUG, "WebDriverConnection::get_current_url");
  79. // 1. If the current top-level browsing context is no longer open, return error with error code no such window.
  80. TRY(ensure_open_top_level_browsing_context());
  81. // FIXME: 2. Handle any user prompts and return its value if it is an error.
  82. // 3. Let url be the serialization of the current top-level browsing context’s active document’s document URL.
  83. auto url = m_page_host.page().top_level_browsing_context().active_document()->url().to_string();
  84. // 4. Return success with data url.
  85. return make_success_response(url);
  86. }
  87. // https://w3c.github.io/webdriver/#dfn-no-longer-open
  88. ErrorOr<void, Web::WebDriver::Error> WebDriverConnection::ensure_open_top_level_browsing_context()
  89. {
  90. // A browsing context is said to be no longer open if it has been discarded.
  91. if (m_page_host.page().top_level_browsing_context().has_been_discarded())
  92. return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchWindow, "Window not found"sv);
  93. return {};
  94. }
  95. }