blob: 3be12a4e699ebabb14a8dbcdfb45fc316cdf55e1 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/dom_storage/session_storage_data_map.h"
#include "base/system/sys_info.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/services/storage/dom_storage/dom_storage_constants.h"
namespace content {
// static
scoped_refptr<SessionStorageDataMap> SessionStorageDataMap::CreateFromDisk(
Listener* listener,
scoped_refptr<SessionStorageMetadata::MapData> map_data,
storage::AsyncDomStorageDatabase* database) {
return base::WrapRefCounted(new SessionStorageDataMap(
listener, std::move(map_data), database, false));
}
// static
scoped_refptr<SessionStorageDataMap> SessionStorageDataMap::CreateEmpty(
Listener* listener,
scoped_refptr<SessionStorageMetadata::MapData> map_data,
storage::AsyncDomStorageDatabase* database) {
return base::WrapRefCounted(
new SessionStorageDataMap(listener, std::move(map_data), database, true));
}
// static
scoped_refptr<SessionStorageDataMap> SessionStorageDataMap::CreateClone(
Listener* listener,
scoped_refptr<SessionStorageMetadata::MapData> map_data,
scoped_refptr<SessionStorageDataMap> clone_from) {
return base::WrapRefCounted(new SessionStorageDataMap(
listener, std::move(map_data), std::move(clone_from)));
}
void SessionStorageDataMap::DidCommit(leveldb::Status status) {
listener_->OnCommitResult(status);
}
SessionStorageDataMap::SessionStorageDataMap(
Listener* listener,
scoped_refptr<SessionStorageMetadata::MapData> map_data,
storage::AsyncDomStorageDatabase* database,
bool is_empty)
: listener_(listener),
map_data_(std::move(map_data)),
storage_area_impl_(
std::make_unique<storage::StorageAreaImpl>(database,
map_data_->KeyPrefix(),
this,
GetOptions())),
storage_area_ptr_(storage_area_impl_.get()) {
if (is_empty)
storage_area_impl_->InitializeAsEmpty();
DCHECK(listener_);
DCHECK(map_data_);
listener_->OnDataMapCreation(map_data_->MapNumberAsBytes(), this);
}
SessionStorageDataMap::SessionStorageDataMap(
Listener* listener,
scoped_refptr<SessionStorageMetadata::MapData> map_data,
scoped_refptr<SessionStorageDataMap> forking_from)
: listener_(listener),
clone_from_data_map_(std::move(forking_from)),
map_data_(std::move(map_data)),
storage_area_impl_(clone_from_data_map_->storage_area()->ForkToNewPrefix(
map_data_->KeyPrefix(),
this,
GetOptions())),
storage_area_ptr_(storage_area_impl_.get()) {
DCHECK(listener_);
DCHECK(map_data_);
listener_->OnDataMapCreation(map_data_->MapNumberAsBytes(), this);
}
SessionStorageDataMap::~SessionStorageDataMap() {
listener_->OnDataMapDestruction(map_data_->MapNumberAsBytes());
}
void SessionStorageDataMap::RemoveBindingReference() {
DCHECK_GT(binding_count_, 0);
--binding_count_;
if (binding_count_ > 0)
return;
// Don't delete ourselves, but do schedule an immediate commit. Possible
// deletion will happen under memory pressure or when another sessionstorage
// area is opened.
storage_area()->ScheduleImmediateCommit();
}
void SessionStorageDataMap::OnMapLoaded(leveldb::Status) {
clone_from_data_map_.reset();
}
// static
storage::StorageAreaImpl::Options SessionStorageDataMap::GetOptions() {
// Delay for a moment after a value is set in anticipation
// of other values being set, so changes are batched.
constexpr const base::TimeDelta kCommitDefaultDelaySecs =
base::TimeDelta::FromSeconds(5);
// To avoid excessive IO we apply limits to the amount of data being
// written and the frequency of writes.
storage::StorageAreaImpl::Options options;
options.max_size = storage::kPerStorageAreaQuota +
storage::kPerStorageAreaOverQuotaAllowance;
options.default_commit_delay = kCommitDefaultDelaySecs;
options.max_bytes_per_hour = storage::kPerStorageAreaQuota;
options.max_commits_per_hour = 60;
options.cache_mode =
storage::StorageAreaImpl::CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
return options;
}
} // namespace content