Contexts.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/JsonObject.h>
  7. #include <LibWeb/DOM/Document.h>
  8. #include <LibWeb/HTML/BrowsingContext.h>
  9. #include <LibWeb/HTML/TraversableNavigable.h>
  10. #include <LibWeb/HTML/WindowProxy.h>
  11. #include <LibWeb/WebDriver/Contexts.h>
  12. namespace Web::WebDriver {
  13. // https://w3c.github.io/webdriver/#dfn-web-window-identifier
  14. static ByteString const WEB_WINDOW_IDENTIFIER = "window-fcc6-11e5-b4f8-330a88ab9d7f"sv;
  15. // https://w3c.github.io/webdriver/#dfn-web-frame-identifier
  16. static ByteString const WEB_FRAME_IDENTIFIER = "frame-075b-4da1-b6ba-e579c2d3230a"sv;
  17. // https://w3c.github.io/webdriver/#dfn-windowproxy-reference-object
  18. JsonObject window_proxy_reference_object(HTML::WindowProxy const& window)
  19. {
  20. // 1. Let identifier be the web window identifier if the associated browsing context of window is a top-level browsing context.
  21. // Otherwise let it be the web frame identifier.
  22. // NOTE: We look at the active browsing context's active document's node navigable instead.
  23. // Because a Browsing context's top-level traversable is this navigable's top level traversable.
  24. // Ref: https://html.spec.whatwg.org/multipage/document-sequences.html#bc-traversable
  25. auto navigable = window.associated_browsing_context()->active_document()->navigable();
  26. auto identifier = navigable->is_top_level_traversable()
  27. ? WEB_WINDOW_IDENTIFIER
  28. : WEB_FRAME_IDENTIFIER;
  29. // 2. Return a JSON Object initialized with the following properties:
  30. JsonObject object;
  31. // identifier
  32. // Associated window handle of the window’s browsing context.
  33. object.set(identifier, navigable->traversable_navigable()->window_handle().to_byte_string());
  34. return object;
  35. }
  36. static GC::Ptr<HTML::Navigable> find_navigable_with_handle(StringView handle, bool should_be_top_level)
  37. {
  38. for (auto* navigable : Web::HTML::all_navigables()) {
  39. if (navigable->is_top_level_traversable() != should_be_top_level)
  40. continue;
  41. if (navigable->traversable_navigable()->window_handle() == handle)
  42. return navigable;
  43. }
  44. return {};
  45. }
  46. // https://w3c.github.io/webdriver/#dfn-represents-a-web-frame
  47. bool represents_a_web_frame(JS::Value value)
  48. {
  49. // An ECMAScript Object represents a web frame if it has a web frame identifier own property.
  50. if (!value.is_object())
  51. return false;
  52. auto result = value.as_object().has_own_property(WEB_FRAME_IDENTIFIER);
  53. return !result.is_error() && result.value();
  54. }
  55. // https://w3c.github.io/webdriver/#dfn-deserialize-a-web-frame
  56. ErrorOr<GC::Ref<HTML::WindowProxy>, WebDriver::Error> deserialize_web_frame(JS::Object const& object)
  57. {
  58. // 1. If object has no own property web frame identifier, return error with error code invalid argument.
  59. auto property = object.get(WEB_FRAME_IDENTIFIER);
  60. if (property.is_error() || !property.value().is_string())
  61. return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web frame"sv);
  62. // 2. Let reference be the result of getting the web frame identifier property from object.
  63. auto reference = property.value().as_string().utf8_string();
  64. // 3. Let browsing context be the browsing context whose window handle is reference, or null if no such browsing
  65. // context exists.
  66. auto navigable = find_navigable_with_handle(reference, false);
  67. // 4. If browsing context is null or a top-level browsing context, return error with error code no such frame.
  68. // NOTE: We filtered on the top-level browsing context condition in the previous step.
  69. if (!navigable)
  70. return WebDriver::Error::from_code(WebDriver::ErrorCode::NoSuchFrame, "Could not locate frame"sv);
  71. // 5. Return success with data browsing context's associated window.
  72. return *navigable->active_window_proxy();
  73. }
  74. // https://w3c.github.io/webdriver/#dfn-represents-a-web-frame
  75. bool represents_a_web_window(JS::Value value)
  76. {
  77. // An ECMAScript Object represents a web window if it has a web window identifier own property.
  78. if (!value.is_object())
  79. return false;
  80. auto result = value.as_object().has_own_property(WEB_WINDOW_IDENTIFIER);
  81. return !result.is_error() && result.value();
  82. }
  83. // https://w3c.github.io/webdriver/#dfn-deserialize-a-web-frame
  84. ErrorOr<GC::Ref<HTML::WindowProxy>, WebDriver::Error> deserialize_web_window(JS::Object const& object)
  85. {
  86. // 1. If object has no own property web window identifier, return error with error code invalid argument.
  87. auto property = object.get(WEB_WINDOW_IDENTIFIER);
  88. if (property.is_error() || !property.value().is_string())
  89. return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web window"sv);
  90. // 2. Let reference be the result of getting the web window identifier property from object.
  91. auto reference = property.value().as_string().utf8_string();
  92. // 3. Let browsing context be the browsing context whose window handle is reference, or null if no such browsing
  93. // context exists.
  94. auto navigable = find_navigable_with_handle(reference, true);
  95. // 4. If browsing context is null or not a top-level browsing context, return error with error code no such window.
  96. // NOTE: We filtered on the top-level browsing context condition in the previous step.
  97. if (!navigable)
  98. return WebDriver::Error::from_code(WebDriver::ErrorCode::NoSuchWindow, "Could not locate window"sv);
  99. // 5. Return success with data browsing context's associated window.
  100. return *navigable->active_window_proxy();
  101. }
  102. }