Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: content/browser/dom_storage/local_storage_context_mojo_unittest.cc

Issue 2604963002: Store per-origin metadata for localstorage. (Closed)
Patch Set: delete metadata when no more data is stored for an origin Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/dom_storage/local_storage_context_mojo.h" 5 #include "content/browser/dom_storage/local_storage_context_mojo.h"
6 6
7 #include "base/files/file_enumerator.h" 7 #include "base/files/file_enumerator.h"
8 #include "base/files/scoped_temp_dir.h" 8 #include "base/files/scoped_temp_dir.h"
9 #include "base/run_loop.h" 9 #include "base/run_loop.h"
10 #include "components/filesystem/public/interfaces/file_system.mojom.h" 10 #include "components/filesystem/public/interfaces/file_system.mojom.h"
11 #include "components/leveldb/public/cpp/util.h" 11 #include "components/leveldb/public/cpp/util.h"
12 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/local_storage_usage_info.h"
13 #include "content/public/test/test_browser_thread_bundle.h" 14 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "content/test/mock_leveldb_database.h" 15 #include "content/test/mock_leveldb_database.h"
15 #include "mojo/public/cpp/bindings/binding.h" 16 #include "mojo/public/cpp/bindings/binding.h"
16 #include "mojo/public/cpp/bindings/binding_set.h" 17 #include "mojo/public/cpp/bindings/binding_set.h"
17 #include "services/file/file_service.h" 18 #include "services/file/file_service.h"
18 #include "services/file/public/interfaces/constants.mojom.h" 19 #include "services/file/public/interfaces/constants.mojom.h"
19 #include "services/file/user_id_map.h" 20 #include "services/file/user_id_map.h"
20 #include "services/service_manager/public/cpp/interface_factory.h" 21 #include "services/service_manager/public/cpp/interface_factory.h"
21 #include "services/service_manager/public/cpp/interface_registry.h" 22 #include "services/service_manager/public/cpp/interface_registry.h"
22 #include "services/service_manager/public/cpp/service_context.h" 23 #include "services/service_manager/public/cpp/service_context.h"
23 #include "services/service_manager/public/cpp/service_test.h" 24 #include "services/service_manager/public/cpp/service_test.h"
24 #include "services/service_manager/public/interfaces/service_factory.mojom.h" 25 #include "services/service_manager/public/interfaces/service_factory.mojom.h"
25 #include "testing/gtest/include/gtest/gtest.h" 26 #include "testing/gtest/include/gtest/gtest.h"
26 27
27 using leveldb::StdStringToUint8Vector; 28 using leveldb::StdStringToUint8Vector;
28 using leveldb::Uint8VectorToStdString; 29 using leveldb::Uint8VectorToStdString;
29 30
30 namespace content { 31 namespace content {
31 32
32 namespace { 33 namespace {
33 34
34 void NoOpSuccess(bool success) {} 35 void NoOpSuccess(bool success) {}
35 36
37 void GetStorageUsageCallback(const base::Closure& callback,
38 std::vector<LocalStorageUsageInfo>* out_result,
39 std::vector<LocalStorageUsageInfo> result) {
40 *out_result = std::move(result);
41 callback.Run();
42 }
43
36 void GetCallback(const base::Closure& callback, 44 void GetCallback(const base::Closure& callback,
37 bool* success_out, 45 bool* success_out,
38 std::vector<uint8_t>* value_out, 46 std::vector<uint8_t>* value_out,
39 bool success, 47 bool success,
40 const std::vector<uint8_t>& value) { 48 const std::vector<uint8_t>& value) {
41 *success_out = success; 49 *success_out = success;
42 *value_out = value; 50 *value_out = value;
43 callback.Run(); 51 callback.Run();
44 } 52 }
45 53
(...skipping 12 matching lines...) Expand all
58 return context_.get(); 66 return context_.get();
59 } 67 }
60 const std::map<std::vector<uint8_t>, std::vector<uint8_t>>& mock_data() { 68 const std::map<std::vector<uint8_t>, std::vector<uint8_t>>& mock_data() {
61 return mock_data_; 69 return mock_data_;
62 } 70 }
63 71
64 void set_mock_data(const std::string& key, const std::string& value) { 72 void set_mock_data(const std::string& key, const std::string& value) {
65 mock_data_[StdStringToUint8Vector(key)] = StdStringToUint8Vector(value); 73 mock_data_[StdStringToUint8Vector(key)] = StdStringToUint8Vector(value);
66 } 74 }
67 75
76 std::vector<LocalStorageUsageInfo> GetStorageUsageSync() {
77 base::RunLoop run_loop;
78 std::vector<LocalStorageUsageInfo> result;
79 context()->GetStorageUsage(base::BindOnce(&GetStorageUsageCallback,
80 run_loop.QuitClosure(), &result));
81 run_loop.Run();
82 return result;
83 }
84
68 private: 85 private:
69 TestBrowserThreadBundle thread_bundle_; 86 TestBrowserThreadBundle thread_bundle_;
70 std::map<std::vector<uint8_t>, std::vector<uint8_t>> mock_data_; 87 std::map<std::vector<uint8_t>, std::vector<uint8_t>> mock_data_;
71 MockLevelDBDatabase db_; 88 MockLevelDBDatabase db_;
72 mojo::Binding<leveldb::mojom::LevelDBDatabase> db_binding_; 89 mojo::Binding<leveldb::mojom::LevelDBDatabase> db_binding_;
73 90
74 std::unique_ptr<LocalStorageContextMojo> context_; 91 std::unique_ptr<LocalStorageContextMojo> context_;
75 92
76 DISALLOW_COPY_AND_ASSIGN(LocalStorageContextMojoTest); 93 DISALLOW_COPY_AND_ASSIGN(LocalStorageContextMojoTest);
77 }; 94 };
78 95
79 TEST_F(LocalStorageContextMojoTest, Basic) { 96 TEST_F(LocalStorageContextMojoTest, Basic) {
80 auto key = StdStringToUint8Vector("key"); 97 auto key = StdStringToUint8Vector("key");
81 auto value = StdStringToUint8Vector("value"); 98 auto value = StdStringToUint8Vector("value");
82 99
83 mojom::LevelDBWrapperPtr wrapper; 100 mojom::LevelDBWrapperPtr wrapper;
84 context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")), 101 context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
85 MakeRequest(&wrapper)); 102 MakeRequest(&wrapper));
86 wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess)); 103 wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
87 wrapper.reset(); 104 wrapper.reset();
88 105
89 base::RunLoop().RunUntilIdle(); 106 base::RunLoop().RunUntilIdle();
90 107
91 ASSERT_EQ(2u, mock_data().size()); 108 // Should have three rows of data, one for the version, one for the actual
92 EXPECT_EQ(value, mock_data().rbegin()->second); 109 // data and one for metadata.
110 ASSERT_EQ(3u, mock_data().size());
93 } 111 }
94 112
95 TEST_F(LocalStorageContextMojoTest, OriginsAreIndependent) { 113 TEST_F(LocalStorageContextMojoTest, OriginsAreIndependent) {
96 url::Origin origin1(GURL("http://foobar.com:123")); 114 url::Origin origin1(GURL("http://foobar.com:123"));
97 url::Origin origin2(GURL("http://foobar.com:1234")); 115 url::Origin origin2(GURL("http://foobar.com:1234"));
98 auto key1 = StdStringToUint8Vector("4key"); 116 auto key1 = StdStringToUint8Vector("4key");
99 auto key2 = StdStringToUint8Vector("key"); 117 auto key2 = StdStringToUint8Vector("key");
100 auto value = StdStringToUint8Vector("value"); 118 auto value = StdStringToUint8Vector("value");
101 119
102 mojom::LevelDBWrapperPtr wrapper; 120 mojom::LevelDBWrapperPtr wrapper;
103 context()->OpenLocalStorage(origin1, MakeRequest(&wrapper)); 121 context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
104 wrapper->Put(key1, value, "source", base::Bind(&NoOpSuccess)); 122 wrapper->Put(key1, value, "source", base::Bind(&NoOpSuccess));
105 wrapper.reset(); 123 wrapper.reset();
106 124
107 context()->OpenLocalStorage(origin2, MakeRequest(&wrapper)); 125 context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
108 wrapper->Put(key2, value, "source", base::Bind(&NoOpSuccess)); 126 wrapper->Put(key2, value, "source", base::Bind(&NoOpSuccess));
109 wrapper.reset(); 127 wrapper.reset();
110 128
111 base::RunLoop().RunUntilIdle(); 129 base::RunLoop().RunUntilIdle();
112 ASSERT_EQ(3u, mock_data().size()); 130 ASSERT_EQ(5u, mock_data().size());
113 EXPECT_EQ(value, mock_data().rbegin()->second);
114 } 131 }
115 132
116 TEST_F(LocalStorageContextMojoTest, ValidVersion) { 133 TEST_F(LocalStorageContextMojoTest, ValidVersion) {
117 set_mock_data("VERSION", "1"); 134 set_mock_data("VERSION", "1");
118 set_mock_data(std::string("_http://foobar.com") + '\x00' + "key", "value"); 135 set_mock_data(std::string("_http://foobar.com") + '\x00' + "key", "value");
119 136
120 mojom::LevelDBWrapperPtr wrapper; 137 mojom::LevelDBWrapperPtr wrapper;
121 context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")), 138 context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
122 MakeRequest(&wrapper)); 139 MakeRequest(&wrapper));
123 140
(...skipping 23 matching lines...) Expand all
147 StdStringToUint8Vector("key"), 164 StdStringToUint8Vector("key"),
148 base::Bind(&GetCallback, run_loop.QuitClosure(), &success, &result)); 165 base::Bind(&GetCallback, run_loop.QuitClosure(), &success, &result));
149 run_loop.Run(); 166 run_loop.Run();
150 EXPECT_FALSE(success); 167 EXPECT_FALSE(success);
151 } 168 }
152 169
153 TEST_F(LocalStorageContextMojoTest, VersionOnlyWrittenOnCommit) { 170 TEST_F(LocalStorageContextMojoTest, VersionOnlyWrittenOnCommit) {
154 mojom::LevelDBWrapperPtr wrapper; 171 mojom::LevelDBWrapperPtr wrapper;
155 context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")), 172 context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
156 MakeRequest(&wrapper)); 173 MakeRequest(&wrapper));
174
157 base::RunLoop run_loop; 175 base::RunLoop run_loop;
158 bool success = false; 176 bool success = false;
159 std::vector<uint8_t> result; 177 std::vector<uint8_t> result;
160 wrapper->Get( 178 wrapper->Get(
161 StdStringToUint8Vector("key"), 179 StdStringToUint8Vector("key"),
162 base::Bind(&GetCallback, run_loop.QuitClosure(), &success, &result)); 180 base::Bind(&GetCallback, run_loop.QuitClosure(), &success, &result));
163 run_loop.Run(); 181 run_loop.Run();
164 EXPECT_FALSE(success); 182 EXPECT_FALSE(success);
165 wrapper.reset(); 183 wrapper.reset();
166 184
167 base::RunLoop().RunUntilIdle(); 185 base::RunLoop().RunUntilIdle();
168 EXPECT_TRUE(mock_data().empty()); 186 EXPECT_TRUE(mock_data().empty());
169 } 187 }
170 188
189 TEST_F(LocalStorageContextMojoTest, GetStorageUsage_NoData) {
190 std::vector<LocalStorageUsageInfo> info = GetStorageUsageSync();
191 EXPECT_EQ(0u, info.size());
192 }
193
194 TEST_F(LocalStorageContextMojoTest, GetStorageUsage_Data) {
195 url::Origin origin1(GURL("http://foobar.com"));
196 url::Origin origin2(GURL("http://example.com"));
197 auto key1 = StdStringToUint8Vector("key1");
198 auto key2 = StdStringToUint8Vector("key");
199 auto value = StdStringToUint8Vector("value");
200
201 base::Time before_write = base::Time::Now();
202
203 mojom::LevelDBWrapperPtr wrapper;
204 context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
205 wrapper->Put(key1, value, "source", base::Bind(&NoOpSuccess));
206 wrapper->Put(key2, value, "source", base::Bind(&NoOpSuccess));
207 wrapper.reset();
208
209 context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
210 wrapper->Put(key2, value, "source", base::Bind(&NoOpSuccess));
211 wrapper.reset();
212
213 // GetStorageUsage only include committed data, so nothing at this point.
214 std::vector<LocalStorageUsageInfo> info = GetStorageUsageSync();
215 EXPECT_EQ(0u, info.size());
216
217 // Make sure all data gets committed to disk.
218 base::RunLoop().RunUntilIdle();
219
220 base::Time after_write = base::Time::Now();
221
222 info = GetStorageUsageSync();
223 ASSERT_EQ(2u, info.size());
224 if (url::Origin(info[0].origin) == origin2)
225 std::swap(info[0], info[1]);
226
227 EXPECT_EQ(origin1, url::Origin(info[0].origin));
228 EXPECT_EQ(origin2, url::Origin(info[1].origin));
229 EXPECT_LE(before_write, info[0].last_modified);
230 EXPECT_LE(before_write, info[1].last_modified);
231 EXPECT_GE(after_write, info[0].last_modified);
232 EXPECT_GE(after_write, info[1].last_modified);
233 EXPECT_GT(info[0].data_size, info[1].data_size);
234 }
235
236 TEST_F(LocalStorageContextMojoTest, MetaDataClearedOnDelete) {
237 url::Origin origin1(GURL("http://foobar.com"));
238 url::Origin origin2(GURL("http://example.com"));
239 auto key = StdStringToUint8Vector("key");
240 auto value = StdStringToUint8Vector("value");
241
242 mojom::LevelDBWrapperPtr wrapper;
243 context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
244 wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
245 wrapper.reset();
246 context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
247 wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
248 wrapper.reset();
249 context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
250 wrapper->Delete(key, "source", base::Bind(&NoOpSuccess));
251 wrapper.reset();
252
253 // Make sure all data gets committed to disk.
254 base::RunLoop().RunUntilIdle();
255
256 // Data from origin2 should exist, including meta-data, but nothing should
257 // exist for origin1.
258 EXPECT_EQ(3u, mock_data().size());
259 for (const auto& it : mock_data()) {
260 if (Uint8VectorToStdString(it.first) == "VERSION")
261 continue;
262 EXPECT_EQ(std::string::npos,
263 Uint8VectorToStdString(it.first).find(origin1.Serialize()));
264 EXPECT_NE(std::string::npos,
265 Uint8VectorToStdString(it.first).find(origin2.Serialize()));
266 }
267 }
268
269 TEST_F(LocalStorageContextMojoTest, MetaDataClearedOnDeleteAll) {
270 url::Origin origin1(GURL("http://foobar.com"));
271 url::Origin origin2(GURL("http://example.com"));
272 auto key = StdStringToUint8Vector("key");
273 auto value = StdStringToUint8Vector("value");
274
275 mojom::LevelDBWrapperPtr wrapper;
276 context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
277 wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
278 wrapper.reset();
279 context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
280 wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
281 wrapper.reset();
282
283 context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
284 wrapper->DeleteAll("source", base::Bind(&NoOpSuccess));
285 wrapper.reset();
286
287 // Make sure all data gets committed to disk.
288 base::RunLoop().RunUntilIdle();
289
290 // Data from origin2 should exist, including meta-data, but nothing should
291 // exist for origin1.
292 EXPECT_EQ(3u, mock_data().size());
293 for (const auto& it : mock_data()) {
294 if (Uint8VectorToStdString(it.first) == "VERSION")
295 continue;
296 EXPECT_EQ(std::string::npos,
297 Uint8VectorToStdString(it.first).find(origin1.Serialize()));
298 EXPECT_NE(std::string::npos,
299 Uint8VectorToStdString(it.first).find(origin2.Serialize()));
300 }
301 }
302
171 namespace { 303 namespace {
172 304
173 class ServiceTestClient : public service_manager::test::ServiceTestClient, 305 class ServiceTestClient : public service_manager::test::ServiceTestClient,
174 public service_manager::mojom::ServiceFactory, 306 public service_manager::mojom::ServiceFactory,
175 public service_manager::InterfaceFactory< 307 public service_manager::InterfaceFactory<
176 service_manager::mojom::ServiceFactory> { 308 service_manager::mojom::ServiceFactory> {
177 public: 309 public:
178 explicit ServiceTestClient(service_manager::test::ServiceTest* test) 310 explicit ServiceTestClient(service_manager::test::ServiceTest* test)
179 : service_manager::test::ServiceTestClient(test) {} 311 : service_manager::test::ServiceTestClient(test) {}
180 ~ServiceTestClient() override {} 312 ~ServiceTestClient() override {}
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 // Should have created files. 498 // Should have created files.
367 EXPECT_EQ(test_path, FirstEntryInDir().BaseName()); 499 EXPECT_EQ(test_path, FirstEntryInDir().BaseName());
368 500
369 // Should be able to re-open. 501 // Should be able to re-open.
370 context.reset(new LocalStorageContextMojo(connector(), test_path)); 502 context.reset(new LocalStorageContextMojo(connector(), test_path));
371 EXPECT_TRUE(DoTestGet(context.get(), key, &result)); 503 EXPECT_TRUE(DoTestGet(context.get(), key, &result));
372 EXPECT_EQ(value, result); 504 EXPECT_EQ(value, result);
373 } 505 }
374 506
375 } // namespace content 507 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698