Commit 66a016e7 authored by Daniel Murphy's avatar Daniel Murphy Committed by Commit Bot

[SessionStorage] Save SessionStorageNamespaceImpl for re-use.

Since the tab restore code keeps a reference to the session namespaces
of recently closed tabs (see sessions::ContentPlatformSpecificTabData
and sessions::TabRestoreService), a SessionStorageNamespaceImpl can
outlive the destruction of the browser window. A session restore can
also happen without the browser context being shutdown or destroyed in
between.

This change keeps track of all 'alive' namespaces in a map. When a
SessionStorageNamespaceImpl is created and there is an entry alive in
that map, then that object is used instead. This allows the browser to
re-use objects that are still alive thanks to the sessions component.

Bug: 811189
Change-Id: I5c9e94ab4fe7b0017264c0f8f522d20134ea0c2b
Reviewed-on: https://chromium-review.googlesource.com/930325
Commit-Queue: Daniel Murphy <dmurph@chromium.org>
Reviewed-by: default avatarMarijn Kruisselbrink <mek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539304}
parent ea83d0c4
...@@ -393,6 +393,26 @@ void DOMStorageContextWrapper::SetLocalStorageDatabaseForTesting( ...@@ -393,6 +393,26 @@ void DOMStorageContextWrapper::SetLocalStorageDatabaseForTesting(
base::Unretained(mojo_state_), std::move(database))); base::Unretained(mojo_state_), std::move(database)));
} }
scoped_refptr<SessionStorageNamespaceImpl>
DOMStorageContextWrapper::MaybeGetExistingNamespace(
const std::string& namespace_id) const {
auto it = alive_namespaces_.find(namespace_id);
return (it != alive_namespaces_.end()) ? it->second : nullptr;
}
void DOMStorageContextWrapper::AddNamespace(
const std::string& namespace_id,
SessionStorageNamespaceImpl* session_namespace) {
DCHECK(alive_namespaces_.find(namespace_id) == alive_namespaces_.end());
alive_namespaces_[namespace_id] = session_namespace;
}
void DOMStorageContextWrapper::RemoveNamespace(
const std::string& namespace_id) {
DCHECK(alive_namespaces_.find(namespace_id) != alive_namespaces_.end());
alive_namespaces_.erase(namespace_id);
}
void DOMStorageContextWrapper::OnMemoryPressure( void DOMStorageContextWrapper::OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
DOMStorageContextImpl::PurgeOption purge_option = DOMStorageContextImpl::PurgeOption purge_option =
......
...@@ -36,6 +36,7 @@ namespace content { ...@@ -36,6 +36,7 @@ namespace content {
class DOMStorageContextImpl; class DOMStorageContextImpl;
class LocalStorageContextMojo; class LocalStorageContextMojo;
class SessionStorageContextMojo; class SessionStorageContextMojo;
class SessionStorageNamespaceImpl;
// This is owned by Storage Partition and encapsulates all its dom storage // This is owned by Storage Partition and encapsulates all its dom storage
// state. // state.
...@@ -101,6 +102,14 @@ class CONTENT_EXPORT DOMStorageContextWrapper ...@@ -101,6 +102,14 @@ class CONTENT_EXPORT DOMStorageContextWrapper
return mojo_task_runner_.get(); return mojo_task_runner_.get();
} }
scoped_refptr<SessionStorageNamespaceImpl> MaybeGetExistingNamespace(
const std::string& namespace_id) const;
void AddNamespace(const std::string& namespace_id,
SessionStorageNamespaceImpl* session_namespace);
void RemoveNamespace(const std::string& namespace_id);
// Called on UI thread when the system is under memory pressure. // Called on UI thread when the system is under memory pressure.
void OnMemoryPressure( void OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
...@@ -117,6 +126,18 @@ class CONTENT_EXPORT DOMStorageContextWrapper ...@@ -117,6 +126,18 @@ class CONTENT_EXPORT DOMStorageContextWrapper
SessionStorageContextMojo* mojo_session_state_ = nullptr; SessionStorageContextMojo* mojo_session_state_ = nullptr;
scoped_refptr<base::SequencedTaskRunner> mojo_task_runner_; scoped_refptr<base::SequencedTaskRunner> mojo_task_runner_;
// Since the tab restore code keeps a reference to the session namespaces
// of recently closed tabs (see sessions::ContentPlatformSpecificTabData and
// sessions::TabRestoreService), a SessionStorageNamespaceImpl can outlive the
// destruction of the browser window. A session restore can also happen
// without the browser context being shutdown or destroyed in between. The
// design of SessionStorageNamespaceImpl assumes there is only one object per
// namespace. A session restore creates new objects for all tabs while the
// Profile wasn't destructed. This map allows the restored session to re-use
// the SessionStorageNamespaceImpl objects that are still alive thanks to the
// sessions component.
std::map<std::string, SessionStorageNamespaceImpl*> alive_namespaces_;
base::FilePath legacy_localstorage_path_; base::FilePath legacy_localstorage_path_;
// To receive memory pressure signals. // To receive memory pressure signals.
......
...@@ -52,6 +52,7 @@ class CONTENT_EXPORT DOMStorageSession { ...@@ -52,6 +52,7 @@ class CONTENT_EXPORT DOMStorageSession {
const std::string& namespace_id() const { return namespace_id_; } const std::string& namespace_id() const { return namespace_id_; }
void SetShouldPersist(bool should_persist); void SetShouldPersist(bool should_persist);
bool should_persist() const; bool should_persist() const;
DOMStorageContextWrapper* context() const { return context_wrapper_.get(); }
bool IsFromContext(DOMStorageContextWrapper* context); bool IsFromContext(DOMStorageContextWrapper* context);
std::unique_ptr<DOMStorageSession> Clone(); std::unique_ptr<DOMStorageSession> Clone();
......
...@@ -23,8 +23,14 @@ scoped_refptr<SessionStorageNamespaceImpl> SessionStorageNamespaceImpl::Create( ...@@ -23,8 +23,14 @@ scoped_refptr<SessionStorageNamespaceImpl> SessionStorageNamespaceImpl::Create(
scoped_refptr<SessionStorageNamespaceImpl> SessionStorageNamespaceImpl::Create( scoped_refptr<SessionStorageNamespaceImpl> SessionStorageNamespaceImpl::Create(
scoped_refptr<DOMStorageContextWrapper> context, scoped_refptr<DOMStorageContextWrapper> context,
const std::string& namepace_id) { const std::string& namepace_id) {
return base::WrapRefCounted(new SessionStorageNamespaceImpl( scoped_refptr<SessionStorageNamespaceImpl> existing =
DOMStorageSession::CreateWithNamespace(std::move(context), namepace_id))); context->MaybeGetExistingNamespace(namepace_id);
if (!existing) {
existing = base::WrapRefCounted(
new SessionStorageNamespaceImpl(DOMStorageSession::CreateWithNamespace(
std::move(context), namepace_id)));
}
return existing;
} }
// static // static
...@@ -61,9 +67,12 @@ bool SessionStorageNamespaceImpl::IsFromContext( ...@@ -61,9 +67,12 @@ bool SessionStorageNamespaceImpl::IsFromContext(
SessionStorageNamespaceImpl::SessionStorageNamespaceImpl( SessionStorageNamespaceImpl::SessionStorageNamespaceImpl(
std::unique_ptr<DOMStorageSession> session) std::unique_ptr<DOMStorageSession> session)
: session_(std::move(session)) {} : session_(std::move(session)) {
session_->context()->AddNamespace(session_->namespace_id(), this);
}
SessionStorageNamespaceImpl::~SessionStorageNamespaceImpl() { SessionStorageNamespaceImpl::~SessionStorageNamespaceImpl() {
session_->context()->RemoveNamespace(session_->namespace_id());
} }
} // namespace content } // namespace content
...@@ -19,14 +19,15 @@ class DOMStorageSession; ...@@ -19,14 +19,15 @@ class DOMStorageSession;
class SessionStorageNamespaceImpl : public SessionStorageNamespace { class SessionStorageNamespaceImpl : public SessionStorageNamespace {
public: public:
// Constructs a |SessionStorageNamespaceImpl| and allocates a new ID for it. // Constructs a SessionStorageNamespaceImpl and allocates a new ID for it.
// //
// The CONTENT_EXPORT allows TestRenderViewHost to instantiate these. // The CONTENT_EXPORT allows TestRenderViewHost to instantiate these.
CONTENT_EXPORT static scoped_refptr<SessionStorageNamespaceImpl> Create( CONTENT_EXPORT static scoped_refptr<SessionStorageNamespaceImpl> Create(
scoped_refptr<DOMStorageContextWrapper> context); scoped_refptr<DOMStorageContextWrapper> context);
// Constructs a |SessionStorageNamespaceImpl| and assigns |namepace_id| // If there is an existing SessionStorageNamespaceImpl with the given id in
// to it. // the DOMStorageContextWrapper, this will return that object. Otherwise this
// constructs a SessionStorageNamespaceImpl and assigns |namepace_id| to it.
static scoped_refptr<SessionStorageNamespaceImpl> Create( static scoped_refptr<SessionStorageNamespaceImpl> Create(
scoped_refptr<DOMStorageContextWrapper> context, scoped_refptr<DOMStorageContextWrapper> context,
const std::string& namepace_id); const std::string& namepace_id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment