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/files/file_util.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/stl_util.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "chrome/browser/browsing_data/browsing_data_file_system_helper.h" 14 #include "chrome/test/base/testing_profile.h" 15 #include "content/public/browser/storage_partition.h" 16 #include "content/public/test/test_browser_thread.h" 17 #include "content/public/test/test_browser_thread_bundle.h" 18 #include "storage/browser/fileapi/file_system_context.h" 19 #include "storage/browser/fileapi/file_system_url.h" 20 #include "storage/common/fileapi/file_system_types.h" 21 22 using content::BrowserContext; 23 using content::BrowserThread; 24 25 namespace { 26 27 // Shorter names for storage::* constants. 28 const storage::FileSystemType kTemporary = storage::kFileSystemTypeTemporary; 29 const storage::FileSystemType kPersistent = storage::kFileSystemTypePersistent; 30 31 // We'll use these three distinct origins for testing, both as strings and as 32 // GURLs in appropriate contexts. 33 const char kTestOrigin1[] = "http://host1:1/"; 34 const char kTestOrigin2[] = "http://host2:2/"; 35 const char kTestOrigin3[] = "http://host3:3/"; 36 37 // Extensions and Devtools should be ignored. 38 const char kTestOriginExt[] = "chrome-extension://abcdefghijklmnopqrstuvwxyz/"; 39 const char kTestOriginDevTools[] = "chrome-devtools://abcdefghijklmnopqrstuvw/"; 40 41 const GURL kOrigin1(kTestOrigin1); 42 const GURL kOrigin2(kTestOrigin2); 43 const GURL kOrigin3(kTestOrigin3); 44 const GURL kOriginExt(kTestOriginExt); 45 const GURL kOriginDevTools(kTestOriginDevTools); 46 47 // TODO(mkwst): Update this size once the discussion in http://crbug.com/86114 48 // is concluded. 49 const int kEmptyFileSystemSize = 0; 50 51 typedef std::list<BrowsingDataFileSystemHelper::FileSystemInfo> 52 FileSystemInfoList; 53 typedef scoped_ptr<FileSystemInfoList> ScopedFileSystemInfoList; 54 55 // The FileSystem APIs are all asynchronous; this testing class wraps up the 56 // boilerplate code necessary to deal with waiting for responses. In a nutshell, 57 // any async call whose response we want to test ought to be followed by a call 58 // to BlockUntilNotified(), which will (shockingly!) block until Notify() is 59 // called. For this to work, you'll need to ensure that each async call is 60 // implemented as a class method that that calls Notify() at an appropriate 61 // point. 62 class BrowsingDataFileSystemHelperTest : public testing::Test { 63 public: 64 BrowsingDataFileSystemHelperTest() { 65 profile_.reset(new TestingProfile()); 66 67 helper_ = BrowsingDataFileSystemHelper::Create( 68 BrowserContext::GetDefaultStoragePartition(profile_.get())-> 69 GetFileSystemContext()); 70 base::MessageLoop::current()->RunUntilIdle(); 71 canned_helper_ = new CannedBrowsingDataFileSystemHelper(profile_.get()); 72 } 73 virtual ~BrowsingDataFileSystemHelperTest() { 74 // Avoid memory leaks. 75 profile_.reset(); 76 base::MessageLoop::current()->RunUntilIdle(); 77 } 78 79 TestingProfile* GetProfile() { 80 return profile_.get(); 81 } 82 83 // Blocks on the current MessageLoop until Notify() is called. 84 void BlockUntilNotified() { 85 base::MessageLoop::current()->Run(); 86 } 87 88 // Unblocks the current MessageLoop. Should be called in response to some sort 89 // of async activity in a callback method. 90 void Notify() { 91 base::MessageLoop::current()->Quit(); 92 } 93 94 // Callback that should be executed in response to 95 // storage::FileSystemContext::OpenFileSystem. 96 void OpenFileSystemCallback(const GURL& root, 97 const std::string& name, 98 base::File::Error error) { 99 open_file_system_result_ = error; 100 Notify(); 101 } 102 103 bool OpenFileSystem(const GURL& origin, 104 storage::FileSystemType type, 105 storage::OpenFileSystemMode open_mode) { 106 BrowserContext::GetDefaultStoragePartition(profile_.get())-> 107 GetFileSystemContext()->OpenFileSystem( 108 origin, type, open_mode, 109 base::Bind( 110 &BrowsingDataFileSystemHelperTest::OpenFileSystemCallback, 111 base::Unretained(this))); 112 BlockUntilNotified(); 113 return open_file_system_result_ == base::File::FILE_OK; 114 } 115 116 // Calls storage::FileSystemContext::OpenFileSystem with 117 // OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT flag 118 // to verify the existence of a file system for a specified type and origin, 119 // blocks until a response is available, then returns the result 120 // synchronously to it's caller. 121 bool FileSystemContainsOriginAndType(const GURL& origin, 122 storage::FileSystemType type) { 123 return OpenFileSystem( 124 origin, type, storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT); 125 } 126 127 // Callback that should be executed in response to StartFetching(), and stores 128 // found file systems locally so that they are available via GetFileSystems(). 129 void CallbackStartFetching( 130 const std::list<BrowsingDataFileSystemHelper::FileSystemInfo>& 131 file_system_info_list) { 132 file_system_info_list_.reset( 133 new std::list<BrowsingDataFileSystemHelper::FileSystemInfo>( 134 file_system_info_list)); 135 Notify(); 136 } 137 138 // Calls StartFetching() on the test's BrowsingDataFileSystemHelper 139 // object, then blocks until the callback is executed. 140 void FetchFileSystems() { 141 helper_->StartFetching( 142 base::Bind(&BrowsingDataFileSystemHelperTest::CallbackStartFetching, 143 base::Unretained(this))); 144 BlockUntilNotified(); 145 } 146 147 // Calls StartFetching() on the test's CannedBrowsingDataFileSystemHelper 148 // object, then blocks until the callback is executed. 149 void FetchCannedFileSystems() { 150 canned_helper_->StartFetching( 151 base::Bind(&BrowsingDataFileSystemHelperTest::CallbackStartFetching, 152 base::Unretained(this))); 153 BlockUntilNotified(); 154 } 155 156 // Sets up kOrigin1 with a temporary file system, kOrigin2 with a persistent 157 // file system, and kOrigin3 with both. 158 virtual void PopulateTestFileSystemData() { 159 CreateDirectoryForOriginAndType(kOrigin1, kTemporary); 160 CreateDirectoryForOriginAndType(kOrigin2, kPersistent); 161 CreateDirectoryForOriginAndType(kOrigin3, kTemporary); 162 CreateDirectoryForOriginAndType(kOrigin3, kPersistent); 163 164 EXPECT_FALSE(FileSystemContainsOriginAndType(kOrigin1, kPersistent)); 165 EXPECT_TRUE(FileSystemContainsOriginAndType(kOrigin1, kTemporary)); 166 EXPECT_TRUE(FileSystemContainsOriginAndType(kOrigin2, kPersistent)); 167 EXPECT_FALSE(FileSystemContainsOriginAndType(kOrigin2, kTemporary)); 168 EXPECT_TRUE(FileSystemContainsOriginAndType(kOrigin3, kPersistent)); 169 EXPECT_TRUE(FileSystemContainsOriginAndType(kOrigin3, kTemporary)); 170 } 171 172 // Calls OpenFileSystem with OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT 173 // to create a filesystem of a given type for a specified origin. 174 void CreateDirectoryForOriginAndType(const GURL& origin, 175 storage::FileSystemType type) { 176 OpenFileSystem( 177 origin, type, storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT); 178 EXPECT_EQ(base::File::FILE_OK, open_file_system_result_); 179 } 180 181 // Returns a list of the FileSystemInfo objects gathered in the most recent 182 // call to StartFetching(). 183 FileSystemInfoList* GetFileSystems() { 184 return file_system_info_list_.get(); 185 } 186 187 protected: 188 content::TestBrowserThreadBundle thread_bundle_; 189 scoped_ptr<TestingProfile> profile_; 190 191 // Temporary storage to pass information back from callbacks. 192 base::File::Error open_file_system_result_; 193 ScopedFileSystemInfoList file_system_info_list_; 194 195 scoped_refptr<BrowsingDataFileSystemHelper> helper_; 196 scoped_refptr<CannedBrowsingDataFileSystemHelper> canned_helper_; 197 198 private: 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[storage::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