mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 16:55:09 +00:00
Browser+LibWeb+WebContent: Track the source of document.cookie requests
To implement the HttpOnly attribute, the CookieJar needs to know where a request originated from. Namely, it needs to distinguish between HTTP / non-HTTP (i.e. JavaScript) requests. When the HttpOnly attribute is set, requests from JavaScript are to be blocked.
This commit is contained in:
parent
7193e518d1
commit
c00760c5f9
20 changed files with 54 additions and 47 deletions
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
namespace Browser {
|
namespace Browser {
|
||||||
|
|
||||||
String CookieJar::get_cookie(const URL& url)
|
String CookieJar::get_cookie(const URL& url, Web::Cookie::Source)
|
||||||
{
|
{
|
||||||
purge_expired_cookies();
|
purge_expired_cookies();
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ String CookieJar::get_cookie(const URL& url)
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CookieJar::set_cookie(const URL& url, const String& cookie_string)
|
void CookieJar::set_cookie(const URL& url, const String& cookie_string, Web::Cookie::Source)
|
||||||
{
|
{
|
||||||
auto domain = canonicalize_domain(url);
|
auto domain = canonicalize_domain(url);
|
||||||
if (!domain.has_value())
|
if (!domain.has_value())
|
||||||
|
|
|
@ -46,8 +46,8 @@ struct CookieStorageKey {
|
||||||
|
|
||||||
class CookieJar {
|
class CookieJar {
|
||||||
public:
|
public:
|
||||||
String get_cookie(const URL& url);
|
String get_cookie(const URL& url, Web::Cookie::Source source);
|
||||||
void set_cookie(const URL& url, const String& cookie);
|
void set_cookie(const URL& url, const String& cookie, Web::Cookie::Source source);
|
||||||
void dump_cookies() const;
|
void dump_cookies() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -242,15 +242,15 @@ Tab::Tab(Type type)
|
||||||
on_favicon_change(icon);
|
on_favicon_change(icon);
|
||||||
};
|
};
|
||||||
|
|
||||||
hooks().on_get_cookie = [this](auto& url) -> String {
|
hooks().on_get_cookie = [this](auto& url, auto source) -> String {
|
||||||
if (on_get_cookie)
|
if (on_get_cookie)
|
||||||
return on_get_cookie(url);
|
return on_get_cookie(url, source);
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
hooks().on_set_cookie = [this](auto& url, auto& cookie) {
|
hooks().on_set_cookie = [this](auto& url, auto& cookie, auto source) {
|
||||||
if (on_set_cookie)
|
if (on_set_cookie)
|
||||||
on_set_cookie(url, cookie);
|
on_set_cookie(url, cookie, source);
|
||||||
};
|
};
|
||||||
|
|
||||||
hooks().on_get_source = [this](auto& url, auto& source) {
|
hooks().on_get_source = [this](auto& url, auto& source) {
|
||||||
|
|
|
@ -70,8 +70,8 @@ public:
|
||||||
Function<void(const URL&)> on_tab_open_request;
|
Function<void(const URL&)> on_tab_open_request;
|
||||||
Function<void(Tab&)> on_tab_close_request;
|
Function<void(Tab&)> on_tab_close_request;
|
||||||
Function<void(const Gfx::Bitmap&)> on_favicon_change;
|
Function<void(const Gfx::Bitmap&)> on_favicon_change;
|
||||||
Function<String(const URL& url)> on_get_cookie;
|
Function<String(const URL& url, Web::Cookie::Source source)> on_get_cookie;
|
||||||
Function<void(const URL& url, const String& cookie)> on_set_cookie;
|
Function<void(const URL& url, const String& cookie, Web::Cookie::Source source)> on_set_cookie;
|
||||||
Function<void()> on_dump_cookies;
|
Function<void()> on_dump_cookies;
|
||||||
|
|
||||||
const String& title() const { return m_title; }
|
const String& title() const { return m_title; }
|
||||||
|
|
|
@ -219,12 +219,12 @@ int main(int argc, char** argv)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
new_tab.on_get_cookie = [&](auto& url) -> String {
|
new_tab.on_get_cookie = [&](auto& url, auto source) -> String {
|
||||||
return cookie_jar.get_cookie(url);
|
return cookie_jar.get_cookie(url, source);
|
||||||
};
|
};
|
||||||
|
|
||||||
new_tab.on_set_cookie = [&](auto& url, auto& cookie) {
|
new_tab.on_set_cookie = [&](auto& url, auto& cookie, auto source) {
|
||||||
cookie_jar.set_cookie(url, cookie);
|
cookie_jar.set_cookie(url, cookie, source);
|
||||||
};
|
};
|
||||||
|
|
||||||
new_tab.on_dump_cookies = [&]() {
|
new_tab.on_dump_cookies = [&]() {
|
||||||
|
|
|
@ -31,6 +31,11 @@
|
||||||
|
|
||||||
namespace Web::Cookie {
|
namespace Web::Cookie {
|
||||||
|
|
||||||
|
enum class Source {
|
||||||
|
NonHttp,
|
||||||
|
Http,
|
||||||
|
};
|
||||||
|
|
||||||
struct Cookie {
|
struct Cookie {
|
||||||
String name;
|
String name;
|
||||||
String value;
|
String value;
|
||||||
|
|
|
@ -821,17 +821,17 @@ void Document::completely_finish_loading()
|
||||||
dispatch_event(DOM::Event::create(HTML::EventNames::load));
|
dispatch_event(DOM::Event::create(HTML::EventNames::load));
|
||||||
}
|
}
|
||||||
|
|
||||||
String Document::cookie()
|
String Document::cookie(Cookie::Source source)
|
||||||
{
|
{
|
||||||
if (auto* page = this->page())
|
if (auto* page = this->page())
|
||||||
return page->client().page_did_request_cookie(m_url);
|
return page->client().page_did_request_cookie(m_url, source);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::set_cookie(String cookie)
|
void Document::set_cookie(String cookie, Cookie::Source source)
|
||||||
{
|
{
|
||||||
if (auto* page = this->page())
|
if (auto* page = this->page())
|
||||||
page->client().page_did_set_cookie(m_url, cookie);
|
page->client().page_did_set_cookie(m_url, cookie, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include <LibWeb/CSS/CSSStyleSheet.h>
|
#include <LibWeb/CSS/CSSStyleSheet.h>
|
||||||
#include <LibWeb/CSS/StyleResolver.h>
|
#include <LibWeb/CSS/StyleResolver.h>
|
||||||
#include <LibWeb/CSS/StyleSheetList.h>
|
#include <LibWeb/CSS/StyleSheetList.h>
|
||||||
|
#include <LibWeb/Cookie/Cookie.h>
|
||||||
#include <LibWeb/DOM/DOMImplementation.h>
|
#include <LibWeb/DOM/DOMImplementation.h>
|
||||||
#include <LibWeb/DOM/ExceptionOr.h>
|
#include <LibWeb/DOM/ExceptionOr.h>
|
||||||
#include <LibWeb/DOM/NonElementParentNode.h>
|
#include <LibWeb/DOM/NonElementParentNode.h>
|
||||||
|
@ -73,8 +74,8 @@ public:
|
||||||
|
|
||||||
virtual ~Document() override;
|
virtual ~Document() override;
|
||||||
|
|
||||||
String cookie();
|
String cookie(Cookie::Source = Cookie::Source::NonHttp);
|
||||||
void set_cookie(String);
|
void set_cookie(String, Cookie::Source = Cookie::Source::NonHttp);
|
||||||
|
|
||||||
bool should_invalidate_styles_on_attribute_changes() const { return m_should_invalidate_styles_on_attribute_changes; }
|
bool should_invalidate_styles_on_attribute_changes() const { return m_should_invalidate_styles_on_attribute_changes; }
|
||||||
void set_should_invalidate_styles_on_attribute_changes(bool b) { m_should_invalidate_styles_on_attribute_changes = b; }
|
void set_should_invalidate_styles_on_attribute_changes(bool b) { m_should_invalidate_styles_on_attribute_changes = b; }
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
namespace Web::Cookie {
|
namespace Web::Cookie {
|
||||||
struct Cookie;
|
struct Cookie;
|
||||||
struct ParsedCookie;
|
struct ParsedCookie;
|
||||||
|
enum class Source;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
|
@ -433,17 +433,17 @@ String InProcessWebView::page_did_request_prompt(const String& message, const St
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
String InProcessWebView::page_did_request_cookie(const URL& url)
|
String InProcessWebView::page_did_request_cookie(const URL& url, Cookie::Source source)
|
||||||
{
|
{
|
||||||
if (on_get_cookie)
|
if (on_get_cookie)
|
||||||
return on_get_cookie(url);
|
return on_get_cookie(url, source);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void InProcessWebView::page_did_set_cookie(const URL& url, const String& cookie)
|
void InProcessWebView::page_did_set_cookie(const URL& url, const String& cookie, Cookie::Source source)
|
||||||
{
|
{
|
||||||
if (on_set_cookie)
|
if (on_set_cookie)
|
||||||
on_set_cookie(url, cookie);
|
on_set_cookie(url, cookie, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,8 +111,8 @@ private:
|
||||||
virtual void page_did_request_alert(const String&) override;
|
virtual void page_did_request_alert(const String&) override;
|
||||||
virtual bool page_did_request_confirm(const String&) override;
|
virtual bool page_did_request_confirm(const String&) override;
|
||||||
virtual String page_did_request_prompt(const String&, const String&) override;
|
virtual String page_did_request_prompt(const String&, const String&) override;
|
||||||
virtual String page_did_request_cookie(const URL&) override;
|
virtual String page_did_request_cookie(const URL&, Cookie::Source) override;
|
||||||
virtual void page_did_set_cookie(const URL&, const String&) override;
|
virtual void page_did_set_cookie(const URL&, const String&, Cookie::Source) override;
|
||||||
|
|
||||||
void layout_and_sync_size();
|
void layout_and_sync_size();
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ void FrameLoader::resource_did_load()
|
||||||
// FIXME: Support multiple instances of the Set-Cookie response header.
|
// FIXME: Support multiple instances of the Set-Cookie response header.
|
||||||
auto set_cookie = resource()->response_headers().get("Set-Cookie");
|
auto set_cookie = resource()->response_headers().get("Set-Cookie");
|
||||||
if (set_cookie.has_value())
|
if (set_cookie.has_value())
|
||||||
document->set_cookie(set_cookie.value());
|
document->set_cookie(set_cookie.value(), Cookie::Source::Http);
|
||||||
|
|
||||||
if (!url.fragment().is_empty())
|
if (!url.fragment().is_empty())
|
||||||
frame().scroll_to_anchor(url.fragment());
|
frame().scroll_to_anchor(url.fragment());
|
||||||
|
|
|
@ -365,17 +365,17 @@ void OutOfProcessWebView::notify_server_did_change_favicon(const Gfx::Bitmap& fa
|
||||||
on_favicon_change(favicon);
|
on_favicon_change(favicon);
|
||||||
}
|
}
|
||||||
|
|
||||||
String OutOfProcessWebView::notify_server_did_request_cookie(Badge<WebContentClient>, const URL& url)
|
String OutOfProcessWebView::notify_server_did_request_cookie(Badge<WebContentClient>, const URL& url, Cookie::Source source)
|
||||||
{
|
{
|
||||||
if (on_get_cookie)
|
if (on_get_cookie)
|
||||||
return on_get_cookie(url);
|
return on_get_cookie(url, source);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutOfProcessWebView::notify_server_did_set_cookie(Badge<WebContentClient>, const URL& url, const String& cookie)
|
void OutOfProcessWebView::notify_server_did_set_cookie(Badge<WebContentClient>, const URL& url, const String& cookie, Cookie::Source source)
|
||||||
{
|
{
|
||||||
if (on_set_cookie)
|
if (on_set_cookie)
|
||||||
on_set_cookie(url, cookie);
|
on_set_cookie(url, cookie, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutOfProcessWebView::did_scroll()
|
void OutOfProcessWebView::did_scroll()
|
||||||
|
|
|
@ -79,8 +79,8 @@ public:
|
||||||
void notify_server_did_get_source(const URL& url, const String& source);
|
void notify_server_did_get_source(const URL& url, const String& source);
|
||||||
void notify_server_did_js_console_output(const String& method, const String& line);
|
void notify_server_did_js_console_output(const String& method, const String& line);
|
||||||
void notify_server_did_change_favicon(const Gfx::Bitmap& favicon);
|
void notify_server_did_change_favicon(const Gfx::Bitmap& favicon);
|
||||||
String notify_server_did_request_cookie(Badge<WebContentClient>, const URL& url);
|
String notify_server_did_request_cookie(Badge<WebContentClient>, const URL& url, Cookie::Source source);
|
||||||
void notify_server_did_set_cookie(Badge<WebContentClient>, const URL& url, const String& cookie);
|
void notify_server_did_set_cookie(Badge<WebContentClient>, const URL& url, const String& cookie, Cookie::Source source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OutOfProcessWebView();
|
OutOfProcessWebView();
|
||||||
|
|
|
@ -111,8 +111,8 @@ public:
|
||||||
virtual void page_did_request_alert(const String&) { }
|
virtual void page_did_request_alert(const String&) { }
|
||||||
virtual bool page_did_request_confirm(const String&) { return false; }
|
virtual bool page_did_request_confirm(const String&) { return false; }
|
||||||
virtual String page_did_request_prompt(const String&, const String&) { return {}; }
|
virtual String page_did_request_prompt(const String&, const String&) { return {}; }
|
||||||
virtual String page_did_request_cookie(const URL&) { return {}; }
|
virtual String page_did_request_cookie(const URL&, Cookie::Source) { return {}; }
|
||||||
virtual void page_did_set_cookie(const URL&, const String&) { }
|
virtual void page_did_set_cookie(const URL&, const String&, Cookie::Source) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,13 +199,13 @@ void WebContentClient::handle(const Messages::WebContentClient::DidChangeFavicon
|
||||||
|
|
||||||
OwnPtr<Messages::WebContentClient::DidRequestCookieResponse> WebContentClient::handle(const Messages::WebContentClient::DidRequestCookie& message)
|
OwnPtr<Messages::WebContentClient::DidRequestCookieResponse> WebContentClient::handle(const Messages::WebContentClient::DidRequestCookie& message)
|
||||||
{
|
{
|
||||||
auto result = m_view.notify_server_did_request_cookie({}, message.url());
|
auto result = m_view.notify_server_did_request_cookie({}, message.url(), static_cast<Cookie::Source>(message.source()));
|
||||||
return make<Messages::WebContentClient::DidRequestCookieResponse>(result);
|
return make<Messages::WebContentClient::DidRequestCookieResponse>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContentClient::handle(const Messages::WebContentClient::DidSetCookie& message)
|
void WebContentClient::handle(const Messages::WebContentClient::DidSetCookie& message)
|
||||||
{
|
{
|
||||||
m_view.notify_server_did_set_cookie({}, message.url(), message.cookie());
|
m_view.notify_server_did_set_cookie({}, message.url(), message.cookie(), static_cast<Cookie::Source>(message.source()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,8 @@ public:
|
||||||
Function<void(DOM::Document*)> on_set_document;
|
Function<void(DOM::Document*)> on_set_document;
|
||||||
Function<void(const URL&, const String&)> on_get_source;
|
Function<void(const URL&, const String&)> on_get_source;
|
||||||
Function<void(const String& method, const String& line)> on_js_console_output;
|
Function<void(const String& method, const String& line)> on_js_console_output;
|
||||||
Function<String(const URL& url)> on_get_cookie;
|
Function<String(const URL& url, Cookie::Source source)> on_get_cookie;
|
||||||
Function<void(const URL& url, const String& cookie)> on_set_cookie;
|
Function<void(const URL& url, const String& cookie, Cookie::Source source)> on_set_cookie;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,14 +208,14 @@ void PageHost::page_did_request_image_context_menu(const Gfx::IntPoint& content_
|
||||||
m_client.post_message(Messages::WebContentClient::DidRequestImageContextMenu(content_position, url, target, modifiers, bitmap->to_shareable_bitmap()));
|
m_client.post_message(Messages::WebContentClient::DidRequestImageContextMenu(content_position, url, target, modifiers, bitmap->to_shareable_bitmap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String PageHost::page_did_request_cookie(const URL& url)
|
String PageHost::page_did_request_cookie(const URL& url, Web::Cookie::Source source)
|
||||||
{
|
{
|
||||||
return m_client.send_sync<Messages::WebContentClient::DidRequestCookie>(url)->cookie();
|
return m_client.send_sync<Messages::WebContentClient::DidRequestCookie>(url, static_cast<u8>(source))->cookie();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageHost::page_did_set_cookie(const URL& url, const String& cookie)
|
void PageHost::page_did_set_cookie(const URL& url, const String& cookie, Web::Cookie::Source source)
|
||||||
{
|
{
|
||||||
m_client.post_message(Messages::WebContentClient::DidSetCookie(url, cookie));
|
m_client.post_message(Messages::WebContentClient::DidSetCookie(url, cookie, static_cast<u8>(source)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,8 @@ private:
|
||||||
virtual String page_did_request_prompt(const String&, const String&) override;
|
virtual String page_did_request_prompt(const String&, const String&) override;
|
||||||
virtual void page_did_change_favicon(const Gfx::Bitmap&) override;
|
virtual void page_did_change_favicon(const Gfx::Bitmap&) override;
|
||||||
virtual void page_did_request_image_context_menu(const Gfx::IntPoint&, const URL&, const String& target, unsigned modifiers, const Gfx::Bitmap*) override;
|
virtual void page_did_request_image_context_menu(const Gfx::IntPoint&, const URL&, const String& target, unsigned modifiers, const Gfx::Bitmap*) override;
|
||||||
virtual String page_did_request_cookie(const URL&) override;
|
virtual String page_did_request_cookie(const URL&, Web::Cookie::Source) override;
|
||||||
virtual void page_did_set_cookie(const URL&, const String&) override;
|
virtual void page_did_set_cookie(const URL&, const String&, Web::Cookie::Source) override;
|
||||||
|
|
||||||
explicit PageHost(ClientConnection&);
|
explicit PageHost(ClientConnection&);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,6 @@ endpoint WebContentClient = 90
|
||||||
DidGetSource(URL url, String source) =|
|
DidGetSource(URL url, String source) =|
|
||||||
DidJSConsoleOutput(String method, String line) =|
|
DidJSConsoleOutput(String method, String line) =|
|
||||||
DidChangeFavicon(Gfx::ShareableBitmap favicon) =|
|
DidChangeFavicon(Gfx::ShareableBitmap favicon) =|
|
||||||
DidRequestCookie(URL url) => (String cookie)
|
DidRequestCookie(URL url, u8 source) => (String cookie)
|
||||||
DidSetCookie(URL url, String cookie) =|
|
DidSetCookie(URL url, String cookie, u8 source) =|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue