ソースを参照

LibWeb: Store cookies for every HTTP response

As per Fetch, we are supposed to store cookies from Set-Cookie as soon
as we receive response headers for any HTTP response, even in error
cases.

Required by Twitter to login, as it sets cookies via XHR.
Luke Wilde 2 年 前
コミット
6d188d72c0

+ 0 - 24
Userland/Libraries/LibWeb/Loader/FrameLoader.cpp

@@ -12,7 +12,6 @@
 #include <LibGfx/ImageDecoder.h>
 #include <LibMarkdown/Document.h>
 #include <LibWeb/Bindings/MainThreadVM.h>
-#include <LibWeb/Cookie/ParsedCookie.h>
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/ElementFactory.h>
 #include <LibWeb/DOM/Text.h>
@@ -363,33 +362,10 @@ void FrameLoader::load_favicon(RefPtr<Gfx::Bitmap> bitmap)
     }
 }
 
-void FrameLoader::store_response_cookies(AK::URL const& url, DeprecatedString const& cookies)
-{
-    auto* page = browsing_context().page();
-    if (!page)
-        return;
-
-    auto set_cookie_json_value = MUST(JsonValue::from_string(cookies));
-    VERIFY(set_cookie_json_value.type() == JsonValue::Type::Array);
-
-    for (auto const& set_cookie_entry : set_cookie_json_value.as_array().values()) {
-        VERIFY(set_cookie_entry.type() == JsonValue::Type::String);
-
-        auto cookie = Cookie::parse_cookie(set_cookie_entry.as_string());
-        if (!cookie.has_value())
-            continue;
-
-        page->client().page_did_set_cookie(url, cookie.value(), Cookie::Source::Http); // FIXME: Determine cookie source correctly
-    }
-}
-
 void FrameLoader::resource_did_load()
 {
     auto url = resource()->url();
 
-    if (auto set_cookie = resource()->response_headers().get("Set-Cookie"); set_cookie.has_value())
-        store_response_cookies(url, *set_cookie);
-
     // For 3xx (Redirection) responses, the Location value refers to the preferred target resource for automatically redirecting the request.
     auto status_code = resource()->status_code();
     if (status_code.has_value() && *status_code >= 300 && *status_code <= 399) {

+ 0 - 2
Userland/Libraries/LibWeb/Loader/FrameLoader.h

@@ -47,8 +47,6 @@ private:
     void load_favicon(RefPtr<Gfx::Bitmap> bitmap = nullptr);
     bool parse_document(DOM::Document&, ByteBuffer const& data);
 
-    void store_response_cookies(AK::URL const& url, DeprecatedString const& cookies);
-
     HTML::BrowsingContext& m_browsing_context;
     size_t m_redirects_count { 0 };
 };

+ 25 - 1
Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp

@@ -10,6 +10,8 @@
 #include <AK/JsonObject.h>
 #include <LibCore/ElapsedTimer.h>
 #include <LibCore/File.h>
+#include <LibWeb/Cookie/Cookie.h>
+#include <LibWeb/Cookie/ParsedCookie.h>
 #include <LibWeb/Loader/ContentFilter.h>
 #include <LibWeb/Loader/LoadRequest.h>
 #include <LibWeb/Loader/ProxyMappings.h>
@@ -136,6 +138,22 @@ static void emit_signpost(DeprecatedString const& message, int id)
 #endif
 }
 
+static void store_response_cookies(Page& page, AK::URL const& url, DeprecatedString const& cookies)
+{
+    auto set_cookie_json_value = MUST(JsonValue::from_string(cookies));
+    VERIFY(set_cookie_json_value.type() == JsonValue::Type::Array);
+
+    for (auto const& set_cookie_entry : set_cookie_json_value.as_array().values()) {
+        VERIFY(set_cookie_entry.type() == JsonValue::Type::String);
+
+        auto cookie = Cookie::parse_cookie(set_cookie_entry.as_string());
+        if (!cookie.has_value())
+            continue;
+
+        page.client().page_did_set_cookie(url, cookie.value(), Cookie::Source::Http); // FIXME: Determine cookie source correctly
+    }
+}
+
 static size_t resource_id = 0;
 
 void ResourceLoader::load(LoadRequest& request, Function<void(ReadonlyBytes, HashMap<DeprecatedString, DeprecatedString, CaseInsensitiveStringTraits> const& response_headers, Optional<u32> status_code)> success_callback, Function<void(DeprecatedString const&, Optional<u32> status_code)> error_callback, Optional<u32> timeout, Function<void()> timeout_callback)
@@ -295,10 +313,16 @@ void ResourceLoader::load(LoadRequest& request, Function<void(ReadonlyBytes, Has
 
         m_active_requests.set(*protocol_request);
 
-        protocol_request->on_buffered_request_finish = [this, success_callback = move(success_callback), error_callback = move(error_callback), log_success, log_failure, request, &protocol_request = *protocol_request](bool success, auto, auto& response_headers, auto status_code, ReadonlyBytes payload) {
+        protocol_request->on_buffered_request_finish = [this, success_callback = move(success_callback), error_callback = move(error_callback), log_success, log_failure, request, &protocol_request = *protocol_request](bool success, auto, auto& response_headers, auto status_code, ReadonlyBytes payload) mutable {
             --m_pending_loads;
             if (on_load_counter_change)
                 on_load_counter_change();
+
+            if (request.page().has_value()) {
+                if (auto set_cookie = response_headers.get("Set-Cookie"); set_cookie.has_value())
+                    store_response_cookies(request.page().value(), request.url(), *set_cookie);
+            }
+
             if (!success || (status_code.has_value() && *status_code >= 400 && *status_code <= 599)) {
                 StringBuilder error_builder;
                 if (status_code.has_value())