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 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 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_
)
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_
)
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 virtual void RegisterClient(storage::QuotaClient
* client
) OVERRIDE
{
107 EXPECT_FALSE(registered_client_
);
108 registered_client_
= client
;
111 virtual 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 virtual 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 virtual void NotifyOriginInUse(const GURL
& origin
) OVERRIDE
{}
131 virtual void NotifyOriginNoLongerInUse(const GURL
& origin
) OVERRIDE
{}
132 virtual void SetUsageCacheEnabled(storage::QuotaClient::ID client_id
,
134 storage::StorageType type
,
135 bool enabled
) OVERRIDE
{}
136 virtual void GetUsageAndQuota(
137 base::SequencedTaskRunner
* original_task_runner
,
139 storage::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
;
160 modifications_
.clear();
163 storage::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_
;
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
);
183 return file
.SetLength(length
);
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
{
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(),
207 special_storage_policy
.get(),
211 // Create and open three databases.
212 int64 database_size
= 0;
213 const std::string kOrigin1
=
214 storage::GetIdentifierFromOrigin(GURL(kOrigin1Url
));
215 const std::string kOrigin2
=
216 storage::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,
224 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
226 tracker
->DatabaseOpened(kOrigin2
, kDB3
, kDescription
, 0,
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
)));
262 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
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
273 base::Time now
= base::Time::Now();
274 EXPECT_TRUE(base::TouchFile(tracker
->GetFullDBFilePath(kOrigin1
, kDB1
),
276 EXPECT_TRUE(base::TouchFile(tracker
->GetFullDBFilePath(kOrigin2
, kDB2
),
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
)));
297 base::PathExists(tracker
->GetFullDBFilePath(kOrigin2
, kDB2
)));
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(),
315 special_storage_policy
.get(),
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 storage::GetIdentifierFromOrigin(GURL(kOrigin1Url
));
329 const std::string kOrigin2
=
330 storage::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,
347 EXPECT_EQ(0, database_size
);
348 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
350 EXPECT_EQ(0, database_size
);
351 tracker
->DatabaseOpened(kOrigin1
, kDB3
, kDescription
, 0,
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,
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,
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,
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,
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
= storage::GetIdentifierFromOrigin(kOrigin
);
456 const base::string16 kName
= ASCIIToUTF16("name");
457 const base::string16 kDescription
= ASCIIToUTF16("description");
459 base::ScopedTempDir temp_dir
;
460 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
462 // Initialize the tracker with a QuotaManagerProxy
463 scoped_refptr
<TestQuotaManagerProxy
> test_quota_proxy(
464 new TestQuotaManagerProxy
);
465 scoped_refptr
<DatabaseTracker
> tracker(
466 new DatabaseTracker(temp_dir
.path(),
467 false /* incognito */,
469 test_quota_proxy
.get(),
471 EXPECT_TRUE(test_quota_proxy
->registered_client_
);
473 // Create a database and modify it a couple of times, close it,
474 // then delete it. Observe the tracker notifies accordingly.
476 int64 database_size
= 0;
477 tracker
->DatabaseOpened(kOriginId
, kName
, kDescription
, 0,
479 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
480 test_quota_proxy
->reset();
482 base::FilePath
db_file(tracker
->GetFullDBFilePath(kOriginId
, kName
));
483 EXPECT_TRUE(base::CreateDirectory(db_file
.DirName()));
484 EXPECT_TRUE(EnsureFileOfSize(db_file
, 10));
485 tracker
->DatabaseModified(kOriginId
, kName
);
486 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, 10));
487 test_quota_proxy
->reset();
489 EXPECT_TRUE(EnsureFileOfSize(db_file
, 100));
490 tracker
->DatabaseModified(kOriginId
, kName
);
491 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, 90));
492 test_quota_proxy
->reset();
494 tracker
->DatabaseClosed(kOriginId
, kName
);
495 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
496 EXPECT_EQ(net::OK
, tracker
->DeleteDatabase(
497 kOriginId
, kName
, net::CompletionCallback()));
498 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, -100));
499 test_quota_proxy
->reset();
501 // Create a database and modify it, try to delete it while open,
502 // then close it (at which time deletion will actually occur).
503 // Observe the tracker notifies accordingly.
505 tracker
->DatabaseOpened(kOriginId
, kName
, kDescription
, 0,
507 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
508 test_quota_proxy
->reset();
510 db_file
= tracker
->GetFullDBFilePath(kOriginId
, kName
);
511 EXPECT_TRUE(base::CreateDirectory(db_file
.DirName()));
512 EXPECT_TRUE(EnsureFileOfSize(db_file
, 100));
513 tracker
->DatabaseModified(kOriginId
, kName
);
514 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, 100));
515 test_quota_proxy
->reset();
517 EXPECT_EQ(net::ERR_IO_PENDING
,
518 tracker
->DeleteDatabase(kOriginId
, kName
,
519 net::CompletionCallback()));
520 EXPECT_FALSE(test_quota_proxy
->WasModificationNotified(kOrigin
, -100));
522 tracker
->DatabaseClosed(kOriginId
, kName
);
523 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
524 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, -100));
525 test_quota_proxy
->reset();
527 // Create a database and up the file size without telling
528 // the tracker about the modification, than simulate a
530 // Observe the tracker notifies accordingly.
532 tracker
->DatabaseOpened(kOriginId
, kName
, kDescription
, 0,
534 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
535 test_quota_proxy
->reset();
536 db_file
= tracker
->GetFullDBFilePath(kOriginId
, kName
);
537 EXPECT_TRUE(base::CreateDirectory(db_file
.DirName()));
538 EXPECT_TRUE(EnsureFileOfSize(db_file
, 100));
539 DatabaseConnections crashed_renderer_connections
;
540 crashed_renderer_connections
.AddConnection(kOriginId
, kName
);
541 EXPECT_FALSE(test_quota_proxy
->WasModificationNotified(kOrigin
, 100));
542 tracker
->CloseDatabases(crashed_renderer_connections
);
543 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, 100));
546 crashed_renderer_connections
.RemoveAllConnections();
547 test_quota_proxy
->SimulateQuotaManagerDestroyed();
550 static void DatabaseTrackerClearSessionOnlyDatabasesOnExit() {
551 int64 database_size
= 0;
552 const std::string kOrigin1
=
553 storage::GetIdentifierFromOrigin(GURL(kOrigin1Url
));
554 const std::string kOrigin2
=
555 storage::GetIdentifierFromOrigin(GURL(kOrigin2Url
));
556 const base::string16 kDB1
= ASCIIToUTF16("db1");
557 const base::string16 kDB2
= ASCIIToUTF16("db2");
558 const base::string16 kDescription
= ASCIIToUTF16("database_description");
560 // Initialize the tracker database.
561 base::MessageLoop message_loop
;
562 base::ScopedTempDir temp_dir
;
563 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
564 base::FilePath origin1_db_dir
;
565 base::FilePath origin2_db_dir
;
567 scoped_refptr
<MockSpecialStoragePolicy
> special_storage_policy
=
568 new MockSpecialStoragePolicy
;
569 special_storage_policy
->AddSessionOnly(GURL(kOrigin2Url
));
570 scoped_refptr
<DatabaseTracker
> tracker(
571 new DatabaseTracker(temp_dir
.path(),
573 special_storage_policy
.get(),
575 base::MessageLoopProxy::current().get()));
577 // Open two new databases.
578 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
580 EXPECT_EQ(0, database_size
);
581 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
583 EXPECT_EQ(0, database_size
);
585 // Write some data to each file.
586 base::FilePath db_file
;
587 db_file
= tracker
->GetFullDBFilePath(kOrigin1
, kDB1
);
588 EXPECT_TRUE(base::CreateDirectory(db_file
.DirName()));
589 EXPECT_TRUE(EnsureFileOfSize(db_file
, 1));
591 db_file
= tracker
->GetFullDBFilePath(kOrigin2
, kDB2
);
592 EXPECT_TRUE(base::CreateDirectory(db_file
.DirName()));
593 EXPECT_TRUE(EnsureFileOfSize(db_file
, 2));
595 // Store the origin database directories as long as they still exist.
596 origin1_db_dir
= tracker
->GetFullDBFilePath(kOrigin1
, kDB1
).DirName();
597 origin2_db_dir
= tracker
->GetFullDBFilePath(kOrigin2
, kDB2
).DirName();
599 tracker
->DatabaseModified(kOrigin1
, kDB1
);
600 tracker
->DatabaseModified(kOrigin2
, kDB2
);
602 // Close all databases.
603 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
604 tracker
->DatabaseClosed(kOrigin2
, kDB2
);
609 // At this point, the database tracker should be gone. Create a new one.
610 scoped_refptr
<DatabaseTracker
> tracker(
611 new DatabaseTracker(temp_dir
.path(), false, NULL
, NULL
, NULL
));
613 // Get all data for all origins.
614 std::vector
<OriginInfo
> origins_info
;
615 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&origins_info
));
616 // kOrigin1 was not session-only, so it survived. kOrigin2 was session-only
617 // and it got deleted.
618 EXPECT_EQ(size_t(1), origins_info
.size());
619 EXPECT_EQ(kOrigin1
, origins_info
[0].GetOriginIdentifier());
621 base::PathExists(tracker
->GetFullDBFilePath(kOrigin1
, kDB1
)));
622 EXPECT_EQ(base::FilePath(), tracker
->GetFullDBFilePath(kOrigin2
, kDB2
));
624 // The origin directory of kOrigin1 remains, but the origin directory of
625 // kOrigin2 is deleted.
626 EXPECT_TRUE(base::PathExists(origin1_db_dir
));
627 EXPECT_FALSE(base::PathExists(origin2_db_dir
));
630 static void DatabaseTrackerSetForceKeepSessionState() {
631 int64 database_size
= 0;
632 const std::string kOrigin1
=
633 storage::GetIdentifierFromOrigin(GURL(kOrigin1Url
));
634 const std::string kOrigin2
=
635 storage::GetIdentifierFromOrigin(GURL(kOrigin2Url
));
636 const base::string16 kDB1
= ASCIIToUTF16("db1");
637 const base::string16 kDB2
= ASCIIToUTF16("db2");
638 const base::string16 kDescription
= ASCIIToUTF16("database_description");
640 // Initialize the tracker database.
641 base::MessageLoop message_loop
;
642 base::ScopedTempDir temp_dir
;
643 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
644 base::FilePath origin1_db_dir
;
645 base::FilePath origin2_db_dir
;
647 scoped_refptr
<MockSpecialStoragePolicy
> special_storage_policy
=
648 new MockSpecialStoragePolicy
;
649 special_storage_policy
->AddSessionOnly(GURL(kOrigin2Url
));
650 scoped_refptr
<DatabaseTracker
> tracker(
651 new DatabaseTracker(temp_dir
.path(),
653 special_storage_policy
.get(),
655 base::MessageLoopProxy::current().get()));
656 tracker
->SetForceKeepSessionState();
658 // Open two new databases.
659 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
661 EXPECT_EQ(0, database_size
);
662 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
664 EXPECT_EQ(0, database_size
);
666 // Write some data to each file.
667 base::FilePath db_file
;
668 db_file
= tracker
->GetFullDBFilePath(kOrigin1
, kDB1
);
669 EXPECT_TRUE(base::CreateDirectory(db_file
.DirName()));
670 EXPECT_TRUE(EnsureFileOfSize(db_file
, 1));
672 db_file
= tracker
->GetFullDBFilePath(kOrigin2
, kDB2
);
673 EXPECT_TRUE(base::CreateDirectory(db_file
.DirName()));
674 EXPECT_TRUE(EnsureFileOfSize(db_file
, 2));
676 // Store the origin database directories as long as they still exist.
677 origin1_db_dir
= tracker
->GetFullDBFilePath(kOrigin1
, kDB1
).DirName();
678 origin2_db_dir
= tracker
->GetFullDBFilePath(kOrigin2
, kDB2
).DirName();
680 tracker
->DatabaseModified(kOrigin1
, kDB1
);
681 tracker
->DatabaseModified(kOrigin2
, kDB2
);
683 // Close all databases.
684 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
685 tracker
->DatabaseClosed(kOrigin2
, kDB2
);
690 // At this point, the database tracker should be gone. Create a new one.
691 scoped_refptr
<DatabaseTracker
> tracker(
692 new DatabaseTracker(temp_dir
.path(), false, NULL
, NULL
, NULL
));
694 // Get all data for all origins.
695 std::vector
<OriginInfo
> origins_info
;
696 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&origins_info
));
697 // No origins were deleted.
698 EXPECT_EQ(size_t(2), origins_info
.size());
700 base::PathExists(tracker
->GetFullDBFilePath(kOrigin1
, kDB1
)));
702 base::PathExists(tracker
->GetFullDBFilePath(kOrigin2
, kDB2
)));
704 EXPECT_TRUE(base::PathExists(origin1_db_dir
));
705 EXPECT_TRUE(base::PathExists(origin2_db_dir
));
708 static void EmptyDatabaseNameIsValid() {
709 const GURL
kOrigin(kOrigin1Url
);
710 const std::string kOriginId
= storage::GetIdentifierFromOrigin(kOrigin
);
711 const base::string16 kEmptyName
;
712 const base::string16
kDescription(ASCIIToUTF16("description"));
713 const base::string16
kChangedDescription(
714 ASCIIToUTF16("changed_description"));
716 // Initialize a tracker database, no need to put it on disk.
717 const bool kUseInMemoryTrackerDatabase
= true;
718 base::ScopedTempDir temp_dir
;
719 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
720 scoped_refptr
<DatabaseTracker
> tracker(
721 new DatabaseTracker(temp_dir
.path(), kUseInMemoryTrackerDatabase
,
724 // Starts off with no databases.
725 std::vector
<OriginInfo
> infos
;
726 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&infos
));
727 EXPECT_TRUE(infos
.empty());
729 // Create a db with an empty name.
730 int64 database_size
= -1;
731 tracker
->DatabaseOpened(kOriginId
, kEmptyName
, kDescription
, 0,
733 EXPECT_EQ(0, database_size
);
734 tracker
->DatabaseModified(kOriginId
, kEmptyName
);
735 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&infos
));
736 EXPECT_EQ(1u, infos
.size());
737 EXPECT_EQ(kDescription
, infos
[0].GetDatabaseDescription(kEmptyName
));
738 EXPECT_FALSE(tracker
->GetFullDBFilePath(kOriginId
, kEmptyName
).empty());
739 tracker
->DatabaseOpened(kOriginId
, kEmptyName
, kChangedDescription
, 0,
742 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&infos
));
743 EXPECT_EQ(1u, infos
.size());
744 EXPECT_EQ(kChangedDescription
, infos
[0].GetDatabaseDescription(kEmptyName
));
745 tracker
->DatabaseClosed(kOriginId
, kEmptyName
);
746 tracker
->DatabaseClosed(kOriginId
, kEmptyName
);
748 // Deleting it should return to the initial state.
749 EXPECT_EQ(net::OK
, tracker
->DeleteDatabase(kOriginId
, kEmptyName
,
750 net::CompletionCallback()));
752 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&infos
));
753 EXPECT_TRUE(infos
.empty());
756 static void HandleSqliteError() {
757 const GURL
kOrigin(kOrigin1Url
);
758 const std::string kOriginId
= storage::GetIdentifierFromOrigin(kOrigin
);
759 const base::string16
kName(ASCIIToUTF16("name"));
760 const base::string16
kDescription(ASCIIToUTF16("description"));
762 // Initialize a tracker database, no need to put it on disk.
763 const bool kUseInMemoryTrackerDatabase
= true;
764 base::ScopedTempDir temp_dir
;
765 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
766 scoped_refptr
<DatabaseTracker
> tracker(
767 new DatabaseTracker(temp_dir
.path(), kUseInMemoryTrackerDatabase
,
770 // Setup to observe OnScheduledForDelete notifications.
771 TestObserver
observer(false, true);
772 tracker
->AddObserver(&observer
);
774 // Verify does no harm when there is no such database.
775 tracker
->HandleSqliteError(kOriginId
, kName
, SQLITE_CORRUPT
);
776 EXPECT_FALSE(tracker
->IsDatabaseScheduledForDeletion(kOriginId
, kName
));
777 EXPECT_FALSE(observer
.DidReceiveNewNotification());
779 // --------------------------------------------------------
780 // Create a record of a database in the tracker db and create
781 // a spoof_db_file on disk in the expected location.
782 int64 database_size
= 0;
783 tracker
->DatabaseOpened(kOriginId
, kName
, kDescription
, 0,
785 base::FilePath spoof_db_file
= tracker
->GetFullDBFilePath(kOriginId
, kName
);
786 EXPECT_FALSE(tracker
->GetFullDBFilePath(kOriginId
, kName
).empty());
787 EXPECT_TRUE(base::CreateDirectory(spoof_db_file
.DirName()));
788 EXPECT_TRUE(EnsureFileOfSize(spoof_db_file
, 1));
790 // Verify does no harm with a non-error is reported.
791 tracker
->HandleSqliteError(kOriginId
, kName
, SQLITE_OK
);
792 EXPECT_FALSE(tracker
->IsDatabaseScheduledForDeletion(kOriginId
, kName
));
793 EXPECT_FALSE(observer
.DidReceiveNewNotification());
795 // Verify that with a connection open, the db is scheduled for deletion,
796 // but that the file still exists.
797 tracker
->HandleSqliteError(kOriginId
, kName
, SQLITE_CORRUPT
);
798 EXPECT_TRUE(tracker
->IsDatabaseScheduledForDeletion(kOriginId
, kName
));
799 EXPECT_TRUE(observer
.DidReceiveNewNotification());
800 EXPECT_TRUE(base::PathExists(spoof_db_file
));
802 // Verify that once closed, the file is deleted and the record in the
803 // tracker db is removed.
804 tracker
->DatabaseClosed(kOriginId
, kName
);
805 EXPECT_FALSE(base::PathExists(spoof_db_file
));
806 EXPECT_TRUE(tracker
->GetFullDBFilePath(kOriginId
, kName
).empty());
808 // --------------------------------------------------------
809 // Create another record of a database in the tracker db and create
810 // a spoof_db_file on disk in the expected location.
811 tracker
->DatabaseOpened(kOriginId
, kName
, kDescription
, 0,
813 base::FilePath spoof_db_file2
= tracker
->GetFullDBFilePath(kOriginId
,
815 EXPECT_FALSE(tracker
->GetFullDBFilePath(kOriginId
, kName
).empty());
816 EXPECT_NE(spoof_db_file
, spoof_db_file2
);
817 EXPECT_TRUE(base::CreateDirectory(spoof_db_file2
.DirName()));
818 EXPECT_TRUE(EnsureFileOfSize(spoof_db_file2
, 1));
820 // Verify that with no connection open, the db is deleted immediately.
821 tracker
->DatabaseClosed(kOriginId
, kName
);
822 tracker
->HandleSqliteError(kOriginId
, kName
, SQLITE_CORRUPT
);
823 EXPECT_FALSE(tracker
->IsDatabaseScheduledForDeletion(kOriginId
, kName
));
824 EXPECT_FALSE(observer
.DidReceiveNewNotification());
825 EXPECT_TRUE(tracker
->GetFullDBFilePath(kOriginId
, kName
).empty());
826 EXPECT_FALSE(base::PathExists(spoof_db_file2
));
828 tracker
->RemoveObserver(&observer
);
832 TEST(DatabaseTrackerTest
, DeleteOpenDatabase
) {
833 DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(false);
836 TEST(DatabaseTrackerTest
, DeleteOpenDatabaseIncognitoMode
) {
837 DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(true);
840 TEST(DatabaseTrackerTest
, DatabaseTracker
) {
841 DatabaseTracker_TestHelper_Test::TestDatabaseTracker(false);
844 TEST(DatabaseTrackerTest
, DatabaseTrackerIncognitoMode
) {
845 DatabaseTracker_TestHelper_Test::TestDatabaseTracker(true);
848 TEST(DatabaseTrackerTest
, DatabaseTrackerQuotaIntegration
) {
849 // There is no difference in behavior between incognito and not.
850 DatabaseTracker_TestHelper_Test::DatabaseTrackerQuotaIntegration();
853 TEST(DatabaseTrackerTest
, DatabaseTrackerClearSessionOnlyDatabasesOnExit
) {
854 // Only works for regular mode.
855 DatabaseTracker_TestHelper_Test::
856 DatabaseTrackerClearSessionOnlyDatabasesOnExit();
859 TEST(DatabaseTrackerTest
, DatabaseTrackerSetForceKeepSessionState
) {
860 // Only works for regular mode.
861 DatabaseTracker_TestHelper_Test::DatabaseTrackerSetForceKeepSessionState();
864 TEST(DatabaseTrackerTest
, EmptyDatabaseNameIsValid
) {
865 DatabaseTracker_TestHelper_Test::EmptyDatabaseNameIsValid();
868 TEST(DatabaseTrackerTest
, HandleSqliteError
) {
869 DatabaseTracker_TestHelper_Test::HandleSqliteError();
872 } // namespace content