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
;
30 const char kOrigin1Url
[] = "http://origin1";
31 const char kOrigin2Url
[] = "http://protected_origin2";
33 class TestObserver
: public storage::DatabaseTracker::Observer
{
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_
)
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_
)
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_
; }
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_
;
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
{
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
,
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
,
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
,
134 storage::StorageType type
,
135 bool enabled
) override
{}
136 void GetUsageAndQuota(base::SequencedTaskRunner
* original_task_runner
,
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
;
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_
;
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
);
180 return file
.SetLength(length
);
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
{
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(),
204 special_storage_policy
.get(),
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,
221 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
223 tracker
->DatabaseOpened(kOrigin2
, kDB3
, kDescription
, 0,
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
)));
259 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
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
270 base::Time now
= base::Time::Now();
271 EXPECT_TRUE(base::TouchFile(tracker
->GetFullDBFilePath(kOrigin1
, kDB1
),
273 EXPECT_TRUE(base::TouchFile(tracker
->GetFullDBFilePath(kOrigin2
, kDB2
),
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
)));
294 base::PathExists(tracker
->GetFullDBFilePath(kOrigin2
, kDB2
)));
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(),
312 special_storage_policy
.get(),
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,
344 EXPECT_EQ(0, database_size
);
345 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
347 EXPECT_EQ(0, database_size
);
348 tracker
->DatabaseOpened(kOrigin1
, kDB3
, kDescription
, 0,
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,
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,
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,
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,
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 */,
466 test_quota_proxy
.get(),
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,
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,
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
527 // Observe the tracker notifies accordingly.
529 tracker
->DatabaseOpened(kOriginId
, kName
, kDescription
, 0,
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));
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,
574 EXPECT_EQ(0, database_size
);
575 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
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
);
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());
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,
652 EXPECT_EQ(0, database_size
);
653 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
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
);
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());
691 base::PathExists(tracker
->GetFullDBFilePath(kOrigin1
, kDB1
)));
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
,
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,
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,
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()));
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
,
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,
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,
804 base::FilePath spoof_db_file2
= tracker
->GetFullDBFilePath(kOriginId
,
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