[Android] A prototype of the interactive media notification.
[chromium-blink-merge.git] / content / browser / database_tracker_unittest.cc
bloba068b4d5d27989ba70c56a5245753aa8476e564b
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/files/file.h"
6 #include "base/files/file_path.h"
7 #include "base/files/file_util.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/strings/utf_string_conversions.h"
12 #include "base/thread_task_runner_handle.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 "storage/browser/database/database_tracker.h"
18 #include "storage/browser/quota/quota_manager_proxy.h"
19 #include "storage/common/database/database_identifier.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "third_party/sqlite/sqlite3.h"
23 using base::ASCIIToUTF16;
24 using storage::DatabaseConnections;
25 using storage::DatabaseTracker;
26 using storage::OriginInfo;
28 namespace {
30 const char kOrigin1Url[] = "http://origin1";
31 const char kOrigin2Url[] = "http://protected_origin2";
33 class TestObserver : public storage::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 ~TestObserver() override {}
47 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 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 storage::QuotaManagerProxy {
100 public:
101 TestQuotaManagerProxy()
102 : QuotaManagerProxy(NULL, NULL),
103 registered_client_(NULL) {
106 void RegisterClient(storage::QuotaClient* client) override {
107 EXPECT_FALSE(registered_client_);
108 registered_client_ = client;
111 void NotifyStorageAccessed(storage::QuotaClient::ID client_id,
112 const GURL& origin,
113 storage::StorageType type) override {
114 EXPECT_EQ(storage::QuotaClient::kDatabase, client_id);
115 EXPECT_EQ(storage::kStorageTypeTemporary, type);
116 accesses_[origin] += 1;
119 void NotifyStorageModified(storage::QuotaClient::ID client_id,
120 const GURL& origin,
121 storage::StorageType type,
122 int64 delta) override {
123 EXPECT_EQ(storage::QuotaClient::kDatabase, client_id);
124 EXPECT_EQ(storage::kStorageTypeTemporary, type);
125 modifications_[origin].first += 1;
126 modifications_[origin].second += delta;
129 // Not needed for our tests.
130 void NotifyOriginInUse(const GURL& origin) override {}
131 void NotifyOriginNoLongerInUse(const GURL& origin) override {}
132 void SetUsageCacheEnabled(storage::QuotaClient::ID client_id,
133 const GURL& origin,
134 storage::StorageType type,
135 bool enabled) override {}
136 void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
137 const GURL& origin,
138 storage::StorageType type,
139 const GetUsageAndQuotaCallback& callback) override {}
141 void SimulateQuotaManagerDestroyed() {
142 if (registered_client_) {
143 registered_client_->OnQuotaManagerDestroyed();
144 registered_client_ = NULL;
148 bool WasAccessNotified(const GURL& origin) {
149 return accesses_[origin] != 0;
152 bool WasModificationNotified(const GURL& origin, int64 amount) {
153 return modifications_[origin].first != 0 &&
154 modifications_[origin].second == amount;
157 void reset() {
158 accesses_.clear();
159 modifications_.clear();
162 storage::QuotaClient* registered_client_;
164 // Map from origin to count of access notifications.
165 std::map<GURL, int> accesses_;
167 // Map from origin to <count, sum of deltas>
168 std::map<GURL, std::pair<int, int64> > modifications_;
170 protected:
171 ~TestQuotaManagerProxy() override { EXPECT_FALSE(registered_client_); }
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);
183 } // namespace
185 namespace content {
187 // We declare a helper class, and make it a friend of DatabaseTracker using
188 // the FORWARD_DECLARE_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<MockSpecialStoragePolicy> special_storage_policy =
199 new 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));
208 // Create and open three databases.
209 int64 database_size = 0;
210 const std::string kOrigin1 =
211 storage::GetIdentifierFromOrigin(GURL(kOrigin1Url));
212 const std::string kOrigin2 =
213 storage::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");
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);
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);
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)));
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);
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));
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)));
298 tracker->DatabaseClosed(kOrigin2, kDB3);
299 tracker->RemoveObserver(&observer);
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<MockSpecialStoragePolicy> special_storage_policy =
307 new 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));
316 // Add two observers.
317 TestObserver observer1;
318 TestObserver observer2;
319 tracker->AddObserver(&observer1);
320 tracker->AddObserver(&observer2);
322 // Open three new databases.
323 int64 database_size = 0;
324 const std::string kOrigin1 =
325 storage::GetIdentifierFromOrigin(GURL(kOrigin1Url));
326 const std::string kOrigin2 =
327 storage::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");
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);
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);
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);
376 // Close all databases
377 tracker->DatabaseClosed(kOrigin1, kDB1);
378 tracker->DatabaseClosed(kOrigin2, kDB2);
379 tracker->DatabaseClosed(kOrigin1, kDB3);
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);
387 // Remove an observer; this should clear all caches.
388 tracker->RemoveObserver(&observer2);
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);
398 // Remove all observers.
399 tracker->RemoveObserver(&observer1);
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);
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));
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));
426 EXPECT_EQ(kOrigin2, origins_info[1].GetOriginIdentifier());
427 EXPECT_EQ(2, origins_info[1].TotalSize());
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);
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());
445 origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
446 EXPECT_TRUE(origin1_info);
447 EXPECT_EQ(0, origin1_info->TotalSize());
450 static void DatabaseTrackerQuotaIntegration() {
451 const GURL kOrigin(kOrigin1Url);
452 const std::string kOriginId = storage::GetIdentifierFromOrigin(kOrigin);
453 const base::string16 kName = ASCIIToUTF16("name");
454 const base::string16 kDescription = ASCIIToUTF16("description");
456 base::ScopedTempDir temp_dir;
457 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
459 // Initialize the tracker with a QuotaManagerProxy
460 scoped_refptr<TestQuotaManagerProxy> test_quota_proxy(
461 new TestQuotaManagerProxy);
462 scoped_refptr<DatabaseTracker> tracker(
463 new DatabaseTracker(temp_dir.path(),
464 false /* incognito */,
465 NULL,
466 test_quota_proxy.get(),
467 NULL));
468 EXPECT_TRUE(test_quota_proxy->registered_client_);
470 // Create a database and modify it a couple of times, close it,
471 // then delete it. Observe the tracker notifies accordingly.
473 int64 database_size = 0;
474 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
475 &database_size);
476 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
477 test_quota_proxy->reset();
479 base::FilePath db_file(tracker->GetFullDBFilePath(kOriginId, kName));
480 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
481 EXPECT_TRUE(EnsureFileOfSize(db_file, 10));
482 tracker->DatabaseModified(kOriginId, kName);
483 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 10));
484 test_quota_proxy->reset();
486 EXPECT_TRUE(EnsureFileOfSize(db_file, 100));
487 tracker->DatabaseModified(kOriginId, kName);
488 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 90));
489 test_quota_proxy->reset();
491 tracker->DatabaseClosed(kOriginId, kName);
492 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
493 EXPECT_EQ(net::OK, tracker->DeleteDatabase(
494 kOriginId, kName, net::CompletionCallback()));
495 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
496 test_quota_proxy->reset();
498 // Create a database and modify it, try to delete it while open,
499 // then close it (at which time deletion will actually occur).
500 // Observe the tracker notifies accordingly.
502 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
503 &database_size);
504 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
505 test_quota_proxy->reset();
507 db_file = tracker->GetFullDBFilePath(kOriginId, kName);
508 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
509 EXPECT_TRUE(EnsureFileOfSize(db_file, 100));
510 tracker->DatabaseModified(kOriginId, kName);
511 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 100));
512 test_quota_proxy->reset();
514 EXPECT_EQ(net::ERR_IO_PENDING,
515 tracker->DeleteDatabase(kOriginId, kName,
516 net::CompletionCallback()));
517 EXPECT_FALSE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
519 tracker->DatabaseClosed(kOriginId, kName);
520 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
521 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
522 test_quota_proxy->reset();
524 // Create a database and up the file size without telling
525 // the tracker about the modification, than simulate a
526 // a renderer crash.
527 // Observe the tracker notifies accordingly.
529 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
530 &database_size);
531 EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
532 test_quota_proxy->reset();
533 db_file = tracker->GetFullDBFilePath(kOriginId, kName);
534 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
535 EXPECT_TRUE(EnsureFileOfSize(db_file, 100));
536 DatabaseConnections crashed_renderer_connections;
537 crashed_renderer_connections.AddConnection(kOriginId, kName);
538 EXPECT_FALSE(test_quota_proxy->WasModificationNotified(kOrigin, 100));
539 tracker->CloseDatabases(crashed_renderer_connections);
540 EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 100));
542 // Cleanup.
543 crashed_renderer_connections.RemoveAllConnections();
544 test_quota_proxy->SimulateQuotaManagerDestroyed();
547 static void DatabaseTrackerClearSessionOnlyDatabasesOnExit() {
548 int64 database_size = 0;
549 const std::string kOrigin1 =
550 storage::GetIdentifierFromOrigin(GURL(kOrigin1Url));
551 const std::string kOrigin2 =
552 storage::GetIdentifierFromOrigin(GURL(kOrigin2Url));
553 const base::string16 kDB1 = ASCIIToUTF16("db1");
554 const base::string16 kDB2 = ASCIIToUTF16("db2");
555 const base::string16 kDescription = ASCIIToUTF16("database_description");
557 // Initialize the tracker database.
558 base::MessageLoop message_loop;
559 base::ScopedTempDir temp_dir;
560 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
561 base::FilePath origin1_db_dir;
562 base::FilePath origin2_db_dir;
564 scoped_refptr<MockSpecialStoragePolicy> special_storage_policy =
565 new MockSpecialStoragePolicy;
566 special_storage_policy->AddSessionOnly(GURL(kOrigin2Url));
567 scoped_refptr<DatabaseTracker> tracker(new DatabaseTracker(
568 temp_dir.path(), false, special_storage_policy.get(), NULL,
569 base::ThreadTaskRunnerHandle::Get().get()));
571 // Open two new databases.
572 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
573 &database_size);
574 EXPECT_EQ(0, database_size);
575 tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
576 &database_size);
577 EXPECT_EQ(0, database_size);
579 // Write some data to each file.
580 base::FilePath db_file;
581 db_file = tracker->GetFullDBFilePath(kOrigin1, kDB1);
582 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
583 EXPECT_TRUE(EnsureFileOfSize(db_file, 1));
585 db_file = tracker->GetFullDBFilePath(kOrigin2, kDB2);
586 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
587 EXPECT_TRUE(EnsureFileOfSize(db_file, 2));
589 // Store the origin database directories as long as they still exist.
590 origin1_db_dir = tracker->GetFullDBFilePath(kOrigin1, kDB1).DirName();
591 origin2_db_dir = tracker->GetFullDBFilePath(kOrigin2, kDB2).DirName();
593 tracker->DatabaseModified(kOrigin1, kDB1);
594 tracker->DatabaseModified(kOrigin2, kDB2);
596 // Close all databases.
597 tracker->DatabaseClosed(kOrigin1, kDB1);
598 tracker->DatabaseClosed(kOrigin2, kDB2);
600 tracker->Shutdown();
603 // At this point, the database tracker should be gone. Create a new one.
604 scoped_refptr<DatabaseTracker> tracker(
605 new DatabaseTracker(temp_dir.path(), false, NULL, NULL, NULL));
607 // Get all data for all origins.
608 std::vector<OriginInfo> origins_info;
609 EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info));
610 // kOrigin1 was not session-only, so it survived. kOrigin2 was session-only
611 // and it got deleted.
612 EXPECT_EQ(size_t(1), origins_info.size());
613 EXPECT_EQ(kOrigin1, origins_info[0].GetOriginIdentifier());
614 EXPECT_TRUE(
615 base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
616 EXPECT_EQ(base::FilePath(), tracker->GetFullDBFilePath(kOrigin2, kDB2));
618 // The origin directory of kOrigin1 remains, but the origin directory of
619 // kOrigin2 is deleted.
620 EXPECT_TRUE(base::PathExists(origin1_db_dir));
621 EXPECT_FALSE(base::PathExists(origin2_db_dir));
624 static void DatabaseTrackerSetForceKeepSessionState() {
625 int64 database_size = 0;
626 const std::string kOrigin1 =
627 storage::GetIdentifierFromOrigin(GURL(kOrigin1Url));
628 const std::string kOrigin2 =
629 storage::GetIdentifierFromOrigin(GURL(kOrigin2Url));
630 const base::string16 kDB1 = ASCIIToUTF16("db1");
631 const base::string16 kDB2 = ASCIIToUTF16("db2");
632 const base::string16 kDescription = ASCIIToUTF16("database_description");
634 // Initialize the tracker database.
635 base::MessageLoop message_loop;
636 base::ScopedTempDir temp_dir;
637 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
638 base::FilePath origin1_db_dir;
639 base::FilePath origin2_db_dir;
641 scoped_refptr<MockSpecialStoragePolicy> special_storage_policy =
642 new MockSpecialStoragePolicy;
643 special_storage_policy->AddSessionOnly(GURL(kOrigin2Url));
644 scoped_refptr<DatabaseTracker> tracker(new DatabaseTracker(
645 temp_dir.path(), false, special_storage_policy.get(), NULL,
646 base::ThreadTaskRunnerHandle::Get().get()));
647 tracker->SetForceKeepSessionState();
649 // Open two new databases.
650 tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
651 &database_size);
652 EXPECT_EQ(0, database_size);
653 tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
654 &database_size);
655 EXPECT_EQ(0, database_size);
657 // Write some data to each file.
658 base::FilePath db_file;
659 db_file = tracker->GetFullDBFilePath(kOrigin1, kDB1);
660 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
661 EXPECT_TRUE(EnsureFileOfSize(db_file, 1));
663 db_file = tracker->GetFullDBFilePath(kOrigin2, kDB2);
664 EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
665 EXPECT_TRUE(EnsureFileOfSize(db_file, 2));
667 // Store the origin database directories as long as they still exist.
668 origin1_db_dir = tracker->GetFullDBFilePath(kOrigin1, kDB1).DirName();
669 origin2_db_dir = tracker->GetFullDBFilePath(kOrigin2, kDB2).DirName();
671 tracker->DatabaseModified(kOrigin1, kDB1);
672 tracker->DatabaseModified(kOrigin2, kDB2);
674 // Close all databases.
675 tracker->DatabaseClosed(kOrigin1, kDB1);
676 tracker->DatabaseClosed(kOrigin2, kDB2);
678 tracker->Shutdown();
681 // At this point, the database tracker should be gone. Create a new one.
682 scoped_refptr<DatabaseTracker> tracker(
683 new DatabaseTracker(temp_dir.path(), false, NULL, NULL, NULL));
685 // Get all data for all origins.
686 std::vector<OriginInfo> origins_info;
687 EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info));
688 // No origins were deleted.
689 EXPECT_EQ(size_t(2), origins_info.size());
690 EXPECT_TRUE(
691 base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
692 EXPECT_TRUE(
693 base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
695 EXPECT_TRUE(base::PathExists(origin1_db_dir));
696 EXPECT_TRUE(base::PathExists(origin2_db_dir));
699 static void EmptyDatabaseNameIsValid() {
700 const GURL kOrigin(kOrigin1Url);
701 const std::string kOriginId = storage::GetIdentifierFromOrigin(kOrigin);
702 const base::string16 kEmptyName;
703 const base::string16 kDescription(ASCIIToUTF16("description"));
704 const base::string16 kChangedDescription(
705 ASCIIToUTF16("changed_description"));
707 // Initialize a tracker database, no need to put it on disk.
708 const bool kUseInMemoryTrackerDatabase = true;
709 base::ScopedTempDir temp_dir;
710 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
711 scoped_refptr<DatabaseTracker> tracker(
712 new DatabaseTracker(temp_dir.path(), kUseInMemoryTrackerDatabase,
713 NULL, NULL, NULL));
715 // Starts off with no databases.
716 std::vector<OriginInfo> infos;
717 EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
718 EXPECT_TRUE(infos.empty());
720 // Create a db with an empty name.
721 int64 database_size = -1;
722 tracker->DatabaseOpened(kOriginId, kEmptyName, kDescription, 0,
723 &database_size);
724 EXPECT_EQ(0, database_size);
725 tracker->DatabaseModified(kOriginId, kEmptyName);
726 EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
727 EXPECT_EQ(1u, infos.size());
728 EXPECT_EQ(kDescription, infos[0].GetDatabaseDescription(kEmptyName));
729 EXPECT_FALSE(tracker->GetFullDBFilePath(kOriginId, kEmptyName).empty());
730 tracker->DatabaseOpened(kOriginId, kEmptyName, kChangedDescription, 0,
731 &database_size);
732 infos.clear();
733 EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
734 EXPECT_EQ(1u, infos.size());
735 EXPECT_EQ(kChangedDescription, infos[0].GetDatabaseDescription(kEmptyName));
736 tracker->DatabaseClosed(kOriginId, kEmptyName);
737 tracker->DatabaseClosed(kOriginId, kEmptyName);
739 // Deleting it should return to the initial state.
740 EXPECT_EQ(net::OK, tracker->DeleteDatabase(kOriginId, kEmptyName,
741 net::CompletionCallback()));
742 infos.clear();
743 EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
744 EXPECT_TRUE(infos.empty());
747 static void HandleSqliteError() {
748 const GURL kOrigin(kOrigin1Url);
749 const std::string kOriginId = storage::GetIdentifierFromOrigin(kOrigin);
750 const base::string16 kName(ASCIIToUTF16("name"));
751 const base::string16 kDescription(ASCIIToUTF16("description"));
753 // Initialize a tracker database, no need to put it on disk.
754 const bool kUseInMemoryTrackerDatabase = true;
755 base::ScopedTempDir temp_dir;
756 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
757 scoped_refptr<DatabaseTracker> tracker(
758 new DatabaseTracker(temp_dir.path(), kUseInMemoryTrackerDatabase,
759 NULL, NULL, NULL));
761 // Setup to observe OnScheduledForDelete notifications.
762 TestObserver observer(false, true);
763 tracker->AddObserver(&observer);
765 // Verify does no harm when there is no such database.
766 tracker->HandleSqliteError(kOriginId, kName, SQLITE_CORRUPT);
767 EXPECT_FALSE(tracker->IsDatabaseScheduledForDeletion(kOriginId, kName));
768 EXPECT_FALSE(observer.DidReceiveNewNotification());
770 // --------------------------------------------------------
771 // Create a record of a database in the tracker db and create
772 // a spoof_db_file on disk in the expected location.
773 int64 database_size = 0;
774 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
775 &database_size);
776 base::FilePath spoof_db_file = tracker->GetFullDBFilePath(kOriginId, kName);
777 EXPECT_FALSE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
778 EXPECT_TRUE(base::CreateDirectory(spoof_db_file.DirName()));
779 EXPECT_TRUE(EnsureFileOfSize(spoof_db_file, 1));
781 // Verify does no harm with a non-error is reported.
782 tracker->HandleSqliteError(kOriginId, kName, SQLITE_OK);
783 EXPECT_FALSE(tracker->IsDatabaseScheduledForDeletion(kOriginId, kName));
784 EXPECT_FALSE(observer.DidReceiveNewNotification());
786 // Verify that with a connection open, the db is scheduled for deletion,
787 // but that the file still exists.
788 tracker->HandleSqliteError(kOriginId, kName, SQLITE_CORRUPT);
789 EXPECT_TRUE(tracker->IsDatabaseScheduledForDeletion(kOriginId, kName));
790 EXPECT_TRUE(observer.DidReceiveNewNotification());
791 EXPECT_TRUE(base::PathExists(spoof_db_file));
793 // Verify that once closed, the file is deleted and the record in the
794 // tracker db is removed.
795 tracker->DatabaseClosed(kOriginId, kName);
796 EXPECT_FALSE(base::PathExists(spoof_db_file));
797 EXPECT_TRUE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
799 // --------------------------------------------------------
800 // Create another record of a database in the tracker db and create
801 // a spoof_db_file on disk in the expected location.
802 tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
803 &database_size);
804 base::FilePath spoof_db_file2 = tracker->GetFullDBFilePath(kOriginId,
805 kName);
806 EXPECT_FALSE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
807 EXPECT_NE(spoof_db_file, spoof_db_file2);
808 EXPECT_TRUE(base::CreateDirectory(spoof_db_file2.DirName()));
809 EXPECT_TRUE(EnsureFileOfSize(spoof_db_file2, 1));
811 // Verify that with no connection open, the db is deleted immediately.
812 tracker->DatabaseClosed(kOriginId, kName);
813 tracker->HandleSqliteError(kOriginId, kName, SQLITE_CORRUPT);
814 EXPECT_FALSE(tracker->IsDatabaseScheduledForDeletion(kOriginId, kName));
815 EXPECT_FALSE(observer.DidReceiveNewNotification());
816 EXPECT_TRUE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
817 EXPECT_FALSE(base::PathExists(spoof_db_file2));
819 tracker->RemoveObserver(&observer);
823 TEST(DatabaseTrackerTest, DeleteOpenDatabase) {
824 DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(false);
827 TEST(DatabaseTrackerTest, DeleteOpenDatabaseIncognitoMode) {
828 DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(true);
831 TEST(DatabaseTrackerTest, DatabaseTracker) {
832 DatabaseTracker_TestHelper_Test::TestDatabaseTracker(false);
835 TEST(DatabaseTrackerTest, DatabaseTrackerIncognitoMode) {
836 DatabaseTracker_TestHelper_Test::TestDatabaseTracker(true);
839 TEST(DatabaseTrackerTest, DatabaseTrackerQuotaIntegration) {
840 // There is no difference in behavior between incognito and not.
841 DatabaseTracker_TestHelper_Test::DatabaseTrackerQuotaIntegration();
844 TEST(DatabaseTrackerTest, DatabaseTrackerClearSessionOnlyDatabasesOnExit) {
845 // Only works for regular mode.
846 DatabaseTracker_TestHelper_Test::
847 DatabaseTrackerClearSessionOnlyDatabasesOnExit();
850 TEST(DatabaseTrackerTest, DatabaseTrackerSetForceKeepSessionState) {
851 // Only works for regular mode.
852 DatabaseTracker_TestHelper_Test::DatabaseTrackerSetForceKeepSessionState();
855 TEST(DatabaseTrackerTest, EmptyDatabaseNameIsValid) {
856 DatabaseTracker_TestHelper_Test::EmptyDatabaseNameIsValid();
859 TEST(DatabaseTrackerTest, HandleSqliteError) {
860 DatabaseTracker_TestHelper_Test::HandleSqliteError();
863 } // namespace content