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.
5 #include "testing/gtest/include/gtest/gtest.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"
23 using content::BrowserContext
;
24 using content::BrowserThread
;
28 // Shorter names for fileapi::* constants.
29 const fileapi::FileSystemType kTemporary
= fileapi::kFileSystemTypeTemporary
;
30 const fileapi::FileSystemType kPersistent
= fileapi::kFileSystemTypePersistent
;
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/";
38 // Extensions and Devtools should be ignored.
39 const char kTestOriginExt
[] = "chrome-extension://abcdefghijklmnopqrstuvwxyz/";
40 const char kTestOriginDevTools
[] = "chrome-devtools://abcdefghijklmnopqrstuvw/";
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
);
48 // TODO(mkwst): Update this size once the discussion in http://crbug.com/86114
50 const int kEmptyFileSystemSize
= 0;
52 typedef std::list
<BrowsingDataFileSystemHelper::FileSystemInfo
>
54 typedef scoped_ptr
<FileSystemInfoList
> ScopedFileSystemInfoList
;
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
63 class BrowsingDataFileSystemHelperTest
: public testing::Test
{
65 BrowsingDataFileSystemHelperTest() {
66 profile_
.reset(new TestingProfile());
68 helper_
= BrowsingDataFileSystemHelper::Create(
69 BrowserContext::GetDefaultStoragePartition(profile_
.get())->
70 GetFileSystemContext());
71 base::MessageLoop::current()->RunUntilIdle();
72 canned_helper_
= new CannedBrowsingDataFileSystemHelper(profile_
.get());
74 virtual ~BrowsingDataFileSystemHelperTest() {
75 // Avoid memory leaks.
77 base::MessageLoop::current()->RunUntilIdle();
80 TestingProfile
* GetProfile() {
81 return profile_
.get();
84 // Blocks on the current MessageLoop until Notify() is called.
85 void BlockUntilNotified() {
86 base::MessageLoop::current()->Run();
89 // Unblocks the current MessageLoop. Should be called in response to some sort
90 // of async activity in a callback method.
92 base::MessageLoop::current()->Quit();
95 // Callback that should be executed in response to
96 // fileapi::FileSystemContext::OpenFileSystem.
97 void OpenFileSystemCallback(const GURL
& root
,
98 const std::string
& name
,
99 base::PlatformFileError error
) {
100 open_file_system_result_
= error
;
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
,
111 &BrowsingDataFileSystemHelperTest::OpenFileSystemCallback
,
112 base::Unretained(this)));
113 BlockUntilNotified();
114 return open_file_system_result_
== base::PLATFORM_FILE_OK
;
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
);
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
));
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();
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();
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
);
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
));
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_
);
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();
189 content::TestBrowserThreadBundle thread_bundle_
;
190 scoped_ptr
<TestingProfile
> profile_
;
192 // Temporary storage to pass information back from callbacks.
193 base::PlatformFileError open_file_system_result_
;
194 ScopedFileSystemInfoList file_system_info_list_
;
196 scoped_refptr
<BrowsingDataFileSystemHelper
> helper_
;
197 scoped_refptr
<CannedBrowsingDataFileSystemHelper
> canned_helper_
;
199 DISALLOW_COPY_AND_ASSIGN(BrowsingDataFileSystemHelperTest
);
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();
209 EXPECT_EQ(3UL, file_system_info_list_
->size());
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();
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
]);
237 ADD_FAILURE() << info
->origin
.spec() << " isn't an origin we added.";
240 for (size_t i
= 0; i
< arraysize(test_hosts_found
); i
++) {
241 EXPECT_TRUE(test_hosts_found
[i
]);
245 // Verifies that the BrowsingDataFileSystemHelper correctly deletes file
246 // systems via DeleteFileSystemOrigin().
247 TEST_F(BrowsingDataFileSystemHelperTest
, DeleteData
) {
248 PopulateTestFileSystemData();
250 helper_
->DeleteFileSystemOrigin(kOrigin1
);
251 helper_
->DeleteFileSystemOrigin(kOrigin2
);
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
]);
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());
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);
281 FetchCannedFileSystems();
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
]);
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
]);
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());