diff options
author | Cronet Mainline Eng <cronet-mainline-eng+copybara@google.com> | 2024-01-24 19:13:11 +0000 |
---|---|---|
committer | Chidera Olibie <colibie@google.com> | 2024-01-24 19:19:32 +0000 |
commit | abce8a39488511c10b95ac52d1a3fdd2e886da83 (patch) | |
tree | 163cb3522692e4ac343079f490b3c29c97da116e /net/extras | |
parent | d14faf319d3e431654f149930db41f3e0adf2d15 (diff) | |
download | cronet-abce8a39488511c10b95ac52d1a3fdd2e886da83.tar.gz |
Import Cronet version 121.0.6167.71
FolderOrigin-RevId: /tmp/copybara-origin/src
Change-Id: Ieee3d31a0e9c404daa9a1630919e62b52ce61d1b
Diffstat (limited to 'net/extras')
7 files changed, 653 insertions, 236 deletions
diff --git a/net/extras/sqlite/cookie_crypto_delegate.h b/net/extras/sqlite/cookie_crypto_delegate.h index 2e9fc8ed6..66581dbae 100644 --- a/net/extras/sqlite/cookie_crypto_delegate.h +++ b/net/extras/sqlite/cookie_crypto_delegate.h @@ -5,7 +5,10 @@ #ifndef NET_EXTRAS_SQLITE_COOKIE_CRYPTO_DELEGATE_H_ #define NET_EXTRAS_SQLITE_COOKIE_CRYPTO_DELEGATE_H_ +#include <string> + #include "base/component_export.h" +#include "base/functional/callback.h" namespace net { @@ -14,13 +17,21 @@ class COMPONENT_EXPORT(NET_EXTRAS) CookieCryptoDelegate { public: virtual ~CookieCryptoDelegate() = default; - // Encrypt |plaintext| string and store the result in |ciphertext|. This - // method is always functional even if ShouldEncrypt() is false. + // Called to initialize the delegate. `EncryptString` and `DecryptString` may + // only be called once the `callback` has executed. `callback` executes on the + // same sequence as the call to `Init` either synchronously or asynchronously. + // Note: `Init` may be called multiple times and implementers should handle + // that appropriately by servicing every callback either synchronously or + // asynchronously. + virtual void Init(base::OnceClosure callback) = 0; + + // Encrypt `plaintext` string and store the result in `ciphertext`. Returns + // true if the encryption succeeded. virtual bool EncryptString(const std::string& plaintext, std::string* ciphertext) = 0; - // Decrypt |ciphertext| string and store the result in |plaintext|. This - // method is always functional even if ShouldEncrypt() is false. + // Decrypt `ciphertext` string and store the result in `plaintext`. Returns + // true if the decryption succeeded. virtual bool DecryptString(const std::string& ciphertext, std::string* plaintext) = 0; }; diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc index e417ac9af..e639bf1ba 100644 --- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc +++ b/net/extras/sqlite/sqlite_persistent_cookie_store.cc @@ -98,19 +98,6 @@ void RecordCookieCommitProblem(CookieCommitProblem event) { COOKIE_COMMIT_PROBLEM_LAST_ENTRY); } -// The persistent cookie store is loaded into memory on eTLD at a time. This -// variable controls the delay between loading eTLDs, so as to not overload the -// CPU or I/O with these low priority requests immediately after start up. -#if BUILDFLAG(IS_IOS) -// TODO(ellyjones): This should be 200ms, but currently CookieStoreIOS is -// waiting for -FinishedLoadingCookies to be called after all eTLD cookies are -// loaded before making any network requests. Changing to 0ms for now. -// crbug.com/462593 -const int kLoadDelayMilliseconds = 0; -#else -const int kLoadDelayMilliseconds = 0; -#endif - } // namespace namespace net { @@ -123,6 +110,8 @@ namespace { // Version number of the database. // +// Version 21 - 2023/11/22 - https://crrev.com/c/5049032 +// Version 20 - 2023/11/14 - https://crrev.com/c/5030577 // Version 19 - 2023/09/22 - https://crrev.com/c/4704672 // Version 18 - 2022/04/19 - https://crrev.com/c/3594203 // Version 17 - 2022/01/25 - https://crrev.com/c/3416230 @@ -147,6 +136,11 @@ namespace { // Version 5 - 2011/12/05 - https://codereview.chromium.org/8533013 // Version 4 - 2009/09/01 - https://codereview.chromium.org/183021 // +// Version 21 removes the is_same_party column. +// +// Version 20 changes the UNIQUE constraint to include the source_scheme and +// source_port and begins to insert, update, and delete cookies based on their +// source_scheme and source_port. // // Version 19 caps expires_utc to no more than 400 days in the future for all // stored cookies with has_expires. This is in compliance with section 7.2 of @@ -178,10 +172,10 @@ namespace { // happens on Windows, on other OS, this migration is a no-op. // // Version 13 adds two new fields: "source_port" (the port number of the source -// origin, and "same_party" (boolean indicating whether the cookie had a +// origin, and "is_same_party" (boolean indicating whether the cookie had a // SameParty attribute). In migrating, source_port defaults to -1 // (url::PORT_UNSPECIFIED) for old entries for which the source port is unknown, -// and same_party defaults to false. +// and is_same_party defaults to false. // // Version 12 adds a column for "source_scheme" to store whether the // cookie was set from a URL with a cryptographic scheme. @@ -234,8 +228,8 @@ namespace { // Version 3 updated the database to include the last access time, so we can // expire them in decreasing order of use when we've reached the maximum // number of cookies. -const int kCurrentVersionNumber = 19; -const int kCompatibleVersionNumber = 19; +const int kCurrentVersionNumber = 21; +const int kCompatibleVersionNumber = 21; } // namespace @@ -286,8 +280,9 @@ class SQLitePersistentCookieStore::Backend // Creates or loads the SQLite database. void Load(LoadedCallback loaded_callback); - // Loads cookies for the domain key (eTLD+1). - void LoadCookiesForKey(const std::string& domain, + // Loads cookies for the domain key (eTLD+1). If no key is supplied then this + // behaves identically to `Load`. + void LoadCookiesForKey(base::optional_ref<const std::string> key, LoadedCallback loaded_callback); // Steps through all results of |statement|, makes a cookie from each, and @@ -353,6 +348,10 @@ class SQLitePersistentCookieStore::Backend void NotifyLoadCompleteInForeground(LoadedCallback loaded_callback, bool load_success); + // Called from Load when crypto gets obtained. + void CryptoHasInitFromLoad(base::optional_ref<const std::string> key, + LoadedCallback loaded_callback); + // Initialize the Cookies table. bool CreateDatabaseSchema() override; @@ -394,7 +393,8 @@ class SQLitePersistentCookieStore::Backend } typedef std::list<std::unique_ptr<PendingOperation>> PendingOperationsForKey; - typedef std::map<CanonicalCookie::UniqueCookieKey, PendingOperationsForKey> + typedef std::map<CanonicalCookie::StrictlyUniqueCookieKey, + PendingOperationsForKey> PendingOperationsMap; PendingOperationsMap pending_ GUARDED_BY(lock_); PendingOperationsMap::size_type num_pending_ GUARDED_BY(lock_) = 0; @@ -645,34 +645,117 @@ bool CreateV18Schema(sql::Database* db) { return true; } -// Initializes the cookies table, returning true on success. -// The table/index cannot exist when calling this function. -bool CreateV19Schema(sql::Database* db) { - return CreateV18Schema(db); +bool CreateV20Schema(sql::Database* db) { + CHECK(!db->DoesTableExist("cookies")); + + const char* kCreateTableQuery = + "CREATE TABLE cookies(" + "creation_utc INTEGER NOT NULL," + "host_key TEXT NOT NULL," + "top_frame_site_key TEXT NOT NULL," + "name TEXT NOT NULL," + "value TEXT NOT NULL," + "encrypted_value BLOB NOT NULL," + "path TEXT NOT NULL," + "expires_utc INTEGER NOT NULL," + "is_secure INTEGER NOT NULL," + "is_httponly INTEGER NOT NULL," + "last_access_utc INTEGER NOT NULL," + "has_expires INTEGER NOT NULL," + "is_persistent INTEGER NOT NULL," + "priority INTEGER NOT NULL," + "samesite INTEGER NOT NULL," + "source_scheme INTEGER NOT NULL," + "source_port INTEGER NOT NULL," + "is_same_party INTEGER NOT NULL," + "last_update_utc INTEGER NOT NULL);"; + + const char* kCreateIndexQuery = + "CREATE UNIQUE INDEX cookies_unique_index " + "ON cookies(host_key, top_frame_site_key, name, path, source_scheme, " + "source_port)"; + + if (!db->Execute(kCreateTableQuery)) { + return false; + } + if (!db->Execute(kCreateIndexQuery)) { + return false; + } + + return true; +} + +bool CreateV21Schema(sql::Database* db) { + CHECK(!db->DoesTableExist("cookies")); + + const char* kCreateTableQuery = + "CREATE TABLE cookies(" + "creation_utc INTEGER NOT NULL," + "host_key TEXT NOT NULL," + "top_frame_site_key TEXT NOT NULL," + "name TEXT NOT NULL," + "value TEXT NOT NULL," + "encrypted_value BLOB NOT NULL," + "path TEXT NOT NULL," + "expires_utc INTEGER NOT NULL," + "is_secure INTEGER NOT NULL," + "is_httponly INTEGER NOT NULL," + "last_access_utc INTEGER NOT NULL," + "has_expires INTEGER NOT NULL," + "is_persistent INTEGER NOT NULL," + "priority INTEGER NOT NULL," + "samesite INTEGER NOT NULL," + "source_scheme INTEGER NOT NULL," + "source_port INTEGER NOT NULL," + "last_update_utc INTEGER NOT NULL);"; + + const char* kCreateIndexQuery = + "CREATE UNIQUE INDEX cookies_unique_index " + "ON cookies(host_key, top_frame_site_key, name, path, source_scheme, " + "source_port)"; + + if (!db->Execute(kCreateTableQuery)) { + return false; + } + if (!db->Execute(kCreateIndexQuery)) { + return false; + } + + return true; } } // namespace void SQLitePersistentCookieStore::Backend::Load( LoadedCallback loaded_callback) { - PostBackgroundTask(FROM_HERE, - base::BindOnce(&Backend::LoadAndNotifyInBackground, this, - absl::nullopt, std::move(loaded_callback))); + LoadCookiesForKey(absl::nullopt, std::move(loaded_callback)); } void SQLitePersistentCookieStore::Backend::LoadCookiesForKey( - const std::string& key, + base::optional_ref<const std::string> key, + LoadedCallback loaded_callback) { + if (crypto_) { + crypto_->Init(base::BindOnce(&Backend::CryptoHasInitFromLoad, this, + key.CopyAsOptional(), + std::move(loaded_callback))); + } else { + CryptoHasInitFromLoad(key, std::move(loaded_callback)); + } +} + +void SQLitePersistentCookieStore::Backend::CryptoHasInitFromLoad( + base::optional_ref<const std::string> key, LoadedCallback loaded_callback) { PostBackgroundTask( - FROM_HERE, base::BindOnce(&Backend::LoadAndNotifyInBackground, this, key, - std::move(loaded_callback))); + FROM_HERE, + base::BindOnce(&Backend::LoadAndNotifyInBackground, this, + key.CopyAsOptional(), std::move(loaded_callback))); } void SQLitePersistentCookieStore::Backend::LoadAndNotifyInBackground( base::optional_ref<const std::string> key, LoadedCallback loaded_callback) { DCHECK(background_task_runner()->RunsTasksInCurrentSequence()); - bool success = false; if (InitializeDatabase()) { @@ -713,7 +796,7 @@ bool SQLitePersistentCookieStore::Backend::CreateDatabaseSchema() { if (db()->DoesTableExist("cookies")) return true; - return CreateV19Schema(db()); + return CreateV21Schema(db()); } bool SQLitePersistentCookieStore::Backend::DoInitializeDatabase() { @@ -764,11 +847,9 @@ void SQLitePersistentCookieStore::Backend::ChainLoadCookies( // then post a background task to continue chain-load; // Otherwise notify on client runner. if (load_success && keys_to_load_.size() > 0) { - bool success = background_task_runner()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&Backend::ChainLoadCookies, this, - std::move(loaded_callback)), - base::Milliseconds(kLoadDelayMilliseconds)); + bool success = background_task_runner()->PostTask( + FROM_HERE, base::BindOnce(&Backend::ChainLoadCookies, this, + std::move(loaded_callback))); if (!success) { LOG(WARNING) << "Failed to post task from " << FROM_HERE.ToString() << " to background_task_runner()."; @@ -789,15 +870,14 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains( "SELECT creation_utc, host_key, top_frame_site_key, name, value, path, " "expires_utc, is_secure, is_httponly, last_access_utc, has_expires, " "is_persistent, priority, encrypted_value, samesite, source_scheme, " - "source_port, is_same_party, last_update_utc FROM cookies WHERE " - "host_key = ?")); + "source_port, last_update_utc FROM cookies WHERE host_key = ?")); } else { smt.Assign(db()->GetCachedStatement( SQL_FROM_HERE, "SELECT creation_utc, host_key, top_frame_site_key, name, value, path, " "expires_utc, is_secure, is_httponly, last_access_utc, has_expires, " "is_persistent, priority, encrypted_value, samesite, source_scheme, " - "source_port, is_same_party, last_update_utc FROM cookies WHERE " + "source_port, last_update_utc FROM cookies WHERE " "host_key = ? AND " "is_persistent = 1")); } @@ -904,14 +984,13 @@ bool SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement( statement.ColumnTime(0), // creation_utc statement.ColumnTime(6), // expires_utc statement.ColumnTime(9), // last_access_utc - statement.ColumnTime(18), // last_update_utc + statement.ColumnTime(17), // last_update_utc statement.ColumnBool(7), // secure statement.ColumnBool(8), // http_only DBCookieSameSiteToCookieSameSite(static_cast<DBCookieSameSite>( statement.ColumnInt(14))), // samesite DBCookiePriorityToCookiePriority(static_cast<DBCookiePriority>( statement.ColumnInt(12))), // priority - statement.ColumnBool(17), // is_same_party std::move(cookie_partition_key), // top_frame_site_key DBToCookieSourceScheme(statement.ColumnInt(15)), // source_scheme statement.ColumnInt(16)); // source_port @@ -1096,6 +1175,105 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { } } + if (cur_version == 19) { + SCOPED_UMA_HISTOGRAM_TIMER("Cookie.TimeDatabaseMigrationToV20"); + + sql::Transaction transaction(db()); + if (!transaction.Begin()) { + return absl::nullopt; + } + + if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) { + return absl::nullopt; + } + if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) { + return absl::nullopt; + } + if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) { + return absl::nullopt; + } + + if (!CreateV20Schema(db())) { + return absl::nullopt; + } + + static constexpr char insert_cookies_sql[] = + "INSERT OR REPLACE INTO cookies " + "(creation_utc, host_key, top_frame_site_key, name, value, " + "encrypted_value, path, expires_utc, is_secure, is_httponly, " + "last_access_utc, has_expires, is_persistent, priority, samesite, " + "source_scheme, source_port, is_same_party, last_update_utc) " + "SELECT creation_utc, host_key, top_frame_site_key, name, value," + " encrypted_value, path, expires_utc, is_secure, is_httponly," + " last_access_utc, has_expires, is_persistent, priority, " + " samesite, source_scheme, source_port, is_same_party, " + "last_update_utc " + "FROM cookies_old ORDER BY creation_utc ASC"; + if (!db()->Execute(insert_cookies_sql)) { + return absl::nullopt; + } + if (!db()->Execute("DROP TABLE cookies_old")) { + return absl::nullopt; + } + + ++cur_version; + if (!meta_table()->SetVersionNumber(cur_version) || + !meta_table()->SetCompatibleVersionNumber( + std::min(cur_version, kCompatibleVersionNumber)) || + !transaction.Commit()) { + return absl::nullopt; + } + } + + if (cur_version == 20) { + SCOPED_UMA_HISTOGRAM_TIMER("Cookie.TimeDatabaseMigrationToV21"); + + sql::Transaction transaction(db()); + if (!transaction.Begin()) { + return absl::nullopt; + } + + if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) { + return absl::nullopt; + } + if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) { + return absl::nullopt; + } + if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) { + return absl::nullopt; + } + + if (!CreateV21Schema(db())) { + return absl::nullopt; + } + + static constexpr char insert_cookies_sql[] = + "INSERT OR REPLACE INTO cookies " + "(creation_utc, host_key, top_frame_site_key, name, value, " + "encrypted_value, path, expires_utc, is_secure, is_httponly, " + "last_access_utc, has_expires, is_persistent, priority, samesite, " + "source_scheme, source_port, last_update_utc) " + "SELECT creation_utc, host_key, top_frame_site_key, name, value," + " encrypted_value, path, expires_utc, is_secure, is_httponly," + " last_access_utc, has_expires, is_persistent, priority, " + " samesite, source_scheme, source_port, last_update_utc " + "FROM cookies_old ORDER BY creation_utc ASC"; + if (!db()->Execute(insert_cookies_sql)) { + return absl::nullopt; + } + if (!db()->Execute("DROP TABLE cookies_old")) { + return absl::nullopt; + } + + ++cur_version; + if (!meta_table()->SetVersionNumber(cur_version) || + !meta_table()->SetCompatibleVersionNumber( + std::min(cur_version, kCompatibleVersionNumber)) || + !transaction.Commit()) { + return absl::nullopt; + } + } + // Put future migration cases here. return absl::make_optional(cur_version); @@ -1133,7 +1311,7 @@ void SQLitePersistentCookieStore::Backend::BatchOperation( base::AutoLock locked(lock_); // When queueing the operation, see if it overwrites any already pending // ones for the same row. - auto key = cc.UniqueKey(); + auto key = cc.StrictlyUniqueKey(); auto iter_and_result = pending_.insert(std::make_pair(key, PendingOperationsForKey())); PendingOperationsForKey& ops_for_key = iter_and_result.first->second; @@ -1197,22 +1375,24 @@ void SQLitePersistentCookieStore::Backend::DoCommit() { "INSERT INTO cookies (creation_utc, host_key, top_frame_site_key, name, " "value, encrypted_value, path, expires_utc, is_secure, is_httponly, " "last_access_utc, has_expires, is_persistent, priority, samesite, " - "source_scheme, source_port, is_same_party, last_update_utc) " - "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); + "source_scheme, source_port, last_update_utc) " + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); if (!add_statement.is_valid()) return; sql::Statement update_access_statement(db()->GetCachedStatement( SQL_FROM_HERE, "UPDATE cookies SET last_access_utc=? WHERE " - "name=? AND host_key=? AND top_frame_site_key=? AND path=?")); + "name=? AND host_key=? AND top_frame_site_key=? AND path=? AND " + "source_scheme=? AND source_port=?")); if (!update_access_statement.is_valid()) return; sql::Statement delete_statement(db()->GetCachedStatement( SQL_FROM_HERE, "DELETE FROM cookies WHERE " - "name=? AND host_key=? AND top_frame_site_key=? AND path=?")); + "name=? AND host_key=? AND top_frame_site_key=? AND path=? AND " + "source_scheme=? AND source_port=?")); if (!delete_statement.is_valid()) return; @@ -1264,8 +1444,7 @@ void SQLitePersistentCookieStore::Backend::DoCommit() { 14, CookieSameSiteToDBCookieSameSite(po->cc().SameSite())); add_statement.BindInt(15, static_cast<int>(po->cc().SourceScheme())); add_statement.BindInt(16, po->cc().SourcePort()); - add_statement.BindBool(17, po->cc().IsSameParty()); - add_statement.BindTime(18, po->cc().LastUpdateDate()); + add_statement.BindTime(17, po->cc().LastUpdateDate()); if (!add_statement.Run()) { DLOG(WARNING) << "Could not add a cookie to the DB."; RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_ADD); @@ -1279,6 +1458,9 @@ void SQLitePersistentCookieStore::Backend::DoCommit() { update_access_statement.BindString(2, po->cc().Domain()); update_access_statement.BindString(3, top_frame_site_key); update_access_statement.BindString(4, po->cc().Path()); + update_access_statement.BindInt( + 5, static_cast<int>(po->cc().SourceScheme())); + update_access_statement.BindInt(6, po->cc().SourcePort()); if (!update_access_statement.Run()) { DLOG(WARNING) << "Could not update cookie last access time in the DB."; @@ -1292,6 +1474,9 @@ void SQLitePersistentCookieStore::Backend::DoCommit() { delete_statement.BindString(1, po->cc().Domain()); delete_statement.BindString(2, top_frame_site_key); delete_statement.BindString(3, po->cc().Path()); + delete_statement.BindInt(4, + static_cast<int>(po->cc().SourceScheme())); + delete_statement.BindInt(5, po->cc().SourcePort()); if (!delete_statement.Run()) { DLOG(WARNING) << "Could not delete a cookie from the DB."; RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_DELETE); diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc index 2a50c6ba9..417b9a5dd 100644 --- a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc +++ b/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc @@ -89,7 +89,7 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test { return *CanonicalCookie::CreateUnsafeCookieForTesting( base::StringPrintf("Cookie_%d", cookie_num), "1", domain_name, "/", t, t, t, t, false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false); + COOKIE_PRIORITY_DEFAULT); } void SetUp() override { diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc index b9610bc49..152966d7e 100644 --- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc +++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc @@ -20,6 +20,7 @@ #include "base/location.h" #include "base/memory/ref_counted.h" #include "base/run_loop.h" +#include "base/sequence_checker.h" #include "base/strings/stringprintf.h" #include "base/synchronization/waitable_event.h" #include "base/task/sequenced_task_runner.h" @@ -47,6 +48,7 @@ #include "sql/meta_table.h" #include "sql/statement.h" #include "sql/transaction.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -62,14 +64,20 @@ const base::FilePath::CharType kCookieFilename[] = FILE_PATH_LITERAL("Cookies"); class CookieCryptor : public CookieCryptoDelegate { public: CookieCryptor(); + void Init(base::OnceClosure callback) override; bool EncryptString(const std::string& plaintext, std::string* ciphertext) override; bool DecryptString(const std::string& ciphertext, std::string* plaintext) override; private: + void InitComplete(); + bool init_ GUARDED_BY_CONTEXT(sequence_checker_) = false; + bool initing_ GUARDED_BY_CONTEXT(sequence_checker_) = false; + base::OnceClosureList callbacks_ GUARDED_BY_CONTEXT(sequence_checker_); std::unique_ptr<crypto::SymmetricKey> key_; crypto::Encryptor encryptor_; + SEQUENCE_CHECKER(sequence_checker_); }; CookieCryptor::CookieCryptor() @@ -81,6 +89,28 @@ CookieCryptor::CookieCryptor() 256)) { std::string iv("the iv: 16 bytes"); encryptor_.Init(key_.get(), crypto::Encryptor::CBC, iv); + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +void CookieCryptor::Init(base::OnceClosure callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (init_) { + std::move(callback).Run(); + return; + } + + // Callbacks here are owned by test fixtures that outlive the CookieCryptor. + callbacks_.AddUnsafe(std::move(callback)); + + if (initing_) { + return; + } + + initing_ = true; + base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&CookieCryptor::InitComplete, base::Unretained(this)), + base::Milliseconds(100)); } bool CookieCryptor::EncryptString(const std::string& plaintext, @@ -93,6 +123,40 @@ bool CookieCryptor::DecryptString(const std::string& ciphertext, return encryptor_.Decrypt(ciphertext, plaintext); } +void CookieCryptor::InitComplete() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + init_ = true; + callbacks_.Notify(); +} + +// Matches the CanonicalCookie's strictly_unique_key and last_access_date +// against a unique_ptr<CanonicalCookie>. +MATCHER_P2(MatchesCookieKeyAndLastAccessDate, + StrictlyUniqueKey, + last_access_date, + "") { + if (!arg) { + return false; + } + const CanonicalCookie& list_cookie = *arg; + + return testing::ExplainMatchResult(StrictlyUniqueKey, + list_cookie.StrictlyUniqueKey(), + result_listener) && + testing::ExplainMatchResult( + last_access_date, list_cookie.LastAccessDate(), result_listener); +} + +// Matches every field of a CanonicalCookie against a +// unique_ptr<CanonicalCookie>. +MATCHER_P(MatchesEveryCookieField, cookie, "") { + if (!arg) { + return false; + } + const CanonicalCookie& list_cookie = *arg; + return cookie.HasEquivalentDataMembers(list_cookie); +} + } // namespace typedef std::vector<std::unique_ptr<CanonicalCookie>> CanonicalCookieVector; @@ -105,31 +169,37 @@ class SQLitePersistentCookieStoreTest : public TestWithTaskEnvironment { db_thread_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED) {} - void OnLoaded(CanonicalCookieVector cookies) { - cookies_.swap(cookies); - loaded_event_.Signal(); - } + void SignalLoadedEvent() { loaded_event_.Signal(); } - void OnKeyLoaded(base::OnceClosure closure, CanonicalCookieVector cookies) { + void OnLoaded(base::OnceClosure closure, CanonicalCookieVector cookies) { cookies_.swap(cookies); std::move(closure).Run(); } void Load(CanonicalCookieVector* cookies) { - EXPECT_FALSE(loaded_event_.IsSignaled()); - store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded, - base::Unretained(this)), - NetLogWithSource::Make(NetLogSourceType::NONE)); - loaded_event_.Wait(); - cookies->swap(cookies_); + base::RunLoop run_loop; + store_->Load( + base::BindLambdaForTesting([&](CanonicalCookieVector obtained_cookies) { + cookies->swap(obtained_cookies); + run_loop.Quit(); + }), + NetLogWithSource::Make(NetLogSourceType::NONE)); + run_loop.Run(); + } + + void LoadAsyncAndSignalEvent() { + store_->Load( + base::BindOnce( + &SQLitePersistentCookieStoreTest::OnLoaded, base::Unretained(this), + base::BindOnce(&SQLitePersistentCookieStoreTest::SignalLoadedEvent, + base::Unretained(this))), + NetLogWithSource::Make(NetLogSourceType::NONE)); } void Flush() { - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED); - store_->Flush( - base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event))); - event.Wait(); + base::RunLoop run_loop; + store_->Flush(run_loop.QuitClosure()); + run_loop.Run(); } void DestroyStore() { @@ -182,7 +252,7 @@ class SQLitePersistentCookieStoreTest : public TestWithTaskEnvironment { store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( name, value, domain, path, creation, creation, base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + COOKIE_PRIORITY_DEFAULT)); } void AddCookieWithExpiration(const std::string& name, @@ -194,7 +264,7 @@ class SQLitePersistentCookieStoreTest : public TestWithTaskEnvironment { store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( name, value, domain, path, creation, expiration, base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + COOKIE_PRIORITY_DEFAULT)); } std::string ReadRawDBContents() { @@ -375,9 +445,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestSessionCookiesDeletedOnStartup) { background_task_runner_->PostTask( FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, base::Unretained(this))); - store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded, - base::Unretained(this)), - NetLogWithSource()); + LoadAsyncAndSignalEvent(); t += base::Microseconds(10); AddCookieWithExpiration("A", "B", "c.com", "/", t, base::Time()); base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, @@ -404,18 +472,16 @@ TEST_F(SQLitePersistentCookieStoreTest, TestSessionCookiesDeletedOnStartup) { store_ = base::MakeRefCounted<SQLitePersistentCookieStore>( temp_dir_.GetPath().Append(kCookieFilename), client_task_runner_, background_task_runner_, true, nullptr, false); - store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded, - base::Unretained(this)), - NetLogWithSource()); + LoadAsyncAndSignalEvent(); loaded_event_.Wait(); ASSERT_EQ(4u, cookies_.size()); cookies_.clear(); } -// Test that priority load of cookies for a specfic domain key could be -// completed before the entire store is loaded +// Test that priority load of cookies for a specific domain key could be +// completed before the entire store is loaded. TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) { - InitializeStore(false, false); + InitializeStore(/*crypt=*/true, /*restore_old_session_cookies=*/false); base::Time t = base::Time::Now(); AddCookie("A", "B", "foo.bar", "/", t); t += base::Microseconds(10); @@ -433,8 +499,13 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) { // preventing client tasks to run, use // base::SingleThreadTaskRunner::GetCurrentDefault() instead of // |client_task_runner_| for this test. - Create(false /* crypt_cookies */, false /* restore_old_session_cookies */, - true /* use_current_thread */, false /* enable_exclusive_access */); + auto cookie_crypto_delegate = std::make_unique<CookieCryptor>(); + store_ = base::MakeRefCounted<SQLitePersistentCookieStore>( + temp_dir_.GetPath().Append(kCookieFilename), + base::SingleThreadTaskRunner::GetCurrentDefault(), + background_task_runner_, + /*restore_old_session_cookies=*/false, cookie_crypto_delegate.get(), + /*enable_exclusive_access=*/false); // Posting a blocking task to db_thread_ makes sure that the DB thread waits // until both Load and LoadCookiesForKey have been posted to its task queue. @@ -442,15 +513,23 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) { FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, base::Unretained(this))); RecordingNetLogObserver net_log_observer; - store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded, - base::Unretained(this)), - NetLogWithSource::Make(NetLogSourceType::NONE)); + LoadAsyncAndSignalEvent(); base::RunLoop run_loop; net_log_observer.SetObserverCaptureMode(NetLogCaptureMode::kDefault); store_->LoadCookiesForKey( "aaa.com", - base::BindOnce(&SQLitePersistentCookieStoreTest::OnKeyLoaded, + base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded, base::Unretained(this), run_loop.QuitClosure())); + + // Complete the initialization of the cookie crypto delegate. This ensures + // that any background tasks from the Load or the LoadCookiesForKey are posted + // to the background_task_runner_. + base::RunLoop cookie_crypto_loop; + cookie_crypto_delegate->Init(cookie_crypto_loop.QuitClosure()); + cookie_crypto_loop.Run(); + + // Post a final blocking task to the background_task_runner_ to ensure no + // other cookie loads take place during the test. background_task_runner_->PostTask( FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, base::Unretained(this))); @@ -581,7 +660,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) { store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( "C", "D", "sessioncookie.com", "/", base::Time::Now(), base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + COOKIE_PRIORITY_DEFAULT)); // Force the store to write its data to the disk. DestroyStore(); @@ -608,7 +687,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) { store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( "C", "D", "sessioncookie.com", "/", base::Time::Now(), base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + COOKIE_PRIORITY_DEFAULT)); // Force the store to write its data to the disk. DestroyStore(); @@ -644,8 +723,8 @@ TEST_F(SQLitePersistentCookieStoreTest, FilterBadCookiesAndFixupDb) { "INSERT INTO cookies (creation_utc, host_key, top_frame_site_key, name, " "value, encrypted_value, path, expires_utc, is_secure, is_httponly, " "samesite, last_access_utc, has_expires, is_persistent, priority, " - "source_scheme, source_port, is_same_party, last_update_utc) " - "VALUES (?,?,?,?,?,'',?,0,0,0,0,0,1,1,0,?,?,0,?)")); + "source_scheme, source_port, last_update_utc) " + "VALUES (?,?,?,?,?,'',?,0,0,0,0,0,1,1,0,?,?,?)")); ASSERT_TRUE(stmt.is_valid()); struct CookieInfo { @@ -720,13 +799,13 @@ TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) { store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( kSessionName, "val", "sessioncookie.com", "/", base::Time::Now(), base::Time(), base::Time(), base::Time(), false, false, - CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false)); + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT)); // Add a persistent cookie. store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( kPersistentName, "val", "sessioncookie.com", "/", base::Time::Now() - base::Days(1), base::Time::Now() + base::Days(1), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + COOKIE_PRIORITY_DEFAULT)); // Force the store to write its data to the disk. DestroyStore(); @@ -767,21 +846,21 @@ TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) { kLowName, kCookieValue, kDomain, kCookiePath, base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false)); + COOKIE_PRIORITY_LOW)); // Add a medium-priority persistent cookie. store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( kMediumName, kCookieValue, kDomain, kCookiePath, base::Time::Now() - base::Minutes(2), base::Time::Now() + base::Days(1), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_MEDIUM, false)); + COOKIE_PRIORITY_MEDIUM)); // Add a high-priority persistent cookie. store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( kHighName, kCookieValue, kDomain, kCookiePath, base::Time::Now() - base::Minutes(3), base::Time::Now() + base::Days(1), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_HIGH, false)); + COOKIE_PRIORITY_HIGH)); // Force the store to write its data to the disk. DestroyStore(); @@ -828,21 +907,21 @@ TEST_F(SQLitePersistentCookieStoreTest, SameSiteIsPersistent) { kNoneName, kCookieValue, kDomain, kCookiePath, base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + COOKIE_PRIORITY_DEFAULT)); // Add a lax-samesite persistent cookie. store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( kLaxName, kCookieValue, kDomain, kCookiePath, base::Time::Now() - base::Minutes(2), base::Time::Now() + base::Days(1), base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE, - COOKIE_PRIORITY_DEFAULT, false)); + COOKIE_PRIORITY_DEFAULT)); // Add a strict-samesite persistent cookie. store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( kStrictName, kCookieValue, kDomain, kCookiePath, base::Time::Now() - base::Minutes(3), base::Time::Now() + base::Days(1), base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE, - COOKIE_PRIORITY_DEFAULT, false)); + COOKIE_PRIORITY_DEFAULT)); // Force the store to write its data to the disk. DestroyStore(); @@ -884,7 +963,7 @@ TEST_F(SQLitePersistentCookieStoreTest, SameSiteExtendedTreatedAsUnspecified) { kExtendedName, kCookieValue, kDomain, kCookiePath, base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1), base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE, - COOKIE_PRIORITY_DEFAULT, false)); + COOKIE_PRIORITY_DEFAULT)); // Force the store to write its data to the disk. DestroyStore(); @@ -910,53 +989,6 @@ TEST_F(SQLitePersistentCookieStoreTest, SameSiteExtendedTreatedAsUnspecified) { EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookies[0]->SameSite()); } -TEST_F(SQLitePersistentCookieStoreTest, SamePartyIsPersistent) { - const char kDomain[] = "sessioncookie.com"; - const char kNonSamePartyCookieName[] = "no_party"; - const char kSamePartyCookieName[] = "party"; - const char kCookieValue[] = "value"; - const char kCookiePath[] = "/"; - - InitializeStore(false, true); - - // Add a non-SameParty persistent cookie. - store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( - kNonSamePartyCookieName, kCookieValue, kDomain, kCookiePath, - base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1), - base::Time(), base::Time(), - /*secure=*/true, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, - /*same_party=*/false)); - - // Add a SameParty persistent cookie. - store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting( - kSamePartyCookieName, kCookieValue, kDomain, kCookiePath, - base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1), - base::Time(), base::Time(), - /*secure=*/true, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, - /*same_party=*/true)); - - // Force the store to write its data to the disk. - DestroyStore(); - - // Create a store that loads session cookie and test that the SameParty - // attribute values are restored. - CanonicalCookieVector cookies; - CreateAndLoad(false, true, &cookies); - ASSERT_EQ(2U, cookies.size()); - - // Put the cookies into a map, by name, for comparison below. - std::map<std::string, CanonicalCookie*> cookie_map; - for (const auto& cookie : cookies) - cookie_map[cookie->Name()] = cookie.get(); - - // Validate that each cookie has the correct SameParty. - ASSERT_EQ(1u, cookie_map.count(kNonSamePartyCookieName)); - EXPECT_FALSE(cookie_map[kNonSamePartyCookieName]->IsSameParty()); - - ASSERT_EQ(1u, cookie_map.count(kSamePartyCookieName)); - EXPECT_TRUE(cookie_map[kSamePartyCookieName]->IsSameParty()); -} - TEST_F(SQLitePersistentCookieStoreTest, SourcePortIsPersistent) { const char kDomain[] = "sessioncookie.com"; const char kCookieValue[] = "value"; @@ -984,7 +1016,6 @@ TEST_F(SQLitePersistentCookieStoreTest, SourcePortIsPersistent) { base::Time(), base::Time(), /*secure=*/true, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, - /*same_party=*/false, /*partition_key=*/absl::nullopt, CookieSourceScheme::kUnset /* Doesn't matter for this test. */, input.port)); @@ -1161,7 +1192,9 @@ TEST_F(SQLitePersistentCookieStoreTest, KeyInconsistency) { // its PersistentCookieStore on the same thread as its methods are invoked on; // so to avoid needing to post every CookieMonster API call, this uses the // current thread for SQLitePersistentCookieStore's |client_task_runner|. - Create(false, false, true /* use_current_thread */, false); + // Note: Cookie encryption is explicitly enabled here to verify threading + // model with async initialization functions correctly. + Create(/*crypt_cookies=*/true, false, true /* use_current_thread */, false); // Create a cookie on a scheme that doesn't handle cookies by default, // and save it. @@ -1325,6 +1358,7 @@ TEST_F(SQLitePersistentCookieStoreTest, Coalescing) { store_->GetQueueLengthForTesting()); db_thread_event_.Signal(); + DestroyStore(); } } @@ -1624,6 +1658,53 @@ bool CreateV18Schema(sql::Database* db) { return true; } +bool CreateV20Schema(sql::Database* db) { + sql::MetaTable meta_table; + if (!meta_table.Init(db, 20, 20)) { + return false; + } + + // Version 20 schema + static constexpr char kCreateSql[] = + "CREATE TABLE cookies(" + "creation_utc INTEGER NOT NULL," + "host_key TEXT NOT NULL," + "top_frame_site_key TEXT NOT NULL," + "name TEXT NOT NULL," + "value TEXT NOT NULL," + "encrypted_value BLOB NOT NULL," + "path TEXT NOT NULL," + "expires_utc INTEGER NOT NULL," + "is_secure INTEGER NOT NULL," + "is_httponly INTEGER NOT NULL," + "last_access_utc INTEGER NOT NULL," + "has_expires INTEGER NOT NULL," + "is_persistent INTEGER NOT NULL," + "priority INTEGER NOT NULL," + "samesite INTEGER NOT NULL," + "source_scheme INTEGER NOT NULL," + "source_port INTEGER NOT NULL," + "is_same_party INTEGER NOT NULL," + "last_update_utc INTEGER NOT NULL," + "UNIQUE (host_key, top_frame_site_key, name, path, source_scheme, " + "source_port))"; + + static constexpr char kCreateIndexSql[] = + "CREATE UNIQUE INDEX cookies_unique_index " + "ON cookies(host_key, top_frame_site_key, name, path, source_scheme, " + "source_port)"; + + if (!db->Execute(kCreateSql)) { + return false; + } + + if (!db->Execute(kCreateIndexSql)) { + return false; + } + + return true; +} + int GetDBCurrentVersionNumber(sql::Database* db) { static constexpr char kGetDBCurrentVersionQuery[] = "SELECT value FROM meta WHERE key='version'"; @@ -1636,35 +1717,30 @@ std::vector<CanonicalCookie> CookiesForMigrationTest() { static base::Time now = base::Time::Now(); std::vector<CanonicalCookie> cookies; - // Note: These are all constructed with the default value of - // is_source_scheme_secure, which is false, but that doesn't matter because - // v11 doesn't store that info. - // Some of these are constructed with SameParty set to true, to test that in - // the DB migration, the is_same_party values are all defaulted to false. cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "example.com", "/", now, now, now, now, true /* secure */, false /* httponly */, CookieSameSite::UNSPECIFIED, - COOKIE_PRIORITY_DEFAULT, false /* same_party */)); + COOKIE_PRIORITY_DEFAULT)); cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "C", "B", "example.com", "/", now, now, now, now, true /* secure */, false /* httponly */, CookieSameSite::UNSPECIFIED, - COOKIE_PRIORITY_DEFAULT, true /* same_party */)); + COOKIE_PRIORITY_DEFAULT)); cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "example2.com", "/", now, now, now, now, true /* secure */, false /* httponly */, CookieSameSite::UNSPECIFIED, - COOKIE_PRIORITY_DEFAULT, true /* same_party */)); + COOKIE_PRIORITY_DEFAULT)); cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "C", "B", "example2.com", "/", now, now + base::Days(399), now, now, false /* secure */, false /* httponly */, CookieSameSite::UNSPECIFIED, - COOKIE_PRIORITY_DEFAULT, false /* same_party */)); + COOKIE_PRIORITY_DEFAULT)); cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "example.com", "/path", now, now + base::Days(400), now, now, false /* secure */, false /* httponly */, CookieSameSite::UNSPECIFIED, - COOKIE_PRIORITY_DEFAULT, false /* same_party */)); + COOKIE_PRIORITY_DEFAULT)); cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "C", "B", "example.com", "/path", now, now + base::Days(401), now, now, false /* secure */, false /* httponly */, CookieSameSite::UNSPECIFIED, - COOKIE_PRIORITY_DEFAULT, false /* same_party */)); + COOKIE_PRIORITY_DEFAULT)); return cookies; } @@ -1709,7 +1785,7 @@ bool AddV15CookiesToDB(sql::Database* db) { statement.BindInt(14, static_cast<int>(cookie.Priority())); statement.BindInt(15, static_cast<int>(cookie.SourceScheme())); statement.BindInt(16, cookie.SourcePort()); - statement.BindInt(17, cookie.IsSameParty()); + statement.BindInt(17, false /* is_same_party */); if (!statement.Run()) return false; } @@ -1729,7 +1805,11 @@ bool AddV17CookiesToDB(sql::Database* db) { return AddV16CookiesToDB(db); } -bool AddV18CookiesToDB(sql::Database* db) { +// Versions 18, 19, and 20 use the same schema so they can reuse this function. +// AddV20CookiesToDB (and future versions) need to set max_expiration_delta to +// base::Days(400) to simulate expiration limits introduced in version 19. +bool AddV18CookiesToDB(sql::Database* db, + base::TimeDelta max_expiration_delta) { std::vector<CanonicalCookie> cookies = CookiesForMigrationTest(); sql::Statement statement(db->GetCachedStatement( SQL_FROM_HERE, @@ -1746,6 +1826,8 @@ bool AddV18CookiesToDB(sql::Database* db) { return false; } for (const CanonicalCookie& cookie : cookies) { + base::Time max_expiration(cookie.CreationDate() + max_expiration_delta); + statement.Reset(true); statement.BindTime(0, cookie.CreationDate()); std::string top_frame_site_key; @@ -1757,7 +1839,7 @@ bool AddV18CookiesToDB(sql::Database* db) { statement.BindString(4, cookie.Value()); statement.BindBlob(5, base::span<uint8_t>()); // encrypted_value statement.BindString(6, cookie.Path()); - statement.BindTime(7, cookie.ExpiryDate()); + statement.BindTime(7, std::min(cookie.ExpiryDate(), max_expiration)); statement.BindInt(8, cookie.IsSecure()); statement.BindInt(9, cookie.IsHttpOnly()); // Note that this, Priority(), and SourceScheme() below nominally rely on @@ -1772,7 +1854,7 @@ bool AddV18CookiesToDB(sql::Database* db) { statement.BindInt(14, static_cast<int>(cookie.Priority())); statement.BindInt(15, static_cast<int>(cookie.SourceScheme())); statement.BindInt(16, cookie.SourcePort()); - statement.BindInt(17, cookie.IsSameParty()); + statement.BindInt(17, false /* is_same_party */); statement.BindTime(18, cookie.LastUpdateDate()); if (!statement.Run()) { return false; @@ -1785,10 +1867,13 @@ bool AddV18CookiesToDB(sql::Database* db) { return true; } +bool AddV20CookiesToDB(sql::Database* db) { + return AddV18CookiesToDB(db, base::Days(400)); +} + // Confirm the cookie list passed in has the above cookies in it. void ConfirmCookiesAfterMigrationTest( std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies, - bool expect_same_party_cookies = false, bool expect_last_update_date = false) { std::sort(read_in_cookies.begin(), read_in_cookies.end(), &CompareCookies); int i = 0; @@ -1798,7 +1883,6 @@ void ConfirmCookiesAfterMigrationTest( EXPECT_EQ("/", read_in_cookies[i]->Path()); EXPECT_TRUE(read_in_cookies[i]->IsSecure()); EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme()); - EXPECT_FALSE(read_in_cookies[i]->IsSameParty()); EXPECT_EQ(read_in_cookies[i]->LastUpdateDate(), expect_last_update_date ? read_in_cookies[i]->CreationDate() : base::Time()); @@ -1812,7 +1896,6 @@ void ConfirmCookiesAfterMigrationTest( EXPECT_EQ("/path", read_in_cookies[i]->Path()); EXPECT_FALSE(read_in_cookies[i]->IsSecure()); EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme()); - EXPECT_FALSE(read_in_cookies[i]->IsSameParty()); EXPECT_EQ(read_in_cookies[i]->LastUpdateDate(), expect_last_update_date ? read_in_cookies[i]->CreationDate() : base::Time()); @@ -1826,7 +1909,6 @@ void ConfirmCookiesAfterMigrationTest( EXPECT_EQ("/", read_in_cookies[i]->Path()); EXPECT_TRUE(read_in_cookies[i]->IsSecure()); EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme()); - EXPECT_EQ(expect_same_party_cookies, read_in_cookies[i]->IsSameParty()); EXPECT_EQ(read_in_cookies[i]->LastUpdateDate(), expect_last_update_date ? read_in_cookies[i]->CreationDate() : base::Time()); @@ -1840,7 +1922,6 @@ void ConfirmCookiesAfterMigrationTest( EXPECT_EQ("/", read_in_cookies[i]->Path()); EXPECT_TRUE(read_in_cookies[i]->IsSecure()); EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme()); - EXPECT_EQ(expect_same_party_cookies, read_in_cookies[i]->IsSameParty()); EXPECT_EQ(read_in_cookies[i]->LastUpdateDate(), expect_last_update_date ? read_in_cookies[i]->CreationDate() : base::Time()); @@ -1854,7 +1935,6 @@ void ConfirmCookiesAfterMigrationTest( EXPECT_EQ("/path", read_in_cookies[i]->Path()); EXPECT_FALSE(read_in_cookies[i]->IsSecure()); EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme()); - EXPECT_FALSE(read_in_cookies[i]->IsSameParty()); EXPECT_EQ(read_in_cookies[i]->LastUpdateDate(), expect_last_update_date ? read_in_cookies[i]->CreationDate() : base::Time()); @@ -1871,12 +1951,13 @@ void ConfirmCookiesAfterMigrationTest( EXPECT_EQ("/", read_in_cookies[i]->Path()); EXPECT_FALSE(read_in_cookies[i]->IsSecure()); EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme()); - EXPECT_FALSE(read_in_cookies[i]->IsSameParty()); EXPECT_EQ(read_in_cookies[i]->LastUpdateDate(), expect_last_update_date ? read_in_cookies[i]->CreationDate() : base::Time()); EXPECT_EQ(read_in_cookies[i]->ExpiryDate(), read_in_cookies[i]->CreationDate() + base::Days(399)); + + EXPECT_EQ(read_in_cookies.size(), static_cast<size_t>(i) + 1); } TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion16) { @@ -1889,8 +1970,7 @@ TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion16) { std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies; CreateAndLoad(false, false, &read_in_cookies); - ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), - /*expect_same_party_cookies=*/true); + ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies)); } TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion17) { @@ -1903,8 +1983,7 @@ TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion17) { std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies; CreateAndLoad(false, false, &read_in_cookies); - ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), - /*expect_same_party_cookies=*/true); + ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies)); ASSERT_GE(GetDBCurrentVersionNumber(&connection), 17); connection.Close(); } @@ -1921,8 +2000,7 @@ TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion17FromFaultyV16) { std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies; CreateAndLoad(false, false, &read_in_cookies); - ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), - /*expect_same_party_cookies=*/true); + ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies)); ASSERT_GE(GetDBCurrentVersionNumber(&connection), 17); connection.Close(); } @@ -1937,8 +2015,7 @@ TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion18) { std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies; CreateAndLoad(false, false, &read_in_cookies); - ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), - /*expect_same_party_cookies=*/true); + ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies)); ASSERT_GE(GetDBCurrentVersionNumber(&connection), 18); connection.Close(); } @@ -1949,17 +2026,179 @@ TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion19) { ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename))); ASSERT_TRUE(CreateV18Schema(&connection)); ASSERT_EQ(GetDBCurrentVersionNumber(&connection), 18); - ASSERT_TRUE(AddV18CookiesToDB(&connection)); + ASSERT_TRUE(AddV18CookiesToDB(&connection, base::TimeDelta::Max())); std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies; CreateAndLoad(false, false, &read_in_cookies); ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), - /*expect_same_party_cookies=*/true, /*expect_last_update_date=*/true); ASSERT_GE(GetDBCurrentVersionNumber(&connection), 19); connection.Close(); } +TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion20) { + // Open db. + sql::Database connection; + ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename))); + // V19's schema is the same as V18, so we can reuse the creation function. + ASSERT_TRUE(CreateV18Schema(&connection)); + ASSERT_EQ(GetDBCurrentVersionNumber(&connection), 18); + ASSERT_TRUE(AddV18CookiesToDB(&connection, base::TimeDelta::Max())); + + std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies; + CreateAndLoad(/*crypt_cookies=*/false, /*restore_old_session_cookies=*/false, + &read_in_cookies); + ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), + /*expect_last_update_date=*/true); + ASSERT_GE(GetDBCurrentVersionNumber(&connection), 20); + connection.Close(); +} + +TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion21) { + // Open db. + sql::Database connection; + ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename))); + ASSERT_TRUE(CreateV20Schema(&connection)); + ASSERT_EQ(GetDBCurrentVersionNumber(&connection), 20); + ASSERT_TRUE(AddV20CookiesToDB(&connection)); + + std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies; + CreateAndLoad(/*crypt_cookies=*/false, /*restore_old_session_cookies=*/false, + &read_in_cookies); + ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), + /*expect_last_update_date=*/true); + ASSERT_GE(GetDBCurrentVersionNumber(&connection), 21); + connection.Close(); +} + +class SQLitePersistentCookieStoreTest_OriginBoundCookies + : public SQLitePersistentCookieStoreTest { + public: + // Creates and stores 4 cookies that differ only by scheme and/or port. When + // this function returns, the store will be created and all the cookies loaded + // into cookies_. + void InitializeTest() { + InitializeStore(/*crypt=*/false, /*restore_old_session_cookies=*/false); + + basic_cookie_ = CanonicalCookie::Create( + basic_url_, "a=b; max-age=100000", /*creation_time=*/base::Time::Now(), + /*server_time=*/absl::nullopt, /*cookie_partition_key=*/absl::nullopt); + + http_cookie_ = std::make_unique<CanonicalCookie>(*basic_cookie_); + http_cookie_->SetSourceScheme(CookieSourceScheme::kNonSecure); + + port_444_cookie_ = std::make_unique<CanonicalCookie>(*basic_cookie_); + port_444_cookie_->SetSourcePort(444); + + http_444_cookie_ = std::make_unique<CanonicalCookie>(*basic_cookie_); + http_444_cookie_->SetSourceScheme(CookieSourceScheme::kNonSecure); + http_444_cookie_->SetSourcePort(444); + + store_->AddCookie(*basic_cookie_); + store_->AddCookie(*http_cookie_); + store_->AddCookie(*port_444_cookie_); + store_->AddCookie(*http_444_cookie_); + // Force the store to write its data to the disk. + DestroyStore(); + + CreateAndLoad(false, false, &cookies_); + + EXPECT_EQ(cookies_.size(), 4UL); + } + + GURL basic_url_ = GURL("https://example.com"); + std::unique_ptr<net::CanonicalCookie> basic_cookie_; + std::unique_ptr<net::CanonicalCookie> http_cookie_; + std::unique_ptr<net::CanonicalCookie> port_444_cookie_; + std::unique_ptr<net::CanonicalCookie> http_444_cookie_; + + CanonicalCookieVector cookies_; +}; + +// Tests that cookies which differ only in their scheme and port are considered +// distinct. +TEST_F(SQLitePersistentCookieStoreTest_OriginBoundCookies, + UniquenessConstraint) { + InitializeTest(); + + // Try to add another cookie that is the same as basic_cookie_ except that its + // value is different. Value isn't considered as part of the unique constraint + // and so this cookie won't be considered unique and should fail to be added. + auto basic_cookie2 = CanonicalCookie::Create( + basic_url_, "a=b2; max-age=100000", + /*creation_time=*/base::Time::Now(), + /*server_time=*/absl::nullopt, /*cookie_partition_key=*/absl::nullopt); + + store_->AddCookie(*basic_cookie2); + + // Force the store to write its data to the disk. + DestroyStore(); + + cookies_.clear(); + CreateAndLoad(false, false, &cookies_); + + // Confirm that basic_cookie2 failed to be added. + EXPECT_THAT(cookies_, testing::UnorderedElementsAre( + MatchesEveryCookieField(*basic_cookie_), + MatchesEveryCookieField(*http_cookie_), + MatchesEveryCookieField(*port_444_cookie_), + MatchesEveryCookieField(*http_444_cookie_))); +} + +// Tests that deleting a cookie correctly takes the scheme and port into +// account. +TEST_F(SQLitePersistentCookieStoreTest_OriginBoundCookies, DeleteCookie) { + InitializeTest(); + + // Try to delete just one of the cookies. + store_->DeleteCookie(*http_444_cookie_); + DestroyStore(); + cookies_.clear(); + + CreateAndLoad(false, false, &cookies_); + + // Only the single cookie should be deleted. + EXPECT_THAT(cookies_, testing::UnorderedElementsAre( + MatchesEveryCookieField(*basic_cookie_), + MatchesEveryCookieField(*http_cookie_), + MatchesEveryCookieField(*port_444_cookie_))); +} + +// Tests that updating a cookie correctly takes the scheme and port into +// account. +TEST_F(SQLitePersistentCookieStoreTest_OriginBoundCookies, + UpdateCookieAccessTime) { + InitializeTest(); + + base::Time basic_last_access = basic_cookie_->LastAccessDate(); + base::Time http_last_access = http_cookie_->LastAccessDate(); + base::Time port_444_last_access = port_444_cookie_->LastAccessDate(); + base::Time http_444_last_access = http_444_cookie_->LastAccessDate(); + + base::Time new_last_access = http_444_last_access + base::Hours(1); + http_444_cookie_->SetLastAccessDate(new_last_access); + + store_->UpdateCookieAccessTime(*http_444_cookie_); + DestroyStore(); + cookies_.clear(); + + CreateAndLoad(false, false, &cookies_); + + // All loaded cookies' should have their original LastAccessDate() except for + // the one updated to new_last_access. + EXPECT_THAT( + cookies_, + testing::UnorderedElementsAre( + MatchesCookieKeyAndLastAccessDate(basic_cookie_->StrictlyUniqueKey(), + basic_last_access), + MatchesCookieKeyAndLastAccessDate(http_cookie_->StrictlyUniqueKey(), + http_last_access), + MatchesCookieKeyAndLastAccessDate( + port_444_cookie_->StrictlyUniqueKey(), port_444_last_access), + MatchesCookieKeyAndLastAccessDate( + http_444_cookie_->StrictlyUniqueKey(), new_last_access))); +} + class PartitionedCookiesSQLitePersistentCookieStoreTest : public SQLitePersistentCookieStoreTest, public testing::WithParamInterface<bool> { @@ -1990,7 +2229,6 @@ TEST_P(PartitionedCookiesSQLitePersistentCookieStoreTest, base::Time::Now(), base::Time::Now() + base::Days(1), base::Time::Now(), base::Time::Now(), true /* secure */, false /* httponly */, CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT, - false /* sameparty */, CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com")))); Flush(); @@ -2015,8 +2253,8 @@ TEST_P(PartitionedCookiesSQLitePersistentCookieStoreTest, "INSERT INTO cookies (creation_utc, host_key, top_frame_site_key, name, " "value, encrypted_value, path, expires_utc, is_secure, is_httponly, " "samesite, last_access_utc, has_expires, is_persistent, priority, " - "source_scheme, source_port, is_same_party, last_update_utc) " - "VALUES (?,?,?,?,?,'',?,?,1,0,0,?,1,1,0,?,?,0,?)")); + "source_scheme, source_port, last_update_utc) " + "VALUES (?,?,?,?,?,'',?,?,1,0,0,?,1,1,0,?,?,?)")); ASSERT_TRUE(stmt.is_valid()); base::Time creation(base::Time::Now()); diff --git a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc index 47c7112f8..d84031456 100644 --- a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc +++ b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc @@ -308,8 +308,8 @@ TEST_F(SQLitePersistentReportingAndNelStoreTest, TestInvalidMetaTableRecovery) { LoadNelPolicies(&policies); ASSERT_EQ(0U, policies.size()); - hist_tester.ExpectUniqueSample("Net.SQLite.CorruptMetaTableRecovered", true, - 1); + hist_tester.ExpectUniqueSample("ReportingAndNEL.CorruptMetaTableRecovered", + true, 1); // Verify that, after, recovery, the database persists properly. NetworkErrorLoggingService::NelPolicy policy2 = MakeNelPolicy( diff --git a/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc b/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc index 92ad36d8d..1e14dbdbb 100644 --- a/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc +++ b/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc @@ -11,6 +11,7 @@ #include "base/pickle.h" #include "base/strings/strcat.h" #include "base/task/sequenced_task_runner.h" +#include "base/types/expected_macros.h" #include "net/base/network_isolation_key.h" #include "net/extras/shared_dictionary/shared_dictionary_isolation_key.h" #include "net/extras/sqlite/sqlite_persistent_store_backend_base.h" @@ -563,10 +564,7 @@ SQLitePersistentSharedDictionaryStore::Backend::RegisterDictionaryImpl( return base::unexpected(error); } - SizeOrError total_dictionary_count_result = GetTotalDictionaryCount(); - if (!total_dictionary_count_result.has_value()) { - return base::unexpected(total_dictionary_count_result.error()); - } + ASSIGN_OR_RETURN(uint64_t total_dictionary_count, GetTotalDictionaryCount()); if (!transaction.Commit()) { return base::unexpected(Error::kFailedToCommitTransaction); @@ -575,7 +573,7 @@ SQLitePersistentSharedDictionaryStore::Backend::RegisterDictionaryImpl( id, replaced_disk_cache_key_token, std::set<base::UnguessableToken>(evicted_disk_cache_key_tokens.begin(), evicted_disk_cache_key_tokens.end()), - total_dictionary_size, total_dictionary_count_result.value()}); + total_dictionary_size, total_dictionary_count}); } SQLitePersistentSharedDictionaryStore::Error @@ -624,35 +622,32 @@ SQLitePersistentSharedDictionaryStore::Backend:: CHECK(primary_keys_out->empty()); CHECK(tokens_out->empty()); CHECK_EQ(0, *total_size_of_candidates_out); - SizeOrError size_per_site = GetDictionarySizePerSite(top_frame_site); - if (!size_per_site.has_value()) { - return size_per_site.error(); - } - SizeOrError count_per_site = GetDictionaryCountPerSite(top_frame_site); - if (!count_per_site.has_value()) { - return count_per_site.error(); - } + + ASSIGN_OR_RETURN(uint64_t size_per_site, + GetDictionarySizePerSite(top_frame_site)); + ASSIGN_OR_RETURN(uint64_t count_per_site, + GetDictionaryCountPerSite(top_frame_site)); base::UmaHistogramMemoryKB( base::StrCat({kHistogramPrefix, "DictionarySizeKBPerSiteWhenAdded"}), - size_per_site.value()); + size_per_site); base::UmaHistogramCounts1000( base::StrCat({kHistogramPrefix, "DictionaryCountPerSiteWhenAdded"}), - count_per_site.value()); + count_per_site); - if ((max_size_per_site == 0 || size_per_site.value() <= max_size_per_site) && - count_per_site.value() <= max_count_per_site) { + if ((max_size_per_site == 0 || size_per_site <= max_size_per_site) && + count_per_site <= max_count_per_site) { return Error::kOk; } uint64_t to_be_removed_count = 0; - if (count_per_site.value() > max_count_per_site) { - to_be_removed_count = count_per_site.value() - max_count_per_site; + if (count_per_site > max_count_per_site) { + to_be_removed_count = count_per_site - max_count_per_site; } int64_t to_be_removed_size = 0; - if (max_size_per_site != 0 && size_per_site.value() > max_size_per_site) { - to_be_removed_size = size_per_site.value() - max_size_per_site; + if (max_size_per_site != 0 && size_per_site > max_size_per_site) { + to_be_removed_size = size_per_site - max_size_per_site; } static constexpr char kQuery[] = // clang-format off @@ -1340,17 +1335,9 @@ SQLitePersistentSharedDictionaryStore::Backend::SelectEvictionCandidates( std::vector<int64_t>* primary_keys_out, std::vector<base::UnguessableToken>* tokens_out, int64_t* total_size_after_eviction_out) { - SizeOrError total_dictionary_size_result = GetTotalDictionarySizeImpl(); - if (!total_dictionary_size_result.has_value()) { - return total_dictionary_size_result.error(); - } - uint64_t total_dictionary_size = total_dictionary_size_result.value(); - - SizeOrError total_dictionary_count_result = GetTotalDictionaryCount(); - if (!total_dictionary_count_result.has_value()) { - return total_dictionary_count_result.error(); - } - uint64_t total_dictionary_count = total_dictionary_count_result.value(); + ASSIGN_OR_RETURN(uint64_t total_dictionary_size, + GetTotalDictionarySizeImpl()); + ASSIGN_OR_RETURN(uint64_t total_dictionary_count, GetTotalDictionaryCount()); if ((cache_max_size == 0 || total_dictionary_size <= cache_max_size) && total_dictionary_count <= cache_max_count) { @@ -1442,20 +1429,19 @@ SQLitePersistentSharedDictionaryStore::Backend:: return Error::kFailedToBeginTransaction; } - base::CheckedNumeric<int64_t> checked_total_dictionary_size; + base::CheckedNumeric<int64_t> checked_total_deleted_dictionary_size; for (const auto& token : disk_cache_key_tokens) { - SizeOrError result = DeleteDictionaryByDiskCacheToken(token); - if (!result.has_value()) { - return result.error(); - } - checked_total_dictionary_size += result.value(); + ASSIGN_OR_RETURN(uint64_t deleted_dictionary_size, + DeleteDictionaryByDiskCacheToken(token)); + checked_total_deleted_dictionary_size += deleted_dictionary_size; } - int64_t deleted_size = checked_total_dictionary_size.ValueOrDie(); - if (deleted_size != 0u) { + int64_t total_deleted_dictionary_size = + checked_total_deleted_dictionary_size.ValueOrDie(); + if (total_deleted_dictionary_size != 0) { uint64_t total_dictionary_size = 0; - Error error = UpdateTotalDictionarySizeInMetaTable(-deleted_size, - &total_dictionary_size); + Error error = UpdateTotalDictionarySizeInMetaTable( + -total_deleted_dictionary_size, &total_dictionary_size); if (error != Error::kOk) { return error; } @@ -1624,13 +1610,10 @@ SQLitePersistentSharedDictionaryStore::Backend:: UpdateTotalDictionarySizeInMetaTable(int64_t size_delta, uint64_t* total_dictionary_size_out) { CHECK(background_task_runner()->RunsTasksInCurrentSequence()); - SizeOrError total_dictionary_size_or_error = GetTotalDictionarySizeImpl(); - if (!total_dictionary_size_or_error.has_value()) { - return total_dictionary_size_or_error.error(); - } - + ASSIGN_OR_RETURN(uint64_t total_dictionary_size, + GetTotalDictionarySizeImpl()); base::CheckedNumeric<uint64_t> checked_total_dictionary_size = - total_dictionary_size_or_error.value(); + total_dictionary_size; checked_total_dictionary_size += size_delta; if (!checked_total_dictionary_size.IsValid()) { LOG(ERROR) << "Invalid total_dict_size detected."; diff --git a/net/extras/sqlite/sqlite_persistent_store_backend_base.cc b/net/extras/sqlite/sqlite_persistent_store_backend_base.cc index fa12f0088..1bd6bbb31 100644 --- a/net/extras/sqlite/sqlite_persistent_store_backend_base.cc +++ b/net/extras/sqlite/sqlite_persistent_store_backend_base.cc @@ -11,7 +11,6 @@ #include "base/functional/bind.h" #include "base/logging.h" #include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros_local.h" #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "base/timer/elapsed_timer.h" @@ -225,7 +224,8 @@ bool SQLitePersistentStoreBackendBase::MigrateDatabaseSchema() { bool recovered = sql::Database::Delete(path_) && db()->Open(path_) && meta_table_.Init(db(), current_version_number_, compatible_version_number_); - LOCAL_HISTOGRAM_BOOLEAN("Net.SQLite.CorruptMetaTableRecovered", recovered); + base::UmaHistogramBoolean(histogram_tag_ + ".CorruptMetaTableRecovered", + recovered); if (!recovered) { NOTREACHED() << "Unable to reset the " << histogram_tag_ << " DB."; meta_table_.Reset(); |