Skip to content

Commit

Permalink
Merge pull request #7154 from brave/ephemeral-cookie-storage-mimimal
Browse files Browse the repository at this point in the history
Add ephemeral storage support for JavaScript cookies
  • Loading branch information
mrobinson committed Dec 11, 2020
2 parents f1ede02 + fe5a8ec commit aca167d
Show file tree
Hide file tree
Showing 26 changed files with 592 additions and 68 deletions.
13 changes: 6 additions & 7 deletions browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ source_set("browser_process") {
# Remove when https://github.com/brave/brave-browser/issues/10657 is resolved
check_includes = false
visibility = [
"//chrome/browser/*",
"//brave/browser/*",
"//brave:browser_dependencies",
"//brave/browser/*",
"//brave/components/brave_ads/test:*",
"//brave/components/brave_rewards/browser:testutil",
"//brave/components/brave_rewards/test:*",
"//brave/components/ipfs/test:*",
"//brave/test:*",
"//chrome/browser/*",
]

sources = [
Expand Down Expand Up @@ -174,8 +174,8 @@ source_set("browser_process") {
"//components/services/patch/content",
"//components/services/unzip/content",
"//components/sessions",
"//components/sync_device_info",
"//components/spellcheck/browser",
"//components/sync_device_info",
"//components/unified_consent",
"//components/update_client:patch_impl",
"//components/update_client:unzip_impl",
Expand All @@ -184,16 +184,15 @@ source_set("browser_process") {
"//extensions/buildflags",
"//services/metrics/public/cpp:metrics_cpp",
"//services/network/public/cpp",
"//third_party/blink/public/common",
"//third_party/blink/public/mojom:mojom_platform_headers",
"//third_party/widevine/cdm:buildflags",
"//ui/base",
]

if (brave_wallet_enabled) {
deps += [
"//brave/components/brave_wallet",
"brave_wallet",
"//brave/components/brave_wallet",
]
}

Expand Down Expand Up @@ -433,10 +432,10 @@ source_set("version_info") {

source_set("browser") {
visibility = [
"//chrome/browser/*",
"//brave/browser/*",
"//brave:browser_dependencies",
"//brave/browser/*",
"//brave/test:*",
"//chrome/browser/*",
]

deps = [ "//chrome/browser" ]
Expand Down
4 changes: 2 additions & 2 deletions browser/brave_tab_helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "brave/components/tor/buildflags/buildflags.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/common/features.h"
#include "net/base/features.h"
#include "third_party/widevine/cdm/buildflags.h"

#if BUILDFLAG(ENABLE_GREASELION)
Expand Down Expand Up @@ -134,7 +134,7 @@ void AttachTabHelpers(content::WebContents* web_contents) {

brave_stats::BraveStatsTabHelper::CreateForWebContents(web_contents);

if (base::FeatureList::IsEnabled(blink::features::kBraveEphemeralStorage)) {
if (base::FeatureList::IsEnabled(net::features::kBraveEphemeralStorage)) {
ephemeral_storage::EphemeralStorageTabHelper::CreateForWebContents(
web_contents);
}
Expand Down
1 change: 1 addition & 0 deletions browser/ephemeral_storage/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ if (!is_android) {
"//chrome/test:test_support_ui",
"//content/public/common",
"//content/test:test_support",
"//net",
"//services/network:test_support",
"//third_party/blink/public/common",
"//url",
Expand Down
69 changes: 67 additions & 2 deletions browser/ephemeral_storage/ephemeral_storage_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/base/features.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "third_party/blink/public/common/features.h"
#include "url/gurl.h"

using content::RenderFrameHost;
Expand Down Expand Up @@ -59,14 +59,24 @@ content::EvalJsResult GetStorageValueInFrame(RenderFrameHost* host,
return content::EvalJs(host, script);
}

void SetCookieInFrame(RenderFrameHost* host, std::string cookie) {
std::string script = base::StringPrintf(
"document.cookie='%s; path=/; SameSite=None; Secure'", cookie.c_str());
ASSERT_TRUE(content::ExecuteScript(host, script));
}

content::EvalJsResult GetCookiesInFrame(RenderFrameHost* host) {
return content::EvalJs(host, "document.cookie");
}

} // namespace

class EphemeralStorageBrowserTest : public InProcessBrowserTest {
public:
EphemeralStorageBrowserTest()
: https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
scoped_feature_list_.InitAndEnableFeature(
blink::features::kBraveEphemeralStorage);
net::features::kBraveEphemeralStorage);
}

void SetUpOnMainThread() override {
Expand Down Expand Up @@ -111,6 +121,7 @@ class EphemeralStorageBrowserTest : public InProcessBrowserTest {
auto set_values_in_frame = [&](RenderFrameHost* frame) {
SetStorageValueInFrame(frame, storage_value, StorageType::Local);
SetStorageValueInFrame(frame, storage_value, StorageType::Session);
SetCookieInFrame(frame, cookie_value);
};

RenderFrameHost* main_frame = web_contents->GetMainFrame();
Expand All @@ -122,12 +133,14 @@ class EphemeralStorageBrowserTest : public InProcessBrowserTest {
struct ValuesFromFrame {
content::EvalJsResult local_storage;
content::EvalJsResult session_storage;
content::EvalJsResult cookies;
};

ValuesFromFrame GetValuesFromFrame(RenderFrameHost* frame) {
return {
GetStorageValueInFrame(frame, StorageType::Local),
GetStorageValueInFrame(frame, StorageType::Session),
GetCookiesInFrame(frame),
};
}

Expand Down Expand Up @@ -192,6 +205,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest, StorageIsPartitioned) {
EXPECT_EQ("a.com", site_a_tab1_values.iframe_1.session_storage);
EXPECT_EQ("a.com", site_a_tab1_values.iframe_2.session_storage);

EXPECT_EQ("from=a.com", site_a_tab1_values.main_frame.cookies);
EXPECT_EQ("from=a.com", site_a_tab1_values.iframe_1.cookies);
EXPECT_EQ("from=a.com", site_a_tab1_values.iframe_2.cookies);

// The second tab is loaded on the same domain, so should see the same
// storage for the third-party iframes.
ValuesFromFrames site_a_tab2_values = GetValuesFromFrames(site_a_tab2);
Expand All @@ -203,6 +220,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest, StorageIsPartitioned) {
EXPECT_EQ(nullptr, site_a_tab2_values.iframe_1.session_storage);
EXPECT_EQ(nullptr, site_a_tab2_values.iframe_2.session_storage);

EXPECT_EQ("from=a.com", site_a_tab2_values.main_frame.cookies);
EXPECT_EQ("from=a.com", site_a_tab2_values.iframe_1.cookies);
EXPECT_EQ("from=a.com", site_a_tab2_values.iframe_2.cookies);

// The storage in the first-party iframes should still reflect the
// original value that was written in the non-ephemeral storage area.
ValuesFromFrames first_party_values = GetValuesFromFrames(first_party_tab);
Expand All @@ -215,6 +236,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest, StorageIsPartitioned) {
EXPECT_EQ("b.com - first party", first_party_values.iframe_1.session_storage);
EXPECT_EQ("b.com - first party", first_party_values.iframe_2.session_storage);

EXPECT_EQ("from=b.com", first_party_values.main_frame.cookies);
EXPECT_EQ("from=b.com", first_party_values.iframe_1.cookies);
EXPECT_EQ("from=b.com", first_party_values.iframe_2.cookies);

// Even though this page loads b.com iframes as third-party iframes, the TLD
// differs, so it should get an entirely different ephemeral storage area.
ValuesFromFrames site_c_tab_values = GetValuesFromFrames(site_c_tab);
Expand All @@ -225,6 +250,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest, StorageIsPartitioned) {
EXPECT_EQ(nullptr, site_c_tab_values.main_frame.session_storage);
EXPECT_EQ(nullptr, site_c_tab_values.iframe_1.session_storage);
EXPECT_EQ(nullptr, site_c_tab_values.iframe_2.session_storage);

EXPECT_EQ("", site_c_tab_values.main_frame.cookies);
EXPECT_EQ("", site_c_tab_values.iframe_1.cookies);
EXPECT_EQ("", site_c_tab_values.iframe_2.cookies);
}

IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
Expand All @@ -245,6 +274,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
EXPECT_EQ("a.com value", values_before.iframe_1.session_storage);
EXPECT_EQ("a.com value", values_before.iframe_2.session_storage);

EXPECT_EQ("from=a.com", values_before.main_frame.cookies);
EXPECT_EQ("from=a.com", values_before.iframe_1.cookies);
EXPECT_EQ("from=a.com", values_before.iframe_2.cookies);

// Navigate away and then navigate back to the original site.
ui_test_utils::NavigateToURL(browser(), b_site_ephemeral_storage_url_);
ui_test_utils::NavigateToURL(browser(), a_site_ephemeral_storage_url_);
Expand All @@ -257,6 +290,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
EXPECT_EQ("a.com value", values_after.main_frame.session_storage);
EXPECT_EQ(nullptr, values_after.iframe_1.session_storage);
EXPECT_EQ(nullptr, values_after.iframe_2.session_storage);

EXPECT_EQ("from=a.com", values_after.main_frame.cookies);
EXPECT_EQ("", values_after.iframe_1.cookies);
EXPECT_EQ("", values_after.iframe_2.cookies);
}

IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
Expand All @@ -277,6 +314,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
EXPECT_EQ("a.com value", values_before.iframe_1.session_storage);
EXPECT_EQ("a.com value", values_before.iframe_2.session_storage);

EXPECT_EQ("from=a.com", values_before.main_frame.cookies);
EXPECT_EQ("from=a.com", values_before.iframe_1.cookies);
EXPECT_EQ("from=a.com", values_before.iframe_2.cookies);

// Close the new tab which we set ephemeral storage value in. This should
// clear the ephemeral storage since this is the last tab which has a.com as
// an eTLD.
Expand All @@ -299,6 +340,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
EXPECT_EQ(nullptr, values_after.main_frame.session_storage);
EXPECT_EQ(nullptr, values_after.iframe_1.session_storage);
EXPECT_EQ(nullptr, values_after.iframe_2.session_storage);

EXPECT_EQ("from=a.com", values_after.main_frame.cookies);
EXPECT_EQ("", values_after.iframe_1.cookies);
EXPECT_EQ("", values_after.iframe_2.cookies);
}

IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
Expand All @@ -319,6 +364,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
EXPECT_EQ("a.com value", values_before.iframe_1.session_storage);
EXPECT_EQ("a.com value", values_before.iframe_2.session_storage);

EXPECT_EQ("from=a.com", values_before.main_frame.cookies);
EXPECT_EQ("from=a.com", values_before.iframe_1.cookies);
EXPECT_EQ("from=a.com", values_before.iframe_2.cookies);

// Reload the page.
ui_test_utils::NavigateToURL(browser(), a_site_ephemeral_storage_url_);

Expand All @@ -330,6 +379,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
EXPECT_EQ("a.com value", values_after.main_frame.session_storage);
EXPECT_EQ("a.com value", values_after.iframe_1.session_storage);
EXPECT_EQ("a.com value", values_after.iframe_2.session_storage);

EXPECT_EQ("from=a.com", values_after.main_frame.cookies);
EXPECT_EQ("from=a.com", values_after.iframe_1.cookies);
EXPECT_EQ("from=a.com", values_after.iframe_2.cookies);
}

IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
Expand All @@ -350,6 +403,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
EXPECT_EQ("a.com value", values_before.iframe_1.session_storage);
EXPECT_EQ("a.com value", values_before.iframe_2.session_storage);

EXPECT_EQ("from=a.com", values_before.main_frame.cookies);
EXPECT_EQ("from=a.com", values_before.iframe_1.cookies);
EXPECT_EQ("from=a.com", values_before.iframe_2.cookies);

// A browser with the same profile should share all values with the
// first browser, including ephemeral storage values.
Browser* same_profile_browser = CreateBrowser(browser()->profile());
Expand All @@ -368,6 +425,10 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
EXPECT_EQ("a.com value", same_profile_values.iframe_1.session_storage);
EXPECT_EQ("a.com value", same_profile_values.iframe_2.session_storage);

EXPECT_EQ("from=a.com", same_profile_values.main_frame.cookies);
EXPECT_EQ("from=a.com", same_profile_values.iframe_1.cookies);
EXPECT_EQ("from=a.com", same_profile_values.iframe_2.cookies);

// A browser with a different profile shouldn't share any values with
// the first set of browsers.
Browser* private_browser = CreateIncognitoBrowser(nullptr);
Expand All @@ -383,4 +444,8 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
EXPECT_EQ(nullptr, private_values.main_frame.session_storage);
EXPECT_EQ(nullptr, private_values.iframe_1.session_storage);
EXPECT_EQ(nullptr, private_values.iframe_2.session_storage);

EXPECT_EQ("", private_values.main_frame.cookies);
EXPECT_EQ("", private_values.iframe_1.cookies);
EXPECT_EQ("", private_values.iframe_2.cookies);
}
33 changes: 14 additions & 19 deletions browser/ephemeral_storage/ephemeral_storage_tab_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@
#include "base/feature_list.h"
#include "base/hash/md5.h"
#include "base/no_destructor.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/session_storage_namespace.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "third_party/blink/public/common/features.h"
#include "net/base/features.h"
#include "net/base/url_util.h"

using content::BrowserContext;
using content::NavigationHandle;
Expand All @@ -28,18 +27,6 @@ namespace ephemeral_storage {

namespace {

std::string URLToStorageDomain(const GURL& url) {
std::string domain = net::registry_controlled_domains::GetDomainAndRegistry(
url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);

// 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();

return domain;
}

// Session storage ids are expected to be 36 character long GUID strings. Since
// we are constructing our own ids, we convert our string into a 32 character
// hash and then use that make up our own GUID-like string. Because of the way
Expand All @@ -54,15 +41,20 @@ std::string StringToSessionStorageId(const std::string& string,

} // namespace

// EphemeralStorageTabHelper helps to manage the lifetime of ephemeral storage.
// For more information about the design of ephemeral storage please see the
// design document at:
// https://github.com/brave/brave-browser/wiki/Ephemeral-Storage-Design
EphemeralStorageTabHelper::EphemeralStorageTabHelper(WebContents* web_contents)
: WebContentsObserver(web_contents) {
DCHECK(base::FeatureList::IsEnabled(blink::features::kBraveEphemeralStorage));
DCHECK(base::FeatureList::IsEnabled(net::features::kBraveEphemeralStorage));

// The URL might not be empty if this is a restored WebContents, for instance.
// In that case we want to make sure it has valid ephemeral storage.
const GURL& url = web_contents->GetLastCommittedURL();
if (!url.is_empty())
CreateEphemeralStorageAreasForDomainAndURL(URLToStorageDomain(url), url);
CreateEphemeralStorageAreasForDomainAndURL(
net::URLToEphemeralStorageDomain(url), url);
}

EphemeralStorageTabHelper::~EphemeralStorageTabHelper() {}
Expand All @@ -75,9 +67,9 @@ void EphemeralStorageTabHelper::ReadyToCommitNavigation(
return;

const GURL& new_url = navigation_handle->GetURL();
std::string new_domain = URLToStorageDomain(new_url);
std::string new_domain = net::URLToEphemeralStorageDomain(new_url);
std::string previous_domain =
URLToStorageDomain(web_contents()->GetLastCommittedURL());
net::URLToEphemeralStorageDomain(web_contents()->GetLastCommittedURL());
if (new_domain == previous_domain)
return;

Expand Down Expand Up @@ -115,6 +107,9 @@ void EphemeralStorageTabHelper::CreateEphemeralStorageAreasForDomainAndURL(
"/ephemeral-session-storage");
session_storage_namespace_ =
content::CreateSessionStorageNamespace(partition, session_partition_id);

tld_ephemeral_lifetime_ = content::TLDEphemeralLifetime::GetOrCreate(
browser_context, partition, new_domain);
}

WEB_CONTENTS_USER_DATA_KEY_IMPL(EphemeralStorageTabHelper)
Expand Down
4 changes: 3 additions & 1 deletion browser/ephemeral_storage/ephemeral_storage_tab_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
#include <string>
#include <utility>

#include "content/public/browser/browser_context.h"
#include "content/public/browser/session_storage_namespace.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"

namespace content {
class WebContents;
class BrowserContext;
class WebContents;
} // namespace content

namespace ephemeral_storage {
Expand Down Expand Up @@ -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::TLDEphemeralLifetime> tld_ephemeral_lifetime_;

WEB_CONTENTS_USER_DATA_KEY_DECL();
};
Expand Down
Loading

0 comments on commit aca167d

Please sign in to comment.