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.
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "base/time/time.h"
13 #include "content/browser/dom_storage/dom_storage_area.h"
14 #include "content/browser/dom_storage/dom_storage_context_impl.h"
15 #include "content/browser/dom_storage/dom_storage_namespace.h"
16 #include "content/browser/dom_storage/dom_storage_task_runner.h"
17 #include "content/public/browser/local_storage_usage_info.h"
18 #include "content/public/browser/session_storage_usage_info.h"
19 #include "content/public/test/mock_special_storage_policy.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using base::ASCIIToUTF16
;
26 class DOMStorageContextImplTest
: public testing::Test
{
28 DOMStorageContextImplTest()
29 : kOrigin(GURL("http://dom_storage/")),
30 kKey(ASCIIToUTF16("key")),
31 kValue(ASCIIToUTF16("value")),
32 kDontIncludeFileInfo(false),
33 kDoIncludeFileInfo(true) {
37 const base::string16 kKey
;
38 const base::string16 kValue
;
39 const bool kDontIncludeFileInfo
;
40 const bool kDoIncludeFileInfo
;
42 void SetUp() override
{
43 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
44 storage_policy_
= new MockSpecialStoragePolicy
;
46 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get());
47 context_
= new DOMStorageContextImpl(temp_dir_
.path(),
49 storage_policy_
.get(),
53 void TearDown() override
{ base::MessageLoop::current()->RunUntilIdle(); }
55 void VerifySingleOriginRemains(const GURL
& origin
) {
56 // Use a new instance to examine the contexts of temp_dir_.
57 scoped_refptr
<DOMStorageContextImpl
> context
=
58 new DOMStorageContextImpl(temp_dir_
.path(), base::FilePath(),
60 std::vector
<LocalStorageUsageInfo
> infos
;
61 context
->GetLocalStorageUsage(&infos
, kDontIncludeFileInfo
);
62 ASSERT_EQ(1u, infos
.size());
63 EXPECT_EQ(origin
, infos
[0].origin
);
67 base::MessageLoop message_loop_
;
68 base::ScopedTempDir temp_dir_
;
69 scoped_refptr
<MockSpecialStoragePolicy
> storage_policy_
;
70 scoped_refptr
<MockDOMStorageTaskRunner
> task_runner_
;
71 scoped_refptr
<DOMStorageContextImpl
> context_
;
72 DISALLOW_COPY_AND_ASSIGN(DOMStorageContextImplTest
);
75 TEST_F(DOMStorageContextImplTest
, Basics
) {
76 // This test doesn't do much, checks that the constructor
77 // initializes members properly and that invoking methods
78 // on a newly created object w/o any data on disk do no harm.
79 EXPECT_EQ(temp_dir_
.path(), context_
->localstorage_directory());
80 EXPECT_EQ(base::FilePath(), context_
->sessionstorage_directory());
81 EXPECT_EQ(storage_policy_
.get(), context_
->special_storage_policy_
.get());
82 context_
->DeleteLocalStorage(GURL("http://chromium.org/"));
83 const int kFirstSessionStorageNamespaceId
= 1;
84 EXPECT_TRUE(context_
->GetStorageNamespace(kLocalStorageNamespaceId
));
85 EXPECT_FALSE(context_
->GetStorageNamespace(kFirstSessionStorageNamespaceId
));
86 EXPECT_EQ(kFirstSessionStorageNamespaceId
, context_
->AllocateSessionId());
87 std::vector
<LocalStorageUsageInfo
> infos
;
88 context_
->GetLocalStorageUsage(&infos
, kDontIncludeFileInfo
);
89 EXPECT_TRUE(infos
.empty());
93 TEST_F(DOMStorageContextImplTest
, UsageInfo
) {
94 // Should be empty initially
95 std::vector
<LocalStorageUsageInfo
> infos
;
96 context_
->GetLocalStorageUsage(&infos
, kDontIncludeFileInfo
);
97 EXPECT_TRUE(infos
.empty());
98 context_
->GetLocalStorageUsage(&infos
, kDoIncludeFileInfo
);
99 EXPECT_TRUE(infos
.empty());
101 // Put some data into local storage and shutdown the context
102 // to ensure data is written to disk.
103 base::NullableString16 old_value
;
104 EXPECT_TRUE(context_
->GetStorageNamespace(kLocalStorageNamespaceId
)->
105 OpenStorageArea(kOrigin
)->SetItem(kKey
, kValue
, &old_value
));
106 context_
->Shutdown();
108 base::MessageLoop::current()->RunUntilIdle();
110 // Create a new context that points to the same directory, see that
111 // it knows about the origin that we stored data for.
112 context_
= new DOMStorageContextImpl(temp_dir_
.path(), base::FilePath(),
114 context_
->GetLocalStorageUsage(&infos
, kDontIncludeFileInfo
);
115 EXPECT_EQ(1u, infos
.size());
116 EXPECT_EQ(kOrigin
, infos
[0].origin
);
117 EXPECT_EQ(0u, infos
[0].data_size
);
118 EXPECT_EQ(base::Time(), infos
[0].last_modified
);
120 context_
->GetLocalStorageUsage(&infos
, kDoIncludeFileInfo
);
121 EXPECT_EQ(1u, infos
.size());
122 EXPECT_EQ(kOrigin
, infos
[0].origin
);
123 EXPECT_NE(0u, infos
[0].data_size
);
124 EXPECT_NE(base::Time(), infos
[0].last_modified
);
127 TEST_F(DOMStorageContextImplTest
, SessionOnly
) {
128 const GURL
kSessionOnlyOrigin("http://www.sessiononly.com/");
129 storage_policy_
->AddSessionOnly(kSessionOnlyOrigin
);
131 // Store data for a normal and a session-only origin and then
132 // invoke Shutdown() which should delete data for session-only
134 base::NullableString16 old_value
;
135 EXPECT_TRUE(context_
->GetStorageNamespace(kLocalStorageNamespaceId
)->
136 OpenStorageArea(kOrigin
)->SetItem(kKey
, kValue
, &old_value
));
137 EXPECT_TRUE(context_
->GetStorageNamespace(kLocalStorageNamespaceId
)->
138 OpenStorageArea(kSessionOnlyOrigin
)->SetItem(kKey
, kValue
, &old_value
));
139 context_
->Shutdown();
141 base::MessageLoop::current()->RunUntilIdle();
143 // Verify that the session-only origin data is gone.
144 VerifySingleOriginRemains(kOrigin
);
147 TEST_F(DOMStorageContextImplTest
, SetForceKeepSessionState
) {
148 const GURL
kSessionOnlyOrigin("http://www.sessiononly.com/");
149 storage_policy_
->AddSessionOnly(kSessionOnlyOrigin
);
151 // Store data for a session-only origin, setup to save session data, then
153 base::NullableString16 old_value
;
154 EXPECT_TRUE(context_
->GetStorageNamespace(kLocalStorageNamespaceId
)->
155 OpenStorageArea(kSessionOnlyOrigin
)->SetItem(kKey
, kValue
, &old_value
));
156 context_
->SetForceKeepSessionState(); // Should override clear behavior.
157 context_
->Shutdown();
159 base::MessageLoop::current()->RunUntilIdle();
161 VerifySingleOriginRemains(kSessionOnlyOrigin
);
164 TEST_F(DOMStorageContextImplTest
, PersistentIds
) {
165 const int kFirstSessionStorageNamespaceId
= 1;
166 const std::string kPersistentId
= "persistent";
167 context_
->CreateSessionNamespace(kFirstSessionStorageNamespaceId
,
169 DOMStorageNamespace
* dom_namespace
=
170 context_
->GetStorageNamespace(kFirstSessionStorageNamespaceId
);
171 ASSERT_TRUE(dom_namespace
);
172 EXPECT_EQ(kPersistentId
, dom_namespace
->persistent_namespace_id());
173 // Verify that the areas inherit the persistent ID.
174 DOMStorageArea
* area
= dom_namespace
->OpenStorageArea(kOrigin
);
175 EXPECT_EQ(kPersistentId
, area
->persistent_namespace_id_
);
177 // Verify that the persistent IDs are handled correctly when cloning.
178 const int kClonedSessionStorageNamespaceId
= 2;
179 const std::string kClonedPersistentId
= "cloned";
180 context_
->CloneSessionNamespace(kFirstSessionStorageNamespaceId
,
181 kClonedSessionStorageNamespaceId
,
182 kClonedPersistentId
);
183 DOMStorageNamespace
* cloned_dom_namespace
=
184 context_
->GetStorageNamespace(kClonedSessionStorageNamespaceId
);
185 ASSERT_TRUE(dom_namespace
);
186 EXPECT_EQ(kClonedPersistentId
,
187 cloned_dom_namespace
->persistent_namespace_id());
188 // Verify that the areas inherit the persistent ID.
189 DOMStorageArea
* cloned_area
= cloned_dom_namespace
->OpenStorageArea(kOrigin
);
190 EXPECT_EQ(kClonedPersistentId
, cloned_area
->persistent_namespace_id_
);
193 TEST_F(DOMStorageContextImplTest
, DeleteSessionStorage
) {
194 // Create a DOMStorageContextImpl which will save sessionStorage on disk.
195 context_
= new DOMStorageContextImpl(temp_dir_
.path(),
197 storage_policy_
.get(),
199 context_
->SetSaveSessionStorageOnDisk();
200 ASSERT_EQ(temp_dir_
.path(), context_
->sessionstorage_directory());
203 const int kSessionStorageNamespaceId
= 1;
204 const std::string kPersistentId
= "persistent";
205 context_
->CreateSessionNamespace(kSessionStorageNamespaceId
,
207 DOMStorageNamespace
* dom_namespace
=
208 context_
->GetStorageNamespace(kSessionStorageNamespaceId
);
209 DOMStorageArea
* area
= dom_namespace
->OpenStorageArea(kOrigin
);
210 const base::string16
kKey(ASCIIToUTF16("foo"));
211 const base::string16
kValue(ASCIIToUTF16("bar"));
212 base::NullableString16 old_nullable_value
;
213 area
->SetItem(kKey
, kValue
, &old_nullable_value
);
214 dom_namespace
->CloseStorageArea(area
);
216 // Destroy and recreate the DOMStorageContextImpl.
217 context_
->Shutdown();
219 base::MessageLoop::current()->RunUntilIdle();
220 context_
= new DOMStorageContextImpl(
221 temp_dir_
.path(), temp_dir_
.path(),
222 storage_policy_
.get(), task_runner_
.get());
223 context_
->SetSaveSessionStorageOnDisk();
225 // Read the data back.
226 context_
->CreateSessionNamespace(kSessionStorageNamespaceId
,
228 dom_namespace
= context_
->GetStorageNamespace(kSessionStorageNamespaceId
);
229 area
= dom_namespace
->OpenStorageArea(kOrigin
);
230 base::NullableString16 read_value
;
231 read_value
= area
->GetItem(kKey
);
232 EXPECT_EQ(kValue
, read_value
.string());
233 dom_namespace
->CloseStorageArea(area
);
235 SessionStorageUsageInfo info
;
236 info
.origin
= kOrigin
;
237 info
.persistent_namespace_id
= kPersistentId
;
238 context_
->DeleteSessionStorage(info
);
240 // Destroy and recreate again.
241 context_
->Shutdown();
243 base::MessageLoop::current()->RunUntilIdle();
244 context_
= new DOMStorageContextImpl(
245 temp_dir_
.path(), temp_dir_
.path(),
246 storage_policy_
.get(), task_runner_
.get());
247 context_
->SetSaveSessionStorageOnDisk();
249 // Now there should be no data.
250 context_
->CreateSessionNamespace(kSessionStorageNamespaceId
,
252 dom_namespace
= context_
->GetStorageNamespace(kSessionStorageNamespaceId
);
253 area
= dom_namespace
->OpenStorageArea(kOrigin
);
254 read_value
= area
->GetItem(kKey
);
255 EXPECT_TRUE(read_value
.is_null());
256 dom_namespace
->CloseStorageArea(area
);
257 context_
->Shutdown();
259 base::MessageLoop::current()->RunUntilIdle();
262 } // namespace content