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