Home | History | Annotate | Download | only in browsing_data
      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 "testing/gtest/include/gtest/gtest.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/file_util.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/platform_file.h"
     12 #include "base/stl_util.h"
     13 #include "base/strings/utf_string_conversions.h"
     14 #include "chrome/browser/browsing_data/browsing_data_file_system_helper.h"
     15 #include "chrome/test/base/testing_profile.h"
     16 #include "content/public/browser/storage_partition.h"
     17 #include "content/public/test/test_browser_thread.h"
     18 #include "content/public/test/test_browser_thread_bundle.h"
     19 #include "webkit/browser/fileapi/file_system_context.h"
     20 #include "webkit/browser/fileapi/file_system_url.h"
     21 #include "webkit/common/fileapi/file_system_types.h"
     22 
     23 using content::BrowserContext;
     24 using content::BrowserThread;
     25 
     26 namespace {
     27 
     28 // Shorter names for fileapi::* constants.
     29 const fileapi::FileSystemType kTemporary = fileapi::kFileSystemTypeTemporary;
     30 const fileapi::FileSystemType kPersistent = fileapi::kFileSystemTypePersistent;
     31 
     32 // We'll use these three distinct origins for testing, both as strings and as
     33 // GURLs in appropriate contexts.
     34 const char kTestOrigin1[] = "http://host1:1/";
     35 const char kTestOrigin2[] = "http://host2:2/";
     36 const char kTestOrigin3[] = "http://host3:3/";
     37 
     38 // Extensions and Devtools should be ignored.
     39 const char kTestOriginExt[] = "chrome-extension://abcdefghijklmnopqrstuvwxyz/";
     40 const char kTestOriginDevTools[] = "chrome-devtools://abcdefghijklmnopqrstuvw/";
     41 
     42 const GURL kOrigin1(kTestOrigin1);
     43 const GURL kOrigin2(kTestOrigin2);
     44 const GURL kOrigin3(kTestOrigin3);
     45 const GURL kOriginExt(kTestOriginExt);
     46 const GURL kOriginDevTools(kTestOriginDevTools);
     47 
     48 // TODO(mkwst): Update this size once the discussion in http://crbug.com/86114
     49 // is concluded.
     50 const int kEmptyFileSystemSize = 0;
     51 
     52 typedef std::list<BrowsingDataFileSystemHelper::FileSystemInfo>
     53     FileSystemInfoList;
     54 typedef scoped_ptr<FileSystemInfoList> ScopedFileSystemInfoList;
     55 
     56 // The FileSystem APIs are all asynchronous; this testing class wraps up the
     57 // boilerplate code necessary to deal with waiting for responses. In a nutshell,
     58 // any async call whose response we want to test ought to be followed by a call
     59 // to BlockUntilNotified(), which will (shockingly!) block until Notify() is
     60 // called. For this to work, you'll need to ensure that each async call is
     61 // implemented as a class method that that calls Notify() at an appropriate
     62 // point.
     63 class BrowsingDataFileSystemHelperTest : public testing::Test {
     64  public:
     65   BrowsingDataFileSystemHelperTest() {
     66     profile_.reset(new TestingProfile());
     67 
     68     helper_ = BrowsingDataFileSystemHelper::Create(
     69         BrowserContext::GetDefaultStoragePartition(profile_.get())->
     70             GetFileSystemContext());
     71     base::MessageLoop::current()->RunUntilIdle();
     72     canned_helper_ = new CannedBrowsingDataFileSystemHelper(profile_.get());
     73   }
     74   virtual ~BrowsingDataFileSystemHelperTest() {
     75     // Avoid memory leaks.
     76     profile_.reset();
     77     base::MessageLoop::current()->RunUntilIdle();
     78   }
     79 
     80   TestingProfile* GetProfile() {
     81     return profile_.get();
     82   }
     83 
     84   // Blocks on the current MessageLoop until Notify() is called.
     85   void BlockUntilNotified() {
     86     base::MessageLoop::current()->Run();
     87   }
     88 
     89   // Unblocks the current MessageLoop. Should be called in response to some sort
     90   // of async activity in a callback method.
     91   void Notify() {
     92     base::MessageLoop::current()->Quit();
     93   }
     94 
     95   // Callback that should be executed in response to
     96   // fileapi::FileSystemContext::OpenFileSystem.
     97   void OpenFileSystemCallback(base::PlatformFileError error,
     98                               const std::string& name,
     99                               const GURL& root) {
    100     open_file_system_result_ = error;
    101     Notify();
    102   }
    103 
    104   bool OpenFileSystem(const GURL& origin,
    105                       fileapi::FileSystemType type,
    106                       fileapi::OpenFileSystemMode open_mode) {
    107     BrowserContext::GetDefaultStoragePartition(profile_.get())->
    108         GetFileSystemContext()->OpenFileSystem(
    109             origin, type, open_mode,
    110             base::Bind(
    111                 &BrowsingDataFileSystemHelperTest::OpenFileSystemCallback,
    112                 base::Unretained(this)));
    113     BlockUntilNotified();
    114     return open_file_system_result_ == base::PLATFORM_FILE_OK;
    115   }
    116 
    117   // Calls fileapi::FileSystemContext::OpenFileSystem with
    118   // OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT flag
    119   // to verify the existence of a file system for a specified type and origin,
    120   // blocks until a response is available, then returns the result
    121   // synchronously to it's caller.
    122   bool FileSystemContainsOriginAndType(const GURL& origin,
    123                                        fileapi::FileSystemType type) {
    124     return OpenFileSystem(origin, type,
    125                           fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT);
    126   }
    127 
    128   // Callback that should be executed in response to StartFetching(), and stores
    129   // found file systems locally so that they are available via GetFileSystems().
    130   void CallbackStartFetching(
    131       const std::list<BrowsingDataFileSystemHelper::FileSystemInfo>&
    132           file_system_info_list) {
    133     file_system_info_list_.reset(
    134         new std::list<BrowsingDataFileSystemHelper::FileSystemInfo>(
    135             file_system_info_list));
    136     Notify();
    137   }
    138 
    139   // Calls StartFetching() on the test's BrowsingDataFileSystemHelper
    140   // object, then blocks until the callback is executed.
    141   void FetchFileSystems() {
    142     helper_->StartFetching(
    143         base::Bind(&BrowsingDataFileSystemHelperTest::CallbackStartFetching,
    144                    base::Unretained(this)));
    145     BlockUntilNotified();
    146   }
    147 
    148   // Calls StartFetching() on the test's CannedBrowsingDataFileSystemHelper
    149   // object, then blocks until the callback is executed.
    150   void FetchCannedFileSystems() {
    151     canned_helper_->StartFetching(
    152         base::Bind(&BrowsingDataFileSystemHelperTest::CallbackStartFetching,
    153                    base::Unretained(this)));
    154     BlockUntilNotified();
    155   }
    156 
    157   // Sets up kOrigin1 with a temporary file system, kOrigin2 with a persistent
    158   // file system, and kOrigin3 with both.
    159   virtual void PopulateTestFileSystemData() {
    160     CreateDirectoryForOriginAndType(kOrigin1, kTemporary);
    161     CreateDirectoryForOriginAndType(kOrigin2, kPersistent);
    162     CreateDirectoryForOriginAndType(kOrigin3, kTemporary);
    163     CreateDirectoryForOriginAndType(kOrigin3, kPersistent);
    164 
    165     EXPECT_FALSE(FileSystemContainsOriginAndType(kOrigin1, kPersistent));
    166     EXPECT_TRUE(FileSystemContainsOriginAndType(kOrigin1, kTemporary));
    167     EXPECT_TRUE(FileSystemContainsOriginAndType(kOrigin2, kPersistent));
    168     EXPECT_FALSE(FileSystemContainsOriginAndType(kOrigin2, kTemporary));
    169     EXPECT_TRUE(FileSystemContainsOriginAndType(kOrigin3, kPersistent));
    170     EXPECT_TRUE(FileSystemContainsOriginAndType(kOrigin3, kTemporary));
    171   }
    172 
    173   // Calls OpenFileSystem with OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT
    174   // to create a filesystem of a given type for a specified origin.
    175   void CreateDirectoryForOriginAndType(const GURL& origin,
    176                                        fileapi::FileSystemType type) {
    177     OpenFileSystem(origin, type,
    178                    fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT);
    179     EXPECT_EQ(base::PLATFORM_FILE_OK, open_file_system_result_);
    180   }
    181 
    182   // Returns a list of the FileSystemInfo objects gathered in the most recent
    183   // call to StartFetching().
    184   FileSystemInfoList* GetFileSystems() {
    185     return file_system_info_list_.get();
    186   }
    187 
    188  protected:
    189   content::TestBrowserThreadBundle thread_bundle_;
    190   scoped_ptr<TestingProfile> profile_;
    191 
    192   // Temporary storage to pass information back from callbacks.
    193   base::PlatformFileError open_file_system_result_;
    194   ScopedFileSystemInfoList file_system_info_list_;
    195 
    196   scoped_refptr<BrowsingDataFileSystemHelper> helper_;
    197   scoped_refptr<CannedBrowsingDataFileSystemHelper> canned_helper_;
    198 
    199   DISALLOW_COPY_AND_ASSIGN(BrowsingDataFileSystemHelperTest);
    200 };
    201 
    202 // Verifies that the BrowsingDataFileSystemHelper correctly finds the test file
    203 // system data, and that each file system returned contains the expected data.
    204 TEST_F(BrowsingDataFileSystemHelperTest, FetchData) {
    205   PopulateTestFileSystemData();
    206 
    207   FetchFileSystems();
    208 
    209   EXPECT_EQ(3UL, file_system_info_list_->size());
    210 
    211   // Order is arbitrary, verify all three origins.
    212   bool test_hosts_found[3] = {false, false, false};
    213   for (std::list<BrowsingDataFileSystemHelper::FileSystemInfo>::iterator info =
    214        file_system_info_list_->begin(); info != file_system_info_list_->end();
    215        ++info) {
    216     if (info->origin == kOrigin1) {
    217       EXPECT_FALSE(test_hosts_found[0]);
    218       test_hosts_found[0] = true;
    219       EXPECT_FALSE(ContainsKey(info->usage_map, kPersistent));
    220       EXPECT_TRUE(ContainsKey(info->usage_map, kTemporary));
    221       EXPECT_EQ(kEmptyFileSystemSize,
    222                 info->usage_map[fileapi::kFileSystemTypeTemporary]);
    223     } else if (info->origin == kOrigin2) {
    224       EXPECT_FALSE(test_hosts_found[1]);
    225       test_hosts_found[1] = true;
    226       EXPECT_TRUE(ContainsKey(info->usage_map, kPersistent));
    227       EXPECT_FALSE(ContainsKey(info->usage_map, kTemporary));
    228       EXPECT_EQ(kEmptyFileSystemSize, info->usage_map[kPersistent]);
    229     } else if (info->origin == kOrigin3) {
    230       EXPECT_FALSE(test_hosts_found[2]);
    231       test_hosts_found[2] = true;
    232       EXPECT_TRUE(ContainsKey(info->usage_map, kPersistent));
    233       EXPECT_TRUE(ContainsKey(info->usage_map, kTemporary));
    234       EXPECT_EQ(kEmptyFileSystemSize, info->usage_map[kPersistent]);
    235       EXPECT_EQ(kEmptyFileSystemSize, info->usage_map[kTemporary]);
    236     } else {
    237       ADD_FAILURE() << info->origin.spec() << " isn't an origin we added.";
    238     }
    239   }
    240   for (size_t i = 0; i < arraysize(test_hosts_found); i++) {
    241     EXPECT_TRUE(test_hosts_found[i]);
    242   }
    243 }
    244 
    245 // Verifies that the BrowsingDataFileSystemHelper correctly deletes file
    246 // systems via DeleteFileSystemOrigin().
    247 TEST_F(BrowsingDataFileSystemHelperTest, DeleteData) {
    248   PopulateTestFileSystemData();
    249 
    250   helper_->DeleteFileSystemOrigin(kOrigin1);
    251   helper_->DeleteFileSystemOrigin(kOrigin2);
    252 
    253   FetchFileSystems();
    254 
    255   EXPECT_EQ(1UL, file_system_info_list_->size());
    256   BrowsingDataFileSystemHelper::FileSystemInfo info =
    257       *(file_system_info_list_->begin());
    258   EXPECT_EQ(kOrigin3, info.origin);
    259   EXPECT_TRUE(ContainsKey(info.usage_map, kPersistent));
    260   EXPECT_TRUE(ContainsKey(info.usage_map, kTemporary));
    261   EXPECT_EQ(kEmptyFileSystemSize, info.usage_map[kPersistent]);
    262   EXPECT_EQ(kEmptyFileSystemSize, info.usage_map[kTemporary]);
    263 }
    264 
    265 // Verifies that the CannedBrowsingDataFileSystemHelper correctly reports
    266 // whether or not it currently contains file systems.
    267 TEST_F(BrowsingDataFileSystemHelperTest, Empty) {
    268   ASSERT_TRUE(canned_helper_->empty());
    269   canned_helper_->AddFileSystem(kOrigin1, kTemporary, 0);
    270   ASSERT_FALSE(canned_helper_->empty());
    271   canned_helper_->Reset();
    272   ASSERT_TRUE(canned_helper_->empty());
    273 }
    274 
    275 // Verifies that AddFileSystem correctly adds file systems, and that both
    276 // the type and usage metadata are reported as provided.
    277 TEST_F(BrowsingDataFileSystemHelperTest, CannedAddFileSystem) {
    278   canned_helper_->AddFileSystem(kOrigin1, kPersistent, 200);
    279   canned_helper_->AddFileSystem(kOrigin2, kTemporary, 100);
    280 
    281   FetchCannedFileSystems();
    282 
    283   EXPECT_EQ(2U, file_system_info_list_->size());
    284   std::list<BrowsingDataFileSystemHelper::FileSystemInfo>::iterator info =
    285       file_system_info_list_->begin();
    286   EXPECT_EQ(kOrigin1, info->origin);
    287   EXPECT_TRUE(ContainsKey(info->usage_map, kPersistent));
    288   EXPECT_FALSE(ContainsKey(info->usage_map, kTemporary));
    289   EXPECT_EQ(200, info->usage_map[kPersistent]);
    290 
    291   info++;
    292   EXPECT_EQ(kOrigin2, info->origin);
    293   EXPECT_FALSE(ContainsKey(info->usage_map, kPersistent));
    294   EXPECT_TRUE(ContainsKey(info->usage_map, kTemporary));
    295   EXPECT_EQ(100, info->usage_map[kTemporary]);
    296 }
    297 
    298 // Verifies that the CannedBrowsingDataFileSystemHelper correctly ignores
    299 // extension and devtools schemes.
    300 TEST_F(BrowsingDataFileSystemHelperTest, IgnoreExtensionsAndDevTools) {
    301   ASSERT_TRUE(canned_helper_->empty());
    302   canned_helper_->AddFileSystem(kOriginExt, kTemporary, 0);
    303   ASSERT_TRUE(canned_helper_->empty());
    304   canned_helper_->AddFileSystem(kOriginDevTools, kTemporary, 0);
    305   ASSERT_TRUE(canned_helper_->empty());
    306 }
    307 
    308 }  // namespace
    309