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

Side by Side Diff: webkit/browser/database/database_tracker_unittest.cc

Issue 259083002: Move mock_special_storage_policy from webkit/ to content/public/test/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 7 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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.
4
5 #include "base/file_util.h"
6 #include "base/files/file.h"
7 #include "base/files/file_path.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/test_completion_callback.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/sqlite/sqlite3.h"
18 #include "webkit/browser/database/database_tracker.h"
19 #include "webkit/browser/quota/mock_special_storage_policy.h"
20 #include "webkit/browser/quota/quota_manager_proxy.h"
21 #include "webkit/common/database/database_identifier.h"
22
23 using base::ASCIIToUTF16;
24
25 namespace {
26
27 const char kOrigin1Url[] = "http://origin1";
28 const char kOrigin2Url[] = "http://protected_origin2";
29
30 class TestObserver : public webkit_database::DatabaseTracker::Observer {
31 public:
32 TestObserver()
33 : new_notification_received_(false),
34 observe_size_changes_(true),
35 observe_scheduled_deletions_(true) {
36 }
37 TestObserver(bool observe_size_changes, bool observe_scheduled_deletions)
38 : new_notification_received_(false),
39 observe_size_changes_(observe_size_changes),
40 observe_scheduled_deletions_(observe_scheduled_deletions) {
41 }
42
43 virtual ~TestObserver() {}
44 virtual void OnDatabaseSizeChanged(const std::string& origin_identifier,
45 const base::string16& database_name,
46 int64 database_size) OVERRIDE {
47 if (!observe_size_changes_)
48 return;
49 new_notification_received_ = true;
50 origin_identifier_ = origin_identifier;
51 database_name_ = database_name;
52 database_size_ = database_size;
53 }
54 virtual void OnDatabaseScheduledForDeletion(
55 const std::string& origin_identifier,
56 const base::string16& database_name) OVERRIDE {
57 if (!observe_scheduled_deletions_)
58 return;
59 new_notification_received_ = true;
60 origin_identifier_ = origin_identifier;
61 database_name_ = database_name;
62 }
63 bool DidReceiveNewNotification() {
64 bool temp_new_notification_received = new_notification_received_;
65 new_notification_received_ = false;
66 return temp_new_notification_received;
67 }
68 std::string GetNotificationOriginIdentifier() {
69 return origin_identifier_;
70 }
71 base::string16 GetNotificationDatabaseName() { return database_name_; }
72 int64 GetNotificationDatabaseSize() { return database_size_; }
73
74 private:
75 bool new_notification_received_;
76 bool observe_size_changes_;
77 bool observe_scheduled_deletions_;
78 std::string origin_identifier_;
79 base::string16 database_name_;
80 int64 database_size_;
81 };
82
83 void CheckNotificationReceived(TestObserver* observer,
84 const std::string& expected_origin_identifier,
85 const base::string16& expected_database_name,
86 int64 expected_database_size) {
87 EXPECT_TRUE(observer->DidReceiveNewNotification());
88 EXPECT_EQ(expected_origin_identifier,
89 observer->GetNotificationOriginIdentifier());
90 EXPECT_EQ(expected_database_name,
91 observer->GetNotificationDatabaseName());
92 EXPECT_EQ(expected_database_size,
93 observer->GetNotificationDatabaseSize());
94 }
95
96 class TestQuotaManagerProxy : public quota::QuotaManagerProxy {
97 public:
98 TestQuotaManagerProxy()
99 : QuotaManagerProxy(NULL, NULL),
100 registered_client_(NULL) {
101 }
102
103 virtual void RegisterClient(quota::QuotaClient* client) OVERRIDE {
104 EXPECT_FALSE(registered_client_);
105 registered_client_ = client;
106 }
107
108 virtual void NotifyStorageAccessed(quota::QuotaClient::ID client_id,
109 const GURL& origin,
110 quota::StorageType type) OVERRIDE {
111 EXPECT_EQ(quota::QuotaClient::kDatabase, client_id);
112 EXPECT_EQ(quota::kStorageTypeTemporary, type);
113 accesses_[origin] += 1;
114 }
115
116 virtual void NotifyStorageModified(quota::QuotaClient::ID client_id,
117 const GURL& origin,
118 quota::StorageType type,
119 int64 delta) OVERRIDE {
120 EXPECT_EQ(quota::QuotaClient::kDatabase, client_id);
121 EXPECT_EQ(quota::kStorageTypeTemporary, type);
122 modifications_[origin].first += 1;
123 modifications_[origin].second += delta;
124 }
125
126 // Not needed for our tests.
127 virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
128 virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
129 virtual void SetUsageCacheEnabled(quota::QuotaClient::ID client_id,
130 const GURL& origin,
131 quota::StorageType type,
132 bool enabled) OVERRIDE {}
133 virtual void GetUsageAndQuota(
134 base::SequencedTaskRunner* original_task_runner,
135 const GURL& origin,
136 quota::StorageType type,
137 const GetUsageAndQuotaCallback& callback) OVERRIDE {}
138
139 void SimulateQuotaManagerDestroyed() {
140 if (registered_client_) {
141 registered_client_->OnQuotaManagerDestroyed();
142 registered_client_ = NULL;
143 }
144 }
145
146 bool WasAccessNotified(const GURL& origin) {
147 return accesses_[origin] != 0;
148 }
149
150 bool WasModificationNotified(const GURL& origin, int64 amount) {
151 return modifications_[origin].first != 0 &&
152 modifications_[origin].second == amount;
153 }
154
155 void reset() {
156 accesses_.clear();
157 modifications_.clear();
158 }
159
160 quota::QuotaClient* registered_client_;
161
162 // Map from origin to count of access notifications.
163 std::map<GURL, int> accesses_;
164
165 // Map from origin to <count, sum of deltas>
166 std::map<GURL, std::pair<int, int64> > modifications_;
167
168 protected:
169 virtual ~TestQuotaManagerProxy() {
170 EXPECT_FALSE(registered_client_);
171 }
172 };
173
174
175 bool EnsureFileOfSize(const base::FilePath& file_path, int64 length) {
176 base::File file(file_path,
177 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE);
178 if (!file.IsValid())
179 return false;
180 return file.SetLength(length);
181 }
182
183 } // namespace
184
185 namespace webkit_database {
186
187 // We declare a helper class, and make it a friend of DatabaseTracker using
188 // the FRIEND_TEST() macro, and we implement all tests we want to run as
189 // static methods of this class. Then we make our TEST() targets call these
190 // static functions. This allows us to run each test in normal mode and
191 // incognito mode without writing the same code twice.
192 class DatabaseTracker_TestHelper_Test {
193 public:
194 static void TestDeleteOpenDatabase(bool incognito_mode) {
195 // Initialize the tracker database.
196 base::ScopedTempDir temp_dir;
197 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
198 scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy =
199 new quota::MockSpecialStoragePolicy;
200 special_storage_policy->AddProtected(GURL(kOrigin2Url));
201 scoped_refptr<DatabaseTracker> tracker(
202 new DatabaseTracker(temp_dir.path(),
203 incognito_mode,
204 special_storage_policy.get(),
205 NULL,
206 NULL));
207
208 // Create and open three databases.
209 int64 database_size = 0;
210 const std::string kOrigin1 =
211 webkit_database::GetIdentifierFromOrigin(GURL(kOrigin1Url));
212 const std::string kOrigin2 =
213 webkit_database::GetIdentifierFromOrigin(GURL(kOrigin2Url));
214 const base::string16 kDB1 = ASCIIToUTF16("db1");
215 const base::string16 kDB2 = ASCIIToUTF16("db2");
216 const base::string16 kDB3 = ASCIIToUTF16("db3");
217 const base::string16 kDescription = ASCIIToUTF16("database_description");
218
219 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
220 &database_size);
221 tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
222 &database_size);
223 tracker->DatabaseOpened(kOrigin2, kDB3, kDescription, 0,
224 &database_size);
225
226 EXPECT_TRUE(base::CreateDirectory(
227 tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
228 tracker->GetOriginDirectory(kOrigin1)))));
229 EXPECT_TRUE(base::CreateDirectory(
230 tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
231 tracker->GetOriginDirectory(kOrigin2)))));
232 EXPECT_EQ(1, base::WriteFile(
233 tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
234 EXPECT_EQ(2, base::WriteFile(
235 tracker->GetFullDBFilePath(kOrigin2, kDB2), "aa", 2));
236 EXPECT_EQ(3, base::WriteFile(
237 tracker->GetFullDBFilePath(kOrigin2, kDB3), "aaa", 3));
238 tracker->DatabaseModified(kOrigin1, kDB1);
239 tracker->DatabaseModified(kOrigin2, kDB2);
240 tracker->DatabaseModified(kOrigin2, kDB3);
241
242 // Delete db1. Should also delete origin1.
243 TestObserver observer;
244 tracker->AddObserver(&observer);
245 net::TestCompletionCallback callback;
246 int result = tracker->DeleteDatabase(kOrigin1, kDB1, callback.callback());
247 EXPECT_EQ(net::ERR_IO_PENDING, result);
248 ASSERT_FALSE(callback.have_result());
249 EXPECT_TRUE(observer.DidReceiveNewNotification());
250 EXPECT_EQ(kOrigin1, observer.GetNotificationOriginIdentifier());
251 EXPECT_EQ(kDB1, observer.GetNotificationDatabaseName());
252 tracker->DatabaseClosed(kOrigin1, kDB1);
253 result = callback.GetResult(result);
254 EXPECT_EQ(net::OK, result);
255 EXPECT_FALSE(base::PathExists(
256 tracker->DatabaseDirectory().AppendASCII(kOrigin1)));
257
258 // Recreate db1.
259 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
260 &database_size);
261 EXPECT_TRUE(base::CreateDirectory(
262 tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
263 tracker->GetOriginDirectory(kOrigin1)))));
264 EXPECT_EQ(1, base::WriteFile(
265 tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
266 tracker->DatabaseModified(kOrigin1, kDB1);
267
268 // Setup file modification times. db1 and db2 are modified now, db3 three
269 // days ago.
270 base::Time now = base::Time::Now();
271 EXPECT_TRUE(base::TouchFile(tracker->GetFullDBFilePath(kOrigin1, kDB1),
272 now, now));
273 EXPECT_TRUE(base::TouchFile(tracker->GetFullDBFilePath(kOrigin2, kDB2),
274 now, now));
275 base::Time three_days_ago = now - base::TimeDelta::FromDays(3);
276 EXPECT_TRUE(base::TouchFile(tracker->GetFullDBFilePath(kOrigin2, kDB3),
277 three_days_ago, three_days_ago));
278
279 // Delete databases modified since yesterday. db2 is whitelisted.
280 base::Time yesterday = base::Time::Now();
281 yesterday -= base::TimeDelta::FromDays(1);
282 result = tracker->DeleteDataModifiedSince(
283 yesterday, callback.callback());
284 EXPECT_EQ(net::ERR_IO_PENDING, result);
285 ASSERT_FALSE(callback.have_result());
286 EXPECT_TRUE(observer.DidReceiveNewNotification());
287 tracker->DatabaseClosed(kOrigin1, kDB1);
288 tracker->DatabaseClosed(kOrigin2, kDB2);
289 result = callback.GetResult(result);
290 EXPECT_EQ(net::OK, result);
291 EXPECT_FALSE(base::PathExists(
292 tracker->DatabaseDirectory().AppendASCII(kOrigin1)));
293 EXPECT_TRUE(
294 base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
295 EXPECT_TRUE(
296 base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB3)));
297
298 tracker->DatabaseClosed(kOrigin2, kDB3);
299 tracker->RemoveObserver(&observer);
300 }
301
302 static void TestDatabaseTracker(bool incognito_mode) {
303 // Initialize the tracker database.
304 base::ScopedTempDir temp_dir;
305 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
306 scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy =
307 new quota::MockSpecialStoragePolicy;
308 special_storage_policy->AddProtected(GURL(kOrigin2Url));
309 scoped_refptr<DatabaseTracker> tracker(
310 new DatabaseTracker(temp_dir.path(),
311 incognito_mode,
312 special_storage_policy.get(),
313 NULL,
314 NULL));
315
316 // Add two observers.
317 TestObserver observer1;
318 TestObserver observer2;
319 tracker->AddObserver(&observer1);
320 tracker->AddObserver(&observer2);
321
322 // Open three new databases.
323 int64 database_size = 0;
324 const std::string kOrigin1 =
325 webkit_database::GetIdentifierFromOrigin(GURL(kOrigin1Url));
326 const std::string kOrigin2 =
327 webkit_database::GetIdentifierFromOrigin(GURL(kOrigin2Url));
328 const base::string16 kDB1 = ASCIIToUTF16("db1");
329 const base::string16 kDB2 = ASCIIToUTF16("db2");
330 const base::string16 kDB3 = ASCIIToUTF16("db3");
331 const base::string16 kDescription = ASCIIToUTF16("database_description");
332
333 // Get the info for kOrigin1 and kOrigin2
334 DatabaseTracker::CachedOriginInfo* origin1_info =
335 tracker->GetCachedOriginInfo(kOrigin1);
336 DatabaseTracker::CachedOriginInfo* origin2_info =
337 tracker->GetCachedOriginInfo(kOrigin1);
338 EXPECT_TRUE(origin1_info);
339 EXPECT_TRUE(origin2_info);
340
341
342 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
343 &database_size);
344 EXPECT_EQ(0, database_size);
345 tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
346 &database_size);
347 EXPECT_EQ(0, database_size);
348 tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0,
349 &database_size);
350 EXPECT_EQ(0, database_size);
351
352 // Write some data to each file and check that the listeners are
353 // called with the appropriate values.
354 EXPECT_TRUE(base::CreateDirectory(
355 tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
356 tracker->GetOriginDirectory(kOrigin1)))));
357 EXPECT_TRUE(base::CreateDirectory(
358 tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
359 tracker->GetOriginDirectory(kOrigin2)))));
360 EXPECT_EQ(1, base::WriteFile(
361 tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
362 EXPECT_EQ(2, base::WriteFile(
363 tracker->GetFullDBFilePath(kOrigin2, kDB2), "aa", 2));
364 EXPECT_EQ(4, base::WriteFile(
365 tracker->GetFullDBFilePath(kOrigin1, kDB3), "aaaa", 4));
366 tracker->DatabaseModified(kOrigin1, kDB1);
367 CheckNotificationReceived(&observer1, kOrigin1, kDB1, 1);
368 CheckNotificationReceived(&observer2, kOrigin1, kDB1, 1);
369 tracker->DatabaseModified(kOrigin2, kDB2);
370 CheckNotificationReceived(&observer1, kOrigin2, kDB2, 2);
371 CheckNotificationReceived(&observer2, kOrigin2, kDB2, 2);
372 tracker->DatabaseModified(kOrigin1, kDB3);
373 CheckNotificationReceived(&observer1, kOrigin1, kDB3, 4);
374 CheckNotificationReceived(&observer2, kOrigin1, kDB3, 4);
375
376 // Close all databases
377 tracker->DatabaseClosed(kOrigin1, kDB1);
378 tracker->DatabaseClosed(kOrigin2, kDB2);
379 tracker->DatabaseClosed(kOrigin1, kDB3);
380
381 // Open an existing database and check the reported size
382 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
383 &database_size);
384 EXPECT_EQ(1, database_size);
385 tracker->DatabaseClosed(kOrigin1, kDB1);
386
387 // Remove an observer; this should clear all caches.
388 tracker->RemoveObserver(&observer2);
389
390 // Close the tracker database and clear all caches.
391 // Then make sure that DatabaseOpened() still returns the correct result.
392 tracker->CloseTrackerDatabaseAndClearCaches();
393 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
394 &database_size);
395 EXPECT_EQ(1, database_size);
396 tracker->DatabaseClosed(kOrigin1, kDB1);
397
398 // Remove all observers.
399 tracker->RemoveObserver(&observer1);
400
401 // Trying to delete a database in use should fail
402 tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0,
403 &database_size);
404 EXPECT_FALSE(tracker->DeleteClosedDatabase(kOrigin1, kDB3));
405 origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
406 EXPECT_TRUE(origin1_info);
407 EXPECT_EQ(4, origin1_info->GetDatabaseSize(kDB3));
408 tracker->DatabaseClosed(kOrigin1, kDB3);
409
410 // Delete a database and make sure the space used by that origin is updated
411 EXPECT_TRUE(tracker->DeleteClosedDatabase(kOrigin1, kDB3));
412 origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
413 EXPECT_TRUE(origin1_info);
414 EXPECT_EQ(1, origin1_info->GetDatabaseSize(kDB1));
415 EXPECT_EQ(0, origin1_info->GetDatabaseSize(kDB3));
416
417 // Get all data for all origins
418 std::vector<OriginInfo> origins_info;
419 EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info));
420 EXPECT_EQ(size_t(2), origins_info.size());
421 EXPECT_EQ(kOrigin1, origins_info[0].GetOriginIdentifier());
422 EXPECT_EQ(1, origins_info[0].TotalSize());
423 EXPECT_EQ(1, origins_info[0].GetDatabaseSize(kDB1));
424 EXPECT_EQ(0, origins_info[0].GetDatabaseSize(kDB3));
425
426 EXPECT_EQ(kOrigin2, origins_info[1].GetOriginIdentifier());
427 EXPECT_EQ(2, origins_info[1].TotalSize());
428
429 // Trying to delete an origin with databases in use should fail
430 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
431 &database_size);
432 EXPECT_FALSE(tracker->DeleteOrigin(kOrigin1, false));
433 origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
434 EXPECT_TRUE(origin1_info);
435 EXPECT_EQ(1, origin1_info->GetDatabaseSize(kDB1));
436 tracker->DatabaseClosed(kOrigin1, kDB1);
437
438 // Delete an origin that doesn't have any database in use
439 EXPECT_TRUE(tracker->DeleteOrigin(kOrigin1, false));
440 origins_info.clear();
441 EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info));
442 EXPECT_EQ(size_t(1), origins_info.size());
443 EXPECT_EQ(kOrigin2, origins_info[0].GetOriginIdentifier());
444
445 origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
446 EXPECT_TRUE(origin1_info);
447 EXPECT_EQ(0, origin1_info->TotalSize());
448 }
449
450 static void DatabaseTrackerQuotaIntegration() {
451 const GURL kOrigin(kOrigin1Url);
452 const std::string kOriginId =
453 webkit_database::GetIdentifierFromOrigin(kOrigin);
454 const base::string16 kName = ASCIIToUTF16("name");
455 const base::string16 kDescription = ASCIIToUTF16("description");
456
457 base::ScopedTempDir temp_dir;
458 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
459
460 // Initialize the tracker with a QuotaManagerProxy
461 scoped_refptr<TestQuotaManagerProxy> test_quota_proxy(
462 new TestQuotaManagerProxy);
463 scoped_refptr<DatabaseTracker> tracker(
464 new DatabaseTracker(temp_dir.path(),
465 false /* incognito */,
466 NULL,
467 test_quota_proxy.get(),
468 NULL));
469 EXPECT_TRUE(test_quota_proxy->registered_client_);
470
471 // Create a database and modify it a couple of times, close it,
472 // then delete it. Observe the tracker notifies accordingly.
473
474 int64 database_size = 0;
475 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
476 &database_size);
477 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
478 test_quota_proxy->reset();
479
480 base::FilePath db_file(tracker->GetFullDBFilePath(kOriginId, kName));
481 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
482 EXPECT_TRUE(EnsureFileOfSize(db_file, 10));
483 tracker->DatabaseModified(kOriginId, kName);
484 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 10));
485 test_quota_proxy->reset();
486
487 EXPECT_TRUE(EnsureFileOfSize(db_file, 100));
488 tracker->DatabaseModified(kOriginId, kName);
489 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 90));
490 test_quota_proxy->reset();
491
492 tracker->DatabaseClosed(kOriginId, kName);
493 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
494 EXPECT_EQ(net::OK, tracker->DeleteDatabase(
495 kOriginId, kName, net::CompletionCallback()));
496 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
497 test_quota_proxy->reset();
498
499 // Create a database and modify it, try to delete it while open,
500 // then close it (at which time deletion will actually occur).
501 // Observe the tracker notifies accordingly.
502
503 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
504 &database_size);
505 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
506 test_quota_proxy->reset();
507
508 db_file = tracker->GetFullDBFilePath(kOriginId, kName);
509 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
510 EXPECT_TRUE(EnsureFileOfSize(db_file, 100));
511 tracker->DatabaseModified(kOriginId, kName);
512 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 100));
513 test_quota_proxy->reset();
514
515 EXPECT_EQ(net::ERR_IO_PENDING,
516 tracker->DeleteDatabase(kOriginId, kName,
517 net::CompletionCallback()));
518 EXPECT_FALSE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
519
520 tracker->DatabaseClosed(kOriginId, kName);
521 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
522 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
523 test_quota_proxy->reset();
524
525 // Create a database and up the file size without telling
526 // the tracker about the modification, than simulate a
527 // a renderer crash.
528 // Observe the tracker notifies accordingly.
529
530 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
531 &database_size);
532 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
533 test_quota_proxy->reset();
534 db_file = tracker->GetFullDBFilePath(kOriginId, kName);
535 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
536 EXPECT_TRUE(EnsureFileOfSize(db_file, 100));
537 DatabaseConnections crashed_renderer_connections;
538 crashed_renderer_connections.AddConnection(kOriginId, kName);
539 EXPECT_FALSE(test_quota_proxy->WasModificationNotified(kOrigin, 100));
540 tracker->CloseDatabases(crashed_renderer_connections);
541 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 100));
542
543 // Cleanup.
544 crashed_renderer_connections.RemoveAllConnections();
545 test_quota_proxy->SimulateQuotaManagerDestroyed();
546 }
547
548 static void DatabaseTrackerClearSessionOnlyDatabasesOnExit() {
549 int64 database_size = 0;
550 const std::string kOrigin1 =
551 webkit_database::GetIdentifierFromOrigin(GURL(kOrigin1Url));
552 const std::string kOrigin2 =
553 webkit_database::GetIdentifierFromOrigin(GURL(kOrigin2Url));
554 const base::string16 kDB1 = ASCIIToUTF16("db1");
555 const base::string16 kDB2 = ASCIIToUTF16("db2");
556 const base::string16 kDescription = ASCIIToUTF16("database_description");
557
558 // Initialize the tracker database.
559 base::MessageLoop message_loop;
560 base::ScopedTempDir temp_dir;
561 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
562 base::FilePath origin1_db_dir;
563 base::FilePath origin2_db_dir;
564 {
565 scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy =
566 new quota::MockSpecialStoragePolicy;
567 special_storage_policy->AddSessionOnly(GURL(kOrigin2Url));
568 scoped_refptr<DatabaseTracker> tracker(
569 new DatabaseTracker(temp_dir.path(),
570 false,
571 special_storage_policy.get(),
572 NULL,
573 base::MessageLoopProxy::current().get()));
574
575 // Open two new databases.
576 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
577 &database_size);
578 EXPECT_EQ(0, database_size);
579 tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
580 &database_size);
581 EXPECT_EQ(0, database_size);
582
583 // Write some data to each file.
584 base::FilePath db_file;
585 db_file = tracker->GetFullDBFilePath(kOrigin1, kDB1);
586 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
587 EXPECT_TRUE(EnsureFileOfSize(db_file, 1));
588
589 db_file = tracker->GetFullDBFilePath(kOrigin2, kDB2);
590 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
591 EXPECT_TRUE(EnsureFileOfSize(db_file, 2));
592
593 // Store the origin database directories as long as they still exist.
594 origin1_db_dir = tracker->GetFullDBFilePath(kOrigin1, kDB1).DirName();
595 origin2_db_dir = tracker->GetFullDBFilePath(kOrigin2, kDB2).DirName();
596
597 tracker->DatabaseModified(kOrigin1, kDB1);
598 tracker->DatabaseModified(kOrigin2, kDB2);
599
600 // Close all databases.
601 tracker->DatabaseClosed(kOrigin1, kDB1);
602 tracker->DatabaseClosed(kOrigin2, kDB2);
603
604 tracker->Shutdown();
605 }
606
607 // At this point, the database tracker should be gone. Create a new one.
608 scoped_refptr<DatabaseTracker> tracker(
609 new DatabaseTracker(temp_dir.path(), false, NULL, NULL, NULL));
610
611 // Get all data for all origins.
612 std::vector<OriginInfo> origins_info;
613 EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info));
614 // kOrigin1 was not session-only, so it survived. kOrigin2 was session-only
615 // and it got deleted.
616 EXPECT_EQ(size_t(1), origins_info.size());
617 EXPECT_EQ(kOrigin1, origins_info[0].GetOriginIdentifier());
618 EXPECT_TRUE(
619 base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
620 EXPECT_EQ(base::FilePath(), tracker->GetFullDBFilePath(kOrigin2, kDB2));
621
622 // The origin directory of kOrigin1 remains, but the origin directory of
623 // kOrigin2 is deleted.
624 EXPECT_TRUE(base::PathExists(origin1_db_dir));
625 EXPECT_FALSE(base::PathExists(origin2_db_dir));
626 }
627
628 static void DatabaseTrackerSetForceKeepSessionState() {
629 int64 database_size = 0;
630 const std::string kOrigin1 =
631 webkit_database::GetIdentifierFromOrigin(GURL(kOrigin1Url));
632 const std::string kOrigin2 =
633 webkit_database::GetIdentifierFromOrigin(GURL(kOrigin2Url));
634 const base::string16 kDB1 = ASCIIToUTF16("db1");
635 const base::string16 kDB2 = ASCIIToUTF16("db2");
636 const base::string16 kDescription = ASCIIToUTF16("database_description");
637
638 // Initialize the tracker database.
639 base::MessageLoop message_loop;
640 base::ScopedTempDir temp_dir;
641 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
642 base::FilePath origin1_db_dir;
643 base::FilePath origin2_db_dir;
644 {
645 scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy =
646 new quota::MockSpecialStoragePolicy;
647 special_storage_policy->AddSessionOnly(GURL(kOrigin2Url));
648 scoped_refptr<DatabaseTracker> tracker(
649 new DatabaseTracker(temp_dir.path(),
650 false,
651 special_storage_policy.get(),
652 NULL,
653 base::MessageLoopProxy::current().get()));
654 tracker->SetForceKeepSessionState();
655
656 // Open two new databases.
657 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
658 &database_size);
659 EXPECT_EQ(0, database_size);
660 tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
661 &database_size);
662 EXPECT_EQ(0, database_size);
663
664 // Write some data to each file.
665 base::FilePath db_file;
666 db_file = tracker->GetFullDBFilePath(kOrigin1, kDB1);
667 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
668 EXPECT_TRUE(EnsureFileOfSize(db_file, 1));
669
670 db_file = tracker->GetFullDBFilePath(kOrigin2, kDB2);
671 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
672 EXPECT_TRUE(EnsureFileOfSize(db_file, 2));
673
674 // Store the origin database directories as long as they still exist.
675 origin1_db_dir = tracker->GetFullDBFilePath(kOrigin1, kDB1).DirName();
676 origin2_db_dir = tracker->GetFullDBFilePath(kOrigin2, kDB2).DirName();
677
678 tracker->DatabaseModified(kOrigin1, kDB1);
679 tracker->DatabaseModified(kOrigin2, kDB2);
680
681 // Close all databases.
682 tracker->DatabaseClosed(kOrigin1, kDB1);
683 tracker->DatabaseClosed(kOrigin2, kDB2);
684
685 tracker->Shutdown();
686 }
687
688 // At this point, the database tracker should be gone. Create a new one.
689 scoped_refptr<DatabaseTracker> tracker(
690 new DatabaseTracker(temp_dir.path(), false, NULL, NULL, NULL));
691
692 // Get all data for all origins.
693 std::vector<OriginInfo> origins_info;
694 EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info));
695 // No origins were deleted.
696 EXPECT_EQ(size_t(2), origins_info.size());
697 EXPECT_TRUE(
698 base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
699 EXPECT_TRUE(
700 base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
701
702 EXPECT_TRUE(base::PathExists(origin1_db_dir));
703 EXPECT_TRUE(base::PathExists(origin2_db_dir));
704 }
705
706 static void EmptyDatabaseNameIsValid() {
707 const GURL kOrigin(kOrigin1Url);
708 const std::string kOriginId =
709 webkit_database::GetIdentifierFromOrigin(kOrigin);
710 const base::string16 kEmptyName;
711 const base::string16 kDescription(ASCIIToUTF16("description"));
712 const base::string16 kChangedDescription(
713 ASCIIToUTF16("changed_description"));
714
715 // Initialize a tracker database, no need to put it on disk.
716 const bool kUseInMemoryTrackerDatabase = true;
717 base::ScopedTempDir temp_dir;
718 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
719 scoped_refptr<DatabaseTracker> tracker(
720 new DatabaseTracker(temp_dir.path(), kUseInMemoryTrackerDatabase,
721 NULL, NULL, NULL));
722
723 // Starts off with no databases.
724 std::vector<OriginInfo> infos;
725 EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
726 EXPECT_TRUE(infos.empty());
727
728 // Create a db with an empty name.
729 int64 database_size = -1;
730 tracker->DatabaseOpened(kOriginId, kEmptyName, kDescription, 0,
731 &database_size);
732 EXPECT_EQ(0, database_size);
733 tracker->DatabaseModified(kOriginId, kEmptyName);
734 EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
735 EXPECT_EQ(1u, infos.size());
736 EXPECT_EQ(kDescription, infos[0].GetDatabaseDescription(kEmptyName));
737 EXPECT_FALSE(tracker->GetFullDBFilePath(kOriginId, kEmptyName).empty());
738 tracker->DatabaseOpened(kOriginId, kEmptyName, kChangedDescription, 0,
739 &database_size);
740 infos.clear();
741 EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
742 EXPECT_EQ(1u, infos.size());
743 EXPECT_EQ(kChangedDescription, infos[0].GetDatabaseDescription(kEmptyName));
744 tracker->DatabaseClosed(kOriginId, kEmptyName);
745 tracker->DatabaseClosed(kOriginId, kEmptyName);
746
747 // Deleting it should return to the initial state.
748 EXPECT_EQ(net::OK, tracker->DeleteDatabase(kOriginId, kEmptyName,
749 net::CompletionCallback()));
750 infos.clear();
751 EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
752 EXPECT_TRUE(infos.empty());
753 }
754
755 static void HandleSqliteError() {
756 const GURL kOrigin(kOrigin1Url);
757 const std::string kOriginId =
758 webkit_database::GetIdentifierFromOrigin(kOrigin);
759 const base::string16 kName(ASCIIToUTF16("name"));
760 const base::string16 kDescription(ASCIIToUTF16("description"));
761
762 // Initialize a tracker database, no need to put it on disk.
763 const bool kUseInMemoryTrackerDatabase = true;
764 base::ScopedTempDir temp_dir;
765 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
766 scoped_refptr<DatabaseTracker> tracker(
767 new DatabaseTracker(temp_dir.path(), kUseInMemoryTrackerDatabase,
768 NULL, NULL, NULL));
769
770 // Setup to observe OnScheduledForDelete notifications.
771 TestObserver observer(false, true);
772 tracker->AddObserver(&observer);
773
774 // Verify does no harm when there is no such database.
775 tracker->HandleSqliteError(kOriginId, kName, SQLITE_CORRUPT);
776 EXPECT_FALSE(tracker->IsDatabaseScheduledForDeletion(kOriginId, kName));
777 EXPECT_FALSE(observer.DidReceiveNewNotification());
778
779 // --------------------------------------------------------
780 // Create a record of a database in the tracker db and create
781 // a spoof_db_file on disk in the expected location.
782 int64 database_size = 0;
783 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
784 &database_size);
785 base::FilePath spoof_db_file = tracker->GetFullDBFilePath(kOriginId, kName);
786 EXPECT_FALSE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
787 EXPECT_TRUE(base::CreateDirectory(spoof_db_file.DirName()));
788 EXPECT_TRUE(EnsureFileOfSize(spoof_db_file, 1));
789
790 // Verify does no harm with a non-error is reported.
791 tracker->HandleSqliteError(kOriginId, kName, SQLITE_OK);
792 EXPECT_FALSE(tracker->IsDatabaseScheduledForDeletion(kOriginId, kName));
793 EXPECT_FALSE(observer.DidReceiveNewNotification());
794
795 // Verify that with a connection open, the db is scheduled for deletion,
796 // but that the file still exists.
797 tracker->HandleSqliteError(kOriginId, kName, SQLITE_CORRUPT);
798 EXPECT_TRUE(tracker->IsDatabaseScheduledForDeletion(kOriginId, kName));
799 EXPECT_TRUE(observer.DidReceiveNewNotification());
800 EXPECT_TRUE(base::PathExists(spoof_db_file));
801
802 // Verify that once closed, the file is deleted and the record in the
803 // tracker db is removed.
804 tracker->DatabaseClosed(kOriginId, kName);
805 EXPECT_FALSE(base::PathExists(spoof_db_file));
806 EXPECT_TRUE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
807
808 // --------------------------------------------------------
809 // Create another record of a database in the tracker db and create
810 // a spoof_db_file on disk in the expected location.
811 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
812 &database_size);
813 base::FilePath spoof_db_file2 = tracker->GetFullDBFilePath(kOriginId, kName) ;
814 EXPECT_FALSE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
815 EXPECT_NE(spoof_db_file, spoof_db_file2);
816 EXPECT_TRUE(base::CreateDirectory(spoof_db_file2.DirName()));
817 EXPECT_TRUE(EnsureFileOfSize(spoof_db_file2, 1));
818
819 // Verify that with no connection open, the db is deleted immediately.
820 tracker->DatabaseClosed(kOriginId, kName);
821 tracker->HandleSqliteError(kOriginId, kName, SQLITE_CORRUPT);
822 EXPECT_FALSE(tracker->IsDatabaseScheduledForDeletion(kOriginId, kName));
823 EXPECT_FALSE(observer.DidReceiveNewNotification());
824 EXPECT_TRUE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
825 EXPECT_FALSE(base::PathExists(spoof_db_file2));
826
827 tracker->RemoveObserver(&observer);
828 }
829 };
830
831 TEST(DatabaseTrackerTest, DeleteOpenDatabase) {
832 DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(false);
833 }
834
835 TEST(DatabaseTrackerTest, DeleteOpenDatabaseIncognitoMode) {
836 DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(true);
837 }
838
839 TEST(DatabaseTrackerTest, DatabaseTracker) {
840 DatabaseTracker_TestHelper_Test::TestDatabaseTracker(false);
841 }
842
843 TEST(DatabaseTrackerTest, DatabaseTrackerIncognitoMode) {
844 DatabaseTracker_TestHelper_Test::TestDatabaseTracker(true);
845 }
846
847 TEST(DatabaseTrackerTest, DatabaseTrackerQuotaIntegration) {
848 // There is no difference in behavior between incognito and not.
849 DatabaseTracker_TestHelper_Test::DatabaseTrackerQuotaIntegration();
850 }
851
852 TEST(DatabaseTrackerTest, DatabaseTrackerClearSessionOnlyDatabasesOnExit) {
853 // Only works for regular mode.
854 DatabaseTracker_TestHelper_Test::
855 DatabaseTrackerClearSessionOnlyDatabasesOnExit();
856 }
857
858 TEST(DatabaseTrackerTest, DatabaseTrackerSetForceKeepSessionState) {
859 // Only works for regular mode.
860 DatabaseTracker_TestHelper_Test::DatabaseTrackerSetForceKeepSessionState();
861 }
862
863 TEST(DatabaseTrackerTest, EmptyDatabaseNameIsValid) {
864 DatabaseTracker_TestHelper_Test::EmptyDatabaseNameIsValid();
865 }
866
867 TEST(DatabaseTrackerTest, HandleSqliteError) {
868 DatabaseTracker_TestHelper_Test::HandleSqliteError();
869 }
870
871 } // namespace webkit_database
OLDNEW
« no previous file with comments | « webkit/browser/database/database_tracker.h ('k') | webkit/browser/quota/mock_special_storage_policy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698