summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-11-11 09:24:07 -0500
committerLinus Groh <mail@linusgroh.de>2022-11-11 18:02:04 +0000
commitc77260c480f5b9b36171894ed11b4708dbbe8a05 (patch)
tree63f77598fdec04cc9b50fdc2f495f0e6c9c885a0 /Userland
parentd2c1957d8f79c9a60ba067b8bef780d7abf64bba (diff)
downloadserenity-c77260c480f5b9b36171894ed11b4708dbbe8a05.zip
Browser+WebContent+WebDriver: Move Get All Cookies to WebContent
There are a couple changes here from the existing Get All Cookies implementation. 1. Previously, WebDriver actually returned *all* cookies in the cookie jar. The spec dictates that we only return cookies that match the document's URL. Specifically, it calls out that we must run just the first step of RFC 6265 section 5.4 to perform domain matching. This change adds a special mode to our implementation of that section to skip the remaining steps. 2. We now fill in the SameSite cookie attribute when serializing the cookie to JSON (this was a trival FIXME that didn't get picked up when SameSite was implemented).
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Applications/Browser/BrowserWindow.cpp4
-rw-r--r--Userland/Applications/Browser/CookieJar.cpp26
-rw-r--r--Userland/Applications/Browser/CookieJar.h8
-rw-r--r--Userland/Applications/Browser/Tab.cpp6
-rw-r--r--Userland/Applications/Browser/Tab.h1
-rw-r--r--Userland/Services/WebContent/WebDriverClient.ipc1
-rw-r--r--Userland/Services/WebContent/WebDriverConnection.cpp43
-rw-r--r--Userland/Services/WebContent/WebDriverConnection.h1
-rw-r--r--Userland/Services/WebDriver/Client.cpp3
-rw-r--r--Userland/Services/WebDriver/Session.cpp24
-rw-r--r--Userland/Services/WebDriver/Session.h1
11 files changed, 89 insertions, 29 deletions
diff --git a/Userland/Applications/Browser/BrowserWindow.cpp b/Userland/Applications/Browser/BrowserWindow.cpp
index dc128bcdec..ba2dac87ea 100644
--- a/Userland/Applications/Browser/BrowserWindow.cpp
+++ b/Userland/Applications/Browser/BrowserWindow.cpp
@@ -575,6 +575,10 @@ void BrowserWindow::create_new_tab(URL url, bool activate)
});
};
+ new_tab.on_get_all_cookies = [this](auto& url) {
+ return m_cookie_jar.get_all_cookies(url);
+ };
+
new_tab.on_get_cookie = [this](auto& url, auto source) -> String {
return m_cookie_jar.get_cookie(url, source);
};
diff --git a/Userland/Applications/Browser/CookieJar.cpp b/Userland/Applications/Browser/CookieJar.cpp
index d0c3df10a6..bf1ec26260 100644
--- a/Userland/Applications/Browser/CookieJar.cpp
+++ b/Userland/Applications/Browser/CookieJar.cpp
@@ -116,6 +116,24 @@ Vector<Web::Cookie::Cookie> CookieJar::get_all_cookies() const
return cookies;
}
+// https://w3c.github.io/webdriver/#dfn-associated-cookies
+Vector<Web::Cookie::Cookie> CookieJar::get_all_cookies(URL const& url)
+{
+ auto domain = canonicalize_domain(url);
+ if (!domain.has_value())
+ return {};
+
+ auto cookie_list = get_matching_cookies(url, domain.value(), Web::Cookie::Source::Http, MatchingCookiesSpecMode::WebDriver);
+
+ Vector<Web::Cookie::Cookie> cookies;
+ cookies.ensure_capacity(cookie_list.size());
+
+ for (auto const& cookie : cookie_list)
+ cookies.unchecked_append(cookie);
+
+ return cookies;
+}
+
Optional<String> CookieJar::canonicalize_domain(const URL& url)
{
// https://tools.ietf.org/html/rfc6265#section-5.1.2
@@ -281,7 +299,7 @@ void CookieJar::store_cookie(Web::Cookie::ParsedCookie const& parsed_cookie, con
m_cookies.set(key, move(cookie));
}
-Vector<Web::Cookie::Cookie&> CookieJar::get_matching_cookies(const URL& url, String const& canonicalized_domain, Web::Cookie::Source source)
+Vector<Web::Cookie::Cookie&> CookieJar::get_matching_cookies(const URL& url, String const& canonicalized_domain, Web::Cookie::Source source, MatchingCookiesSpecMode mode)
{
// https://tools.ietf.org/html/rfc6265#section-5.4
@@ -310,6 +328,12 @@ Vector<Web::Cookie::Cookie&> CookieJar::get_matching_cookies(const URL& url, Str
if (cookie.value.http_only && (source != Web::Cookie::Source::Http))
continue;
+ // NOTE: The WebDriver spec expects only step 1 above to be executed to match cookies.
+ if (mode == MatchingCookiesSpecMode::WebDriver) {
+ cookie_list.append(cookie.value);
+ continue;
+ }
+
// 2. The user agent SHOULD sort the cookie-list in the following order:
// - Cookies with longer paths are listed before cookies with shorter paths.
// - Among cookies that have equal-length path fields, cookies with earlier creation-times are listed before cookies with later creation-times.
diff --git a/Userland/Applications/Browser/CookieJar.h b/Userland/Applications/Browser/CookieJar.h
index 7bae12c04f..2db6f41b73 100644
--- a/Userland/Applications/Browser/CookieJar.h
+++ b/Userland/Applications/Browser/CookieJar.h
@@ -31,6 +31,7 @@ public:
void update_cookie(URL const&, Web::Cookie::Cookie);
void dump_cookies() const;
Vector<Web::Cookie::Cookie> get_all_cookies() const;
+ Vector<Web::Cookie::Cookie> get_all_cookies(URL const& url);
private:
static Optional<String> canonicalize_domain(const URL& url);
@@ -38,8 +39,13 @@ private:
static bool path_matches(String const& request_path, String const& cookie_path);
static String default_path(const URL& url);
+ enum class MatchingCookiesSpecMode {
+ RFC6265,
+ WebDriver,
+ };
+
void store_cookie(Web::Cookie::ParsedCookie const& parsed_cookie, const URL& url, String canonicalized_domain, Web::Cookie::Source source);
- Vector<Web::Cookie::Cookie&> get_matching_cookies(const URL& url, String const& canonicalized_domain, Web::Cookie::Source source);
+ Vector<Web::Cookie::Cookie&> get_matching_cookies(const URL& url, String const& canonicalized_domain, Web::Cookie::Source source, MatchingCookiesSpecMode mode = MatchingCookiesSpecMode::RFC6265);
void purge_expired_cookies();
HashMap<CookieStorageKey, Web::Cookie::Cookie> m_cookies;
diff --git a/Userland/Applications/Browser/Tab.cpp b/Userland/Applications/Browser/Tab.cpp
index 2262c4e899..905978ab3f 100644
--- a/Userland/Applications/Browser/Tab.cpp
+++ b/Userland/Applications/Browser/Tab.cpp
@@ -351,6 +351,12 @@ Tab::Tab(BrowserWindow& window)
on_favicon_change(icon);
};
+ view().on_get_all_cookies = [this](auto& url) -> Vector<Web::Cookie::Cookie> {
+ if (on_get_all_cookies)
+ return on_get_all_cookies(url);
+ return {};
+ };
+
view().on_get_cookie = [this](auto& url, auto source) -> String {
if (on_get_cookie)
return on_get_cookie(url, source);
diff --git a/Userland/Applications/Browser/Tab.h b/Userland/Applications/Browser/Tab.h
index c016783209..9477fefb7f 100644
--- a/Userland/Applications/Browser/Tab.h
+++ b/Userland/Applications/Browser/Tab.h
@@ -64,6 +64,7 @@ public:
Function<void(Tab&)> on_tab_close_request;
Function<void(Tab&)> on_tab_close_other_request;
Function<void(Gfx::Bitmap const&)> on_favicon_change;
+ Function<Vector<Web::Cookie::Cookie>(AK::URL const& url)> on_get_all_cookies;
Function<String(const URL&, Web::Cookie::Source source)> on_get_cookie;
Function<void(const URL&, Web::Cookie::ParsedCookie const& cookie, Web::Cookie::Source source)> on_set_cookie;
Function<void()> on_dump_cookies;
diff --git a/Userland/Services/WebContent/WebDriverClient.ipc b/Userland/Services/WebContent/WebDriverClient.ipc
index b8f803f2f3..a7d70c8ff5 100644
--- a/Userland/Services/WebContent/WebDriverClient.ipc
+++ b/Userland/Services/WebContent/WebDriverClient.ipc
@@ -24,6 +24,7 @@ endpoint WebDriverClient {
get_source() => (Web::WebDriver::Response response)
execute_script(JsonValue payload) => (Web::WebDriver::Response response)
execute_async_script(JsonValue payload) => (Web::WebDriver::Response response)
+ get_all_cookies() => (Web::WebDriver::Response response)
take_screenshot() => (Web::WebDriver::Response response)
take_element_screenshot(String element_id) => (Web::WebDriver::Response response)
}
diff --git a/Userland/Services/WebContent/WebDriverConnection.cpp b/Userland/Services/WebContent/WebDriverConnection.cpp
index 9b4e67098b..94b12c8a46 100644
--- a/Userland/Services/WebContent/WebDriverConnection.cpp
+++ b/Userland/Services/WebContent/WebDriverConnection.cpp
@@ -16,6 +16,7 @@
#include <LibWeb/CSS/PropertyID.h>
#include <LibWeb/CSS/StyleProperties.h>
#include <LibWeb/CSS/StyleValue.h>
+#include <LibWeb/Cookie/Cookie.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Element.h>
#include <LibWeb/Geometry/DOMRect.h>
@@ -41,6 +42,22 @@ static JsonValue make_success_response(JsonValue value)
return result;
}
+// https://w3c.github.io/webdriver/#dfn-serialized-cookie
+static JsonValue serialize_cookie(Web::Cookie::Cookie const& cookie)
+{
+ JsonObject serialized_cookie;
+ serialized_cookie.set("name"sv, cookie.name);
+ serialized_cookie.set("value"sv, cookie.value);
+ serialized_cookie.set("path"sv, cookie.path);
+ serialized_cookie.set("domain"sv, cookie.domain);
+ serialized_cookie.set("secure"sv, cookie.secure);
+ serialized_cookie.set("httpOnly"sv, cookie.http_only);
+ serialized_cookie.set("expiry"sv, cookie.expiry_time.timestamp());
+ serialized_cookie.set("sameSite"sv, Web::Cookie::same_site_to_string(cookie.same_site));
+
+ return serialized_cookie;
+}
+
static JsonValue serialize_rect(Gfx::IntRect const& rect)
{
JsonObject serialized_rect = {};
@@ -829,6 +846,32 @@ Messages::WebDriverClient::ExecuteAsyncScriptResponse WebDriverConnection::execu
VERIFY_NOT_REACHED();
}
+// 14.1 Get All Cookies, https://w3c.github.io/webdriver/#dfn-get-all-cookies
+Messages::WebDriverClient::GetAllCookiesResponse WebDriverConnection::get_all_cookies()
+{
+ // 1. If the current browsing context is no longer open, return error with error code no such window.
+ TRY(ensure_open_top_level_browsing_context());
+
+ // FIXME: 2. Handle any user prompts, and return its value if it is an error.
+
+ // 3. Let cookies be a new JSON List.
+ JsonArray cookies;
+
+ // 4. For each cookie in all associated cookies of the current browsing context’s active document:
+ auto* document = m_page_host.page().top_level_browsing_context().active_document();
+
+ for (auto const& cookie : m_web_content_client.did_request_all_cookies(document->url())) {
+ // 1. Let serialized cookie be the result of serializing cookie.
+ auto serialized_cookie = serialize_cookie(cookie);
+
+ // 2. Append serialized cookie to cookies
+ cookies.append(move(serialized_cookie));
+ }
+
+ // 5. Return success with data cookies.
+ return make_success_response(move(cookies));
+}
+
// 17.1 Take Screenshot, https://w3c.github.io/webdriver/#take-screenshot
Messages::WebDriverClient::TakeScreenshotResponse WebDriverConnection::take_screenshot()
{
diff --git a/Userland/Services/WebContent/WebDriverConnection.h b/Userland/Services/WebContent/WebDriverConnection.h
index 56e00a907e..91f6735056 100644
--- a/Userland/Services/WebContent/WebDriverConnection.h
+++ b/Userland/Services/WebContent/WebDriverConnection.h
@@ -56,6 +56,7 @@ private:
virtual Messages::WebDriverClient::GetSourceResponse get_source() override;
virtual Messages::WebDriverClient::ExecuteScriptResponse execute_script(JsonValue const& payload) override;
virtual Messages::WebDriverClient::ExecuteAsyncScriptResponse execute_async_script(JsonValue const& payload) override;
+ virtual Messages::WebDriverClient::GetAllCookiesResponse get_all_cookies() override;
virtual Messages::WebDriverClient::TakeScreenshotResponse take_screenshot() override;
virtual Messages::WebDriverClient::TakeElementScreenshotResponse take_element_screenshot(String const& element_id) override;
diff --git a/Userland/Services/WebDriver/Client.cpp b/Userland/Services/WebDriver/Client.cpp
index 0587209c91..c5f660eacc 100644
--- a/Userland/Services/WebDriver/Client.cpp
+++ b/Userland/Services/WebDriver/Client.cpp
@@ -753,8 +753,7 @@ Web::WebDriver::Response Client::handle_get_all_cookies(Vector<StringView> const
{
dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/cookie");
auto* session = TRY(find_session_with_id(parameters[0]));
- auto cookies = TRY(session->get_all_cookies());
- return make_json_value(cookies);
+ return session->web_content_connection().get_all_cookies();
}
// 14.2 Get Named Cookie, https://w3c.github.io/webdriver/#dfn-get-named-cookie
diff --git a/Userland/Services/WebDriver/Session.cpp b/Userland/Services/WebDriver/Session.cpp
index 4732d4fef3..3c9c816c8c 100644
--- a/Userland/Services/WebDriver/Session.cpp
+++ b/Userland/Services/WebDriver/Session.cpp
@@ -313,30 +313,6 @@ static JsonObject serialize_cookie(Web::Cookie::Cookie const& cookie)
return serialized_cookie;
}
-// 14.1 Get All Cookies, https://w3c.github.io/webdriver/#dfn-get-all-cookies
-Web::WebDriver::Response Session::get_all_cookies()
-{
- // 1. If the current browsing context is no longer open, return error with error code no such window.
- TRY(check_for_open_top_level_browsing_context_or_return_error());
-
- // FIXME: 2. Handle any user prompts, and return its value if it is an error.
-
- // 3. Let cookies be a new JSON List.
- JsonArray cookies = {};
-
- // 4. For each cookie in all associated cookies of the current browsing context’s active document:
- for (auto const& cookie : m_browser_connection->get_all_cookies()) {
- // 1. Let serialized cookie be the result of serializing cookie.
- auto serialized_cookie = serialize_cookie(cookie);
-
- // 2. Append serialized cookie to cookies
- cookies.append(serialized_cookie);
- }
-
- // 5. Return success with data cookies.
- return JsonValue(cookies);
-}
-
// 14.2 Get Named Cookie, https://w3c.github.io/webdriver/#dfn-get-named-cookie
Web::WebDriver::Response Session::get_named_cookie(String const& name)
{
diff --git a/Userland/Services/WebDriver/Session.h b/Userland/Services/WebDriver/Session.h
index da590dc1ed..cb7fcdccc5 100644
--- a/Userland/Services/WebDriver/Session.h
+++ b/Userland/Services/WebDriver/Session.h
@@ -58,7 +58,6 @@ public:
Web::WebDriver::Response get_window_handle();
ErrorOr<void, Variant<Web::WebDriver::Error, Error>> close_window();
Web::WebDriver::Response get_window_handles() const;
- Web::WebDriver::Response get_all_cookies();
Web::WebDriver::Response get_named_cookie(String const& name);
Web::WebDriver::Response add_cookie(JsonValue const& payload);
Web::WebDriver::Response delete_cookie(StringView name);