1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/dom_storage/dom_storage_namespace.h"
7 #include "base/basictypes.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "content/browser/dom_storage/dom_storage_area.h"
12 #include "content/browser/dom_storage/dom_storage_task_runner.h"
13 #include "content/browser/dom_storage/session_storage_database.h"
14 #include "content/common/dom_storage/dom_storage_types.h"
18 DOMStorageNamespace::DOMStorageNamespace(
19 const base::FilePath
& directory
,
20 DOMStorageTaskRunner
* task_runner
)
21 : namespace_id_(kLocalStorageNamespaceId
),
22 directory_(directory
),
23 task_runner_(task_runner
) {
26 DOMStorageNamespace::DOMStorageNamespace(
28 const std::string
& persistent_namespace_id
,
29 SessionStorageDatabase
* session_storage_database
,
30 DOMStorageTaskRunner
* task_runner
)
31 : namespace_id_(namespace_id
),
32 persistent_namespace_id_(persistent_namespace_id
),
33 task_runner_(task_runner
),
34 session_storage_database_(session_storage_database
) {
35 DCHECK_NE(kLocalStorageNamespaceId
, namespace_id
);
38 DOMStorageNamespace::~DOMStorageNamespace() {
41 DOMStorageArea
* DOMStorageNamespace::OpenStorageArea(const GURL
& origin
) {
42 if (AreaHolder
* holder
= GetAreaHolder(origin
)) {
43 ++(holder
->open_count_
);
44 return holder
->area_
.get();
47 if (namespace_id_
== kLocalStorageNamespaceId
) {
48 area
= new DOMStorageArea(origin
, directory_
, task_runner_
.get());
50 area
= new DOMStorageArea(
51 namespace_id_
, persistent_namespace_id_
, origin
,
52 session_storage_database_
.get(), task_runner_
.get());
54 areas_
[origin
] = AreaHolder(area
, 1);
58 void DOMStorageNamespace::CloseStorageArea(DOMStorageArea
* area
) {
59 AreaHolder
* holder
= GetAreaHolder(area
->origin());
61 DCHECK_EQ(holder
->area_
.get(), area
);
62 --(holder
->open_count_
);
63 // TODO(michaeln): Clean up areas that aren't needed in memory anymore.
64 // The in-process-webkit based impl didn't do this either, but would be nice.
67 DOMStorageArea
* DOMStorageNamespace::GetOpenStorageArea(const GURL
& origin
) {
68 AreaHolder
* holder
= GetAreaHolder(origin
);
69 if (holder
&& holder
->open_count_
)
70 return holder
->area_
.get();
74 DOMStorageNamespace
* DOMStorageNamespace::Clone(
75 int64 clone_namespace_id
,
76 const std::string
& clone_persistent_namespace_id
) {
77 DCHECK_NE(kLocalStorageNamespaceId
, namespace_id_
);
78 DCHECK_NE(kLocalStorageNamespaceId
, clone_namespace_id
);
79 DOMStorageNamespace
* clone
= new DOMStorageNamespace(
80 clone_namespace_id
, clone_persistent_namespace_id
,
81 session_storage_database_
.get(), task_runner_
.get());
82 AreaMap::const_iterator it
= areas_
.begin();
83 // Clone the in-memory structures.
84 for (; it
!= areas_
.end(); ++it
) {
85 DOMStorageArea
* area
= it
->second
.area_
->ShallowCopy(
86 clone_namespace_id
, clone_persistent_namespace_id
);
87 clone
->areas_
[it
->first
] = AreaHolder(area
, 0);
89 // And clone the on-disk structures, too.
90 if (session_storage_database_
.get()) {
91 task_runner_
->PostShutdownBlockingTask(
93 DOMStorageTaskRunner::COMMIT_SEQUENCE
,
94 base::Bind(base::IgnoreResult(&SessionStorageDatabase::CloneNamespace
),
95 session_storage_database_
.get(), persistent_namespace_id_
,
96 clone_persistent_namespace_id
));
101 void DOMStorageNamespace::DeleteLocalStorageOrigin(const GURL
& origin
) {
102 DCHECK(!session_storage_database_
.get());
103 AreaHolder
* holder
= GetAreaHolder(origin
);
105 holder
->area_
->DeleteOrigin();
108 if (!directory_
.empty()) {
109 scoped_refptr
<DOMStorageArea
> area
=
110 new DOMStorageArea(origin
, directory_
, task_runner_
.get());
111 area
->DeleteOrigin();
115 void DOMStorageNamespace::DeleteSessionStorageOrigin(const GURL
& origin
) {
116 DOMStorageArea
* area
= OpenStorageArea(origin
);
118 CloseStorageArea(area
);
121 void DOMStorageNamespace::PurgeMemory(PurgeOption option
) {
122 if (directory_
.empty())
123 return; // We can't purge w/o backing on disk.
124 AreaMap::iterator it
= areas_
.begin();
125 while (it
!= areas_
.end()) {
126 // Leave it alone if changes are pending
127 if (it
->second
.area_
->HasUncommittedChanges()) {
132 // If not in use, we can shut it down and remove
133 // it from our collection entirely.
134 if (it
->second
.open_count_
== 0) {
135 it
->second
.area_
->Shutdown();
140 if (option
== PURGE_AGGRESSIVE
) {
141 // If aggressive is true, we clear caches and such
143 it
->second
.area_
->PurgeMemory();
150 void DOMStorageNamespace::Shutdown() {
151 AreaMap::const_iterator it
= areas_
.begin();
152 for (; it
!= areas_
.end(); ++it
)
153 it
->second
.area_
->Shutdown();
156 unsigned int DOMStorageNamespace::CountInMemoryAreas() const {
157 unsigned int area_count
= 0;
158 for (AreaMap::const_iterator it
= areas_
.begin(); it
!= areas_
.end(); ++it
) {
159 if (it
->second
.area_
->IsLoadedInMemory())
165 DOMStorageNamespace::AreaHolder
*
166 DOMStorageNamespace::GetAreaHolder(const GURL
& origin
) {
167 AreaMap::iterator found
= areas_
.find(origin
);
168 if (found
== areas_
.end())
170 return &(found
->second
);
175 DOMStorageNamespace::AreaHolder::AreaHolder()
179 DOMStorageNamespace::AreaHolder::AreaHolder(
180 DOMStorageArea
* area
, int count
)
181 : area_(area
), open_count_(count
) {
184 DOMStorageNamespace::AreaHolder::~AreaHolder() {
187 } // namespace content