Index: content/browser/dom_storage/local_storage_context_mojo.cc |
diff --git a/content/browser/dom_storage/local_storage_context_mojo.cc b/content/browser/dom_storage/local_storage_context_mojo.cc |
index ddc0ef8323938f5d4c310ebce7e034d3eee53070..6a9f0df8c3643ae9c51c5ef62ad5feddcdd8ab4b 100644 |
--- a/content/browser/dom_storage/local_storage_context_mojo.cc |
+++ b/content/browser/dom_storage/local_storage_context_mojo.cc |
@@ -19,6 +19,7 @@ |
#include "services/file/public/interfaces/constants.mojom.h" |
#include "services/service_manager/public/cpp/connector.h" |
#include "sql/connection.h" |
+#include "storage/browser/quota/special_storage_policy.h" |
#include "third_party/leveldatabase/env_chromium.h" |
namespace content { |
@@ -219,15 +220,15 @@ LocalStorageContextMojo::LocalStorageContextMojo( |
service_manager::Connector* connector, |
scoped_refptr<DOMStorageTaskRunner> task_runner, |
const base::FilePath& old_localstorage_path, |
- const base::FilePath& subdirectory) |
- : connector_(connector), |
+ const base::FilePath& subdirectory, |
+ storage::SpecialStoragePolicy* special_storage_policy) |
+ : connector_(connector ? connector->Clone() : nullptr), |
subdirectory_(subdirectory), |
+ special_storage_policy_(special_storage_policy), |
task_runner_(std::move(task_runner)), |
old_localstorage_path_(old_localstorage_path), |
weak_ptr_factory_(this) {} |
-LocalStorageContextMojo::~LocalStorageContextMojo() {} |
- |
void LocalStorageContextMojo::OpenLocalStorage( |
const url::Origin& origin, |
mojom::LevelDBWrapperRequest request) { |
@@ -245,8 +246,8 @@ void LocalStorageContextMojo::GetStorageUsage( |
void LocalStorageContextMojo::DeleteStorage(const url::Origin& origin) { |
if (connection_state_ != CONNECTION_FINISHED) { |
- RunWhenConnected(base::BindOnce(&LocalStorageContextMojo::DeleteStorage, |
- weak_ptr_factory_.GetWeakPtr(), origin)); |
+ RunWhenConnected( |
+ base::BindOnce(&LocalStorageContextMojo::DeleteStorage, this, origin)); |
return; |
} |
@@ -260,8 +261,8 @@ void LocalStorageContextMojo::DeleteStorage(const url::Origin& origin) { |
void LocalStorageContextMojo::DeleteStorageForPhysicalOrigin( |
const url::Origin& origin) { |
GetStorageUsage(base::BindOnce( |
- &LocalStorageContextMojo::OnGotStorageUsageForDeletePhysicalOrigin, |
- weak_ptr_factory_.GetWeakPtr(), origin)); |
+ &LocalStorageContextMojo::OnGotStorageUsageForDeletePhysicalOrigin, this, |
+ origin)); |
} |
void LocalStorageContextMojo::Flush() { |
@@ -274,6 +275,47 @@ void LocalStorageContextMojo::Flush() { |
it.second->level_db_wrapper()->ScheduleImmediateCommit(); |
} |
+void LocalStorageContextMojo::Shutdown() { |
+ DCHECK(!is_shutdown_); |
+ DCHECK_NE(connection_state_, CONNECTION_SHUTDOWN); |
+ |
+ // Nothing to do if no connection to the database was ever made. |
+ if (connection_state_ == NO_CONNECTION) { |
+ connection_state_ = CONNECTION_SHUTDOWN; |
+ is_shutdown_ = true; |
+ return; |
+ } |
+ |
+ if (connection_state_ != CONNECTION_FINISHED) { |
michaeln
2017/05/03 21:01:29
Similar to the NO_CONNECTION case, maybe we don't
Marijn Kruisselbrink
2017/05/04 23:03:46
Yeah, agreed that it makes sense to just immediate
|
+ RunWhenConnected(base::BindOnce(&LocalStorageContextMojo::Shutdown, this)); |
+ return; |
+ } |
+ |
+ connection_state_ = CONNECTION_SHUTDOWN; |
+ |
+ // Flush any uncommitted data. |
+ for (const auto& it : level_db_wrappers_) |
+ it.second->level_db_wrapper()->ScheduleImmediateCommit(); |
+ |
+ // Respect the content policy settings about what to |
+ // keep and what to discard. |
+ if (force_keep_session_state_) { |
+ OnShutdownCommitComplete(leveldb::mojom::DatabaseError::OK); |
+ return; // Keep everything. |
+ } |
+ |
+ bool has_session_only_origins = |
+ special_storage_policy_.get() && |
+ special_storage_policy_->HasSessionOnlyOrigins(); |
+ |
+ if (has_session_only_origins) { |
+ RetrieveStorageUsage(base::BindOnce( |
+ &LocalStorageContextMojo::OnGotStorageUsageForShutdown, this)); |
+ } else { |
+ OnShutdownCommitComplete(leveldb::mojom::DatabaseError::OK); |
+ } |
+} |
+ |
void LocalStorageContextMojo::PurgeMemory() { |
for (const auto& it : level_db_wrappers_) |
it.second->level_db_wrapper()->PurgeMemory(); |
@@ -302,7 +344,14 @@ std::vector<uint8_t> LocalStorageContextMojo::MigrateString( |
return result; |
} |
+LocalStorageContextMojo::~LocalStorageContextMojo() { |
+ DCHECK(is_shutdown_); |
+ DCHECK_EQ(connection_state_, CONNECTION_SHUTDOWN); |
+} |
+ |
void LocalStorageContextMojo::RunWhenConnected(base::OnceClosure callback) { |
+ DCHECK_NE(connection_state_, CONNECTION_SHUTDOWN); |
+ |
// If we don't have a filesystem_connection_, we'll need to establish one. |
if (connection_state_ == NO_CONNECTION) { |
connection_state_ = CONNECTION_IN_PROGRESS; |
@@ -584,4 +633,47 @@ void LocalStorageContextMojo::OnGotStorageUsageForDeletePhysicalOrigin( |
DeleteStorage(origin); |
} |
+void LocalStorageContextMojo::OnGotStorageUsageForShutdown( |
+ std::vector<LocalStorageUsageInfo> usage) { |
+ std::vector<leveldb::mojom::BatchedOperationPtr> operations; |
+ for (const auto& info : usage) { |
+ if (special_storage_policy_->IsStorageProtected(info.origin)) |
+ continue; |
+ if (!special_storage_policy_->IsStorageSessionOnly(info.origin)) |
+ continue; |
+ |
+ url::Origin origin(info.origin); |
michaeln
2017/05/03 21:01:29
i see you've copied the behavior for the sqlite im
Marijn Kruisselbrink
2017/05/04 23:03:46
Not sure.. but I imagine properly accounting for s
|
+ leveldb::mojom::BatchedOperationPtr item = |
+ leveldb::mojom::BatchedOperation::New(); |
+ item->type = leveldb::mojom::BatchOperationType::DELETE_PREFIXED_KEY; |
+ item->key = leveldb::StdStringToUint8Vector( |
+ kDataPrefix + origin.Serialize() + kOriginSeparator); |
+ operations.push_back(std::move(item)); |
+ |
+ item = leveldb::mojom::BatchedOperation::New(); |
+ item->type = leveldb::mojom::BatchOperationType::DELETE_KEY; |
+ item->key = CreateMetaDataKey(origin); |
+ operations.push_back(std::move(item)); |
+ } |
+ |
+ if (!operations.empty()) { |
+ database_->Write( |
+ std::move(operations), |
+ base::Bind(&LocalStorageContextMojo::OnShutdownCommitComplete, this)); |
+ } else { |
+ OnShutdownCommitComplete(leveldb::mojom::DatabaseError::OK); |
+ } |
+} |
+ |
+void LocalStorageContextMojo::OnShutdownCommitComplete( |
+ leveldb::mojom::DatabaseError error) { |
+ is_shutdown_ = true; |
+ file_system_.reset(); |
+ directory_.reset(); |
+ leveldb_service_.reset(); |
+ level_db_wrappers_.clear(); |
+ database_.reset(); |
+ connector_.reset(); |
+} |
+ |
} // namespace content |