diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp index 973b9cdd8dd0..e981df36ae75 100644 --- a/dom/html/nsHTMLDocument.cpp +++ b/dom/html/nsHTMLDocument.cpp @@ -1225,6 +1225,32 @@ nsHTMLDocument::GetCookie(nsAString& aCookie) return rv.ErrorCode(); } +already_AddRefed +nsHTMLDocument::CreateDummyChannelForCookies(nsIURI* aCodebaseURI) +{ + // The cookie service reads the privacy status of the channel we pass to it in + // order to determine which cookie database to query. In some cases we don't + // have a proper channel to hand it to the cookie service though. This + // function creates a dummy channel that is not used to load anything, for the + // sole purpose of handing it to the cookie service. DO NOT USE THIS CHANNEL + // FOR ANY OTHER PURPOSE. + MOZ_ASSERT(!mChannel); + + nsCOMPtr channel; + NS_NewChannel(getter_AddRefs(channel), aCodebaseURI, this, + nsILoadInfo::SEC_NORMAL, + nsIContentPolicy::TYPE_INVALID); + nsCOMPtr pbChannel = + do_QueryInterface(channel); + nsCOMPtr docShell(mDocumentContainer); + nsCOMPtr loadContext = do_QueryInterface(docShell); + if (!pbChannel || !loadContext) { + return nullptr; + } + pbChannel->SetPrivate(loadContext->UsePrivateBrowsing()); + return channel.forget(); +} + void nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv) { @@ -1257,8 +1283,16 @@ nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv) return; } + nsCOMPtr channel(mChannel); + if (!channel) { + channel = CreateDummyChannelForCookies(codebaseURI); + if (!channel) { + return; + } + } + nsXPIDLCString cookie; - service->GetCookieString(codebaseURI, mChannel, getter_Copies(cookie)); + service->GetCookieString(codebaseURI, channel, getter_Copies(cookie)); // CopyUTF8toUTF16 doesn't handle error // because it assumes that the input is valid. nsContentUtils::ConvertStringFromEncoding(NS_LITERAL_CSTRING("UTF-8"), @@ -1302,8 +1336,16 @@ nsHTMLDocument::SetCookie(const nsAString& aCookie, ErrorResult& rv) return; } + nsCOMPtr channel(mChannel); + if (!channel) { + channel = CreateDummyChannelForCookies(codebaseURI); + if (!channel) { + return; + } + } + NS_ConvertUTF16toUTF8 cookie(aCookie); - service->SetCookieString(codebaseURI, nullptr, cookie.get(), mChannel); + service->SetCookieString(codebaseURI, nullptr, cookie.get(), channel); } } diff --git a/dom/html/nsHTMLDocument.h b/dom/html/nsHTMLDocument.h index 0812dc41e703..170563a699bd 100644 --- a/dom/html/nsHTMLDocument.h +++ b/dom/html/nsHTMLDocument.h @@ -275,6 +275,9 @@ protected: nsresult CreateAndAddWyciwygChannel(void); nsresult RemoveWyciwygChannel(void); + // This should *ONLY* be used in GetCookie/SetCookie. + already_AddRefed CreateDummyChannelForCookies(nsIURI* aCodebaseURI); + /** * Like IsEditingOn(), but will flush as needed first. */