Home | History | Annotate | Download | only in indexed_db
      1 // Copyright (c) 2012 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/file_util.h"
      6 #include "base/files/scoped_temp_dir.h"
      7 #include "base/test/test_simple_task_runner.h"
      8 #include "base/threading/thread.h"
      9 #include "content/browser/browser_thread_impl.h"
     10 #include "content/browser/indexed_db/indexed_db_connection.h"
     11 #include "content/browser/indexed_db/indexed_db_context_impl.h"
     12 #include "content/public/browser/storage_partition.h"
     13 #include "content/public/common/url_constants.h"
     14 #include "content/public/test/test_browser_context.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "webkit/browser/quota/mock_special_storage_policy.h"
     17 #include "webkit/browser/quota/quota_manager.h"
     18 #include "webkit/browser/quota/special_storage_policy.h"
     19 #include "webkit/common/database/database_identifier.h"
     20 
     21 namespace content {
     22 
     23 class IndexedDBTest : public testing::Test {
     24  public:
     25   const GURL kNormalOrigin;
     26   const GURL kSessionOnlyOrigin;
     27 
     28   IndexedDBTest()
     29       : kNormalOrigin("http://normal/"),
     30         kSessionOnlyOrigin("http://session-only/"),
     31         message_loop_(base::MessageLoop::TYPE_IO),
     32         task_runner_(new base::TestSimpleTaskRunner),
     33         special_storage_policy_(new quota::MockSpecialStoragePolicy),
     34         file_thread_(BrowserThread::FILE_USER_BLOCKING, &message_loop_),
     35         io_thread_(BrowserThread::IO, &message_loop_) {
     36     special_storage_policy_->AddSessionOnly(kSessionOnlyOrigin);
     37   }
     38 
     39  protected:
     40   void FlushIndexedDBTaskRunner() { task_runner_->RunUntilIdle(); }
     41 
     42   base::MessageLoop message_loop_;
     43   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
     44   scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy_;
     45 
     46  private:
     47   BrowserThreadImpl file_thread_;
     48   BrowserThreadImpl io_thread_;
     49 };
     50 
     51 TEST_F(IndexedDBTest, ClearSessionOnlyDatabases) {
     52   base::ScopedTempDir temp_dir;
     53   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
     54 
     55   base::FilePath normal_path;
     56   base::FilePath session_only_path;
     57 
     58   // Create the scope which will ensure we run the destructor of the context
     59   // which should trigger the clean up.
     60   {
     61     scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
     62         temp_dir.path(), special_storage_policy_, NULL, task_runner_);
     63 
     64     normal_path = idb_context->GetFilePathForTesting(
     65         webkit_database::GetIdentifierFromOrigin(kNormalOrigin));
     66     session_only_path = idb_context->GetFilePathForTesting(
     67         webkit_database::GetIdentifierFromOrigin(kSessionOnlyOrigin));
     68     ASSERT_TRUE(file_util::CreateDirectory(normal_path));
     69     ASSERT_TRUE(file_util::CreateDirectory(session_only_path));
     70     FlushIndexedDBTaskRunner();
     71     message_loop_.RunUntilIdle();
     72   }
     73 
     74   FlushIndexedDBTaskRunner();
     75   message_loop_.RunUntilIdle();
     76 
     77   EXPECT_TRUE(base::DirectoryExists(normal_path));
     78   EXPECT_FALSE(base::DirectoryExists(session_only_path));
     79 }
     80 
     81 TEST_F(IndexedDBTest, SetForceKeepSessionState) {
     82   base::ScopedTempDir temp_dir;
     83   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
     84 
     85   base::FilePath normal_path;
     86   base::FilePath session_only_path;
     87 
     88   // Create the scope which will ensure we run the destructor of the context.
     89   {
     90     // Create some indexedDB paths.
     91     // With the levelDB backend, these are directories.
     92     scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
     93         temp_dir.path(), special_storage_policy_, NULL, task_runner_);
     94 
     95     // Save session state. This should bypass the destruction-time deletion.
     96     idb_context->SetForceKeepSessionState();
     97 
     98     normal_path = idb_context->GetFilePathForTesting(
     99         webkit_database::GetIdentifierFromOrigin(kNormalOrigin));
    100     session_only_path = idb_context->GetFilePathForTesting(
    101         webkit_database::GetIdentifierFromOrigin(kSessionOnlyOrigin));
    102     ASSERT_TRUE(file_util::CreateDirectory(normal_path));
    103     ASSERT_TRUE(file_util::CreateDirectory(session_only_path));
    104     message_loop_.RunUntilIdle();
    105   }
    106 
    107   // Make sure we wait until the destructor has run.
    108   message_loop_.RunUntilIdle();
    109 
    110   // No data was cleared because of SetForceKeepSessionState.
    111   EXPECT_TRUE(base::DirectoryExists(normal_path));
    112   EXPECT_TRUE(base::DirectoryExists(session_only_path));
    113 }
    114 
    115 class MockConnection : public IndexedDBConnection {
    116  public:
    117   explicit MockConnection(bool expect_force_close)
    118       : IndexedDBConnection(NULL, NULL),
    119         expect_force_close_(expect_force_close),
    120         force_close_called_(false) {}
    121 
    122   virtual ~MockConnection() {
    123     EXPECT_TRUE(force_close_called_ == expect_force_close_);
    124   }
    125 
    126   virtual void ForceClose() OVERRIDE {
    127     ASSERT_TRUE(expect_force_close_);
    128     force_close_called_ = true;
    129   }
    130 
    131  private:
    132   bool expect_force_close_;
    133   bool force_close_called_;
    134 };
    135 
    136 TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
    137   base::ScopedTempDir temp_dir;
    138   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    139 
    140   base::FilePath test_path;
    141 
    142   // Create the scope which will ensure we run the destructor of the context.
    143   {
    144     TestBrowserContext browser_context;
    145 
    146     const GURL kTestOrigin("http://test/");
    147 
    148     scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
    149         temp_dir.path(), special_storage_policy_, NULL, task_runner_);
    150 
    151     test_path = idb_context->GetFilePathForTesting(
    152         webkit_database::GetIdentifierFromOrigin(kTestOrigin));
    153     ASSERT_TRUE(file_util::CreateDirectory(test_path));
    154 
    155     const bool kExpectForceClose = true;
    156 
    157     MockConnection connection1(kExpectForceClose);
    158     idb_context->TaskRunner()->PostTask(
    159         FROM_HERE,
    160         base::Bind(&IndexedDBContextImpl::ConnectionOpened,
    161                    idb_context,
    162                    kTestOrigin,
    163                    &connection1));
    164 
    165     MockConnection connection2(!kExpectForceClose);
    166     idb_context->TaskRunner()->PostTask(
    167         FROM_HERE,
    168         base::Bind(&IndexedDBContextImpl::ConnectionOpened,
    169                    idb_context,
    170                    kTestOrigin,
    171                    &connection2));
    172     idb_context->TaskRunner()->PostTask(
    173         FROM_HERE,
    174         base::Bind(&IndexedDBContextImpl::ConnectionClosed,
    175                    idb_context,
    176                    kTestOrigin,
    177                    &connection2));
    178 
    179     idb_context->TaskRunner()->PostTask(
    180         FROM_HERE,
    181         base::Bind(
    182             &IndexedDBContextImpl::DeleteForOrigin, idb_context, kTestOrigin));
    183     FlushIndexedDBTaskRunner();
    184     message_loop_.RunUntilIdle();
    185   }
    186 
    187   // Make sure we wait until the destructor has run.
    188   message_loop_.RunUntilIdle();
    189 
    190   EXPECT_FALSE(base::DirectoryExists(test_path));
    191 }
    192 
    193 }  // namespace content
    194