From a0fcd1ca4bedbea30e1a969b7ed2513d269cfdc6 Mon Sep 17 00:00:00 2001 From: cdesouza-chromium Date: Wed, 13 Nov 2024 22:31:47 +0000 Subject: [PATCH] [unsafe-buffers] Improve ephemeral storage browser tests (#26529) This change removes all uses of unsafe buffers in ephemeral storage browser tests. It also cherry picks the recently introduced `base::zip` into brave. Resolves https://github.com/brave/brave-browser/issues/42269 Resolves https://github.com/brave/brave-browser/issues/42271 --- .../ephemeral_storage_qa_browsertest.cc | 429 ++++++++++-------- chromium_src/base/types/zip.h | 136 ++++++ chromium_src/check_chromium_src_config.json5 | 1 + .../ephemeral_storage_service.h | 4 +- 4 files changed, 387 insertions(+), 183 deletions(-) create mode 100644 chromium_src/base/types/zip.h diff --git a/browser/ephemeral_storage/ephemeral_storage_qa_browsertest.cc b/browser/ephemeral_storage/ephemeral_storage_qa_browsertest.cc index 5543fbc6200..c65344a8f3c 100644 --- a/browser/ephemeral_storage/ephemeral_storage_qa_browsertest.cc +++ b/browser/ephemeral_storage/ephemeral_storage_qa_browsertest.cc @@ -3,15 +3,14 @@ * 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/. */ -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(https://github.com/brave/brave-browser/issues/41661): Remove this and -// convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif +#include +#include "base/containers/span.h" #include "base/feature_list.h" #include "base/memory/raw_ptr.h" #include "base/path_service.h" +#include "base/types/cxx23_to_underlying.h" +#include "base/types/zip.h" #include "brave/browser/ephemeral_storage/ephemeral_storage_service_factory.h" #include "brave/components/brave_shields/content/browser/brave_shields_util.h" #include "brave/components/constants/brave_paths.h" @@ -82,38 +81,23 @@ class TabActivationWaiter : public TabStripModelObserver { int number_of_unconsumed_active_tab_changes_ = 0; }; -} // namespace - constexpr char kEphemeralStorageTestPage[] = "/storage/ephemeral-storage.html"; -typedef enum StorageResult { - kSuccess, - kEmpty, - kBlocked, - kNA, -} StorageResult; +enum class StorageResult { + kSuccess = 0, + kEmpty = 1, + kBlocked = 2, + kNA = 6, +}; -// Converts a StorageResult to its corresponding JS `testOutcomeEnum ` -// representation. -int AsNumber(StorageResult r) { - switch (r) { - case StorageResult::kSuccess: - return 0; - case StorageResult::kEmpty: - return 1; - case StorageResult::kBlocked: - return 2; - case StorageResult::kNA: - return 6; - } -} +using ResultSet = std::array; -typedef enum class StorageType { +enum class StorageType { kCookies, kLocalStorage, kSessionStorage, kIndexDB, -} StorageType; +}; // Converts a StorageType to its corresponding representation in the report // from the page's JS code. @@ -130,6 +114,8 @@ std::string AsString(StorageType t) { } } +} // namespace + // This test suite recreates the behavior of the ephemeral storage tests // available on Brave's QA test pages, whose source is located at // https://github.com/brave-experiments/qa-test-pages @@ -149,9 +135,10 @@ std::string AsString(StorageType t) { // - local frame // - remote frame // - nested frame -class EphemeralStorageTest : public InProcessBrowserTest { +class EphemeralStorageQaBrowserTest : public InProcessBrowserTest { public: - EphemeralStorageTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { + EphemeralStorageQaBrowserTest() + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { std::vector disabled_features; feature_list_.InitWithFeatures({net::features::kBraveEphemeralStorage}, disabled_features); @@ -193,7 +180,7 @@ class EphemeralStorageTest : public InProcessBrowserTest { void SetThirdPartyCookiePref(bool setting) { browser()->profile()->GetPrefs()->SetInteger( prefs::kCookieControlsMode, - static_cast( + base::to_underlying( setting ? content_settings::CookieControlsMode::kBlockThirdParty : content_settings::CookieControlsMode::kOff)); } @@ -267,40 +254,40 @@ class EphemeralStorageTest : public InProcessBrowserTest { // Checks that the test page's generated storage report matches the expected // values void CheckStorageResults(content::WebContents* contents, - const StorageResult expected[4][4]) { - CheckStorageResults(contents, StorageType::kCookies, expected[0]); - CheckStorageResults(contents, StorageType::kLocalStorage, expected[1]); - CheckStorageResults(contents, StorageType::kSessionStorage, expected[2]); - CheckStorageResults(contents, StorageType::kIndexDB, expected[3]); + base::span expected) { + static constexpr auto kStringTypes = + std::to_array({StorageType::kCookies, StorageType::kLocalStorage, + StorageType::kSessionStorage, StorageType::kIndexDB}); + + for (auto [type, results] : base::zip(kStringTypes, expected)) { + CheckStorageResults(contents, type, results); + } } // Checks a particular row of the 2D storage results matrix, corresponding to // a single storage type void CheckStorageResults(content::WebContents* contents, StorageType storage_type, - const StorageResult expected[4]) { + const ResultSet& expected) { SCOPED_TRACE(::testing::Message() - << "StorageType: " << static_cast(storage_type)); - EXPECT_EQ(AsNumber(expected[0]), - EvalJs(contents, - "window.generateStorageReport().then(report => report['" + - AsString(storage_type) + "']['this-frame'])")); - EXPECT_EQ(AsNumber(expected[1]), - EvalJs(contents, - "window.generateStorageReport().then(report => report['" + - AsString(storage_type) + "']['local-frame'])")); - EXPECT_EQ(AsNumber(expected[2]), - EvalJs(contents, - "window.generateStorageReport().then(report => report['" + - AsString(storage_type) + "']['remote-frame'])")); - EXPECT_EQ(AsNumber(expected[3]), - EvalJs(contents, - "window.generateStorageReport().then(report => report['" + - AsString(storage_type) + "']['nested-frame'])")); + << "StorageType: " << base::to_underlying(storage_type)); + + // The frames we want to test against and in the expected order. + static constexpr auto kFrames = std::to_array( + {"this-frame", "local-frame", "remote-frame", "nested-frame"}); + + for (auto [result, frame] : base::zip(expected, kFrames)) { + EXPECT_EQ( + base::to_underlying(result), + content::EvalJs(contents, content::JsReplace( + "window.generateStorageReport().then(" + "report => report[$1][$2])", + AsString(storage_type), frame))); + } } // Tests storage stored and then loaded within a single page session. - void TestInitialCase(const StorageResult expected[4][4]) { + void TestInitialCase(base::span expected) { ASSERT_TRUE(original_tab_); CheckStorageResults(original_tab_, expected); @@ -308,7 +295,7 @@ class EphemeralStorageTest : public InProcessBrowserTest { // Tests storage stored from one page and then loaded from a remote page in // the same browsing session. - void TestRemotePageSameSession(const StorageResult expected[4][4]) { + void TestRemotePageSameSession(base::span expected) { ASSERT_TRUE(original_tab_); ASSERT_EQ(1, tabs_->count()); @@ -325,7 +312,7 @@ class EphemeralStorageTest : public InProcessBrowserTest { // Tests storage stored from one page and then loaded from a remote page in a // new browsing session. - void TestRemotePageNewSession(const StorageResult expected[4][4]) { + void TestRemotePageNewSession(base::span expected) { ASSERT_TRUE(original_tab_); ASSERT_EQ(1, tabs_->count()); @@ -334,8 +321,9 @@ class EphemeralStorageTest : public InProcessBrowserTest { ASSERT_EQ(1, tabs_->active_index()); std::string target = - EvalJs(original_tab_.get(), - "document.getElementById('continue-test-url-step-3').value") + content::EvalJs( + original_tab_.get(), + "document.getElementById('continue-test-url-step-3').value") .ExtractString(); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(target))); @@ -348,7 +336,7 @@ class EphemeralStorageTest : public InProcessBrowserTest { // Tests storage stored from one page and then loaded from the same page in a // new tab from the same browsing session. - void TestThisPageSameSession(const StorageResult expected[4][4]) { + void TestThisPageSameSession(base::span expected) { ASSERT_TRUE(original_tab_); ASSERT_EQ(1, tabs_->count()); @@ -365,7 +353,7 @@ class EphemeralStorageTest : public InProcessBrowserTest { // Tests storage stored from one page and then loaded from the same page in a // new tab from a different browsing session. - void TestThisPageDifferentSession(const StorageResult expected[4][4]) { + void TestThisPageDifferentSession(base::span expected) { ASSERT_TRUE(original_tab_); ASSERT_EQ(1, tabs_->count()); @@ -374,8 +362,9 @@ class EphemeralStorageTest : public InProcessBrowserTest { ASSERT_EQ(1, tabs_->active_index()); std::string target = - EvalJs(original_tab_.get(), - "document.getElementById('continue-test-url-step-5').value") + content::EvalJs( + original_tab_.get(), + "document.getElementById('continue-test-url-step-5').value") .ExtractString(); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(target))); @@ -388,7 +377,7 @@ class EphemeralStorageTest : public InProcessBrowserTest { // Tests storage stored from one page and then loaded from the same page // after having reset the browsing session. - void TestNewPageResetSession(const StorageResult expected[4][4]) { + void TestNewPageResetSession(base::span expected) { ASSERT_TRUE(original_tab_); ASSERT_EQ(1, tabs_->count()); @@ -397,8 +386,9 @@ class EphemeralStorageTest : public InProcessBrowserTest { ASSERT_EQ(1, tabs_->active_index()); std::string target = - EvalJs(original_tab_.get(), - "document.getElementById('continue-test-url-step-6').value") + content::EvalJs( + original_tab_.get(), + "document.getElementById('continue-test-url-step-6').value") .ExtractString(); const int previous_tab_count = browser()->tab_strip_model()->count(); @@ -440,286 +430,359 @@ class EphemeralStorageTest : public InProcessBrowserTest { raw_ptr tabs_ = nullptr; }; -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, CrossSiteCookiesBlockedInitial) { +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, + CrossSiteCookiesBlockedInitial) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(true); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kSuccess}, - {kSuccess, kSuccess, kSuccess, kEmpty}, - {kSuccess, kSuccess, kSuccess, kEmpty}, - {kSuccess, kSuccess, kSuccess, kEmpty}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kSuccess}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kEmpty}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kEmpty}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kEmpty}, }; TestInitialCase(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CrossSiteCookiesBlockedRemotePageSameSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(true); SetupTestPage(); - const StorageResult expected[4][4] = { - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, + const ResultSet expected[4] = { + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, }; TestRemotePageSameSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CrossSiteCookiesBlockedRemotePageNewSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(true); SetupTestPage(); - const StorageResult expected[4][4] = { - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, + const ResultSet expected[4] = { + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, }; TestRemotePageNewSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CrossSiteCookiesBlockedThisPageSameSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(true); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, }; TestThisPageSameSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CrossSiteCookiesBlockedThisPageDifferentSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(true); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, }; TestThisPageDifferentSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CrossSiteCookiesBlockedNewPageResetSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(true); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kEmpty, kNA}, - {kSuccess, kSuccess, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kSuccess, kSuccess, kEmpty, kNA}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, StorageResult::kEmpty, + StorageResult::kNA}, }; TestNewPageResetSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, CookiesBlockedInitial) { +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesBlockedInitial) { SetCookiePref(CONTENT_SETTING_BLOCK); SetupTestPage(); - const StorageResult expected[4][4] = { - {kBlocked, kBlocked, kBlocked, kBlocked}, - {kBlocked, kBlocked, kBlocked, kBlocked}, - {kBlocked, kBlocked, kBlocked, kBlocked}, - {kBlocked, kBlocked, kBlocked, kBlocked}, + const ResultSet expected[4] = { + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kBlocked}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kBlocked}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kBlocked}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kBlocked}, }; TestInitialCase(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesBlockedRemotePageSameSession) { SetCookiePref(CONTENT_SETTING_BLOCK); SetupTestPage(); - const StorageResult expected[4][4] = { - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, + const ResultSet expected[4] = { + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, }; TestRemotePageSameSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesBlockedRemotePageNewSession) { SetCookiePref(CONTENT_SETTING_BLOCK); SetupTestPage(); - const StorageResult expected[4][4] = { - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, + const ResultSet expected[4] = { + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, }; TestRemotePageNewSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesBlockedThisPageSameSession) { SetCookiePref(CONTENT_SETTING_BLOCK); SetupTestPage(); - const StorageResult expected[4][4] = { - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, + const ResultSet expected[4] = { + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, }; TestThisPageSameSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesBlockedThisPageDifferentSession) { SetCookiePref(CONTENT_SETTING_BLOCK); SetupTestPage(); - const StorageResult expected[4][4] = { - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, + const ResultSet expected[4] = { + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, }; TestThisPageDifferentSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesBlockedNewPageResetSession) { SetCookiePref(CONTENT_SETTING_BLOCK); SetupTestPage(); - const StorageResult expected[4][4] = { - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, - {kBlocked, kBlocked, kBlocked, kNA}, + const ResultSet expected[4] = { + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, + {StorageResult::kBlocked, StorageResult::kBlocked, + StorageResult::kBlocked, StorageResult::kNA}, }; TestNewPageResetSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, CookiesAllowedInitial) { +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesAllowedInitial) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(false); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kSuccess}, - {kSuccess, kSuccess, kSuccess, kEmpty}, - {kSuccess, kSuccess, kSuccess, kEmpty}, - {kSuccess, kSuccess, kSuccess, kEmpty}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kSuccess}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kEmpty}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kEmpty}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kEmpty}, }; TestInitialCase(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesAllowedRemotePageSameSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(false); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, }; TestRemotePageSameSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesAllowedRemotePageNewSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(false); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, }; TestRemotePageNewSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesAllowedThisPageSameSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(false); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, }; TestThisPageSameSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesAllowedThisPageDifferentSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(false); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, }; TestThisPageDifferentSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesAllowedNewPageResetSession) { SetCookiePref(CONTENT_SETTING_ALLOW); SetThirdPartyCookiePref(false); SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, }; TestNewPageResetSession(expected); } -IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, +IN_PROC_BROWSER_TEST_F(EphemeralStorageQaBrowserTest, CookiesAllowedNewPageResetSessionSetPerDomain) { // Set the cookie control type to allow for the test page's domain (not // browser-wide!). @@ -727,11 +790,15 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageTest, SetupTestPage(); - const StorageResult expected[4][4] = { - {kSuccess, kSuccess, kSuccess, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, - {kEmpty, kEmpty, kEmpty, kNA}, - {kSuccess, kSuccess, kSuccess, kNA}, + const ResultSet expected[4] = { + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, + {StorageResult::kEmpty, StorageResult::kEmpty, StorageResult::kEmpty, + StorageResult::kNA}, + {StorageResult::kSuccess, StorageResult::kSuccess, + StorageResult::kSuccess, StorageResult::kNA}, }; TestNewPageResetSession(expected); } diff --git a/chromium_src/base/types/zip.h b/chromium_src/base/types/zip.h new file mode 100644 index 00000000000..6cce72b8597 --- /dev/null +++ b/chromium_src/base/types/zip.h @@ -0,0 +1,136 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BRAVE_CHROMIUM_SRC_BASE_TYPES_ZIP_H_ +#define BRAVE_CHROMIUM_SRC_BASE_TYPES_ZIP_H_ + +#include +#include +#include +#include + +#include "base/check.h" +#include "base/compiler_specific.h" + +namespace base { + +namespace internal { + +template +class Zipper { + public: + constexpr explicit Zipper(Ranges&... ranges LIFETIME_BOUND) noexcept + : ranges_(ranges...) {} + + // A sentinel used by the iterator to constrain the comparison to make sure it + // has the proper end of each range. + struct ZipEnd {}; + + class iterator { + public: + using value_type = std::tuple< + std::remove_cv_t()))>...>; + using reference = value_type; + using element_type = value_type; + using difference_type = std::ptrdiff_t; + using pointer = void; + // TODO(https://crbug.com/377940847): This could be improved going forward + // to select a better iterator category, based on the common denominator of + // the union of iterators, for instance output iterators, etc. + using iterator_category = std::input_iterator_tag; + using iterator_concept = std::input_iterator_tag; + + constexpr iterator& operator++() noexcept LIFETIME_BOUND { + advance(std::index_sequence_for{}); + return *this; + } + + constexpr auto operator*() const noexcept LIFETIME_BOUND { + return deref(std::index_sequence_for{}); + } + + // Determines if the iterator has reached the end, so a for-range loop bails + // out. + constexpr bool operator!=(ZipEnd) const noexcept LIFETIME_BOUND { + return has_more(std::index_sequence_for{}); + } + + private: + friend class Zipper; + + constexpr explicit iterator( + std::tuple()))...> begin + LIFETIME_BOUND, + std::tuple()))...> end + LIFETIME_BOUND) noexcept + : begin_(begin), end_(end) {} + + // Checks if any range has reached the end. + template + constexpr bool has_more(std::index_sequence) const { + return (... && (std::get(begin_) != std::get(end_))); + } + + template + constexpr void advance(std::index_sequence) LIFETIME_BOUND { + CHECK(operator!=(ZipEnd())); + // SAFETY: The increment is safe as it has been just CHECKed so it is + // guaranteed to be inside [begin_, end_). + UNSAFE_BUFFERS((++std::get(begin_), ...)); + } + + template + constexpr value_type deref(std::index_sequence) const + LIFETIME_BOUND { + return {*std::get(begin_)...}; + } + + std::tuple()))...> begin_; + std::tuple()))...> end_; + }; + + constexpr iterator begin() noexcept LIFETIME_BOUND { + return begin_impl(std::index_sequence_for{}); + } + + constexpr ZipEnd end() noexcept { return ZipEnd(); } + + private: + template + constexpr iterator begin_impl(std::index_sequence) LIFETIME_BOUND { + return iterator(std::make_tuple(std::begin(std::get(ranges_))...), + std::make_tuple(std::end(std::get(ranges_))...)); + } + + std::tuple ranges_; +}; + +} // namespace internal + +// Zipping utility that allows iterating over multiple ranges in lockstep. +// +// Example: +// +// std::vector a = {1, 2, 3}; +// std::vector b = {4.5, 5.5, 6.5}; +// std::vector c = {"x", "y", "z"}; +// for (auto [x, y, z] : zip(a, b, c)) { +// LOG(INFO) << x << " " << y << " " << z; +// } +// +// Zipping will carry on until one of the ranges run out, at which the loop will +// bail. +template +constexpr internal::Zipper zip(Ranges&... ranges LIFETIME_BOUND) { + return internal::Zipper(ranges...); +} + +} // namespace base + +#endif // BRAVE_CHROMIUM_SRC_BASE_TYPES_ZIP_H_ diff --git a/chromium_src/check_chromium_src_config.json5 b/chromium_src/check_chromium_src_config.json5 index df895fcc788..ce0006e1dc7 100644 --- a/chromium_src/check_chromium_src_config.json5 +++ b/chromium_src/check_chromium_src_config.json5 @@ -17,6 +17,7 @@ // Please, keep in alphabetical order. "path_excludes": [ "base/feature_override.h", + "base/types/zip.h", "check_chromium_src_config.json5", "chrome/browser/devtools/url_constants_unittest.cc", "chrome/browser/history/history_utils_unittest.cc", diff --git a/components/ephemeral_storage/ephemeral_storage_service.h b/components/ephemeral_storage/ephemeral_storage_service.h index cd51f83c69a..55293068b81 100644 --- a/components/ephemeral_storage/ephemeral_storage_service.h +++ b/components/ephemeral_storage/ephemeral_storage_service.h @@ -29,7 +29,7 @@ #include "url/origin.h" class EphemeralStorageBrowserTest; -class EphemeralStorageTest; +class EphemeralStorageQaBrowserTest; class HostContentSettingsMap; class PrefService; @@ -84,7 +84,7 @@ class EphemeralStorageService : public KeyedService { private: friend EphemeralStorageBrowserTest; - friend EphemeralStorageTest; + friend EphemeralStorageQaBrowserTest; friend permissions::PermissionLifetimeManagerBrowserTest; void FirstPartyStorageAreaInUse(const std::string& ephemeral_domain);