mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-05 17:16:04 +00:00
LibWeb: Implement the document.cookie setter/getter according to spec
This ensures we cannot set or get cookies on non-HTTP(S) origins. Since this would prevent our ability to test cookies during LibWeb tests, this also adds an internals API to allow cookie access on file:// URLs.
This commit is contained in:
parent
86744449e3
commit
527218da19
Notes:
github-actions[bot]
2024-10-23 07:06:33 +00:00
Author: https://github.com/trflynn89
Commit: 527218da19
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1926
7 changed files with 69 additions and 8 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
Cookie averse test: ""
|
||||||
Basic test: "cookie=value"
|
Basic test: "cookie=value"
|
||||||
Multiple cookies: "cookie1=value1; cookie2=value2; cookie3=value3"
|
Multiple cookies: "cookie1=value1; cookie2=value2; cookie3=value3"
|
||||||
Nameless cookie: "value"
|
Nameless cookie: "value"
|
||||||
|
|
|
@ -12,6 +12,11 @@
|
||||||
document.cookie = `${name}=""; max-age=-9999`;
|
document.cookie = `${name}=""; max-age=-9999`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cookieAverseTest = () => {
|
||||||
|
document.cookie = "cookie=value";
|
||||||
|
printCookies("Cookie averse test");
|
||||||
|
};
|
||||||
|
|
||||||
const basicTest = () => {
|
const basicTest = () => {
|
||||||
document.cookie = "cookie=value";
|
document.cookie = "cookie=value";
|
||||||
printCookies("Basic test");
|
printCookies("Basic test");
|
||||||
|
@ -178,6 +183,10 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
test(() => {
|
test(() => {
|
||||||
|
cookieAverseTest();
|
||||||
|
|
||||||
|
internals.enableCookiesOnFileDomains();
|
||||||
|
|
||||||
basicTest();
|
basicTest();
|
||||||
multipleCookiesTest();
|
multipleCookiesTest();
|
||||||
|
|
||||||
|
|
|
@ -2492,18 +2492,58 @@ void Document::completely_finish_loading()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String Document::cookie(Cookie::Source source)
|
// https://html.spec.whatwg.org/#dom-document-cookie
|
||||||
|
WebIDL::ExceptionOr<String> Document::cookie(Cookie::Source source)
|
||||||
{
|
{
|
||||||
|
// On getting, if the document is a cookie-averse Document object, then the user agent must return the empty string.
|
||||||
|
if (is_cookie_averse())
|
||||||
|
return String {};
|
||||||
|
|
||||||
|
// Otherwise, if the Document's origin is an opaque origin, the user agent must throw a "SecurityError" DOMException.
|
||||||
|
if (origin().is_opaque())
|
||||||
|
return WebIDL::SecurityError::create(realm(), "Document origin is opaque"_string);
|
||||||
|
|
||||||
|
// Otherwise, the user agent must return the cookie-string for the document's URL for a "non-HTTP" API, decoded using
|
||||||
|
// UTF-8 decode without BOM.
|
||||||
return page().client().page_did_request_cookie(m_url, source);
|
return page().client().page_did_request_cookie(m_url, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::set_cookie(StringView cookie_string, Cookie::Source source)
|
// https://html.spec.whatwg.org/#dom-document-cookie
|
||||||
|
WebIDL::ExceptionOr<void> Document::set_cookie(StringView cookie_string, Cookie::Source source)
|
||||||
{
|
{
|
||||||
auto cookie = Cookie::parse_cookie(url(), cookie_string);
|
// On setting, if the document is a cookie-averse Document object, then the user agent must do nothing.
|
||||||
if (!cookie.has_value())
|
if (is_cookie_averse())
|
||||||
return;
|
return {};
|
||||||
|
|
||||||
|
// Otherwise, if the Document's origin is an opaque origin, the user agent must throw a "SecurityError" DOMException.
|
||||||
|
if (origin().is_opaque())
|
||||||
|
return WebIDL::SecurityError::create(realm(), "Document origin is opaque"_string);
|
||||||
|
|
||||||
|
// Otherwise, the user agent must act as it would when receiving a set-cookie-string for the document's URL via a
|
||||||
|
// "non-HTTP" API, consisting of the new value encoded as UTF-8.
|
||||||
|
if (auto cookie = Cookie::parse_cookie(url(), cookie_string); cookie.has_value())
|
||||||
page().client().page_did_set_cookie(m_url, cookie.value(), source);
|
page().client().page_did_set_cookie(m_url, cookie.value(), source);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/#cookie-averse-document-object
|
||||||
|
bool Document::is_cookie_averse() const
|
||||||
|
{
|
||||||
|
// A Document object that falls into one of the following conditions is a cookie-averse Document object:
|
||||||
|
|
||||||
|
// * A Document object whose browsing context is null.
|
||||||
|
if (!browsing_context())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// * A Document whose URL's scheme is not an HTTP(S) scheme.
|
||||||
|
if (!url().scheme().is_one_of("http"sv, "https"sv)) {
|
||||||
|
// AD-HOC: This allows us to write cookie integration tests.
|
||||||
|
if (!m_enable_cookies_on_file_domains || url().scheme() != "file"sv)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Document::fg_color() const
|
String Document::fg_color() const
|
||||||
|
|
|
@ -116,8 +116,10 @@ public:
|
||||||
|
|
||||||
JS::GCPtr<Selection::Selection> get_selection() const;
|
JS::GCPtr<Selection::Selection> get_selection() const;
|
||||||
|
|
||||||
String cookie(Cookie::Source = Cookie::Source::NonHttp);
|
WebIDL::ExceptionOr<String> cookie(Cookie::Source = Cookie::Source::NonHttp);
|
||||||
void set_cookie(StringView, Cookie::Source = Cookie::Source::NonHttp);
|
WebIDL::ExceptionOr<void> set_cookie(StringView, Cookie::Source = Cookie::Source::NonHttp);
|
||||||
|
bool is_cookie_averse() const;
|
||||||
|
void enable_cookies_on_file_domains(Badge<Internals::Internals>) { m_enable_cookies_on_file_domains = true; }
|
||||||
|
|
||||||
String fg_color() const;
|
String fg_color() const;
|
||||||
void set_fg_color(String const&);
|
void set_fg_color(String const&);
|
||||||
|
@ -1020,6 +1022,8 @@ private:
|
||||||
|
|
||||||
bool m_needs_repaint { false };
|
bool m_needs_repaint { false };
|
||||||
|
|
||||||
|
bool m_enable_cookies_on_file_domains { false };
|
||||||
|
|
||||||
Optional<PaintConfig> m_cached_display_list_paint_config;
|
Optional<PaintConfig> m_cached_display_list_paint_config;
|
||||||
RefPtr<Painting::DisplayList> m_cached_display_list;
|
RefPtr<Painting::DisplayList> m_cached_display_list;
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,11 @@ void Internals::simulate_drop(double x, double y)
|
||||||
page.handle_drag_and_drop_event(DragEvent::Type::Drop, position, position, UIEvents::MouseButton::Primary, 0, 0, {});
|
page.handle_drag_and_drop_event(DragEvent::Type::Drop, position, position, UIEvents::MouseButton::Primary, 0, 0, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Internals::enable_cookies_on_file_domains()
|
||||||
|
{
|
||||||
|
internals_window().associated_document().enable_cookies_on_file_domains({});
|
||||||
|
}
|
||||||
|
|
||||||
void Internals::expire_cookies_with_time_offset(WebIDL::LongLong seconds)
|
void Internals::expire_cookies_with_time_offset(WebIDL::LongLong seconds)
|
||||||
{
|
{
|
||||||
internals_page().client().page_did_expire_cookies_with_time_offset(AK::Duration::from_seconds(seconds));
|
internals_page().client().page_did_expire_cookies_with_time_offset(AK::Duration::from_seconds(seconds));
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
void simulate_drag_move(double x, double y);
|
void simulate_drag_move(double x, double y);
|
||||||
void simulate_drop(double x, double y);
|
void simulate_drop(double x, double y);
|
||||||
|
|
||||||
|
void enable_cookies_on_file_domains();
|
||||||
void expire_cookies_with_time_offset(WebIDL::LongLong seconds);
|
void expire_cookies_with_time_offset(WebIDL::LongLong seconds);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -34,5 +34,6 @@ interface Internals {
|
||||||
undefined simulateDragMove(double x, double y);
|
undefined simulateDragMove(double x, double y);
|
||||||
undefined simulateDrop(double x, double y);
|
undefined simulateDrop(double x, double y);
|
||||||
|
|
||||||
|
undefined enableCookiesOnFileDomains();
|
||||||
undefined expireCookiesWithTimeOffset(long long seconds);
|
undefined expireCookiesWithTimeOffset(long long seconds);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue