1 // Copyright (c) 2011 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_path.h"
6 #include "base/file_util.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop_proxy.h"
9 #include "base/platform_file.h"
10 #include "base/scoped_temp_dir.h"
11 #include "base/time.h"
12 #include "base/utf_string_conversions.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/test_completion_callback.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "webkit/database/database_tracker.h"
17 #include "webkit/database/database_util.h"
18 #include "webkit/quota/mock_special_storage_policy.h"
19 #include "webkit/quota/quota_manager.h"
23 const char kOrigin1Url
[] = "http://origin1";
24 const char kOrigin2Url
[] = "http://protected_origin2";
26 class TestObserver
: public webkit_database::DatabaseTracker::Observer
{
28 TestObserver() : new_notification_received_(false) {}
29 virtual ~TestObserver() {}
30 virtual void OnDatabaseSizeChanged(const string16
& origin_identifier
,
31 const string16
& database_name
,
32 int64 database_size
) {
33 new_notification_received_
= true;
34 origin_identifier_
= origin_identifier
;
35 database_name_
= database_name
;
36 database_size_
= database_size
;
38 virtual void OnDatabaseScheduledForDeletion(const string16
& origin_identifier
,
39 const string16
& database_name
) {
40 new_notification_received_
= true;
41 origin_identifier_
= origin_identifier
;
42 database_name_
= database_name
;
44 bool DidReceiveNewNotification() {
45 bool temp_new_notification_received
= new_notification_received_
;
46 new_notification_received_
= false;
47 return temp_new_notification_received
;
49 string16
GetNotificationOriginIdentifier() { return origin_identifier_
; }
50 string16
GetNotificationDatabaseName() { return database_name_
; }
51 int64
GetNotificationDatabaseSize() { return database_size_
; }
54 bool new_notification_received_
;
55 string16 origin_identifier_
;
56 string16 database_name_
;
60 void CheckNotificationReceived(TestObserver
* observer
,
61 const string16
& expected_origin_identifier
,
62 const string16
& expected_database_name
,
63 int64 expected_database_size
) {
64 EXPECT_TRUE(observer
->DidReceiveNewNotification());
65 EXPECT_EQ(expected_origin_identifier
,
66 observer
->GetNotificationOriginIdentifier());
67 EXPECT_EQ(expected_database_name
,
68 observer
->GetNotificationDatabaseName());
69 EXPECT_EQ(expected_database_size
,
70 observer
->GetNotificationDatabaseSize());
73 class TestQuotaManagerProxy
: public quota::QuotaManagerProxy
{
75 TestQuotaManagerProxy()
76 : QuotaManagerProxy(NULL
, NULL
),
77 registered_client_(NULL
) {
80 virtual ~TestQuotaManagerProxy() {
81 EXPECT_FALSE(registered_client_
);
84 virtual void RegisterClient(quota::QuotaClient
* client
) {
85 EXPECT_FALSE(registered_client_
);
86 registered_client_
= client
;
89 virtual void NotifyStorageAccessed(quota::QuotaClient::ID client_id
,
91 quota::StorageType type
) {
92 EXPECT_EQ(quota::QuotaClient::kDatabase
, client_id
);
93 EXPECT_EQ(quota::kStorageTypeTemporary
, type
);
94 accesses_
[origin
] += 1;
97 virtual void NotifyStorageModified(quota::QuotaClient::ID client_id
,
99 quota::StorageType type
,
101 EXPECT_EQ(quota::QuotaClient::kDatabase
, client_id
);
102 EXPECT_EQ(quota::kStorageTypeTemporary
, type
);
103 modifications_
[origin
].first
+= 1;
104 modifications_
[origin
].second
+= delta
;
107 // Not needed for our tests.
108 virtual void NotifyOriginInUse(const GURL
& origin
) {}
109 virtual void NotifyOriginNoLongerInUse(const GURL
& origin
) {}
111 void SimulateQuotaManagerDestroyed() {
112 if (registered_client_
) {
113 registered_client_
->OnQuotaManagerDestroyed();
114 registered_client_
= NULL
;
118 bool WasAccessNotified(const GURL
& origin
) {
119 return accesses_
[origin
] != 0;
122 bool WasModificationNotified(const GURL
& origin
, int64 amount
) {
123 return modifications_
[origin
].first
!= 0 &&
124 modifications_
[origin
].second
== amount
;
129 modifications_
.clear();
132 quota::QuotaClient
* registered_client_
;
134 // Map from origin to count of access notifications.
135 std::map
<GURL
, int> accesses_
;
137 // Map from origin to <count, sum of deltas>
138 std::map
<GURL
, std::pair
<int, int64
> > modifications_
;
142 bool EnsureFileOfSize(const FilePath
& file_path
, int64 length
) {
143 base::PlatformFileError
error_code(base::PLATFORM_FILE_ERROR_FAILED
);
144 base::PlatformFile file
=
145 base::CreatePlatformFile(
147 base::PLATFORM_FILE_OPEN_ALWAYS
| base::PLATFORM_FILE_WRITE
,
150 if (error_code
!= base::PLATFORM_FILE_OK
)
152 if (!base::TruncatePlatformFile(file
, length
))
153 error_code
= base::PLATFORM_FILE_ERROR_FAILED
;
154 base::ClosePlatformFile(file
);
155 return error_code
== base::PLATFORM_FILE_OK
;
160 namespace webkit_database
{
162 // We declare a helper class, and make it a friend of DatabaseTracker using
163 // the FRIEND_TEST() macro, and we implement all tests we want to run as
164 // static methods of this class. Then we make our TEST() targets call these
165 // static functions. This allows us to run each test in normal mode and
166 // incognito mode without writing the same code twice.
167 class DatabaseTracker_TestHelper_Test
{
169 static void TestDeleteOpenDatabase(bool incognito_mode
) {
170 // Initialize the tracker database.
171 ScopedTempDir temp_dir
;
172 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
173 scoped_refptr
<quota::MockSpecialStoragePolicy
> special_storage_policy
=
174 new quota::MockSpecialStoragePolicy
;
175 special_storage_policy
->AddProtected(GURL(kOrigin2Url
));
176 scoped_refptr
<DatabaseTracker
> tracker(
177 new DatabaseTracker(temp_dir
.path(), incognito_mode
, false,
178 special_storage_policy
, NULL
, NULL
));
180 // Create and open three databases.
181 int64 database_size
= 0;
182 const string16 kOrigin1
=
183 DatabaseUtil::GetOriginIdentifier(GURL(kOrigin1Url
));
184 const string16 kOrigin2
=
185 DatabaseUtil::GetOriginIdentifier(GURL(kOrigin2Url
));
186 const string16 kDB1
= ASCIIToUTF16("db1");
187 const string16 kDB2
= ASCIIToUTF16("db2");
188 const string16 kDB3
= ASCIIToUTF16("db3");
189 const string16 kDescription
= ASCIIToUTF16("database_description");
191 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
193 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
195 tracker
->DatabaseOpened(kOrigin2
, kDB3
, kDescription
, 0,
198 EXPECT_TRUE(file_util::CreateDirectory(tracker
->DatabaseDirectory().Append(
199 FilePath::FromWStringHack(UTF16ToWide(
200 tracker
->GetOriginDirectory(kOrigin1
))))));
201 EXPECT_TRUE(file_util::CreateDirectory(tracker
->DatabaseDirectory().Append(
202 FilePath::FromWStringHack(UTF16ToWide(
203 tracker
->GetOriginDirectory(kOrigin2
))))));
204 EXPECT_EQ(1, file_util::WriteFile(
205 tracker
->GetFullDBFilePath(kOrigin1
, kDB1
), "a", 1));
206 EXPECT_EQ(2, file_util::WriteFile(
207 tracker
->GetFullDBFilePath(kOrigin2
, kDB2
), "aa", 2));
208 EXPECT_EQ(3, file_util::WriteFile(
209 tracker
->GetFullDBFilePath(kOrigin2
, kDB3
), "aaa", 3));
210 tracker
->DatabaseModified(kOrigin1
, kDB1
);
211 tracker
->DatabaseModified(kOrigin2
, kDB2
);
212 tracker
->DatabaseModified(kOrigin2
, kDB3
);
214 // Delete db1. Should also delete origin1.
215 TestObserver observer
;
216 tracker
->AddObserver(&observer
);
217 TestOldCompletionCallback callback
;
218 int result
= tracker
->DeleteDatabase(kOrigin1
, kDB1
, &callback
);
219 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
220 ASSERT_FALSE(callback
.have_result());
221 EXPECT_TRUE(observer
.DidReceiveNewNotification());
222 EXPECT_EQ(kOrigin1
, observer
.GetNotificationOriginIdentifier());
223 EXPECT_EQ(kDB1
, observer
.GetNotificationDatabaseName());
224 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
225 result
= callback
.GetResult(result
);
226 EXPECT_EQ(net::OK
, result
);
227 EXPECT_FALSE(file_util::PathExists(tracker
->DatabaseDirectory().Append(
228 FilePath::FromWStringHack(UTF16ToWide(kOrigin1
)))));
231 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
233 EXPECT_TRUE(file_util::CreateDirectory(tracker
->DatabaseDirectory().Append(
234 FilePath::FromWStringHack(UTF16ToWide(
235 tracker
->GetOriginDirectory(kOrigin1
))))));
236 EXPECT_EQ(1, file_util::WriteFile(
237 tracker
->GetFullDBFilePath(kOrigin1
, kDB1
), "a", 1));
238 tracker
->DatabaseModified(kOrigin1
, kDB1
);
240 // Setup file modification times. db1 and db2 are modified now, db3 three
242 EXPECT_TRUE(file_util::SetLastModifiedTime(
243 tracker
->GetFullDBFilePath(kOrigin1
, kDB1
), base::Time::Now()));
244 EXPECT_TRUE(file_util::SetLastModifiedTime(
245 tracker
->GetFullDBFilePath(kOrigin2
, kDB2
), base::Time::Now()));
246 base::Time three_days_ago
= base::Time::Now();
247 three_days_ago
-= base::TimeDelta::FromDays(3);
248 EXPECT_TRUE(file_util::SetLastModifiedTime(
249 tracker
->GetFullDBFilePath(kOrigin2
, kDB3
), three_days_ago
));
251 // Delete databases modified since yesterday. db2 is whitelisted.
252 base::Time yesterday
= base::Time::Now();
253 yesterday
-= base::TimeDelta::FromDays(1);
254 result
= tracker
->DeleteDataModifiedSince(
255 yesterday
, &callback
);
256 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
257 ASSERT_FALSE(callback
.have_result());
258 EXPECT_TRUE(observer
.DidReceiveNewNotification());
259 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
260 tracker
->DatabaseClosed(kOrigin2
, kDB2
);
261 result
= callback
.GetResult(result
);
262 EXPECT_EQ(net::OK
, result
);
263 EXPECT_FALSE(file_util::PathExists(tracker
->DatabaseDirectory().Append(
264 FilePath::FromWStringHack(UTF16ToWide(kOrigin1
)))));
266 file_util::PathExists(tracker
->GetFullDBFilePath(kOrigin2
, kDB2
)));
268 file_util::PathExists(tracker
->GetFullDBFilePath(kOrigin2
, kDB3
)));
270 tracker
->DatabaseClosed(kOrigin2
, kDB3
);
271 tracker
->RemoveObserver(&observer
);
274 static void TestDatabaseTracker(bool incognito_mode
) {
275 // Initialize the tracker database.
276 ScopedTempDir temp_dir
;
277 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
278 scoped_refptr
<quota::MockSpecialStoragePolicy
> special_storage_policy
=
279 new quota::MockSpecialStoragePolicy
;
280 special_storage_policy
->AddProtected(GURL(kOrigin2Url
));
281 scoped_refptr
<DatabaseTracker
> tracker(
282 new DatabaseTracker(temp_dir
.path(), incognito_mode
, false,
283 special_storage_policy
, NULL
, NULL
));
285 // Add two observers.
286 TestObserver observer1
;
287 TestObserver observer2
;
288 tracker
->AddObserver(&observer1
);
289 tracker
->AddObserver(&observer2
);
291 // Open three new databases.
292 int64 database_size
= 0;
293 const string16 kOrigin1
=
294 DatabaseUtil::GetOriginIdentifier(GURL(kOrigin1Url
));
295 const string16 kOrigin2
=
296 DatabaseUtil::GetOriginIdentifier(GURL(kOrigin2Url
));
297 const string16 kDB1
= ASCIIToUTF16("db1");
298 const string16 kDB2
= ASCIIToUTF16("db2");
299 const string16 kDB3
= ASCIIToUTF16("db3");
300 const string16 kDescription
= ASCIIToUTF16("database_description");
302 // Get the info for kOrigin1 and kOrigin2
303 DatabaseTracker::CachedOriginInfo
* origin1_info
=
304 tracker
->GetCachedOriginInfo(kOrigin1
);
305 DatabaseTracker::CachedOriginInfo
* origin2_info
=
306 tracker
->GetCachedOriginInfo(kOrigin1
);
307 EXPECT_TRUE(origin1_info
);
308 EXPECT_TRUE(origin2_info
);
311 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
313 EXPECT_EQ(0, database_size
);
314 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
316 EXPECT_EQ(0, database_size
);
317 tracker
->DatabaseOpened(kOrigin1
, kDB3
, kDescription
, 0,
319 EXPECT_EQ(0, database_size
);
321 // Write some data to each file and check that the listeners are
322 // called with the appropriate values.
323 EXPECT_TRUE(file_util::CreateDirectory(tracker
->DatabaseDirectory().Append(
324 FilePath::FromWStringHack(UTF16ToWide(
325 tracker
->GetOriginDirectory(kOrigin1
))))));
326 EXPECT_TRUE(file_util::CreateDirectory(tracker
->DatabaseDirectory().Append(
327 FilePath::FromWStringHack(UTF16ToWide(
328 tracker
->GetOriginDirectory(kOrigin2
))))));
329 EXPECT_EQ(1, file_util::WriteFile(
330 tracker
->GetFullDBFilePath(kOrigin1
, kDB1
), "a", 1));
331 EXPECT_EQ(2, file_util::WriteFile(
332 tracker
->GetFullDBFilePath(kOrigin2
, kDB2
), "aa", 2));
333 EXPECT_EQ(4, file_util::WriteFile(
334 tracker
->GetFullDBFilePath(kOrigin1
, kDB3
), "aaaa", 4));
335 tracker
->DatabaseModified(kOrigin1
, kDB1
);
336 CheckNotificationReceived(&observer1
, kOrigin1
, kDB1
, 1);
337 CheckNotificationReceived(&observer2
, kOrigin1
, kDB1
, 1);
338 tracker
->DatabaseModified(kOrigin2
, kDB2
);
339 CheckNotificationReceived(&observer1
, kOrigin2
, kDB2
, 2);
340 CheckNotificationReceived(&observer2
, kOrigin2
, kDB2
, 2);
341 tracker
->DatabaseModified(kOrigin1
, kDB3
);
342 CheckNotificationReceived(&observer1
, kOrigin1
, kDB3
, 4);
343 CheckNotificationReceived(&observer2
, kOrigin1
, kDB3
, 4);
345 // Close all databases
346 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
347 tracker
->DatabaseClosed(kOrigin2
, kDB2
);
348 tracker
->DatabaseClosed(kOrigin1
, kDB3
);
350 // Open an existing database and check the reported size
351 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
353 EXPECT_EQ(1, database_size
);
354 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
356 // Remove an observer; this should clear all caches.
357 tracker
->RemoveObserver(&observer2
);
359 // Close the tracker database and clear all caches.
360 // Then make sure that DatabaseOpened() still returns the correct result.
361 tracker
->CloseTrackerDatabaseAndClearCaches();
362 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
364 EXPECT_EQ(1, database_size
);
365 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
367 // Remove all observers.
368 tracker
->RemoveObserver(&observer1
);
370 // Trying to delete a database in use should fail
371 tracker
->DatabaseOpened(kOrigin1
, kDB3
, kDescription
, 0,
373 EXPECT_FALSE(tracker
->DeleteClosedDatabase(kOrigin1
, kDB3
));
374 origin1_info
= tracker
->GetCachedOriginInfo(kOrigin1
);
375 EXPECT_TRUE(origin1_info
);
376 EXPECT_EQ(4, origin1_info
->GetDatabaseSize(kDB3
));
377 tracker
->DatabaseClosed(kOrigin1
, kDB3
);
379 // Delete a database and make sure the space used by that origin is updated
380 EXPECT_TRUE(tracker
->DeleteClosedDatabase(kOrigin1
, kDB3
));
381 origin1_info
= tracker
->GetCachedOriginInfo(kOrigin1
);
382 EXPECT_TRUE(origin1_info
);
383 EXPECT_EQ(1, origin1_info
->GetDatabaseSize(kDB1
));
384 EXPECT_EQ(0, origin1_info
->GetDatabaseSize(kDB3
));
386 // Get all data for all origins
387 std::vector
<OriginInfo
> origins_info
;
388 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&origins_info
));
389 EXPECT_EQ(size_t(2), origins_info
.size());
390 EXPECT_EQ(kOrigin1
, origins_info
[0].GetOrigin());
391 EXPECT_EQ(1, origins_info
[0].TotalSize());
392 EXPECT_EQ(1, origins_info
[0].GetDatabaseSize(kDB1
));
393 EXPECT_EQ(0, origins_info
[0].GetDatabaseSize(kDB3
));
395 EXPECT_EQ(kOrigin2
, origins_info
[1].GetOrigin());
396 EXPECT_EQ(2, origins_info
[1].TotalSize());
398 // Trying to delete an origin with databases in use should fail
399 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
401 EXPECT_FALSE(tracker
->DeleteOrigin(kOrigin1
, false));
402 origin1_info
= tracker
->GetCachedOriginInfo(kOrigin1
);
403 EXPECT_TRUE(origin1_info
);
404 EXPECT_EQ(1, origin1_info
->GetDatabaseSize(kDB1
));
405 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
407 // Delete an origin that doesn't have any database in use
408 EXPECT_TRUE(tracker
->DeleteOrigin(kOrigin1
, false));
409 origins_info
.clear();
410 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&origins_info
));
411 EXPECT_EQ(size_t(1), origins_info
.size());
412 EXPECT_EQ(kOrigin2
, origins_info
[0].GetOrigin());
414 origin1_info
= tracker
->GetCachedOriginInfo(kOrigin1
);
415 EXPECT_TRUE(origin1_info
);
416 EXPECT_EQ(0, origin1_info
->TotalSize());
419 static void DatabaseTrackerQuotaIntegration() {
420 const GURL
kOrigin(kOrigin1Url
);
421 const string16 kOriginId
= DatabaseUtil::GetOriginIdentifier(kOrigin
);
422 const string16 kName
= ASCIIToUTF16("name");
423 const string16 kDescription
= ASCIIToUTF16("description");
425 ScopedTempDir temp_dir
;
426 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
428 // Initialize the tracker with a QuotaManagerProxy
429 scoped_refptr
<TestQuotaManagerProxy
> test_quota_proxy(
430 new TestQuotaManagerProxy
);
431 scoped_refptr
<DatabaseTracker
> tracker(
432 new DatabaseTracker(temp_dir
.path(), false /* incognito */, false,
433 NULL
, test_quota_proxy
, NULL
));
434 EXPECT_TRUE(test_quota_proxy
->registered_client_
);
436 // Create a database and modify it a couple of times, close it,
437 // then delete it. Observe the tracker notifies accordingly.
439 int64 database_size
= 0;
440 tracker
->DatabaseOpened(kOriginId
, kName
, kDescription
, 0,
442 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
443 test_quota_proxy
->reset();
445 FilePath
db_file(tracker
->GetFullDBFilePath(kOriginId
, kName
));
446 EXPECT_TRUE(file_util::CreateDirectory(db_file
.DirName()));
447 EXPECT_TRUE(EnsureFileOfSize(db_file
, 10));
448 tracker
->DatabaseModified(kOriginId
, kName
);
449 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, 10));
450 test_quota_proxy
->reset();
452 EXPECT_TRUE(EnsureFileOfSize(db_file
, 100));
453 tracker
->DatabaseModified(kOriginId
, kName
);
454 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, 90));
455 test_quota_proxy
->reset();
457 tracker
->DatabaseClosed(kOriginId
, kName
);
458 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
459 EXPECT_EQ(net::OK
, tracker
->DeleteDatabase(kOriginId
, kName
, NULL
));
460 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, -100));
461 test_quota_proxy
->reset();
463 // Create a database and modify it, try to delete it while open,
464 // then close it (at which time deletion will actually occur).
465 // Observe the tracker notifies accordingly.
467 tracker
->DatabaseOpened(kOriginId
, kName
, kDescription
, 0,
469 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
470 test_quota_proxy
->reset();
472 db_file
= tracker
->GetFullDBFilePath(kOriginId
, kName
);
473 EXPECT_TRUE(file_util::CreateDirectory(db_file
.DirName()));
474 EXPECT_TRUE(EnsureFileOfSize(db_file
, 100));
475 tracker
->DatabaseModified(kOriginId
, kName
);
476 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, 100));
477 test_quota_proxy
->reset();
479 EXPECT_EQ(net::ERR_IO_PENDING
,
480 tracker
->DeleteDatabase(kOriginId
, kName
, NULL
));
481 EXPECT_FALSE(test_quota_proxy
->WasModificationNotified(kOrigin
, -100));
483 tracker
->DatabaseClosed(kOriginId
, kName
);
484 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
485 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, -100));
486 test_quota_proxy
->reset();
488 // Create a database and up the file size without telling
489 // the tracker about the modification, than simulate a
491 // Observe the tracker notifies accordingly.
493 tracker
->DatabaseOpened(kOriginId
, kName
, kDescription
, 0,
495 EXPECT_TRUE(test_quota_proxy
->WasAccessNotified(kOrigin
));
496 test_quota_proxy
->reset();
497 db_file
= tracker
->GetFullDBFilePath(kOriginId
, kName
);
498 EXPECT_TRUE(file_util::CreateDirectory(db_file
.DirName()));
499 EXPECT_TRUE(EnsureFileOfSize(db_file
, 100));
500 DatabaseConnections crashed_renderer_connections
;
501 crashed_renderer_connections
.AddConnection(kOriginId
, kName
);
502 EXPECT_FALSE(test_quota_proxy
->WasModificationNotified(kOrigin
, 100));
503 tracker
->CloseDatabases(crashed_renderer_connections
);
504 EXPECT_TRUE(test_quota_proxy
->WasModificationNotified(kOrigin
, 100));
507 crashed_renderer_connections
.RemoveAllConnections();
508 test_quota_proxy
->SimulateQuotaManagerDestroyed();
511 static void DatabaseTrackerClearLocalStateOnExit() {
512 int64 database_size
= 0;
513 const string16 kOrigin1
=
514 DatabaseUtil::GetOriginIdentifier(GURL(kOrigin1Url
));
515 const string16 kOrigin2
=
516 DatabaseUtil::GetOriginIdentifier(GURL(kOrigin2Url
));
517 const string16 kDB1
= ASCIIToUTF16("db1");
518 const string16 kDB2
= ASCIIToUTF16("db2");
519 const string16 kDB3
= ASCIIToUTF16("db3");
520 const string16 kDescription
= ASCIIToUTF16("database_description");
522 // Initialize the tracker database.
523 ScopedTempDir temp_dir
;
524 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
525 FilePath origin1_db_dir
;
527 scoped_refptr
<quota::MockSpecialStoragePolicy
> special_storage_policy
=
528 new quota::MockSpecialStoragePolicy
;
529 special_storage_policy
->AddProtected(GURL(kOrigin2Url
));
530 scoped_refptr
<DatabaseTracker
> tracker(
532 temp_dir
.path(), false, true,
533 special_storage_policy
, NULL
,
534 base::MessageLoopProxy::current()));
536 // Open three new databases.
537 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
539 EXPECT_EQ(0, database_size
);
540 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
542 EXPECT_EQ(0, database_size
);
543 tracker
->DatabaseOpened(kOrigin1
, kDB3
, kDescription
, 0,
545 EXPECT_EQ(0, database_size
);
547 // Write some data to each file.
549 db_file
= tracker
->GetFullDBFilePath(kOrigin1
, kDB1
);
550 EXPECT_TRUE(file_util::CreateDirectory(db_file
.DirName()));
551 EXPECT_TRUE(EnsureFileOfSize(db_file
, 1));
553 db_file
= tracker
->GetFullDBFilePath(kOrigin2
, kDB2
);
554 EXPECT_TRUE(file_util::CreateDirectory(db_file
.DirName()));
555 EXPECT_TRUE(EnsureFileOfSize(db_file
, 2));
557 db_file
= tracker
->GetFullDBFilePath(kOrigin1
, kDB3
);
558 EXPECT_TRUE(file_util::CreateDirectory(db_file
.DirName()));
559 EXPECT_TRUE(EnsureFileOfSize(db_file
, 3));
561 // Store the origin database directory as long as it still exists.
562 origin1_db_dir
= tracker
->GetFullDBFilePath(kOrigin1
, kDB3
).DirName();
564 tracker
->DatabaseModified(kOrigin1
, kDB1
);
565 tracker
->DatabaseModified(kOrigin2
, kDB2
);
566 tracker
->DatabaseModified(kOrigin1
, kDB3
);
568 // Close all databases but one database.
569 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
570 tracker
->DatabaseClosed(kOrigin2
, kDB2
);
572 // Keep an open file handle to the last database.
573 base::PlatformFile file_handle
= base::CreatePlatformFile(
574 tracker
->GetFullDBFilePath(kOrigin1
, kDB3
),
575 base::PLATFORM_FILE_READ
|
576 base::PLATFORM_FILE_WRITE
|
577 base::PLATFORM_FILE_EXCLUSIVE_READ
|
578 base::PLATFORM_FILE_EXCLUSIVE_WRITE
|
579 base::PLATFORM_FILE_OPEN_ALWAYS
|
580 base::PLATFORM_FILE_SHARE_DELETE
,
585 base::ClosePlatformFile(file_handle
);
586 tracker
->DatabaseClosed(kOrigin1
, kDB3
);
589 // At this point, the database tracker should be gone. Create a new one.
590 scoped_refptr
<quota::MockSpecialStoragePolicy
> special_storage_policy
=
591 new quota::MockSpecialStoragePolicy
;
592 special_storage_policy
->AddProtected(GURL(kOrigin2Url
));
593 scoped_refptr
<DatabaseTracker
> tracker(
594 new DatabaseTracker(temp_dir
.path(), false, false,
595 special_storage_policy
, NULL
, NULL
));
597 // Get all data for all origins.
598 std::vector
<OriginInfo
> origins_info
;
599 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&origins_info
));
600 EXPECT_EQ(size_t(1), origins_info
.size());
601 EXPECT_EQ(kOrigin2
, origins_info
[0].GetOrigin());
602 EXPECT_EQ(FilePath(), tracker
->GetFullDBFilePath(kOrigin1
, kDB1
));
604 file_util::PathExists(tracker
->GetFullDBFilePath(kOrigin2
, kDB2
)));
605 EXPECT_EQ(FilePath(), tracker
->GetFullDBFilePath(kOrigin1
, kDB3
));
607 // The origin directory should be gone as well.
608 EXPECT_FALSE(file_util::PathExists(origin1_db_dir
));
611 static void DatabaseTrackerClearSessionOnlyDatabasesOnExit() {
612 int64 database_size
= 0;
613 const string16 kOrigin1
=
614 DatabaseUtil::GetOriginIdentifier(GURL(kOrigin1Url
));
615 const string16 kOrigin2
=
616 DatabaseUtil::GetOriginIdentifier(GURL(kOrigin2Url
));
617 const string16 kDB1
= ASCIIToUTF16("db1");
618 const string16 kDB2
= ASCIIToUTF16("db2");
619 const string16 kDescription
= ASCIIToUTF16("database_description");
621 // Initialize the tracker database.
622 ScopedTempDir temp_dir
;
623 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
624 FilePath origin1_db_dir
;
625 FilePath origin2_db_dir
;
627 scoped_refptr
<quota::MockSpecialStoragePolicy
> special_storage_policy
=
628 new quota::MockSpecialStoragePolicy
;
629 special_storage_policy
->AddSessionOnly(GURL(kOrigin2Url
));
630 scoped_refptr
<DatabaseTracker
> tracker(
632 temp_dir
.path(), false, false /*clear_local_state_on_exit*/,
633 special_storage_policy
, NULL
,
634 base::MessageLoopProxy::current()));
636 // Open two new databases.
637 tracker
->DatabaseOpened(kOrigin1
, kDB1
, kDescription
, 0,
639 EXPECT_EQ(0, database_size
);
640 tracker
->DatabaseOpened(kOrigin2
, kDB2
, kDescription
, 0,
642 EXPECT_EQ(0, database_size
);
644 // Write some data to each file.
646 db_file
= tracker
->GetFullDBFilePath(kOrigin1
, kDB1
);
647 EXPECT_TRUE(file_util::CreateDirectory(db_file
.DirName()));
648 EXPECT_TRUE(EnsureFileOfSize(db_file
, 1));
650 db_file
= tracker
->GetFullDBFilePath(kOrigin2
, kDB2
);
651 EXPECT_TRUE(file_util::CreateDirectory(db_file
.DirName()));
652 EXPECT_TRUE(EnsureFileOfSize(db_file
, 2));
654 // Store the origin database directories as long as they still exist.
655 origin1_db_dir
= tracker
->GetFullDBFilePath(kOrigin1
, kDB1
).DirName();
656 origin2_db_dir
= tracker
->GetFullDBFilePath(kOrigin2
, kDB2
).DirName();
658 tracker
->DatabaseModified(kOrigin1
, kDB1
);
659 tracker
->DatabaseModified(kOrigin2
, kDB2
);
661 // Close all databases.
662 tracker
->DatabaseClosed(kOrigin1
, kDB1
);
663 tracker
->DatabaseClosed(kOrigin2
, kDB2
);
668 // At this point, the database tracker should be gone. Create a new one.
669 scoped_refptr
<DatabaseTracker
> tracker(
670 new DatabaseTracker(temp_dir
.path(), false, false,
673 // Get all data for all origins.
674 std::vector
<OriginInfo
> origins_info
;
675 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&origins_info
));
676 // kOrigin1 was not session-only, so it survived. kOrigin2 was session-only
677 // and it got deleted.
678 EXPECT_EQ(size_t(1), origins_info
.size());
679 EXPECT_EQ(kOrigin1
, origins_info
[0].GetOrigin());
681 file_util::PathExists(tracker
->GetFullDBFilePath(kOrigin1
, kDB1
)));
682 EXPECT_EQ(FilePath(), tracker
->GetFullDBFilePath(kOrigin2
, kDB2
));
684 // The origin directory of kOrigin1 remains, but the origin directory of
685 // kOrigin2 is deleted.
686 EXPECT_TRUE(file_util::PathExists(origin1_db_dir
));
687 EXPECT_FALSE(file_util::PathExists(origin2_db_dir
));
690 static void EmptyDatabaseNameIsValid() {
691 const GURL
kOrigin(kOrigin1Url
);
692 const string16 kOriginId
= DatabaseUtil::GetOriginIdentifier(kOrigin
);
693 const string16 kEmptyName
;
694 const string16
kDescription(ASCIIToUTF16("description"));
695 const string16
kChangedDescription(ASCIIToUTF16("changed_description"));
697 // Initialize a tracker database, no need to put it on disk.
698 const bool kUseInMemoryTrackerDatabase
= true;
699 ScopedTempDir temp_dir
;
700 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
701 scoped_refptr
<DatabaseTracker
> tracker(
702 new DatabaseTracker(temp_dir
.path(), kUseInMemoryTrackerDatabase
,
703 false, NULL
, NULL
, NULL
));
705 // Starts off with no databases.
706 std::vector
<OriginInfo
> infos
;
707 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&infos
));
708 EXPECT_TRUE(infos
.empty());
710 // Create a db with an empty name.
711 int64 database_size
= -1;
712 tracker
->DatabaseOpened(kOriginId
, kEmptyName
, kDescription
, 0,
714 EXPECT_EQ(0, database_size
);
715 tracker
->DatabaseModified(kOriginId
, kEmptyName
);
716 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&infos
));
717 EXPECT_EQ(1u, infos
.size());
718 EXPECT_EQ(kDescription
, infos
[0].GetDatabaseDescription(kEmptyName
));
719 EXPECT_FALSE(tracker
->GetFullDBFilePath(kOriginId
, kEmptyName
).empty());
720 tracker
->DatabaseOpened(kOriginId
, kEmptyName
, kChangedDescription
, 0,
723 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&infos
));
724 EXPECT_EQ(1u, infos
.size());
725 EXPECT_EQ(kChangedDescription
, infos
[0].GetDatabaseDescription(kEmptyName
));
726 tracker
->DatabaseClosed(kOriginId
, kEmptyName
);
727 tracker
->DatabaseClosed(kOriginId
, kEmptyName
);
729 // Deleting it should return to the initial state.
730 EXPECT_EQ(net::OK
, tracker
->DeleteDatabase(kOriginId
, kEmptyName
, NULL
));
732 EXPECT_TRUE(tracker
->GetAllOriginsInfo(&infos
));
733 EXPECT_TRUE(infos
.empty());
737 TEST(DatabaseTrackerTest
, DeleteOpenDatabase
) {
738 DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(false);
741 TEST(DatabaseTrackerTest
, DeleteOpenDatabaseIncognitoMode
) {
742 DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(true);
745 TEST(DatabaseTrackerTest
, DatabaseTracker
) {
746 DatabaseTracker_TestHelper_Test::TestDatabaseTracker(false);
749 TEST(DatabaseTrackerTest
, DatabaseTrackerIncognitoMode
) {
750 DatabaseTracker_TestHelper_Test::TestDatabaseTracker(true);
753 TEST(DatabaseTrackerTest
, DatabaseTrackerQuotaIntegration
) {
754 // There is no difference in behavior between incognito and not.
755 DatabaseTracker_TestHelper_Test::DatabaseTrackerQuotaIntegration();
758 TEST(DatabaseTrackerTest
, DatabaseTrackerClearLocalStateOnExit
) {
759 // Only works for regular mode.
760 DatabaseTracker_TestHelper_Test::DatabaseTrackerClearLocalStateOnExit();
763 TEST(DatabaseTrackerTest
, DatabaseTrackerClearSessionOnlyDatabasesOnExit
) {
764 // Only works for regular mode.
765 DatabaseTracker_TestHelper_Test::
766 DatabaseTrackerClearSessionOnlyDatabasesOnExit();
769 TEST(DatabaseTrackerTest
, EmptyDatabaseNameIsValid
) {
770 DatabaseTracker_TestHelper_Test::EmptyDatabaseNameIsValid();
773 } // namespace webkit_database