Home | History | Annotate | Download | only in browser
      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.
      4 
      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/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 "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"
     22 
     23 using base::ASCIIToUTF16;
     24 using storage::DatabaseConnections;
     25 using storage::DatabaseTracker;
     26 using storage::OriginInfo;
     27 
     28 namespace {
     29 
     30 const char kOrigin1Url[] = "http://origin1";
     31 const char kOrigin2Url[] = "http://protected_origin2";
     32 
     33 class TestObserver : public storage::DatabaseTracker::Observer {
     34  public:
     35   TestObserver()
     36       : new_notification_received_(false),
     37         observe_size_changes_(true),
     38         observe_scheduled_deletions_(true) {
     39   }
     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) {
     44   }
     45 
     46   virtual ~TestObserver() {}
     47   virtual void OnDatabaseSizeChanged(const std::string& origin_identifier,
     48                                      const base::string16& database_name,
     49                                      int64 database_size) OVERRIDE {
     50     if (!observe_size_changes_)
     51       return;
     52     new_notification_received_ = true;
     53     origin_identifier_ = origin_identifier;
     54     database_name_ = database_name;
     55     database_size_ = database_size;
     56   }
     57   virtual void OnDatabaseScheduledForDeletion(
     58       const std::string& origin_identifier,
     59       const base::string16& database_name) OVERRIDE {
     60     if (!observe_scheduled_deletions_)
     61       return;
     62     new_notification_received_ = true;
     63     origin_identifier_ = origin_identifier;
     64     database_name_ = database_name;
     65   }
     66   bool DidReceiveNewNotification() {
     67     bool temp_new_notification_received = new_notification_received_;
     68     new_notification_received_ = false;
     69     return temp_new_notification_received;
     70   }
     71   std::string GetNotificationOriginIdentifier() {
     72     return origin_identifier_;
     73   }
     74   base::string16 GetNotificationDatabaseName() { return database_name_; }
     75   int64 GetNotificationDatabaseSize() { return database_size_; }
     76 
     77  private:
     78   bool new_notification_received_;
     79   bool observe_size_changes_;
     80   bool observe_scheduled_deletions_;
     81   std::string origin_identifier_;
     82   base::string16 database_name_;
     83   int64 database_size_;
     84 };
     85 
     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());
     97 }
     98 
     99 class TestQuotaManagerProxy : public storage::QuotaManagerProxy {
    100  public:
    101   TestQuotaManagerProxy()
    102       : QuotaManagerProxy(NULL, NULL),
    103         registered_client_(NULL) {
    104   }
    105 
    106   virtual void RegisterClient(storage::QuotaClient* client) OVERRIDE {
    107     EXPECT_FALSE(registered_client_);
    108     registered_client_ = client;
    109   }
    110 
    111   virtual void NotifyStorageAccessed(storage::QuotaClient::ID client_id,
    112                                      const GURL& origin,
    113                                      storage::StorageType type) OVERRIDE {
    114     EXPECT_EQ(storage::QuotaClient::kDatabase, client_id);
    115     EXPECT_EQ(storage::kStorageTypeTemporary, type);
    116     accesses_[origin] += 1;
    117   }
    118 
    119   virtual void NotifyStorageModified(storage::QuotaClient::ID client_id,
    120                                      const GURL& origin,
    121                                      storage::StorageType type,
    122                                      int64 delta) OVERRIDE {
    123     EXPECT_EQ(storage::QuotaClient::kDatabase, client_id);
    124     EXPECT_EQ(storage::kStorageTypeTemporary, type);
    125     modifications_[origin].first += 1;
    126     modifications_[origin].second += delta;
    127   }
    128 
    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,
    133                                     const GURL& origin,
    134                                     storage::StorageType type,
    135                                     bool enabled) OVERRIDE {}
    136   virtual void GetUsageAndQuota(
    137       base::SequencedTaskRunner* original_task_runner,
    138       const GURL& origin,
    139       storage::StorageType type,
    140       const GetUsageAndQuotaCallback& callback) OVERRIDE {}
    141 
    142   void SimulateQuotaManagerDestroyed() {
    143     if (registered_client_) {
    144       registered_client_->OnQuotaManagerDestroyed();
    145       registered_client_ = NULL;
    146     }
    147   }
    148 
    149   bool WasAccessNotified(const GURL& origin) {
    150     return accesses_[origin] != 0;
    151   }
    152 
    153   bool WasModificationNotified(const GURL& origin, int64 amount) {
    154     return modifications_[origin].first != 0 &&
    155            modifications_[origin].second == amount;
    156   }
    157 
    158   void reset() {
    159     accesses_.clear();
    160     modifications_.clear();
    161   }
    162 
    163   storage::QuotaClient* registered_client_;
    164 
    165   // Map from origin to count of access notifications.
    166   std::map<GURL, int> accesses_;
    167 
    168   // Map from origin to <count, sum of deltas>
    169   std::map<GURL, std::pair<int, int64> > modifications_;
    170 
    171  protected:
    172   virtual ~TestQuotaManagerProxy() {
    173     EXPECT_FALSE(registered_client_);
    174   }
    175 };
    176 
    177 
    178 bool EnsureFileOfSize(const base::FilePath& file_path, int64 length) {
    179   base::File file(file_path,
    180                   base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE);
    181   if (!file.IsValid())
    182     return false;
    183   return file.SetLength(length);
    184 }
    185 
    186 }  // namespace
    187 
    188 namespace content {
    189 
    190 // We declare a helper class, and make it a friend of DatabaseTracker using
    191 // the FORWARD_DECLARE_TEST macro, and we implement all tests we want to run as
    192 // static methods of this class. Then we make our TEST() targets call these
    193 // static functions. This allows us to run each test in normal mode and
    194 // incognito mode without writing the same code twice.
    195 class DatabaseTracker_TestHelper_Test {
    196  public:
    197   static void TestDeleteOpenDatabase(bool incognito_mode) {
    198     // Initialize the tracker database.
    199     base::ScopedTempDir temp_dir;
    200     ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    201     scoped_refptr<MockSpecialStoragePolicy> special_storage_policy =
    202         new MockSpecialStoragePolicy;
    203     special_storage_policy->AddProtected(GURL(kOrigin2Url));
    204     scoped_refptr<DatabaseTracker> tracker(
    205         new DatabaseTracker(temp_dir.path(),
    206                             incognito_mode,
    207                             special_storage_policy.get(),
    208                             NULL,
    209                             NULL));
    210 
    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");
    221 
    222     tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
    223                             &database_size);
    224     tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
    225                             &database_size);
    226     tracker->DatabaseOpened(kOrigin2, kDB3, kDescription, 0,
    227                             &database_size);
    228 
    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);
    244 
    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)));
    260 
    261     // Recreate db1.
    262     tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
    263                             &database_size);
    264     EXPECT_TRUE(base::CreateDirectory(
    265         tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
    266             tracker->GetOriginDirectory(kOrigin1)))));
    267     EXPECT_EQ(1, base::WriteFile(
    268         tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
    269     tracker->DatabaseModified(kOrigin1, kDB1);
    270 
    271     // Setup file modification times.  db1 and db2 are modified now, db3 three
    272     // days ago.
    273     base::Time now = base::Time::Now();
    274     EXPECT_TRUE(base::TouchFile(tracker->GetFullDBFilePath(kOrigin1, kDB1),
    275                                 now, now));
    276     EXPECT_TRUE(base::TouchFile(tracker->GetFullDBFilePath(kOrigin2, kDB2),
    277                                 now, now));
    278     base::Time three_days_ago = now - base::TimeDelta::FromDays(3);
    279     EXPECT_TRUE(base::TouchFile(tracker->GetFullDBFilePath(kOrigin2, kDB3),
    280                                 three_days_ago, three_days_ago));
    281 
    282     // Delete databases modified since yesterday. db2 is whitelisted.
    283     base::Time yesterday = base::Time::Now();
    284     yesterday -= base::TimeDelta::FromDays(1);
    285     result = tracker->DeleteDataModifiedSince(
    286         yesterday, callback.callback());
    287     EXPECT_EQ(net::ERR_IO_PENDING, result);
    288     ASSERT_FALSE(callback.have_result());
    289     EXPECT_TRUE(observer.DidReceiveNewNotification());
    290     tracker->DatabaseClosed(kOrigin1, kDB1);
    291     tracker->DatabaseClosed(kOrigin2, kDB2);
    292     result = callback.GetResult(result);
    293     EXPECT_EQ(net::OK, result);
    294     EXPECT_FALSE(base::PathExists(
    295         tracker->DatabaseDirectory().AppendASCII(kOrigin1)));
    296     EXPECT_TRUE(
    297         base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
    298     EXPECT_TRUE(
    299         base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB3)));
    300 
    301     tracker->DatabaseClosed(kOrigin2, kDB3);
    302     tracker->RemoveObserver(&observer);
    303   }
    304 
    305   static void TestDatabaseTracker(bool incognito_mode) {
    306     // Initialize the tracker database.
    307     base::ScopedTempDir temp_dir;
    308     ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    309     scoped_refptr<MockSpecialStoragePolicy> special_storage_policy =
    310         new MockSpecialStoragePolicy;
    311     special_storage_policy->AddProtected(GURL(kOrigin2Url));
    312     scoped_refptr<DatabaseTracker> tracker(
    313         new DatabaseTracker(temp_dir.path(),
    314                             incognito_mode,
    315                             special_storage_policy.get(),
    316                             NULL,
    317                             NULL));
    318 
    319     // Add two observers.
    320     TestObserver observer1;
    321     TestObserver observer2;
    322     tracker->AddObserver(&observer1);
    323     tracker->AddObserver(&observer2);
    324 
    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");
    335 
    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);
    343 
    344 
    345     tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
    346                             &database_size);
    347     EXPECT_EQ(0, database_size);
    348     tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
    349                             &database_size);
    350     EXPECT_EQ(0, database_size);
    351     tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0,
    352                             &database_size);
    353     EXPECT_EQ(0, database_size);
    354 
    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);
    378 
    379     // Close all databases
    380     tracker->DatabaseClosed(kOrigin1, kDB1);
    381     tracker->DatabaseClosed(kOrigin2, kDB2);
    382     tracker->DatabaseClosed(kOrigin1, kDB3);
    383 
    384     // Open an existing database and check the reported size
    385     tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
    386                             &database_size);
    387     EXPECT_EQ(1, database_size);
    388     tracker->DatabaseClosed(kOrigin1, kDB1);
    389 
    390     // Remove an observer; this should clear all caches.
    391     tracker->RemoveObserver(&observer2);
    392 
    393     // Close the tracker database and clear all caches.
    394     // Then make sure that DatabaseOpened() still returns the correct result.
    395     tracker->CloseTrackerDatabaseAndClearCaches();
    396     tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
    397                             &database_size);
    398     EXPECT_EQ(1, database_size);
    399     tracker->DatabaseClosed(kOrigin1, kDB1);
    400 
    401     // Remove all observers.
    402     tracker->RemoveObserver(&observer1);
    403 
    404     // Trying to delete a database in use should fail
    405     tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0,
    406                             &database_size);
    407     EXPECT_FALSE(tracker->DeleteClosedDatabase(kOrigin1, kDB3));
    408     origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
    409     EXPECT_TRUE(origin1_info);
    410     EXPECT_EQ(4, origin1_info->GetDatabaseSize(kDB3));
    411     tracker->DatabaseClosed(kOrigin1, kDB3);
    412 
    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));
    419 
    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));
    428 
    429     EXPECT_EQ(kOrigin2, origins_info[1].GetOriginIdentifier());
    430     EXPECT_EQ(2, origins_info[1].TotalSize());
    431 
    432     // Trying to delete an origin with databases in use should fail
    433     tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
    434                             &database_size);
    435     EXPECT_FALSE(tracker->DeleteOrigin(kOrigin1, false));
    436     origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
    437     EXPECT_TRUE(origin1_info);
    438     EXPECT_EQ(1, origin1_info->GetDatabaseSize(kDB1));
    439     tracker->DatabaseClosed(kOrigin1, kDB1);
    440 
    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());
    447 
    448     origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
    449     EXPECT_TRUE(origin1_info);
    450     EXPECT_EQ(0, origin1_info->TotalSize());
    451   }
    452 
    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");
    458 
    459     base::ScopedTempDir temp_dir;
    460     ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    461 
    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 */,
    468                             NULL,
    469                             test_quota_proxy.get(),
    470                             NULL));
    471     EXPECT_TRUE(test_quota_proxy->registered_client_);
    472 
    473     // Create a database and modify it a couple of times, close it,
    474     // then delete it. Observe the tracker notifies accordingly.
    475 
    476     int64 database_size = 0;
    477     tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
    478                             &database_size);
    479     EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
    480     test_quota_proxy->reset();
    481 
    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();
    488 
    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();
    493 
    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();
    500 
    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.
    504 
    505     tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
    506                             &database_size);
    507     EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
    508     test_quota_proxy->reset();
    509 
    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();
    516 
    517     EXPECT_EQ(net::ERR_IO_PENDING,
    518               tracker->DeleteDatabase(kOriginId, kName,
    519                                       net::CompletionCallback()));
    520     EXPECT_FALSE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
    521 
    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();
    526 
    527     // Create a database and up the file size without telling
    528     // the tracker about the modification, than simulate a
    529     // a renderer crash.
    530     // Observe the tracker notifies accordingly.
    531 
    532     tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
    533                             &database_size);
    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));
    544 
    545     // Cleanup.
    546     crashed_renderer_connections.RemoveAllConnections();
    547     test_quota_proxy->SimulateQuotaManagerDestroyed();
    548   }
    549 
    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");
    559 
    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;
    566     {
    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(),
    572                               false,
    573                               special_storage_policy.get(),
    574                               NULL,
    575                               base::MessageLoopProxy::current().get()));
    576 
    577       // Open two new databases.
    578       tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
    579                               &database_size);
    580       EXPECT_EQ(0, database_size);
    581       tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
    582                               &database_size);
    583       EXPECT_EQ(0, database_size);
    584 
    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));
    590 
    591       db_file = tracker->GetFullDBFilePath(kOrigin2, kDB2);
    592       EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
    593       EXPECT_TRUE(EnsureFileOfSize(db_file, 2));
    594 
    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();
    598 
    599       tracker->DatabaseModified(kOrigin1, kDB1);
    600       tracker->DatabaseModified(kOrigin2, kDB2);
    601 
    602       // Close all databases.
    603       tracker->DatabaseClosed(kOrigin1, kDB1);
    604       tracker->DatabaseClosed(kOrigin2, kDB2);
    605 
    606       tracker->Shutdown();
    607     }
    608 
    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));
    612 
    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());
    620     EXPECT_TRUE(
    621         base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
    622     EXPECT_EQ(base::FilePath(), tracker->GetFullDBFilePath(kOrigin2, kDB2));
    623 
    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));
    628   }
    629 
    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");
    639 
    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;
    646     {
    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(),
    652                               false,
    653                               special_storage_policy.get(),
    654                               NULL,
    655                               base::MessageLoopProxy::current().get()));
    656       tracker->SetForceKeepSessionState();
    657 
    658       // Open two new databases.
    659       tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
    660                               &database_size);
    661       EXPECT_EQ(0, database_size);
    662       tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
    663                               &database_size);
    664       EXPECT_EQ(0, database_size);
    665 
    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));
    671 
    672       db_file = tracker->GetFullDBFilePath(kOrigin2, kDB2);
    673       EXPECT_TRUE(base::CreateDirectory(db_file.DirName()));
    674       EXPECT_TRUE(EnsureFileOfSize(db_file, 2));
    675 
    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();
    679 
    680       tracker->DatabaseModified(kOrigin1, kDB1);
    681       tracker->DatabaseModified(kOrigin2, kDB2);
    682 
    683       // Close all databases.
    684       tracker->DatabaseClosed(kOrigin1, kDB1);
    685       tracker->DatabaseClosed(kOrigin2, kDB2);
    686 
    687       tracker->Shutdown();
    688     }
    689 
    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));
    693 
    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());
    699     EXPECT_TRUE(
    700         base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
    701     EXPECT_TRUE(
    702         base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
    703 
    704     EXPECT_TRUE(base::PathExists(origin1_db_dir));
    705     EXPECT_TRUE(base::PathExists(origin2_db_dir));
    706   }
    707 
    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"));
    715 
    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,
    722                             NULL, NULL, NULL));
    723 
    724     // Starts off with no databases.
    725     std::vector<OriginInfo> infos;
    726     EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
    727     EXPECT_TRUE(infos.empty());
    728 
    729     // Create a db with an empty name.
    730     int64 database_size = -1;
    731     tracker->DatabaseOpened(kOriginId, kEmptyName, kDescription, 0,
    732                             &database_size);
    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,
    740                             &database_size);
    741     infos.clear();
    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);
    747 
    748     // Deleting it should return to the initial state.
    749     EXPECT_EQ(net::OK, tracker->DeleteDatabase(kOriginId, kEmptyName,
    750                                                net::CompletionCallback()));
    751     infos.clear();
    752     EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
    753     EXPECT_TRUE(infos.empty());
    754   }
    755 
    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"));
    761 
    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,
    768                             NULL, NULL, NULL));
    769 
    770     // Setup to observe OnScheduledForDelete notifications.
    771     TestObserver observer(false, true);
    772     tracker->AddObserver(&observer);
    773 
    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());
    778 
    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,
    784                             &database_size);
    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));
    789 
    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());
    794 
    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));
    801 
    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());
    807 
    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,
    812         &database_size);
    813     base::FilePath spoof_db_file2 = tracker->GetFullDBFilePath(kOriginId,
    814         kName);
    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));
    819 
    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));
    827 
    828     tracker->RemoveObserver(&observer);
    829   }
    830 };
    831 
    832 TEST(DatabaseTrackerTest, DeleteOpenDatabase) {
    833   DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(false);
    834 }
    835 
    836 TEST(DatabaseTrackerTest, DeleteOpenDatabaseIncognitoMode) {
    837   DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(true);
    838 }
    839 
    840 TEST(DatabaseTrackerTest, DatabaseTracker) {
    841   DatabaseTracker_TestHelper_Test::TestDatabaseTracker(false);
    842 }
    843 
    844 TEST(DatabaseTrackerTest, DatabaseTrackerIncognitoMode) {
    845   DatabaseTracker_TestHelper_Test::TestDatabaseTracker(true);
    846 }
    847 
    848 TEST(DatabaseTrackerTest, DatabaseTrackerQuotaIntegration) {
    849   // There is no difference in behavior between incognito and not.
    850   DatabaseTracker_TestHelper_Test::DatabaseTrackerQuotaIntegration();
    851 }
    852 
    853 TEST(DatabaseTrackerTest, DatabaseTrackerClearSessionOnlyDatabasesOnExit) {
    854   // Only works for regular mode.
    855   DatabaseTracker_TestHelper_Test::
    856       DatabaseTrackerClearSessionOnlyDatabasesOnExit();
    857 }
    858 
    859 TEST(DatabaseTrackerTest, DatabaseTrackerSetForceKeepSessionState) {
    860   // Only works for regular mode.
    861   DatabaseTracker_TestHelper_Test::DatabaseTrackerSetForceKeepSessionState();
    862 }
    863 
    864 TEST(DatabaseTrackerTest, EmptyDatabaseNameIsValid) {
    865   DatabaseTracker_TestHelper_Test::EmptyDatabaseNameIsValid();
    866 }
    867 
    868 TEST(DatabaseTrackerTest, HandleSqliteError) {
    869   DatabaseTracker_TestHelper_Test::HandleSqliteError();
    870 }
    871 
    872 }  // namespace content
    873