diff options
Diffstat (limited to 'chromium/content/browser/indexed_db')
26 files changed, 412 insertions, 200 deletions
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc index d02f5368073..94ee23ff221 100644 --- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc @@ -33,6 +33,7 @@ #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h" #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_iterator.h" #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_transaction.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom.h" #include "content/browser/indexed_db/indexed_db_active_blob_registry.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_data_format_version.h" @@ -51,7 +52,6 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_context.h" #include "storage/browser/blob/blob_data_handle.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom.h" #include "storage/browser/file_system/file_stream_writer.h" #include "storage/browser/file_system/file_writer_delegate.h" #include "storage/browser/file_system/local_file_stream_writer.h" @@ -91,6 +91,7 @@ using indexed_db::PutVarInt; using indexed_db::ReportOpenStatus; namespace { + FilePath GetBlobDirectoryName(const FilePath& path_base, int64_t database_id) { return path_base.AppendASCII(base::StringPrintf("%" PRIx64, database_id)); } @@ -426,9 +427,14 @@ Status DeleteBlobsInRange(IndexedDBBackingStore::Transaction* transaction, const std::string& start_key, const std::string& end_key, bool upper_open) { + Status s; std::unique_ptr<TransactionalLevelDBIterator> it = - transaction->transaction()->CreateIterator(); - Status s = it->Seek(start_key); + transaction->transaction()->CreateIterator(s); + if (!s.ok()) { + INTERNAL_WRITE_ERROR_UNTESTED(CREATE_ITERATOR); + return s; + } + s = it->Seek(start_key); for (; s.ok() && it->IsValid() && (upper_open ? CompareKeys(it->Key(), end_key) < 0 : CompareKeys(it->Key(), end_key) <= 0); @@ -1468,7 +1474,11 @@ Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber( ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey()); std::unique_ptr<TransactionalLevelDBIterator> it = - leveldb_transaction->CreateIterator(); + leveldb_transaction->CreateIterator(s); + if (!s.ok()) { + INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER); + return s; + } int64_t max_numeric_key = 0; for (s = it->Seek(start_key); @@ -1925,9 +1935,14 @@ Status IndexedDBBackingStore::FindKeyInIndex( transaction->transaction(); const std::string leveldb_key = IndexDataKey::Encode(database_id, object_store_id, index_id, key); + Status s; std::unique_ptr<TransactionalLevelDBIterator> it = - leveldb_transaction->CreateIterator(); - Status s = it->Seek(leveldb_key); + leveldb_transaction->CreateIterator(s); + if (!s.ok()) { + INTERNAL_WRITE_ERROR_UNTESTED(CREATE_ITERATOR); + return s; + } + s = it->Seek(leveldb_key); if (!s.ok()) { INTERNAL_READ_ERROR_UNTESTED(FIND_KEY_IN_INDEX); return s; @@ -2043,21 +2058,15 @@ Status IndexedDBBackingStore::KeyExistsInIndex( } IndexedDBBackingStore::Cursor::Cursor( - const IndexedDBBackingStore::Cursor* other) + const IndexedDBBackingStore::Cursor* other, + std::unique_ptr<TransactionalLevelDBIterator> iterator) : transaction_(other->transaction_), database_id_(other->database_id_), cursor_options_(other->cursor_options_), + iterator_(std::move(iterator)), current_key_(std::make_unique<IndexedDBKey>(*other->current_key_)) { DCHECK(transaction_); - if (other->iterator_) { - iterator_ = transaction_->transaction()->CreateIterator(); - - if (other->iterator_->IsValid()) { - Status s = iterator_->Seek(other->iterator_->Key()); - // TODO(cmumford): Handle this error (crbug.com/363397) - DCHECK(iterator_->IsValid()); - } - } + DCHECK(iterator_); } IndexedDBBackingStore::Cursor::Cursor(base::WeakPtr<Transaction> transaction, @@ -2068,12 +2077,43 @@ IndexedDBBackingStore::Cursor::Cursor(base::WeakPtr<Transaction> transaction, cursor_options_(cursor_options) { DCHECK(transaction_); } + IndexedDBBackingStore::Cursor::~Cursor() {} +std::unique_ptr<TransactionalLevelDBIterator> +IndexedDBBackingStore::Cursor::CloneIterator( + const IndexedDBBackingStore::Cursor* other) { + if (!other) + return nullptr; + if (!other->iterator_) + return nullptr; + + Status s; + auto iter = other->transaction_->transaction()->CreateIterator(s); + if (!s.ok()) { + INTERNAL_WRITE_ERROR_UNTESTED(CREATE_ITERATOR); + return nullptr; + } + + if (other->iterator_->IsValid()) { + s = iter->Seek(other->iterator_->Key()); + // TODO(cmumford): Handle this error (crbug.com/363397) + DCHECK(iter->IsValid()); + } + + return iter; +} + bool IndexedDBBackingStore::Cursor::FirstSeek(Status* s) { DCHECK_CALLED_ON_VALID_SEQUENCE(idb_sequence_checker_); DCHECK(transaction_); - iterator_ = transaction_->transaction()->CreateIterator(); + DCHECK(s); + iterator_ = transaction_->transaction()->CreateIterator(*s); + if (!s->ok()) { + INTERNAL_WRITE_ERROR_UNTESTED(CREATE_ITERATOR); + return false; + } + { IDB_TRACE("IndexedDBBackingStore::Cursor::FirstSeek::Seek"); if (cursor_options_.forward) @@ -2339,7 +2379,11 @@ class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor { std::unique_ptr<Cursor> Clone() const override { DCHECK_CALLED_ON_VALID_SEQUENCE(idb_sequence_checker_); - return base::WrapUnique(new ObjectStoreKeyCursorImpl(this)); + auto iter = CloneIterator(this); + if (!iter) + return nullptr; + return base::WrapUnique( + new ObjectStoreKeyCursorImpl(this, std::move(iter))); } // IndexedDBBackingStore::Cursor @@ -2362,8 +2406,10 @@ class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor { } private: - explicit ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other) - : IndexedDBBackingStore::Cursor(other) {} + explicit ObjectStoreKeyCursorImpl( + const ObjectStoreKeyCursorImpl* other, + std::unique_ptr<TransactionalLevelDBIterator> iterator) + : IndexedDBBackingStore::Cursor(other, std::move(iterator)) {} DISALLOW_COPY_AND_ASSIGN(ObjectStoreKeyCursorImpl); }; @@ -2418,7 +2464,10 @@ class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { std::unique_ptr<Cursor> Clone() const override { DCHECK_CALLED_ON_VALID_SEQUENCE(idb_sequence_checker_); - return base::WrapUnique(new ObjectStoreCursorImpl(this)); + auto iter = CloneIterator(this); + if (!iter) + return nullptr; + return base::WrapUnique(new ObjectStoreCursorImpl(this, std::move(iter))); } // IndexedDBBackingStore::Cursor @@ -2441,9 +2490,10 @@ class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { } private: - explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other) - : IndexedDBBackingStore::Cursor(other), - current_value_(other->current_value_) {} + explicit ObjectStoreCursorImpl( + const ObjectStoreCursorImpl* other, + std::unique_ptr<TransactionalLevelDBIterator> iterator) + : IndexedDBBackingStore::Cursor(other, std::move(iterator)) {} IndexedDBValue current_value_; @@ -2497,7 +2547,10 @@ class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { std::unique_ptr<Cursor> Clone() const override { DCHECK_CALLED_ON_VALID_SEQUENCE(idb_sequence_checker_); - return base::WrapUnique(new IndexKeyCursorImpl(this)); + auto iter = CloneIterator(this); + if (!iter) + return nullptr; + return base::WrapUnique(new IndexKeyCursorImpl(this, std::move(iter))); } // IndexedDBBackingStore::Cursor @@ -2532,8 +2585,10 @@ class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { } private: - explicit IndexKeyCursorImpl(const IndexKeyCursorImpl* other) - : IndexedDBBackingStore::Cursor(other), + explicit IndexKeyCursorImpl( + const IndexKeyCursorImpl* other, + std::unique_ptr<TransactionalLevelDBIterator> iterator) + : IndexedDBBackingStore::Cursor(other, std::move(iterator)), primary_key_(std::make_unique<IndexedDBKey>(*other->primary_key_)) {} std::unique_ptr<IndexedDBKey> primary_key_; @@ -2621,7 +2676,10 @@ class IndexCursorImpl : public IndexedDBBackingStore::Cursor { std::unique_ptr<Cursor> Clone() const override { DCHECK_CALLED_ON_VALID_SEQUENCE(idb_sequence_checker_); - return base::WrapUnique(new IndexCursorImpl(this)); + auto iter = CloneIterator(this); + if (!iter) + return nullptr; + return base::WrapUnique(new IndexCursorImpl(this, std::move(iter))); } // IndexedDBBackingStore::Cursor @@ -2656,8 +2714,10 @@ class IndexCursorImpl : public IndexedDBBackingStore::Cursor { } private: - explicit IndexCursorImpl(const IndexCursorImpl* other) - : IndexedDBBackingStore::Cursor(other), + explicit IndexCursorImpl( + const IndexCursorImpl* other, + std::unique_ptr<TransactionalLevelDBIterator> iterator) + : IndexedDBBackingStore::Cursor(other, std::move(iterator)), primary_key_(std::make_unique<IndexedDBKey>(*other->primary_key_)), current_value_(other->current_value_), primary_leveldb_key_(other->primary_leveldb_key_) {} diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_backing_store.h index 6862f7ab257..21bff56f02f 100644 --- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h +++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h @@ -25,6 +25,7 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "components/services/storage/indexed_db/scopes/scope_lock.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom-forward.h" #include "components/services/storage/public/mojom/native_file_system_context.mojom-forward.h" #include "content/browser/indexed_db/indexed_db.h" #include "content/browser/indexed_db/indexed_db_external_object.h" @@ -32,7 +33,6 @@ #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" #include "content/common/content_export.h" #include "storage/browser/blob/blob_data_handle.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom-forward.h" #include "storage/common/file_system/file_system_mount_option.h" #include "third_party/blink/public/common/indexeddb/indexeddb_key.h" #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" @@ -262,6 +262,7 @@ class CONTENT_EXPORT IndexedDBBackingStore { bool Advance(uint32_t count, leveldb::Status*); bool FirstSeek(leveldb::Status*); + // Clone may return a nullptr if cloning fails for any reason. virtual std::unique_ptr<Cursor> Clone() const = 0; virtual const blink::IndexedDBKey& primary_key() const; virtual IndexedDBValue* value() = 0; @@ -272,7 +273,12 @@ class CONTENT_EXPORT IndexedDBBackingStore { Cursor(base::WeakPtr<Transaction> transaction, int64_t database_id, const CursorOptions& cursor_options); - explicit Cursor(const IndexedDBBackingStore::Cursor* other); + explicit Cursor(const IndexedDBBackingStore::Cursor* other, + std::unique_ptr<TransactionalLevelDBIterator> iterator); + + // May return nullptr. + static std::unique_ptr<TransactionalLevelDBIterator> CloneIterator( + const IndexedDBBackingStore::Cursor* other); virtual std::string EncodeKey(const blink::IndexedDBKey& key) = 0; virtual std::string EncodeKey(const blink::IndexedDBKey& key, diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc index ba33ee14668..3a782cbeac1 100644 --- a/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc +++ b/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc @@ -271,14 +271,11 @@ class MockNativeFileSystemContext class IndexedDBBackingStoreTest : public testing::Test { public: IndexedDBBackingStoreTest() - : special_storage_policy_( - base::MakeRefCounted<storage::MockSpecialStoragePolicy>()), - quota_manager_proxy_( + : quota_manager_proxy_( base::MakeRefCounted<storage::MockQuotaManagerProxy>(nullptr, nullptr)) {} void SetUp() override { - special_storage_policy_->SetAllUnlimited(true); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); blob_context_ = std::make_unique<MockBlobStorageContext>(); @@ -286,7 +283,7 @@ class IndexedDBBackingStoreTest : public testing::Test { std::make_unique<MockNativeFileSystemContext>(); idb_context_ = base::MakeRefCounted<IndexedDBContextImpl>( - temp_dir_.GetPath(), special_storage_policy_, quota_manager_proxy_, + temp_dir_.GetPath(), quota_manager_proxy_, base::DefaultClock::GetInstance(), /*blob_storage_context=*/mojo::NullRemote(), /*native_file_system_context=*/mojo::NullRemote(), @@ -423,7 +420,6 @@ class IndexedDBBackingStoreTest : public testing::Test { base::ScopedTempDir temp_dir_; std::unique_ptr<MockBlobStorageContext> blob_context_; std::unique_ptr<MockNativeFileSystemContext> native_file_system_context_; - scoped_refptr<storage::MockSpecialStoragePolicy> special_storage_policy_; scoped_refptr<storage::MockQuotaManagerProxy> quota_manager_proxy_; scoped_refptr<IndexedDBContextImpl> idb_context_; std::unique_ptr<TestIDBFactory> idb_factory_; diff --git a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc index d05598c4303..2eaadd5261b 100644 --- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc +++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc @@ -21,7 +21,6 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/utf_string_conversions.h" -#include "base/task/post_task.h" #include "base/test/bind_test_util.h" #include "base/test/thread_test_helper.h" #include "base/threading/thread_restrictions.h" @@ -183,8 +182,8 @@ class IndexedDBBrowserTest : public ContentBrowserTest, static void SetTempQuota(int per_host_quota_kilobytes, scoped_refptr<QuotaManager> qm) { if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&IndexedDBBrowserTest::SetTempQuota, + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&IndexedDBBrowserTest::SetTempQuota, per_host_quota_kilobytes, qm)); return; } diff --git a/chromium/content/browser/indexed_db/indexed_db_callback_helpers.h b/chromium/content/browser/indexed_db/indexed_db_callback_helpers.h index b63fb72517b..dfd7805ae65 100644 --- a/chromium/content/browser/indexed_db/indexed_db_callback_helpers.h +++ b/chromium/content/browser/indexed_db/indexed_db_callback_helpers.h @@ -8,7 +8,7 @@ #include <memory> #include <utility> -#include "base/logging.h" +#include "base/check.h" #include "base/memory/weak_ptr.h" #include "content/browser/indexed_db/indexed_db_transaction.h" #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-forward.h" diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.h b/chromium/content/browser/indexed_db/indexed_db_callbacks.h index e487d26140a..c2c0b746a3f 100644 --- a/chromium/content/browser/indexed_db/indexed_db_callbacks.h +++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.h @@ -11,7 +11,7 @@ #include <string> #include <vector> -#include "base/logging.h" +#include "base/check.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc index 1f0b7d1fe2f..264ea5e5812 100644 --- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc +++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc @@ -41,8 +41,10 @@ #include "content/browser/indexed_db/indexed_db_transaction.h" #include "content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h" #include "storage/browser/database/database_util.h" +#include "storage/browser/quota/quota_client_type.h" #include "storage/common/database/database_identifier.h" #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "third_party/zlib/google/zip.h" #include "url/origin.h" @@ -107,7 +109,6 @@ void GetAllOriginsAndPaths(const base::FilePath& indexeddb_path, IndexedDBContextImpl::IndexedDBContextImpl( const base::FilePath& data_path, - scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, base::Clock* clock, mojo::PendingRemote<storage::mojom::BlobStorageContext> @@ -126,7 +127,6 @@ IndexedDBContextImpl::IndexedDBContextImpl( base::TaskShutdownBehavior::BLOCK_SHUTDOWN}))), indexed_db_factory_(this), force_keep_session_state_(false), - special_storage_policy_(special_storage_policy), quota_manager_proxy_(quota_manager_proxy), io_task_runner_(io_task_runner), clock_(clock) { @@ -134,7 +134,9 @@ IndexedDBContextImpl::IndexedDBContextImpl( if (!data_path.empty()) data_path_ = data_path.Append(kIndexedDBDirectory); quota_manager_proxy->RegisterClient( - base::MakeRefCounted<IndexedDBQuotaClient>(this)); + base::MakeRefCounted<IndexedDBQuotaClient>(this), + storage::QuotaClientType::kIndexedDatabase, + {blink::mojom::StorageType::kTemporary}); // This is safe because the IndexedDBContextImpl must be destructed on the // IDBTaskRunner, and this task will always happen before that. @@ -425,6 +427,17 @@ void IndexedDBContextImpl::SetForceKeepSessionState() { force_keep_session_state_ = true; } +void IndexedDBContextImpl::ApplyPolicyUpdates( + std::vector<storage::mojom::IndexedDBStoragePolicyUpdatePtr> + policy_updates) { + for (const auto& update : policy_updates) { + if (!update->purge_on_shutdown) + origins_to_purge_on_shutdown_.erase(update->origin); + else + origins_to_purge_on_shutdown_.insert(std::move(update->origin)); + } +} + void IndexedDBContextImpl::BindTestInterface( mojo::PendingReceiver<storage::mojom::IndexedDBControlTest> receiver) { DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); @@ -490,6 +503,7 @@ void IndexedDBContextImpl::HasV2SchemaCorruptionForTesting( if (is_incognito() || !HasOrigin(origin)) { std::move(callback).Run( storage::mojom::V2SchemaCorruptionStatus::CORRUPTION_UNKNOWN); + return; } if (indexeddb_factory_.get()) { @@ -793,37 +807,32 @@ void IndexedDBContextImpl::Shutdown() { return; // Clear session-only databases. - if (special_storage_policy_ && - special_storage_policy_->HasSessionOnlyOrigins()) { - IDBTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce( - [](const base::FilePath& indexeddb_path, - scoped_refptr<IndexedDBContextImpl> context, - scoped_refptr<storage::SpecialStoragePolicy> - special_storage_policy) { - std::vector<Origin> origins; - std::vector<base::FilePath> file_paths; - // This function only needs the factory, and not the context, but - // the context is used because passing that is thread-safe. - IndexedDBFactoryImpl* factory = context->GetIDBFactory(); - GetAllOriginsAndPaths(indexeddb_path, &origins, &file_paths); - DCHECK_EQ(origins.size(), file_paths.size()); - auto file_path = file_paths.cbegin(); - auto origin = origins.cbegin(); - for (; origin != origins.cend(); ++origin, ++file_path) { - const GURL origin_url = GURL(origin->Serialize()); - if (!special_storage_policy->IsStorageSessionOnly(origin_url)) - continue; - if (special_storage_policy->IsStorageProtected(origin_url)) - continue; - if (factory) - factory->ForceClose(*origin, false); - base::DeleteFileRecursively(*file_path); - } - }, - data_path_, base::WrapRefCounted(this), special_storage_policy_)); - } + if (origins_to_purge_on_shutdown_.empty()) + return; + + IDBTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce( + [](scoped_refptr<IndexedDBContextImpl> context) { + std::vector<Origin> origins; + std::vector<base::FilePath> file_paths; + // This function only needs the factory, and not the context, but + // the context is used because passing that is thread-safe. + IndexedDBFactoryImpl* factory = context->GetIDBFactory(); + GetAllOriginsAndPaths(context->data_path_, &origins, &file_paths); + DCHECK_EQ(origins.size(), file_paths.size()); + + auto file_path = file_paths.cbegin(); + auto origin = origins.cbegin(); + for (; origin != origins.cend(); ++origin, ++file_path) { + if (context->origins_to_purge_on_shutdown_.find(*origin) == + context->origins_to_purge_on_shutdown_.end()) + continue; + factory->ForceClose(*origin, false); + base::DeleteFileRecursively(*file_path); + } + }, + base::WrapRefCounted(this))); } base::FilePath IndexedDBContextImpl::GetBlobStorePath( diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.h b/chromium/content/browser/indexed_db/indexed_db_context_impl.h index ab7b2ea7115..7a862de5fbb 100644 --- a/chromium/content/browser/indexed_db/indexed_db_context_impl.h +++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.h @@ -19,6 +19,7 @@ #include "base/macros.h" #include "base/memory/ref_counted_delete_on_sequence.h" #include "base/strings/string16.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom.h" #include "components/services/storage/public/mojom/indexed_db_control.mojom.h" #include "components/services/storage/public/mojom/indexed_db_control_test.mojom.h" #include "components/services/storage/public/mojom/native_file_system_context.mojom.h" @@ -28,7 +29,6 @@ #include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/remote_set.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/quota/special_storage_policy.h" #include "url/origin.h" @@ -61,7 +61,6 @@ class CONTENT_EXPORT IndexedDBContextImpl // This is *not* called on the IDBTaskRunner, unlike most other functions. IndexedDBContextImpl( const base::FilePath& data_path, - scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, base::Clock* clock, mojo::PendingRemote<storage::mojom::BlobStorageContext> @@ -89,6 +88,9 @@ class CONTENT_EXPORT IndexedDBContextImpl DownloadOriginDataCallback callback) override; void GetAllOriginsDetails(GetAllOriginsDetailsCallback callback) override; void SetForceKeepSessionState() override; + void ApplyPolicyUpdates( + std::vector<storage::mojom::IndexedDBStoragePolicyUpdatePtr> + policy_updates) override; void BindTestInterface( mojo::PendingReceiver<storage::mojom::IndexedDBControlTest> receiver) override; @@ -251,6 +253,8 @@ class CONTENT_EXPORT IndexedDBContextImpl scoped_refptr<base::SequencedTaskRunner> io_task_runner_; std::unique_ptr<std::set<url::Origin>> origin_set_; std::map<url::Origin, int64_t> origin_size_map_; + // The set of origins whose storage should be cleared on shutdown. + std::set<url::Origin> origins_to_purge_on_shutdown_; base::Clock* clock_; mojo::ReceiverSet<storage::mojom::IndexedDBControl> receivers_; diff --git a/chromium/content/browser/indexed_db/indexed_db_control_wrapper.cc b/chromium/content/browser/indexed_db/indexed_db_control_wrapper.cc index e187c7e8c4e..af11a211032 100644 --- a/chromium/content/browser/indexed_db/indexed_db_control_wrapper.cc +++ b/chromium/content/browser/indexed_db/indexed_db_control_wrapper.cc @@ -4,23 +4,85 @@ #include "content/browser/indexed_db/indexed_db_control_wrapper.h" +#include "base/task/post_task.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" + namespace content { +// Observer for the SpecialStoragePolicy on the IO thread. +class IndexedDBControlWrapper::StoragePolicyObserver + : public storage::SpecialStoragePolicy::Observer { + public: + explicit StoragePolicyObserver( + scoped_refptr<base::SequencedTaskRunner> reply_task_runner, + scoped_refptr<storage::SpecialStoragePolicy> storage_policy, + base::WeakPtr<IndexedDBControlWrapper> control_wrapper) + : reply_task_runner_(std::move(reply_task_runner)), + storage_policy_(std::move(storage_policy)), + control_wrapper_(std::move(control_wrapper)) { + storage_policy_->AddObserver(this); + } + + ~StoragePolicyObserver() override { storage_policy_->RemoveObserver(this); } + + // storage::SpecialStoragePolicy::Observer implementation: + void OnPolicyChanged() override { + reply_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&IndexedDBControlWrapper::OnSpecialStoragePolicyChanged, + control_wrapper_)); + } + + private: + scoped_refptr<base::SequencedTaskRunner> reply_task_runner_; + scoped_refptr<storage::SpecialStoragePolicy> storage_policy_; + + // control_wrapper_ is bound to the reply_task_runner sequence, + // so should not be checked other than on that sequence. + base::WeakPtr<IndexedDBControlWrapper> control_wrapper_; +}; + IndexedDBControlWrapper::IndexedDBControlWrapper( - scoped_refptr<IndexedDBContextImpl> context) - : context_(std::move(context)) {} + const base::FilePath& data_path, + scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, + scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, + base::Clock* clock, + mojo::PendingRemote<storage::mojom::BlobStorageContext> + blob_storage_context, + mojo::PendingRemote<storage::mojom::NativeFileSystemContext> + native_file_system_context, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, + scoped_refptr<base::SequencedTaskRunner> custom_task_runner) + : special_storage_policy_(std::move(special_storage_policy)) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + context_ = base::MakeRefCounted<IndexedDBContextImpl>( + data_path, std::move(quota_manager_proxy), clock, + std::move(blob_storage_context), std::move(native_file_system_context), + io_task_runner, std::move(custom_task_runner)); + + if (special_storage_policy_) { + storage_policy_observer_ = base::SequenceBound<StoragePolicyObserver>( + io_task_runner, base::SequencedTaskRunnerHandle::Get(), + special_storage_policy_, weak_factory_.GetWeakPtr()); + } +} -IndexedDBControlWrapper::~IndexedDBControlWrapper() = default; +IndexedDBControlWrapper::~IndexedDBControlWrapper() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} void IndexedDBControlWrapper::BindIndexedDB( const url::Origin& origin, mojo::PendingReceiver<blink::mojom::IDBFactory> receiver) { - // TODO(enne): track special storage policy here. + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); + TrackOriginPolicyState(origin); indexed_db_control_->BindIndexedDB(origin, std::move(receiver)); } void IndexedDBControlWrapper::GetUsage(GetUsageCallback usage_callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); indexed_db_control_->GetUsage(std::move(usage_callback)); } @@ -28,6 +90,7 @@ void IndexedDBControlWrapper::GetUsage(GetUsageCallback usage_callback) { void IndexedDBControlWrapper::DeleteForOrigin( const url::Origin& origin, DeleteForOriginCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); indexed_db_control_->DeleteForOrigin(origin, std::move(callback)); } @@ -36,6 +99,7 @@ void IndexedDBControlWrapper::ForceClose( const url::Origin& origin, storage::mojom::ForceCloseReason reason, base::OnceClosure callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); indexed_db_control_->ForceClose(origin, reason, std::move(callback)); } @@ -43,6 +107,7 @@ void IndexedDBControlWrapper::ForceClose( void IndexedDBControlWrapper::GetConnectionCount( const url::Origin& origin, GetConnectionCountCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); indexed_db_control_->GetConnectionCount(origin, std::move(callback)); } @@ -50,34 +115,90 @@ void IndexedDBControlWrapper::GetConnectionCount( void IndexedDBControlWrapper::DownloadOriginData( const url::Origin& origin, DownloadOriginDataCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); indexed_db_control_->DownloadOriginData(origin, std::move(callback)); } void IndexedDBControlWrapper::GetAllOriginsDetails( GetAllOriginsDetailsCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); indexed_db_control_->GetAllOriginsDetails(std::move(callback)); } void IndexedDBControlWrapper::SetForceKeepSessionState() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); indexed_db_control_->SetForceKeepSessionState(); } +void IndexedDBControlWrapper::ApplyPolicyUpdates( + std::vector<storage::mojom::IndexedDBStoragePolicyUpdatePtr> + policy_updates) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + BindRemoteIfNeeded(); + indexed_db_control_->ApplyPolicyUpdates(std::move(policy_updates)); +} + void IndexedDBControlWrapper::BindTestInterface( mojo::PendingReceiver<storage::mojom::IndexedDBControlTest> receiver) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); indexed_db_control_->BindTestInterface(std::move(receiver)); } void IndexedDBControlWrapper::AddObserver( mojo::PendingRemote<storage::mojom::IndexedDBObserver> observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BindRemoteIfNeeded(); indexed_db_control_->AddObserver(std::move(observer)); } +void IndexedDBControlWrapper::OnSpecialStoragePolicyChanged() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + BindRemoteIfNeeded(); + + std::vector<storage::mojom::IndexedDBStoragePolicyUpdatePtr> policy_updates; + for (auto& entry : origin_state_) { + const GURL& origin = entry.first; + OriginState& state = entry.second; + state.should_purge_on_shutdown = ShouldPurgeOnShutdown(origin); + + if (state.should_purge_on_shutdown != state.will_purge_on_shutdown) { + state.will_purge_on_shutdown = state.should_purge_on_shutdown; + policy_updates.push_back( + storage::mojom::IndexedDBStoragePolicyUpdate::New( + url::Origin::Create(origin), state.should_purge_on_shutdown)); + } + } + if (!policy_updates.empty()) + ApplyPolicyUpdates(std::move(policy_updates)); +} + +void IndexedDBControlWrapper::TrackOriginPolicyState( + const url::Origin& origin) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + const GURL origin_url = GURL(origin.Serialize()); + auto it = origin_state_.find(origin_url); + if (it == origin_state_.end()) + origin_state_[origin_url] = {}; + OnSpecialStoragePolicyChanged(); +} + +bool IndexedDBControlWrapper::ShouldPurgeOnShutdown(const GURL& origin) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!special_storage_policy_) + return false; + if (!special_storage_policy_->IsStorageSessionOnly(origin)) + return false; + if (special_storage_policy_->IsStorageProtected(origin)) + return false; + return true; +} + void IndexedDBControlWrapper::BindRemoteIfNeeded() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK( !(indexed_db_control_.is_bound() && !indexed_db_control_.is_connected())) << "Rebinding is not supported yet."; diff --git a/chromium/content/browser/indexed_db/indexed_db_control_wrapper.h b/chromium/content/browser/indexed_db/indexed_db_control_wrapper.h index 5457ed16c76..96730777eb2 100644 --- a/chromium/content/browser/indexed_db/indexed_db_control_wrapper.h +++ b/chromium/content/browser/indexed_db/indexed_db_control_wrapper.h @@ -5,15 +5,27 @@ #ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CONTROL_WRAPPER_H_ #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CONTROL_WRAPPER_H_ +#include "base/threading/sequence_bound.h" #include "components/services/storage/public/mojom/indexed_db_control.mojom.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" namespace content { +// All functions should be called on the UI thread. class CONTENT_EXPORT IndexedDBControlWrapper : public storage::mojom::IndexedDBControl { public: - explicit IndexedDBControlWrapper(scoped_refptr<IndexedDBContextImpl> context); + explicit IndexedDBControlWrapper( + const base::FilePath& data_path, + scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, + scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, + base::Clock* clock, + mojo::PendingRemote<storage::mojom::BlobStorageContext> + blob_storage_context, + mojo::PendingRemote<storage::mojom::NativeFileSystemContext> + native_file_system_context, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, + scoped_refptr<base::SequencedTaskRunner> custom_task_runner); ~IndexedDBControlWrapper() override; // mojom::IndexedDBControl implementation: @@ -32,6 +44,9 @@ class CONTENT_EXPORT IndexedDBControlWrapper DownloadOriginDataCallback callback) override; void GetAllOriginsDetails(GetAllOriginsDetailsCallback callback) override; void SetForceKeepSessionState() override; + void ApplyPolicyUpdates( + std::vector<storage::mojom::IndexedDBStoragePolicyUpdatePtr> + policy_updates) override; void BindTestInterface( mojo::PendingReceiver<storage::mojom::IndexedDBControlTest> receiver) override; @@ -42,11 +57,36 @@ class CONTENT_EXPORT IndexedDBControlWrapper IndexedDBContextImpl* GetIndexedDBContextInternal() { return context_.get(); } private: + void OnSpecialStoragePolicyChanged(); + void TrackOriginPolicyState(const url::Origin& origin); + bool ShouldPurgeOnShutdown(const GURL& origin); void BindRemoteIfNeeded(); + // Special storage policy may be null. + scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_; + + // Observer for the SpecialStoragePolicy on the IO thread. May be null. + class StoragePolicyObserver; + base::SequenceBound<StoragePolicyObserver> storage_policy_observer_; + mojo::Remote<storage::mojom::IndexedDBControl> indexed_db_control_; scoped_refptr<IndexedDBContextImpl> context_; + struct OriginState { + // Indicates that storage for this origin should be purged on shutdown. + bool should_purge_on_shutdown = false; + // Indicates the last value for |purge_on_shutdown| communicated to the + // IndexedDB implementation. + bool will_purge_on_shutdown = false; + }; + // NOTE: The GURL key is specifically an origin GURL. + // Special storage policy uses GURLs and not Origins, so it's simpler + // to store everything in GURL form. + std::map<GURL, OriginState> origin_state_; + + SEQUENCE_CHECKER(sequence_checker_); + base::WeakPtrFactory<IndexedDBControlWrapper> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(IndexedDBControlWrapper); }; diff --git a/chromium/content/browser/indexed_db/indexed_db_data_format_version.h b/chromium/content/browser/indexed_db/indexed_db_data_format_version.h index 72d09dbc79f..ed8f6cf9ef3 100644 --- a/chromium/content/browser/indexed_db/indexed_db_data_format_version.h +++ b/chromium/content/browser/indexed_db/indexed_db_data_format_version.h @@ -8,7 +8,7 @@ #include <cstdint> #include <limits> -#include "base/logging.h" +#include "base/check_op.h" #include "content/common/content_export.h" namespace content { diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h index 8aeebcdfef0..05b06c170c8 100644 --- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h +++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h @@ -16,6 +16,7 @@ #include "base/macros.h" #include "base/sequence_checker.h" #include "base/strings/string16.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom-forward.h" #include "components/services/storage/public/mojom/native_file_system_context.mojom-forward.h" #include "content/browser/indexed_db/indexed_db_external_object.h" #include "content/common/content_export.h" @@ -23,7 +24,6 @@ #include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/unique_associated_receiver_set.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom-forward.h" #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" #include "url/origin.h" diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc index 49795b37524..a546cfe2164 100644 --- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc +++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc @@ -179,7 +179,6 @@ class IndexedDBDispatcherHostTest : public testing::Test { special_storage_policy_)), context_impl_(base::MakeRefCounted<IndexedDBContextImpl>( temp_dir_.GetPath(), - special_storage_policy_, quota_manager_->proxy(), base::DefaultClock::GetInstance(), mojo::NullRemote(), diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc index 017d721550b..688d957577b 100644 --- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc +++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc @@ -38,6 +38,7 @@ #include "components/services/storage/indexed_db/scopes/leveldb_scopes_factory.h" #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h" #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom.h" #include "components/services/storage/public/mojom/indexed_db_control.mojom.h" #include "content/browser/indexed_db/indexed_db_class_factory.h" #include "content/browser/indexed_db/indexed_db_connection.h" @@ -52,7 +53,6 @@ #include "content/browser/indexed_db/indexed_db_task_helper.h" #include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h" #include "content/browser/indexed_db/indexed_db_tracing.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom.h" #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" #include "third_party/leveldatabase/env_chromium.h" diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h index 2a0c0414869..b1590b6e3bf 100644 --- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h +++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h @@ -24,6 +24,7 @@ #include "base/time/time.h" #include "base/trace_event/memory_dump_provider.h" #include "components/services/storage/indexed_db/scopes/leveldb_scopes_factory.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom-forward.h" #include "components/services/storage/public/mojom/native_file_system_context.mojom-forward.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_data_loss_info.h" @@ -31,7 +32,6 @@ #include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_origin_state_handle.h" #include "content/browser/indexed_db/indexed_db_task_helper.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom-forward.h" #include "third_party/leveldatabase/src/include/leveldb/status.h" #include "url/origin.h" diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc index 176b39499b9..cfc1b4190ea 100644 --- a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc +++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc @@ -110,8 +110,7 @@ class IndexedDBFactoryTest : public testing::Test { void SetupContext() { context_ = base::MakeRefCounted<IndexedDBContextImpl>( - temp_dir_.GetPath(), - /*special_storage_policy=*/nullptr, quota_manager_proxy_.get(), + temp_dir_.GetPath(), quota_manager_proxy_.get(), base::DefaultClock::GetInstance(), /*blob_storage_context=*/mojo::NullRemote(), /*native_file_system_context=*/mojo::NullRemote(), @@ -121,8 +120,7 @@ class IndexedDBFactoryTest : public testing::Test { void SetupInMemoryContext() { context_ = base::MakeRefCounted<IndexedDBContextImpl>( - base::FilePath(), - /*special_storage_policy=*/nullptr, quota_manager_proxy_.get(), + base::FilePath(), quota_manager_proxy_.get(), base::DefaultClock::GetInstance(), /*blob_storage_context=*/mojo::NullRemote(), /*native_file_system_context=*/mojo::NullRemote(), @@ -132,8 +130,7 @@ class IndexedDBFactoryTest : public testing::Test { void SetupContextWithFactories(LevelDBFactory* factory, base::Clock* clock) { context_ = base::MakeRefCounted<IndexedDBContextImpl>( - temp_dir_.GetPath(), - /*special_storage_policy=*/nullptr, quota_manager_proxy_.get(), clock, + temp_dir_.GetPath(), quota_manager_proxy_.get(), clock, /*blob_storage_context=*/mojo::NullRemote(), /*native_file_system_context=*/mojo::NullRemote(), base::SequencedTaskRunnerHandle::Get(), diff --git a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc index 8af1508cefe..b67daae10b6 100644 --- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc +++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc @@ -27,6 +27,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/url_constants.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "storage/common/database/database_identifier.h" #include "ui/base/text/bytes_formatting.h" #include "url/origin.h" @@ -50,7 +51,8 @@ IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui) base::Unretained(this))); WebUIDataSource* source = WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->UseStringsJs(); source->AddResourcePath("indexeddb_internals.js", @@ -317,8 +319,8 @@ FileDeleter::~FileDeleter() { FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, - base::BindOnce(base::IgnoreResult(&base::DeleteFile), - std::move(temp_dir_), true)); + base::BindOnce(base::GetDeletePathRecursivelyCallback(), + std::move(temp_dir_))); } void IndexedDBInternalsUI::OnDownloadStarted( diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h index c1906f62f56..43581e91c66 100644 --- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h +++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h @@ -13,7 +13,6 @@ #include <utility> #include <vector> -#include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/strings/string16.h" diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.cc index ad4254bd96b..f9ba1ff3980 100644 --- a/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.cc +++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_operations.cc @@ -122,11 +122,12 @@ std::string ReadCorruptionInfo(const base::FilePath& path_base, if (file.IsValid()) { std::string input_js(file_size, '\0'); if (file_size == file.Read(0, base::data(input_js), file_size)) { - base::JSONReader reader; - std::unique_ptr<base::DictionaryValue> val( - base::DictionaryValue::From(reader.ReadToValueDeprecated(input_js))); - if (val) - val->GetString("message", &message); + base::Optional<base::Value> val = base::JSONReader::Read(input_js); + if (val && val->is_dict()) { + std::string* s = val->FindStringKey("message"); + if (s) + message = *s; + } } file.Close(); } @@ -466,7 +467,12 @@ bool FindGreatestKeyLessThanOrEqual( std::string* found_key, Status* s) { std::unique_ptr<TransactionalLevelDBIterator> it = - transaction->CreateIterator(); + transaction->CreateIterator(*s); + if (!s->ok()) { + INTERNAL_WRITE_ERROR_UNTESTED(CREATE_ITERATOR); + return false; + } + *s = it->Seek(target); if (!s->ok()) return false; diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata_coding.cc b/chromium/content/browser/indexed_db/indexed_db_metadata_coding.cc index 22c45237912..e7e4b786146 100644 --- a/chromium/content/browser/indexed_db/indexed_db_metadata_coding.cc +++ b/chromium/content/browser/indexed_db/indexed_db_metadata_coding.cc @@ -45,13 +45,16 @@ using indexed_db::PutVarInt; namespace { std::unique_ptr<TransactionalLevelDBIterator> CreateIterator( - TransactionalLevelDBDatabase* database) { - return database->CreateIterator(database->DefaultReadOptions()); + TransactionalLevelDBDatabase& database, + Status& status) { + status = Status(); + return database.CreateIterator(database.DefaultReadOptions()); } std::unique_ptr<TransactionalLevelDBIterator> CreateIterator( - TransactionalLevelDBTransaction* transaction) { - return transaction->CreateIterator(); + TransactionalLevelDBTransaction& transaction, + Status& status) { + return transaction.CreateIterator(status); } // Reads all indexes for the given database and object store in |indexes|. @@ -71,9 +74,14 @@ Status ReadIndexes(DatabaseOrTransaction* db_or_transaction, DCHECK(indexes->empty()); + Status s; std::unique_ptr<TransactionalLevelDBIterator> it = - CreateIterator(db_or_transaction); - Status s = it->Seek(start_key); + CreateIterator(*db_or_transaction, s); + if (!s.ok()) { + INTERNAL_WRITE_ERROR_UNTESTED(CREATE_ITERATOR); + return s; + } + s = it->Seek(start_key); while (s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) { IndexMetaDataKey meta_data_key; { @@ -174,9 +182,14 @@ Status ReadObjectStores( DCHECK(object_stores->empty()); + Status s; std::unique_ptr<TransactionalLevelDBIterator> it = - CreateIterator(db_or_transaction); - Status s = it->Seek(start_key); + CreateIterator(*db_or_transaction, s); + if (!s.ok()) { + INTERNAL_WRITE_ERROR_UNTESTED(CREATE_ITERATOR); + return s; + } + s = it->Seek(start_key); while (s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) { ObjectStoreMetaDataKey meta_data_key; { @@ -344,9 +357,13 @@ Status ReadDatabaseNamesAndVersionsInternal( DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier); DCHECK(names_and_versions->empty()); - std::unique_ptr<TransactionalLevelDBIterator> it = - CreateIterator(db_or_transaction); Status s; + std::unique_ptr<TransactionalLevelDBIterator> it = + CreateIterator(*db_or_transaction, s); + if (!s.ok()) { + INTERNAL_WRITE_ERROR_UNTESTED(CREATE_ITERATOR); + return s; + } for (s = it->Seek(start_key); s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; s = it->Next()) { diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client.cc index f35ae3da5a9..70ba56f959e 100644 --- a/chromium/content/browser/indexed_db/indexed_db_quota_client.cc +++ b/chromium/content/browser/indexed_db/indexed_db_quota_client.cc @@ -15,9 +15,10 @@ #include "base/task_runner_util.h" #include "base/threading/sequenced_task_runner_handle.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" -#include "net/base/url_util.h" #include "storage/browser/database/database_util.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" +#include "url/origin.h" using blink::mojom::StorageType; using storage::DatabaseUtil; @@ -60,8 +61,7 @@ void GetOriginsForHostOnIndexedDBThread( std::set<url::Origin>* origins_to_return) { DCHECK(context->IDBTaskRunner()->RunsTasksInCurrentSequence()); for (const auto& origin : context->GetAllOrigins()) { - GURL origin_url(origin.Serialize()); - if (host == net::GetHostOrSpecFromURL(origin_url)) + if (host == origin.host()) origins_to_return->insert(origin); } } @@ -78,22 +78,13 @@ IndexedDBQuotaClient::IndexedDBQuotaClient( IndexedDBQuotaClient::~IndexedDBQuotaClient() = default; -storage::QuotaClientType IndexedDBQuotaClient::type() const { - return storage::QuotaClientType::kIndexedDatabase; -} - void IndexedDBQuotaClient::OnQuotaManagerDestroyed() {} void IndexedDBQuotaClient::GetOriginUsage(const url::Origin& origin, StorageType type, GetUsageCallback callback) { DCHECK(!callback.is_null()); - - // IndexedDB is in the temp namespace for now. - if (type != StorageType::kTemporary) { - std::move(callback).Run(0); - return; - } + DCHECK_EQ(type, StorageType::kTemporary); base::PostTaskAndReplyWithResult( indexed_db_context_->IDBTaskRunner(), FROM_HERE, @@ -105,12 +96,7 @@ void IndexedDBQuotaClient::GetOriginUsage(const url::Origin& origin, void IndexedDBQuotaClient::GetOriginsForType(StorageType type, GetOriginsCallback callback) { DCHECK(!callback.is_null()); - - // All databases are in the temp namespace for now. - if (type != StorageType::kTemporary) { - std::move(callback).Run(std::set<url::Origin>()); - return; - } + DCHECK_EQ(type, StorageType::kTemporary); std::set<url::Origin>* origins_to_return = new std::set<url::Origin>(); indexed_db_context_->IDBTaskRunner()->PostTaskAndReply( @@ -126,12 +112,7 @@ void IndexedDBQuotaClient::GetOriginsForHost(StorageType type, const std::string& host, GetOriginsCallback callback) { DCHECK(!callback.is_null()); - - // All databases are in the temp namespace for now. - if (type != StorageType::kTemporary) { - std::move(callback).Run(std::set<url::Origin>()); - return; - } + DCHECK_EQ(type, StorageType::kTemporary); std::set<url::Origin>* origins_to_return = new std::set<url::Origin>(); indexed_db_context_->IDBTaskRunner()->PostTaskAndReply( @@ -146,10 +127,8 @@ void IndexedDBQuotaClient::GetOriginsForHost(StorageType type, void IndexedDBQuotaClient::DeleteOriginData(const url::Origin& origin, StorageType type, DeletionCallback callback) { - if (type != StorageType::kTemporary) { - std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk); - return; - } + DCHECK(!callback.is_null()); + DCHECK_EQ(type, StorageType::kTemporary); indexed_db_context_->IDBTaskRunner()->PostTask( FROM_HERE, @@ -165,8 +144,4 @@ void IndexedDBQuotaClient::PerformStorageCleanup(blink::mojom::StorageType type, std::move(callback).Run(); } -bool IndexedDBQuotaClient::DoesSupport(StorageType type) const { - return type == StorageType::kTemporary; -} - } // namespace content diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client.h b/chromium/content/browser/indexed_db/indexed_db_quota_client.h index fe85dc97592..28b40b96c93 100644 --- a/chromium/content/browser/indexed_db/indexed_db_quota_client.h +++ b/chromium/content/browser/indexed_db/indexed_db_quota_client.h @@ -30,7 +30,6 @@ class IndexedDBQuotaClient : public storage::QuotaClient { scoped_refptr<IndexedDBContextImpl> indexed_db_context); // QuotaClient implementation: - storage::QuotaClientType type() const override; void OnQuotaManagerDestroyed() override; void GetOriginUsage(const url::Origin& origin, blink::mojom::StorageType type, @@ -45,7 +44,6 @@ class IndexedDBQuotaClient : public storage::QuotaClient { DeletionCallback callback) override; void PerformStorageCleanup(blink::mojom::StorageType type, base::OnceClosure callback) override; - bool DoesSupport(blink::mojom::StorageType type) const override; private: ~IndexedDBQuotaClient() override; diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc index 4bfeb7cd60d..604b43132e3 100644 --- a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc +++ b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc @@ -24,14 +24,16 @@ #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_quota_client.h" #include "storage/browser/test/mock_quota_manager.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" +#include "url/gurl.h" +#include "url/origin.h" using blink::mojom::StorageType; // Declared to shorten the line lengths. static const StorageType kTemp = StorageType::kTemporary; -static const StorageType kPerm = StorageType::kPersistent; -static const StorageType kSync = StorageType::kSyncable; namespace content { @@ -45,15 +47,14 @@ class IndexedDBQuotaClientTest : public testing::Test { IndexedDBQuotaClientTest() : kOriginA(url::Origin::Create(GURL("http://host"))), kOriginB(url::Origin::Create(GURL("http://host:8000"))), - kOriginOther(url::Origin::Create(GURL("http://other"))), - usage_(0) { + kOriginOther(url::Origin::Create(GURL("http://other"))) { CreateTempDir(); auto quota_manager = base::MakeRefCounted<storage::MockQuotaManager>( /*in_memory=*/false, temp_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get(), nullptr); idb_context_ = base::MakeRefCounted<IndexedDBContextImpl>( - temp_dir_.GetPath(), nullptr, quota_manager->proxy(), + temp_dir_.GetPath(), quota_manager->proxy(), base::DefaultClock::GetInstance(), /*blob_storage_context=*/mojo::NullRemote(), /*native_file_system_context=*/mojo::NullRemote(), @@ -78,66 +79,67 @@ class IndexedDBQuotaClientTest : public testing::Test { base::RunLoop().RunUntilIdle(); } - int64_t GetOriginUsage(scoped_refptr<storage::QuotaClient> client, - const url::Origin& origin, - StorageType type) { - usage_ = -1; + static int64_t GetOriginUsage(scoped_refptr<storage::QuotaClient> client, + const url::Origin& origin, + StorageType type) { + int result = -1; base::RunLoop loop; client->GetOriginUsage(origin, type, base::BindLambdaForTesting([&](int64_t usage) { - usage_ = usage; + result = usage; loop.Quit(); })); loop.Run(); - EXPECT_GT(usage_, -1); - return usage_; + EXPECT_GT(result, -1); + return result; } - const std::set<url::Origin>& GetOriginsForType( + static std::set<url::Origin> GetOriginsForType( scoped_refptr<storage::QuotaClient> client, StorageType type) { - origins_.clear(); + std::set<url::Origin> result; base::RunLoop loop; client->GetOriginsForType( type, base::BindLambdaForTesting([&](const std::set<url::Origin>& origins) { - origins_ = origins; + result = origins; loop.Quit(); })); loop.Run(); - return origins_; + return result; } - const std::set<url::Origin>& GetOriginsForHost( + static std::set<url::Origin> GetOriginsForHost( scoped_refptr<storage::QuotaClient> client, StorageType type, const std::string& host) { - origins_.clear(); + std::set<url::Origin> result; base::RunLoop loop; client->GetOriginsForHost( type, host, base::BindLambdaForTesting([&](const std::set<url::Origin>& origins) { - origins_ = origins; + result = origins; loop.Quit(); })); loop.Run(); - return origins_; + return result; } - blink::mojom::QuotaStatusCode DeleteOrigin( + static blink::mojom::QuotaStatusCode DeleteOriginData( scoped_refptr<storage::QuotaClient> client, const url::Origin& origin, StorageType type) { - delete_status_ = blink::mojom::QuotaStatusCode::kUnknown; + blink::mojom::QuotaStatusCode result = + blink::mojom::QuotaStatusCode::kUnknown; base::RunLoop loop; client->DeleteOriginData( origin, type, base::BindLambdaForTesting([&](blink::mojom::QuotaStatusCode code) { - delete_status_ = code; + result = code; loop.Quit(); })); loop.Run(); - return delete_status_; + return result; } IndexedDBContextImpl* idb_context() { return idb_context_.get(); } @@ -175,10 +177,7 @@ class IndexedDBQuotaClientTest : public testing::Test { private: base::test::TaskEnvironment task_environment_; base::ScopedTempDir temp_dir_; - int64_t usage_; - std::set<url::Origin> origins_; scoped_refptr<IndexedDBContextImpl> idb_context_; - blink::mojom::QuotaStatusCode delete_status_; base::WeakPtrFactory<IndexedDBQuotaClientTest> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(IndexedDBQuotaClientTest); @@ -190,15 +189,11 @@ TEST_F(IndexedDBQuotaClientTest, GetOriginUsage) { AddFakeIndexedDB(kOriginA, 6); AddFakeIndexedDB(kOriginB, 3); EXPECT_EQ(6, GetOriginUsage(client, kOriginA, kTemp)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); EXPECT_EQ(3, GetOriginUsage(client, kOriginB, kTemp)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginB, kPerm)); AddFakeIndexedDB(kOriginA, 1000); EXPECT_EQ(1000, GetOriginUsage(client, kOriginA, kTemp)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); EXPECT_EQ(3, GetOriginUsage(client, kOriginB, kTemp)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginB, kPerm)); } TEST_F(IndexedDBQuotaClientTest, GetOriginsForHost) { @@ -222,7 +217,6 @@ TEST_F(IndexedDBQuotaClientTest, GetOriginsForHost) { EXPECT_TRUE(origins.find(kOriginA) != origins.end()); EXPECT_TRUE(origins.find(kOriginB) != origins.end()); - EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty()); EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginOther.host()).empty()); } @@ -230,14 +224,11 @@ TEST_F(IndexedDBQuotaClientTest, GetOriginsForType) { auto client = base::MakeRefCounted<IndexedDBQuotaClient>(idb_context()); EXPECT_TRUE(GetOriginsForType(client, kTemp).empty()); - EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); AddFakeIndexedDB(kOriginA, 1000); std::set<url::Origin> origins = GetOriginsForType(client, kTemp); EXPECT_EQ(origins.size(), 1ul); EXPECT_TRUE(origins.find(kOriginA) != origins.end()); - - EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); } TEST_F(IndexedDBQuotaClientTest, DeleteOrigin) { @@ -249,18 +240,10 @@ TEST_F(IndexedDBQuotaClientTest, DeleteOrigin) { EXPECT_EQ(50, GetOriginUsage(client, kOriginB, kTemp)); blink::mojom::QuotaStatusCode delete_status = - DeleteOrigin(client, kOriginA, kTemp); + DeleteOriginData(client, kOriginA, kTemp); EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, delete_status); EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kTemp)); EXPECT_EQ(50, GetOriginUsage(client, kOriginB, kTemp)); - - // IndexedDB only supports temporary storage; requests to delete other types - // are no-ops, but should not fail. - delete_status = DeleteOrigin(client, kOriginA, kPerm); - EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, delete_status); - - delete_status = DeleteOrigin(client, kOriginA, kSync); - EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, delete_status); } } // namespace content diff --git a/chromium/content/browser/indexed_db/indexed_db_reporting.h b/chromium/content/browser/indexed_db/indexed_db_reporting.h index 7be6d541336..740f526b293 100644 --- a/chromium/content/browser/indexed_db/indexed_db_reporting.h +++ b/chromium/content/browser/indexed_db/indexed_db_reporting.h @@ -52,6 +52,7 @@ enum IndexedDBBackingStoreErrorSource { GET_BLOB_INFO_FOR_RECORD = 29, UPGRADING_SCHEMA_CORRUPTED_BLOBS = 30, REVERT_SCHEMA_TO_V2 = 31, + CREATE_ITERATOR = 32, INTERNAL_ERROR_MAX, }; diff --git a/chromium/content/browser/indexed_db/indexed_db_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_unittest.cc index f3666863558..ecfa8d96100 100644 --- a/chromium/content/browser/indexed_db/indexed_db_unittest.cc +++ b/chromium/content/browser/indexed_db/indexed_db_unittest.cc @@ -85,21 +85,22 @@ class IndexedDBTest : public testing::Test { IndexedDBTest() : kNormalOrigin(url::Origin::Create(GURL("http://normal/"))), kSessionOnlyOrigin(url::Origin::Create(GURL("http://session-only/"))), - special_storage_policy_( - base::MakeRefCounted<storage::MockSpecialStoragePolicy>()), quota_manager_proxy_( base::MakeRefCounted<storage::MockQuotaManagerProxy>(nullptr, nullptr)), context_(base::MakeRefCounted<IndexedDBContextImpl>( CreateAndReturnTempDir(&temp_dir_), - /*special_storage_policy=*/special_storage_policy_.get(), quota_manager_proxy_.get(), base::DefaultClock::GetInstance(), /*blob_storage_context=*/mojo::NullRemote(), /*native_file_system_context=*/mojo::NullRemote(), base::SequencedTaskRunnerHandle::Get(), base::SequencedTaskRunnerHandle::Get())) { - special_storage_policy_->AddSessionOnly(kSessionOnlyOrigin.GetURL()); + std::vector<storage::mojom::IndexedDBStoragePolicyUpdatePtr> policy_updates; + bool should_purge_on_shutdown = true; + policy_updates.push_back(storage::mojom::IndexedDBStoragePolicyUpdate::New( + kSessionOnlyOrigin, should_purge_on_shutdown)); + context_->ApplyPolicyUpdates(std::move(policy_updates)); } ~IndexedDBTest() override { quota_manager_proxy_->SimulateQuotaManagerDestroyed(); @@ -152,7 +153,6 @@ class IndexedDBTest : public testing::Test { protected: IndexedDBContextImpl* context() const { return context_.get(); } - scoped_refptr<storage::MockSpecialStoragePolicy> special_storage_policy_; scoped_refptr<storage::MockQuotaManagerProxy> quota_manager_proxy_; private: diff --git a/chromium/content/browser/indexed_db/list_set.h b/chromium/content/browser/indexed_db/list_set.h index 696e63e9178..a132221bc55 100644 --- a/chromium/content/browser/indexed_db/list_set.h +++ b/chromium/content/browser/indexed_db/list_set.h @@ -13,7 +13,7 @@ #include <memory> #include <set> -#include "base/logging.h" +#include "base/check_op.h" // // A container class that provides fast containment test (like a set) |