• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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/bind.h"
6 #include "base/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/run_loop.h"
9 #include "content/public/test/async_file_test_helper.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "webkit/browser/fileapi/file_system_backend.h"
12 #include "webkit/browser/fileapi/file_system_context.h"
13 #include "webkit/browser/fileapi/file_system_operation_runner.h"
14 #include "webkit/browser/fileapi/file_system_url.h"
15 #include "webkit/browser/quota/quota_manager.h"
16 #include "webkit/common/fileapi/file_system_util.h"
17 
18 namespace content {
19 
20 typedef fileapi::FileSystemOperation::FileEntryList FileEntryList;
21 
22 namespace {
23 
AssignAndQuit(base::RunLoop * run_loop,base::File::Error * result_out,base::File::Error result)24 void AssignAndQuit(base::RunLoop* run_loop,
25                    base::File::Error* result_out,
26                    base::File::Error result) {
27   *result_out = result;
28   run_loop->Quit();
29 }
30 
31 base::Callback<void(base::File::Error)>
AssignAndQuitCallback(base::RunLoop * run_loop,base::File::Error * result)32 AssignAndQuitCallback(base::RunLoop* run_loop,
33                       base::File::Error* result) {
34   return base::Bind(&AssignAndQuit, run_loop, base::Unretained(result));
35 }
36 
GetMetadataCallback(base::RunLoop * run_loop,base::File::Error * result_out,base::File::Info * file_info_out,base::File::Error result,const base::File::Info & file_info)37 void GetMetadataCallback(base::RunLoop* run_loop,
38                          base::File::Error* result_out,
39                          base::File::Info* file_info_out,
40                          base::File::Error result,
41                          const base::File::Info& file_info) {
42   *result_out = result;
43   if (file_info_out)
44     *file_info_out = file_info;
45   run_loop->Quit();
46 }
47 
CreateSnapshotFileCallback(base::RunLoop * run_loop,base::File::Error * result_out,base::FilePath * platform_path_out,base::File::Error result,const base::File::Info & file_info,const base::FilePath & platform_path,const scoped_refptr<webkit_blob::ShareableFileReference> & file_ref)48 void CreateSnapshotFileCallback(
49     base::RunLoop* run_loop,
50     base::File::Error* result_out,
51     base::FilePath* platform_path_out,
52     base::File::Error result,
53     const base::File::Info& file_info,
54     const base::FilePath& platform_path,
55     const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
56   DCHECK(!file_ref.get());
57   *result_out = result;
58   if (platform_path_out)
59     *platform_path_out = platform_path;
60   run_loop->Quit();
61 }
62 
ReadDirectoryCallback(base::RunLoop * run_loop,base::File::Error * result_out,FileEntryList * entries_out,base::File::Error result,const FileEntryList & entries,bool has_more)63 void ReadDirectoryCallback(base::RunLoop* run_loop,
64                            base::File::Error* result_out,
65                            FileEntryList* entries_out,
66                            base::File::Error result,
67                            const FileEntryList& entries,
68                            bool has_more) {
69   *result_out = result;
70   entries_out->insert(entries_out->end(), entries.begin(), entries.end());
71   if (result != base::File::FILE_OK || !has_more)
72     run_loop->Quit();
73 }
74 
DidGetUsageAndQuota(quota::QuotaStatusCode * status_out,int64 * usage_out,int64 * quota_out,quota::QuotaStatusCode status,int64 usage,int64 quota)75 void DidGetUsageAndQuota(quota::QuotaStatusCode* status_out,
76                          int64* usage_out,
77                          int64* quota_out,
78                          quota::QuotaStatusCode status,
79                          int64 usage,
80                          int64 quota) {
81   if (status_out)
82     *status_out = status;
83   if (usage_out)
84     *usage_out = usage;
85   if (quota_out)
86     *quota_out = quota;
87 }
88 
89 }  // namespace
90 
91 const int64 AsyncFileTestHelper::kDontCheckSize = -1;
92 
Copy(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & src,const fileapi::FileSystemURL & dest)93 base::File::Error AsyncFileTestHelper::Copy(
94     fileapi::FileSystemContext* context,
95     const fileapi::FileSystemURL& src,
96     const fileapi::FileSystemURL& dest) {
97   return CopyWithProgress(context, src, dest, CopyProgressCallback());
98 }
99 
CopyWithProgress(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & src,const fileapi::FileSystemURL & dest,const CopyProgressCallback & progress_callback)100 base::File::Error AsyncFileTestHelper::CopyWithProgress(
101     fileapi::FileSystemContext* context,
102     const fileapi::FileSystemURL& src,
103     const fileapi::FileSystemURL& dest,
104     const CopyProgressCallback& progress_callback) {
105   base::File::Error result = base::File::FILE_ERROR_FAILED;
106   base::RunLoop run_loop;
107   context->operation_runner()->Copy(
108       src, dest, fileapi::FileSystemOperation::OPTION_NONE, progress_callback,
109       AssignAndQuitCallback(&run_loop, &result));
110   run_loop.Run();
111   return result;
112 }
113 
Move(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & src,const fileapi::FileSystemURL & dest)114 base::File::Error AsyncFileTestHelper::Move(
115     fileapi::FileSystemContext* context,
116     const fileapi::FileSystemURL& src,
117     const fileapi::FileSystemURL& dest) {
118   base::File::Error result = base::File::FILE_ERROR_FAILED;
119   base::RunLoop run_loop;
120   context->operation_runner()->Move(
121       src, dest, fileapi::FileSystemOperation::OPTION_NONE,
122       AssignAndQuitCallback(&run_loop, &result));
123   run_loop.Run();
124   return result;
125 }
126 
Remove(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url,bool recursive)127 base::File::Error AsyncFileTestHelper::Remove(
128     fileapi::FileSystemContext* context,
129     const fileapi::FileSystemURL& url,
130     bool recursive) {
131   base::File::Error result = base::File::FILE_ERROR_FAILED;
132   base::RunLoop run_loop;
133   context->operation_runner()->Remove(
134       url, recursive, AssignAndQuitCallback(&run_loop, &result));
135   run_loop.Run();
136   return result;
137 }
138 
ReadDirectory(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url,FileEntryList * entries)139 base::File::Error AsyncFileTestHelper::ReadDirectory(
140     fileapi::FileSystemContext* context,
141     const fileapi::FileSystemURL& url,
142     FileEntryList* entries) {
143   base::File::Error result = base::File::FILE_ERROR_FAILED;
144   DCHECK(entries);
145   entries->clear();
146   base::RunLoop run_loop;
147   context->operation_runner()->ReadDirectory(
148       url, base::Bind(&ReadDirectoryCallback, &run_loop, &result, entries));
149   run_loop.Run();
150   return result;
151 }
152 
CreateDirectory(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url)153 base::File::Error AsyncFileTestHelper::CreateDirectory(
154     fileapi::FileSystemContext* context,
155     const fileapi::FileSystemURL& url) {
156   base::File::Error result = base::File::FILE_ERROR_FAILED;
157   base::RunLoop run_loop;
158   context->operation_runner()->CreateDirectory(
159       url,
160       false /* exclusive */,
161       false /* recursive */,
162       AssignAndQuitCallback(&run_loop, &result));
163   run_loop.Run();
164   return result;
165 }
166 
CreateFile(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url)167 base::File::Error AsyncFileTestHelper::CreateFile(
168     fileapi::FileSystemContext* context,
169     const fileapi::FileSystemURL& url) {
170   base::File::Error result = base::File::FILE_ERROR_FAILED;
171   base::RunLoop run_loop;
172   context->operation_runner()->CreateFile(
173       url, false /* exclusive */,
174       AssignAndQuitCallback(&run_loop, &result));
175   run_loop.Run();
176   return result;
177 }
178 
CreateFileWithData(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url,const char * buf,int buf_size)179 base::File::Error AsyncFileTestHelper::CreateFileWithData(
180     fileapi::FileSystemContext* context,
181     const fileapi::FileSystemURL& url,
182     const char* buf,
183     int buf_size) {
184   base::ScopedTempDir dir;
185   if (!dir.CreateUniqueTempDir())
186     return base::File::FILE_ERROR_FAILED;
187   base::FilePath local_path = dir.path().AppendASCII("tmp");
188   if (buf_size != base::WriteFile(local_path, buf, buf_size))
189     return base::File::FILE_ERROR_FAILED;
190   base::File::Error result = base::File::FILE_ERROR_FAILED;
191   base::RunLoop run_loop;
192   context->operation_runner()->CopyInForeignFile(
193       local_path, url, AssignAndQuitCallback(&run_loop, &result));
194   run_loop.Run();
195   return result;
196 }
197 
TruncateFile(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url,size_t size)198 base::File::Error AsyncFileTestHelper::TruncateFile(
199     fileapi::FileSystemContext* context,
200     const fileapi::FileSystemURL& url,
201     size_t size) {
202   base::RunLoop run_loop;
203   base::File::Error result = base::File::FILE_ERROR_FAILED;
204   context->operation_runner()->Truncate(
205       url, size, AssignAndQuitCallback(&run_loop, &result));
206   run_loop.Run();
207   return result;
208 }
209 
GetMetadata(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url,base::File::Info * file_info)210 base::File::Error AsyncFileTestHelper::GetMetadata(
211     fileapi::FileSystemContext* context,
212     const fileapi::FileSystemURL& url,
213     base::File::Info* file_info) {
214   base::File::Error result = base::File::FILE_ERROR_FAILED;
215   base::RunLoop run_loop;
216   context->operation_runner()->GetMetadata(
217       url, base::Bind(&GetMetadataCallback, &run_loop, &result,
218                       file_info));
219   run_loop.Run();
220   return result;
221 }
222 
GetPlatformPath(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url,base::FilePath * platform_path)223 base::File::Error AsyncFileTestHelper::GetPlatformPath(
224     fileapi::FileSystemContext* context,
225     const fileapi::FileSystemURL& url,
226     base::FilePath* platform_path) {
227   base::File::Error result = base::File::FILE_ERROR_FAILED;
228   base::RunLoop run_loop;
229   context->operation_runner()->CreateSnapshotFile(
230       url, base::Bind(&CreateSnapshotFileCallback, &run_loop, &result,
231                       platform_path));
232   run_loop.Run();
233   return result;
234 }
235 
FileExists(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url,int64 expected_size)236 bool AsyncFileTestHelper::FileExists(
237     fileapi::FileSystemContext* context,
238     const fileapi::FileSystemURL& url,
239     int64 expected_size) {
240   base::File::Info file_info;
241   base::File::Error result = GetMetadata(context, url, &file_info);
242   if (result != base::File::FILE_OK || file_info.is_directory)
243     return false;
244   return expected_size == kDontCheckSize || file_info.size == expected_size;
245 }
246 
DirectoryExists(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & url)247 bool AsyncFileTestHelper::DirectoryExists(
248     fileapi::FileSystemContext* context,
249     const fileapi::FileSystemURL& url) {
250   base::File::Info file_info;
251   base::File::Error result = GetMetadata(context, url, &file_info);
252   return (result == base::File::FILE_OK) && file_info.is_directory;
253 }
254 
GetUsageAndQuota(quota::QuotaManager * quota_manager,const GURL & origin,fileapi::FileSystemType type,int64 * usage,int64 * quota)255 quota::QuotaStatusCode AsyncFileTestHelper::GetUsageAndQuota(
256     quota::QuotaManager* quota_manager,
257     const GURL& origin,
258     fileapi::FileSystemType type,
259     int64* usage,
260     int64* quota) {
261   quota::QuotaStatusCode status = quota::kQuotaStatusUnknown;
262   quota_manager->GetUsageAndQuota(
263       origin,
264       FileSystemTypeToQuotaStorageType(type),
265       base::Bind(&DidGetUsageAndQuota, &status, usage, quota));
266   base::RunLoop().RunUntilIdle();
267   return status;
268 }
269 
270 }  // namespace fileapi
271