-
Notifications
You must be signed in to change notification settings - Fork 905
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ephemeral storage support for JavaScript cookies #7154
Conversation
7672844
to
6dac143
Compare
#define BRAVE_COOKIE_MONSTER_H \ | ||
std::map<std::string, std::unique_ptr<CookieMonster>> \ | ||
ephemeral_cookie_stores_; \ | ||
CookieMonster* GetOrCreateEphemeralCookieStoreForDomain( \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method doesn't need to be in the header, you can pass in ephemeral_cookie_stores_ to non-class method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method also uses net_log_ from CookieMonster
in order to create the ephemeral monster. Since it's using two instance variables, I think it's simpler for it to be a method. Is there a reason why having fewer methods here is better?
|
||
// Delete session/persistent cookies. | ||
CookieDeletionSessionControl session_control = IGNORE_CONTROL; | ||
+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
never add blank lines or comments to patches
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
// GetDomainAndRegistry might return an empty string if this host is an IP | ||
// address or a file URL. | ||
if (domain.empty()) | ||
domain = url::Origin::Create(url.GetOrigin()).Serialize(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this is the correct behavior. You should create a URL from the domain even if it's empty and in turn Origin will create an opaque origin for those entries
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would mean that all sites that are accessed with IP addresses share the same ephemeral storage. If that the behaviour that we want, I think it makes sense to make that change in a separate PR that also adds tests for that functionality. Since this PR is just about adding support for ephemeral document.cookie
, I'm not sure it belongs here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, opaque origins are unique by design, but I think actually it would cause the opposite problem where the same IP in more than one tab would go into different ephemeral storage domains
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is domain
for a file url with this code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The storage domain for a file URL is "file://" and for a IP address it will be "http://127.0.0.1:8000". This means that all file URLs share the same ephemeral storage lifetime and sites accessed via IP address have lifetimes that follow same-origin conventions.
if (url::Origin::Create(url) == top_frame_origin) | ||
return; | ||
options->ephemeral_storage_domain_ = | ||
net::URLToEphemeralStorageDomain(top_frame_origin.GetURL()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setting the ephemeral storage domain seems to overly complicate things compared to just setting the top level url and figuring out the storage domain inside the CookieMonster
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@@ -80,4 +82,16 @@ bool ParseAuthHostAndPort(base::StringPiece input, | |||
return true; // Success. | |||
} | |||
|
|||
std::string URLToEphemeralStorageDomain(const GURL& url) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this method is needed here https://github.com/brave/brave-core/pull/7154/files#r524857285
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do you suggest this goes in a way that it can be used in the CookieMonster
and also in EphemeralTabStorageHelper
or do you prefer to have two versions of this code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need two versions of the code if we just pass in the url and only convert it to ephemeral storage domain when we actually create it. The code would only ever be called from one file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also called in EphemeralStorageTabHelper
to manage DOM storage. We need to make sure the conversion from URL to storage domain is in sync.
@@ -43,6 +44,7 @@ class EphemeralStorageTabHelper | |||
friend class content::WebContentsUserData<EphemeralStorageTabHelper>; | |||
scoped_refptr<content::SessionStorageNamespace> local_storage_namespace_; | |||
scoped_refptr<content::SessionStorageNamespace> session_storage_namespace_; | |||
scoped_refptr<content::TLDEphemeralStorage> tld_ephemeral_storage_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this a scoped_refptr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reference-counting is used to manage the lifetime of all ephemeral storage. This matches how the lifetime of storage is managed for DOM storage via SessionStorageNamespace
in upstream Chromium and in our ephemeral storage implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I see what's happening now with the weakptr map
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
index 140b61a81dcd748aa22e9dec472f1d375bebcfae..527470acda3863843bca0bcb93e918aa2c35961a 100644 | ||
--- a/net/cookies/cookie_monster.cc | ||
+++ b/net/cookies/cookie_monster.cc | ||
@@ -579,6 +579,7 @@ void CookieMonster::AttachAccessSemanticsListForCookieList( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all of these can be eliminated by subclassing CookieMonster and doing a chromium_src override in content::CreateCookieStore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did consider subclassing CookieMonster
and maybe that does make sense. The issue is that content::CreateCookieStore
is not always used to create the CookieStore
. Crucially, it isn't used for navigation cookies and instead the constructor is called directly. See net/url_request/url_request_context_builder.cc
and in services/network/network_context.cc
(using make_unique
). If we simply override the factory, there is a chance that this will require more work rebasing onto new versions of Chromium.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chatted on slack with @bridiver about this and he clarified that by using chromium_src override, we should be able to create a subclass called CookieMonster
and then use macros to rename the original CookieMonster. I will give this a shot.
->id(); | ||
} | ||
|
||
TLDEphemeralStorage::TLDEphemeralStorage(TLDEphemeralStorageKey key, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does this need to be in content?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is the public interface that EphemeralStorageTabHelper
uses to access private API in content. Is there a better place for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what private api?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the only private apis I see are accessed outside of this class and we're now adding two new patches for this. It would be better I think to just keep it all included in the browser_context override. Also brave/content should never have been created in the first place and the files that are already in there are misplaced
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you created a separate file for tld_ephemeral_storage.cc/.h and included it from browser_context.cc you would put it in chromium_src because if brave/content was a valid location to put files, it would be confusing that these files were not part of brave/content/BUILD.gn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are three interfaces into private API here CreateSessionStorageNamespace and GetSessionStorageNamespaceId, which used to be in BrowserContext
(still part of content). The final piece is TLDEphemeralStorage
which talks to the CookieStore
in order to manage ephemeral cookie lifetime. The idea is that eventually CreateSessionStorageNamespace and GetSessionStorageNamespaceId would become part of TLDEphemeralStorage
.
06421fe
to
1859783
Compare
@bridiver Okay. I've pushed a new commit, which I believe addresses your concerns. PTAL. |
CookieSameSiteContext same_site_cookie_context; | ||
bool update_access_time = true; | ||
bool return_excluded_cookies = false; | ||
+ url.mojom.Url top_frame_url_for_ephemeral_storage; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I don't think we need to specify that this is for ephemeral storage here
@@ -23,7 +23,7 @@ | |||
#include "brave/components/speedreader/buildflags.h" | |||
#include "brave/components/tor/buildflags/buildflags.h" | |||
#include "content/public/browser/web_contents.h" | |||
#include "third_party/blink/public/common/features.h" | |||
#include "net/base/features.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like you need to add //net
Okay. I've pushed a new version of the branch which I believe addresses the review comments above. Thanks! |
1ffa6de
to
71d01f4
Compare
: key_(key), storage_partition_(storage_partition) { | ||
DCHECK(active_tld_storage_areas().find(key) == | ||
active_tld_storage_areas().end()); | ||
active_tld_storage_areas().emplace(key, weak_factory_.GetWeakPtr()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite follow why do we need a weak pointer instead of a raw one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case the weak pointer is just a sanity check which catches errors where the TLDEphemeralStorage is dereferenced and deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which checks do you have in mind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.get()
on the weak pointer will return nullptr instead of a garbage value, but I will also add a DCHECK to also produce an assertion failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using WeakPtr
in this way sounds unusual to me, but probably fine - could you write a comment describing this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I'll leave a comment.
|
||
#include <map> | ||
#include "base/no_destructor.h" | ||
#include "content/browser/dom_storage/dom_storage_context_wrapper.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are many unused headers, probably if we drop them we could move the whole class outside of chromium_src
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will definitely remove the unused headers, but the idea is that eventually the private API exposed in browser_context.h can move into this class and it can eventually handle keeping track of all TLD-associated ephemeral DOM storage as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree if this refactoring is a short-term plan. Otherwise it most probably will stuck forever :)
#ifndef BRAVE_CHROMIUM_SRC_NET_COOKIES_COOKIE_MONSTER_H_ | ||
#define BRAVE_CHROMIUM_SRC_NET_COOKIES_COOKIE_MONSTER_H_ | ||
|
||
#define CookieMonster SimpleCookieMonster |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ChromiumCookieMonster
?
|
||
#include "net/cookies/cookie_monster.h" | ||
|
||
#include <iostream> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not needed?
CookieMonster::GetOrCreateEphemeralCookieStoreForTopFrameURL( | ||
const GURL& top_frame_url) { | ||
std::string domain = URLToEphemeralStorageDomain(top_frame_url); | ||
auto it = ephemeral_cookie_stores_.find(domain); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for this check, emplace
will do the trick on its own
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this result in creating another instantiation of ChromiumCookieMonster
every time we call this method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it seems we should leave it alone
// | ||
// TODO(mrobinson): Have this class also manage ephemeral local storage and | ||
// take care of handing out new instances of session storage. | ||
class CONTENT_EXPORT TLDEphemeralStorage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about future plans for this class, but for now it doesn't look like a "storage", rather something like TLDEphemeralLifetime
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't changed this yet, because perhaps it doesn't make sense to rename this class and then rename it back in a followup change. I'm happy to keep discussing it though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But even with encapsulated DOMStorage - would it still be "storage"? For now we basically only keep namespaces and manage their lifetime in the tab helper, instead of "storing" something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I will change the name.
Assuming that the patching work is negotiated with @bridiver and most probably cannot be done any better, the whole thing looks good. I'll try to give it test, but for now it fails to build on top of master |
(I also assume that commit messages will be updated before merging) |
71d01f4
to
7f6d63a
Compare
I've pushed a rebased version of this PR and as well a commit addressing review comments. |
6297fbe
to
42c7c76
Compare
I've pushed a commit which I believe addresses the remaining review comments. |
1385d1f
to
be5b657
Compare
It seems that the Windows build has an issue with patches to mojom trait headers. I've taken a different tactic, which is to extend the |
50a27ab
to
7121219
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pls mention a link to the wiki explainer somewhere in the code (e.g. ephemeral_storage_tab_helper.h and/or ephemeral_storage_lifetime.h)
7121219
to
5abef69
Compare
e7b0404
to
fa71ccb
Compare
@@ -6,11 +6,14 @@ | |||
#ifndef BRAVE_CHROMIUM_SRC_CONTENT_PUBLIC_BROWSER_BROWSER_CONTEXT_H_ | |||
#define BRAVE_CHROMIUM_SRC_CONTENT_PUBLIC_BROWSER_BROWSER_CONTEXT_H_ | |||
|
|||
#define IsOffTheRecord IsTor() const; \ | |||
virtual bool IsOffTheRecord | |||
#define IsOffTheRecord \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is this change? Doesn't seem related and also should have 4 space indent for continuation of a line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There have been changes to the lint script which mean that the CI fails unless you do a full format. This will possibly be resolved when #7402 lands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the meantime, I can remove these full format changes.
* License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
* You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
#include "brave/chromium_src/content/public/browser/tld_ephemeral_lifetime.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not use brave/chromium_src in the include path
namespace content { | ||
bool BrowserContext::IsTor() const { | ||
return false; | ||
} | ||
} // namespace content | ||
|
||
#include "../../../../content/browser/browser_context.cc" | ||
#include "brave/chromium_src/content/browser/tld_ephemeral_lifetime.cc" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not use brave/chromium_src in the include path
#include "../../../../../content/public/browser/browser_context.h" | ||
#undef IsOffTheRecord | ||
|
||
#include "brave/chromium_src/content/public/browser/tld_ephemeral_lifetime.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't use brave/chromium_src in the include path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approved pending the few small fixes
This change adds a new class EphemeralStoragePartition which provides access to an ephemeral version of a RestrictedCookieManager for the content process. In an upcoming change this will also provide a StoragePartition for navigation requests in third-party frames in order to add support for navigation cookies.
4fa55ef
to
fe5a8ec
Compare
There are three failures in CI:
Given this, I feel fairly confident about merging this change despite the CI failures. |
This change adds a new class EphemeralStoragePartition which provides
access to an ephemeral version of a RestrictedCookieManager for the
content process. In an upcoming change this will also provide a
StoragePartition for navigation requests in third-party frames in order
to add support for navigation cookies.
Resolves brave/brave-browser#12591
Submitter Checklist:
npm run lint
,npm run gn_check
)git rebase master
(if needed).git rebase -i
to squash commits (if needed).QA/Yes
orQA/No
) to the associated issuerelease-notes/include
orrelease-notes/exclude
) to the associated issueReviewer Checklist:
After-merge Checklist:
changes has landed on.