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