OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/browser/fileapi/sandbox_file_system_backend.h" | 5 #include "webkit/browser/fileapi/sandbox_file_system_backend.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
12 #include "base/stl_util.h" | |
13 #include "base/task_runner_util.h" | 11 #include "base/task_runner_util.h" |
14 #include "net/base/net_util.h" | |
15 #include "url/gurl.h" | 12 #include "url/gurl.h" |
16 #include "webkit/browser/fileapi/async_file_util_adapter.h" | 13 #include "webkit/browser/fileapi/async_file_util_adapter.h" |
17 #include "webkit/browser/fileapi/copy_or_move_file_validator.h" | 14 #include "webkit/browser/fileapi/copy_or_move_file_validator.h" |
18 #include "webkit/browser/fileapi/file_system_context.h" | 15 #include "webkit/browser/fileapi/file_system_context.h" |
19 #include "webkit/browser/fileapi/file_system_file_stream_reader.h" | 16 #include "webkit/browser/fileapi/file_system_file_stream_reader.h" |
20 #include "webkit/browser/fileapi/file_system_operation_context.h" | 17 #include "webkit/browser/fileapi/file_system_operation_context.h" |
21 #include "webkit/browser/fileapi/file_system_options.h" | 18 #include "webkit/browser/fileapi/file_system_options.h" |
22 #include "webkit/browser/fileapi/file_system_task_runners.h" | 19 #include "webkit/browser/fileapi/file_system_task_runners.h" |
23 #include "webkit/browser/fileapi/file_system_usage_cache.h" | |
24 #include "webkit/browser/fileapi/local_file_system_operation.h" | 20 #include "webkit/browser/fileapi/local_file_system_operation.h" |
25 #include "webkit/browser/fileapi/obfuscated_file_util.h" | 21 #include "webkit/browser/fileapi/obfuscated_file_util.h" |
26 #include "webkit/browser/fileapi/sandbox_context.h" | 22 #include "webkit/browser/fileapi/sandbox_context.h" |
27 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h" | 23 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h" |
28 #include "webkit/browser/fileapi/sandbox_quota_observer.h" | 24 #include "webkit/browser/fileapi/sandbox_quota_observer.h" |
29 #include "webkit/browser/fileapi/syncable/syncable_file_system_operation.h" | 25 #include "webkit/browser/fileapi/syncable/syncable_file_system_operation.h" |
30 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h" | 26 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h" |
31 #include "webkit/browser/quota/quota_manager.h" | 27 #include "webkit/browser/quota/quota_manager.h" |
32 #include "webkit/common/fileapi/file_system_types.h" | 28 #include "webkit/common/fileapi/file_system_types.h" |
33 #include "webkit/common/fileapi/file_system_util.h" | 29 #include "webkit/common/fileapi/file_system_util.h" |
(...skipping 17 matching lines...) Expand all Loading... |
51 kInvalidSchemeError, | 47 kInvalidSchemeError, |
52 kCreateDirectoryError, | 48 kCreateDirectoryError, |
53 kNotFound, | 49 kNotFound, |
54 kUnknownError, | 50 kUnknownError, |
55 kFileSystemErrorMax, | 51 kFileSystemErrorMax, |
56 }; | 52 }; |
57 | 53 |
58 const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount"; | 54 const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount"; |
59 const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount"; | 55 const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount"; |
60 | 56 |
61 // Restricted names. | |
62 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions | |
63 const base::FilePath::CharType* const kRestrictedNames[] = { | |
64 FILE_PATH_LITERAL("."), FILE_PATH_LITERAL(".."), | |
65 }; | |
66 | |
67 // Restricted chars. | |
68 const base::FilePath::CharType kRestrictedChars[] = { | |
69 FILE_PATH_LITERAL('/'), FILE_PATH_LITERAL('\\'), | |
70 }; | |
71 | |
72 class ObfuscatedOriginEnumerator | |
73 : public SandboxFileSystemBackend::OriginEnumerator { | |
74 public: | |
75 explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) { | |
76 enum_.reset(file_util->CreateOriginEnumerator()); | |
77 } | |
78 virtual ~ObfuscatedOriginEnumerator() {} | |
79 | |
80 virtual GURL Next() OVERRIDE { | |
81 return enum_->Next(); | |
82 } | |
83 | |
84 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { | |
85 return enum_->HasFileSystemType(type); | |
86 } | |
87 | |
88 private: | |
89 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_; | |
90 }; | |
91 | |
92 void DidOpenFileSystem( | 57 void DidOpenFileSystem( |
93 base::WeakPtr<SandboxFileSystemBackend> sandbox_backend, | 58 base::WeakPtr<SandboxFileSystemBackend> sandbox_backend, |
94 const base::Callback<void(base::PlatformFileError error)>& callback, | 59 const base::Callback<void(base::PlatformFileError error)>& callback, |
95 base::PlatformFileError* error) { | 60 base::PlatformFileError* error) { |
96 if (sandbox_backend.get()) | 61 if (sandbox_backend.get()) |
97 sandbox_backend.get()->CollectOpenFileSystemMetrics(*error); | 62 sandbox_backend.get()->CollectOpenFileSystemMetrics(*error); |
98 callback.Run(*error); | 63 callback.Run(*error); |
99 } | 64 } |
100 | 65 |
101 void OpenFileSystemOnFileThread( | 66 void OpenFileSystemOnFileThread( |
(...skipping 13 matching lines...) Expand all Loading... |
115 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kOK, kFileSystemErrorMax); | 80 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kOK, kFileSystemErrorMax); |
116 } | 81 } |
117 // The reference of file_util will be derefed on the FILE thread | 82 // The reference of file_util will be derefed on the FILE thread |
118 // when the storage of this callback gets deleted regardless of whether | 83 // when the storage of this callback gets deleted regardless of whether |
119 // this method is called or not. | 84 // this method is called or not. |
120 } | 85 } |
121 | 86 |
122 } // anonymous namespace | 87 } // anonymous namespace |
123 | 88 |
124 SandboxFileSystemBackend::SandboxFileSystemBackend( | 89 SandboxFileSystemBackend::SandboxFileSystemBackend( |
125 SandboxContext* sandbox_context, | 90 SandboxContext* sandbox_context) |
126 const FileSystemOptions& file_system_options) | 91 : sandbox_context_(sandbox_context), |
127 : file_system_options_(file_system_options), | |
128 sandbox_context_(sandbox_context), | |
129 enable_temporary_file_system_in_incognito_(false), | 92 enable_temporary_file_system_in_incognito_(false), |
130 weak_factory_(this) { | 93 weak_factory_(this) { |
131 } | 94 } |
132 | 95 |
133 SandboxFileSystemBackend::~SandboxFileSystemBackend() { | 96 SandboxFileSystemBackend::~SandboxFileSystemBackend() { |
134 } | 97 } |
135 | 98 |
136 bool SandboxFileSystemBackend::CanHandleType(FileSystemType type) const { | 99 bool SandboxFileSystemBackend::CanHandleType(FileSystemType type) const { |
137 return type == kFileSystemTypeTemporary || | 100 return type == kFileSystemTypeTemporary || |
138 type == kFileSystemTypePersistent || | 101 type == kFileSystemTypePersistent || |
(...skipping 10 matching lines...) Expand all Loading... |
149 sandbox_context_->quota_observer(), NULL); | 112 sandbox_context_->quota_observer(), NULL); |
150 | 113 |
151 syncable_update_observers_ = update_observers_; | 114 syncable_update_observers_ = update_observers_; |
152 | 115 |
153 if (!sandbox_context_->file_task_runner()->RunsTasksOnCurrentThread()) { | 116 if (!sandbox_context_->file_task_runner()->RunsTasksOnCurrentThread()) { |
154 // Post prepopulate task only if it's not already running on | 117 // Post prepopulate task only if it's not already running on |
155 // file_task_runner (which implies running in tests). | 118 // file_task_runner (which implies running in tests). |
156 sandbox_context_->file_task_runner()->PostTask( | 119 sandbox_context_->file_task_runner()->PostTask( |
157 FROM_HERE, | 120 FROM_HERE, |
158 base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase, | 121 base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase, |
159 base::Unretained(sandbox_sync_file_util()))); | 122 base::Unretained(sandbox_context_->sync_file_util()))); |
160 } | 123 } |
161 } | 124 } |
162 | 125 |
163 void SandboxFileSystemBackend::OpenFileSystem( | 126 void SandboxFileSystemBackend::OpenFileSystem( |
164 const GURL& origin_url, | 127 const GURL& origin_url, |
165 fileapi::FileSystemType type, | 128 fileapi::FileSystemType type, |
166 OpenFileSystemMode mode, | 129 OpenFileSystemMode mode, |
167 const OpenFileSystemCallback& callback) { | 130 const OpenFileSystemCallback& callback) { |
168 if (file_system_options_.is_incognito() && | 131 DCHECK(CanHandleType(type)); |
| 132 DCHECK(sandbox_context_); |
| 133 if (sandbox_context_->file_system_options().is_incognito() && |
169 !(type == kFileSystemTypeTemporary && | 134 !(type == kFileSystemTypeTemporary && |
170 enable_temporary_file_system_in_incognito_)) { | 135 enable_temporary_file_system_in_incognito_)) { |
171 // TODO(kinuko): return an isolated temporary directory. | 136 // TODO(kinuko): return an isolated temporary directory. |
172 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); | 137 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); |
173 return; | 138 return; |
174 } | 139 } |
175 | 140 |
176 if (!IsAllowedScheme(origin_url)) { | 141 if (!sandbox_context_->IsAllowedScheme(origin_url)) { |
177 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); | 142 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); |
178 return; | 143 return; |
179 } | 144 } |
180 | 145 |
181 // TODO(nhiroki): Factor out SyncFS related code to SyncFileSystemBackend we | 146 // TODO(nhiroki): Factor out SyncFS related code to SyncFileSystemBackend we |
182 // plan to introduce. (http://crbug.com/242422/) | 147 // plan to introduce. (http://crbug.com/242422/) |
183 GURL root_url = (type == kFileSystemTypeSyncable) | 148 GURL root_url = (type == kFileSystemTypeSyncable) |
184 ? sync_file_system::GetSyncableFileSystemRootURI(origin_url) | 149 ? sync_file_system::GetSyncableFileSystemRootURI(origin_url) |
185 : GetFileSystemRootURI(origin_url, type); | 150 : GetFileSystemRootURI(origin_url, type); |
186 std::string name = GetFileSystemName(origin_url, type); | 151 std::string name = GetFileSystemName(origin_url, type); |
187 | 152 |
188 base::PlatformFileError* error_ptr = new base::PlatformFileError; | 153 base::PlatformFileError* error_ptr = new base::PlatformFileError; |
189 sandbox_context_->file_task_runner()->PostTaskAndReply( | 154 sandbox_context_->file_task_runner()->PostTaskAndReply( |
190 FROM_HERE, | 155 FROM_HERE, |
191 base::Bind(&OpenFileSystemOnFileThread, | 156 base::Bind(&OpenFileSystemOnFileThread, |
192 sandbox_sync_file_util(), | 157 sandbox_context_->sync_file_util(), |
193 origin_url, type, mode, | 158 origin_url, type, mode, |
194 base::Unretained(error_ptr)), | 159 base::Unretained(error_ptr)), |
195 base::Bind(&DidOpenFileSystem, | 160 base::Bind(&DidOpenFileSystem, |
196 weak_factory_.GetWeakPtr(), | 161 weak_factory_.GetWeakPtr(), |
197 base::Bind(callback, root_url, name), | 162 base::Bind(callback, root_url, name), |
198 base::Owned(error_ptr))); | 163 base::Owned(error_ptr))); |
199 }; | 164 }; |
200 | 165 |
201 FileSystemFileUtil* SandboxFileSystemBackend::GetFileUtil( | 166 FileSystemFileUtil* SandboxFileSystemBackend::GetFileUtil( |
202 FileSystemType type) { | 167 FileSystemType type) { |
(...skipping 13 matching lines...) Expand all Loading... |
216 base::PlatformFileError* error_code) { | 181 base::PlatformFileError* error_code) { |
217 DCHECK(error_code); | 182 DCHECK(error_code); |
218 *error_code = base::PLATFORM_FILE_OK; | 183 *error_code = base::PLATFORM_FILE_OK; |
219 return NULL; | 184 return NULL; |
220 } | 185 } |
221 | 186 |
222 FileSystemOperation* SandboxFileSystemBackend::CreateFileSystemOperation( | 187 FileSystemOperation* SandboxFileSystemBackend::CreateFileSystemOperation( |
223 const FileSystemURL& url, | 188 const FileSystemURL& url, |
224 FileSystemContext* context, | 189 FileSystemContext* context, |
225 base::PlatformFileError* error_code) const { | 190 base::PlatformFileError* error_code) const { |
226 if (!IsAccessValid(url)) { | 191 DCHECK(CanHandleType(url.type())); |
| 192 DCHECK(sandbox_context_); |
| 193 if (!sandbox_context_->IsAccessValid(url)) { |
227 *error_code = base::PLATFORM_FILE_ERROR_SECURITY; | 194 *error_code = base::PLATFORM_FILE_ERROR_SECURITY; |
228 return NULL; | 195 return NULL; |
229 } | 196 } |
230 | 197 |
231 scoped_ptr<FileSystemOperationContext> operation_context( | 198 scoped_ptr<FileSystemOperationContext> operation_context( |
232 new FileSystemOperationContext(context)); | 199 new FileSystemOperationContext(context)); |
233 | 200 |
234 // Copy the observer lists (assuming we only have small number of observers). | 201 // Copy the observer lists (assuming we only have small number of observers). |
235 if (url.type() == kFileSystemTypeSyncable) { | 202 if (url.type() == kFileSystemTypeSyncable) { |
236 operation_context->set_update_observers(syncable_update_observers_); | 203 operation_context->set_update_observers(syncable_update_observers_); |
(...skipping 14 matching lines...) Expand all Loading... |
251 | 218 |
252 return new LocalFileSystemOperation(url, context, operation_context.Pass()); | 219 return new LocalFileSystemOperation(url, context, operation_context.Pass()); |
253 } | 220 } |
254 | 221 |
255 scoped_ptr<webkit_blob::FileStreamReader> | 222 scoped_ptr<webkit_blob::FileStreamReader> |
256 SandboxFileSystemBackend::CreateFileStreamReader( | 223 SandboxFileSystemBackend::CreateFileStreamReader( |
257 const FileSystemURL& url, | 224 const FileSystemURL& url, |
258 int64 offset, | 225 int64 offset, |
259 const base::Time& expected_modification_time, | 226 const base::Time& expected_modification_time, |
260 FileSystemContext* context) const { | 227 FileSystemContext* context) const { |
261 if (!IsAccessValid(url)) | 228 DCHECK(CanHandleType(url.type())); |
| 229 DCHECK(sandbox_context_); |
| 230 if (!sandbox_context_->IsAccessValid(url)) |
262 return scoped_ptr<webkit_blob::FileStreamReader>(); | 231 return scoped_ptr<webkit_blob::FileStreamReader>(); |
263 return scoped_ptr<webkit_blob::FileStreamReader>( | 232 return scoped_ptr<webkit_blob::FileStreamReader>( |
264 new FileSystemFileStreamReader( | 233 new FileSystemFileStreamReader( |
265 context, url, offset, expected_modification_time)); | 234 context, url, offset, expected_modification_time)); |
266 } | 235 } |
267 | 236 |
268 scoped_ptr<fileapi::FileStreamWriter> | 237 scoped_ptr<fileapi::FileStreamWriter> |
269 SandboxFileSystemBackend::CreateFileStreamWriter( | 238 SandboxFileSystemBackend::CreateFileStreamWriter( |
270 const FileSystemURL& url, | 239 const FileSystemURL& url, |
271 int64 offset, | 240 int64 offset, |
272 FileSystemContext* context) const { | 241 FileSystemContext* context) const { |
273 if (!IsAccessValid(url)) | 242 DCHECK(CanHandleType(url.type())); |
| 243 DCHECK(sandbox_context_); |
| 244 if (!sandbox_context_->IsAccessValid(url)) |
274 return scoped_ptr<fileapi::FileStreamWriter>(); | 245 return scoped_ptr<fileapi::FileStreamWriter>(); |
275 return scoped_ptr<fileapi::FileStreamWriter>( | 246 return scoped_ptr<fileapi::FileStreamWriter>( |
276 new SandboxFileStreamWriter(context, url, offset, update_observers_)); | 247 new SandboxFileStreamWriter(context, url, offset, update_observers_)); |
277 } | 248 } |
278 | 249 |
279 FileSystemQuotaUtil* SandboxFileSystemBackend::GetQuotaUtil() { | 250 FileSystemQuotaUtil* SandboxFileSystemBackend::GetQuotaUtil() { |
280 return this; | 251 return this; |
281 } | 252 } |
282 | 253 |
283 SandboxFileSystemBackend::OriginEnumerator* | 254 SandboxContext::OriginEnumerator* |
284 SandboxFileSystemBackend::CreateOriginEnumerator() { | 255 SandboxFileSystemBackend::CreateOriginEnumerator() { |
285 return new ObfuscatedOriginEnumerator(sandbox_sync_file_util()); | 256 DCHECK(sandbox_context_); |
286 } | 257 return sandbox_context_->CreateOriginEnumerator(); |
287 | |
288 base::FilePath SandboxFileSystemBackend::GetBaseDirectoryForOriginAndType( | |
289 const GURL& origin_url, fileapi::FileSystemType type, bool create) { | |
290 base::PlatformFileError error = base::PLATFORM_FILE_OK; | |
291 base::FilePath path = sandbox_sync_file_util()->GetDirectoryForOriginAndType( | |
292 origin_url, type, create, &error); | |
293 if (error != base::PLATFORM_FILE_OK) | |
294 return base::FilePath(); | |
295 return path; | |
296 } | 258 } |
297 | 259 |
298 base::PlatformFileError | 260 base::PlatformFileError |
299 SandboxFileSystemBackend::DeleteOriginDataOnFileThread( | 261 SandboxFileSystemBackend::DeleteOriginDataOnFileThread( |
300 FileSystemContext* file_system_context, | 262 FileSystemContext* file_system_context, |
301 QuotaManagerProxy* proxy, | 263 QuotaManagerProxy* proxy, |
302 const GURL& origin_url, | 264 const GURL& origin_url, |
303 fileapi::FileSystemType type) { | 265 fileapi::FileSystemType type) { |
304 int64 usage = GetOriginUsageOnFileThread(file_system_context, | 266 DCHECK(CanHandleType(type)); |
305 origin_url, type); | 267 DCHECK(sandbox_context_); |
306 | 268 return sandbox_context_->DeleteOriginDataOnFileThread( |
307 usage_cache()->CloseCacheFiles(); | 269 file_system_context, proxy, origin_url, type); |
308 bool result = sandbox_sync_file_util()->DeleteDirectoryForOriginAndType( | |
309 origin_url, type); | |
310 if (result && proxy) { | |
311 proxy->NotifyStorageModified( | |
312 quota::QuotaClient::kFileSystem, | |
313 origin_url, | |
314 FileSystemTypeToQuotaStorageType(type), | |
315 -usage); | |
316 } | |
317 | |
318 if (result) | |
319 return base::PLATFORM_FILE_OK; | |
320 return base::PLATFORM_FILE_ERROR_FAILED; | |
321 } | 270 } |
322 | 271 |
323 void SandboxFileSystemBackend::GetOriginsForTypeOnFileThread( | 272 void SandboxFileSystemBackend::GetOriginsForTypeOnFileThread( |
324 fileapi::FileSystemType type, std::set<GURL>* origins) { | 273 fileapi::FileSystemType type, std::set<GURL>* origins) { |
325 DCHECK(CanHandleType(type)); | 274 DCHECK(CanHandleType(type)); |
326 DCHECK(origins); | 275 DCHECK(sandbox_context_); |
327 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | 276 sandbox_context_->GetOriginsForTypeOnFileThread(type, origins); |
328 GURL origin; | |
329 while (!(origin = enumerator->Next()).is_empty()) { | |
330 if (enumerator->HasFileSystemType(type)) | |
331 origins->insert(origin); | |
332 } | |
333 switch (type) { | 277 switch (type) { |
334 case kFileSystemTypeTemporary: | 278 case kFileSystemTypeTemporary: |
335 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size()); | 279 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size()); |
336 break; | 280 break; |
337 case kFileSystemTypePersistent: | 281 case kFileSystemTypePersistent: |
338 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size()); | 282 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size()); |
339 break; | 283 break; |
340 default: | 284 default: |
341 break; | 285 break; |
342 } | 286 } |
343 } | 287 } |
344 | 288 |
345 void SandboxFileSystemBackend::GetOriginsForHostOnFileThread( | 289 void SandboxFileSystemBackend::GetOriginsForHostOnFileThread( |
346 fileapi::FileSystemType type, const std::string& host, | 290 fileapi::FileSystemType type, const std::string& host, |
347 std::set<GURL>* origins) { | 291 std::set<GURL>* origins) { |
348 DCHECK(CanHandleType(type)); | 292 DCHECK(CanHandleType(type)); |
349 DCHECK(origins); | 293 DCHECK(sandbox_context_); |
350 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | 294 sandbox_context_->GetOriginsForHostOnFileThread(type, host, origins); |
351 GURL origin; | |
352 while (!(origin = enumerator->Next()).is_empty()) { | |
353 if (host == net::GetHostOrSpecFromURL(origin) && | |
354 enumerator->HasFileSystemType(type)) | |
355 origins->insert(origin); | |
356 } | |
357 } | 295 } |
358 | 296 |
359 int64 SandboxFileSystemBackend::GetOriginUsageOnFileThread( | 297 int64 SandboxFileSystemBackend::GetOriginUsageOnFileThread( |
360 FileSystemContext* file_system_context, | 298 FileSystemContext* file_system_context, |
361 const GURL& origin_url, | 299 const GURL& origin_url, |
362 fileapi::FileSystemType type) { | 300 fileapi::FileSystemType type) { |
363 DCHECK(CanHandleType(type)); | 301 DCHECK(CanHandleType(type)); |
364 | 302 DCHECK(sandbox_context_); |
365 // Don't use usage cache and return recalculated usage for sticky invalidated | 303 return sandbox_context_->GetOriginUsageOnFileThread( |
366 // origins. | 304 file_system_context, origin_url, type); |
367 if (ContainsKey(sticky_dirty_origins_, std::make_pair(origin_url, type))) | |
368 return RecalculateUsage(file_system_context, origin_url, type); | |
369 | |
370 base::FilePath base_path = | |
371 GetBaseDirectoryForOriginAndType(origin_url, type, false); | |
372 if (base_path.empty() || !base::DirectoryExists(base_path)) | |
373 return 0; | |
374 base::FilePath usage_file_path = | |
375 base_path.Append(FileSystemUsageCache::kUsageFileName); | |
376 | |
377 bool is_valid = usage_cache()->IsValid(usage_file_path); | |
378 uint32 dirty_status = 0; | |
379 bool dirty_status_available = | |
380 usage_cache()->GetDirty(usage_file_path, &dirty_status); | |
381 bool visited = !visited_origins_.insert(origin_url).second; | |
382 if (is_valid && (dirty_status == 0 || (dirty_status_available && visited))) { | |
383 // The usage cache is clean (dirty == 0) or the origin is already | |
384 // initialized and running. Read the cache file to get the usage. | |
385 int64 usage = 0; | |
386 return usage_cache()->GetUsage(usage_file_path, &usage) ? usage : -1; | |
387 } | |
388 // The usage cache has not been initialized or the cache is dirty. | |
389 // Get the directory size now and update the cache. | |
390 usage_cache()->Delete(usage_file_path); | |
391 | |
392 int64 usage = RecalculateUsage(file_system_context, origin_url, type); | |
393 | |
394 // This clears the dirty flag too. | |
395 usage_cache()->UpdateUsage(usage_file_path, usage); | |
396 return usage; | |
397 } | 305 } |
398 | 306 |
399 void SandboxFileSystemBackend::InvalidateUsageCache( | 307 void SandboxFileSystemBackend::InvalidateUsageCache( |
400 const GURL& origin, | 308 const GURL& origin, |
401 fileapi::FileSystemType type) { | 309 fileapi::FileSystemType type) { |
402 DCHECK(CanHandleType(type)); | 310 DCHECK(CanHandleType(type)); |
403 base::PlatformFileError error = base::PLATFORM_FILE_OK; | 311 DCHECK(sandbox_context_); |
404 base::FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 312 sandbox_context_->InvalidateUsageCache(origin, type); |
405 sandbox_sync_file_util(), origin, type, &error); | |
406 if (error != base::PLATFORM_FILE_OK) | |
407 return; | |
408 usage_cache()->IncrementDirty(usage_file_path); | |
409 } | 313 } |
410 | 314 |
411 void SandboxFileSystemBackend::StickyInvalidateUsageCache( | 315 void SandboxFileSystemBackend::StickyInvalidateUsageCache( |
412 const GURL& origin, | 316 const GURL& origin, |
413 fileapi::FileSystemType type) { | 317 fileapi::FileSystemType type) { |
414 DCHECK(CanHandleType(type)); | 318 DCHECK(CanHandleType(type)); |
415 sticky_dirty_origins_.insert(std::make_pair(origin, type)); | 319 DCHECK(sandbox_context_); |
416 sandbox_context_->quota_observer()->SetUsageCacheEnabled(origin, type, false); | 320 sandbox_context_->StickyInvalidateUsageCache(origin, type); |
417 InvalidateUsageCache(origin, type); | |
418 } | 321 } |
419 | 322 |
420 void SandboxFileSystemBackend::AddFileUpdateObserver( | 323 void SandboxFileSystemBackend::AddFileUpdateObserver( |
421 FileSystemType type, | 324 FileSystemType type, |
422 FileUpdateObserver* observer, | 325 FileUpdateObserver* observer, |
423 base::SequencedTaskRunner* task_runner) { | 326 base::SequencedTaskRunner* task_runner) { |
424 DCHECK(CanHandleType(type)); | 327 DCHECK(CanHandleType(type)); |
425 UpdateObserverList* list = &update_observers_; | 328 UpdateObserverList* list = &update_observers_; |
426 if (type == kFileSystemTypeSyncable) | 329 if (type == kFileSystemTypeSyncable) |
427 list = &syncable_update_observers_; | 330 list = &syncable_update_observers_; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 REPORT(kNotFound); | 402 REPORT(kNotFound); |
500 break; | 403 break; |
501 case base::PLATFORM_FILE_ERROR_FAILED: | 404 case base::PLATFORM_FILE_ERROR_FAILED: |
502 default: | 405 default: |
503 REPORT(kUnknownError); | 406 REPORT(kUnknownError); |
504 break; | 407 break; |
505 } | 408 } |
506 #undef REPORT | 409 #undef REPORT |
507 } | 410 } |
508 | 411 |
509 bool SandboxFileSystemBackend::IsAccessValid( | |
510 const FileSystemURL& url) const { | |
511 if (!IsAllowedScheme(url.origin())) | |
512 return false; | |
513 | |
514 if (!CanHandleType(url.type())) | |
515 return false; | |
516 | |
517 if (url.path().ReferencesParent()) | |
518 return false; | |
519 | |
520 // Return earlier if the path is '/', because VirtualPath::BaseName() | |
521 // returns '/' for '/' and we fail the "basename != '/'" check below. | |
522 // (We exclude '.' because it's disallowed by spec.) | |
523 if (VirtualPath::IsRootPath(url.path()) && | |
524 url.path() != base::FilePath(base::FilePath::kCurrentDirectory)) | |
525 return true; | |
526 | |
527 // Restricted names specified in | |
528 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restriction
s | |
529 base::FilePath filename = VirtualPath::BaseName(url.path()); | |
530 // See if the name is allowed to create. | |
531 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) { | |
532 if (filename.value() == kRestrictedNames[i]) | |
533 return false; | |
534 } | |
535 for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) { | |
536 if (filename.value().find(kRestrictedChars[i]) != | |
537 base::FilePath::StringType::npos) | |
538 return false; | |
539 } | |
540 | |
541 return true; | |
542 } | |
543 | |
544 base::FilePath SandboxFileSystemBackend::GetUsageCachePathForOriginAndType( | |
545 const GURL& origin_url, | |
546 FileSystemType type) { | |
547 base::PlatformFileError error; | |
548 base::FilePath path = GetUsageCachePathForOriginAndType( | |
549 sandbox_sync_file_util(), origin_url, type, &error); | |
550 if (error != base::PLATFORM_FILE_OK) | |
551 return base::FilePath(); | |
552 return path; | |
553 } | |
554 | |
555 // static | |
556 base::FilePath SandboxFileSystemBackend::GetUsageCachePathForOriginAndType( | |
557 ObfuscatedFileUtil* sandbox_file_util, | |
558 const GURL& origin_url, | |
559 fileapi::FileSystemType type, | |
560 base::PlatformFileError* error_out) { | |
561 DCHECK(error_out); | |
562 *error_out = base::PLATFORM_FILE_OK; | |
563 base::FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType( | |
564 origin_url, type, false /* create */, error_out); | |
565 if (*error_out != base::PLATFORM_FILE_OK) | |
566 return base::FilePath(); | |
567 return base_path.Append(FileSystemUsageCache::kUsageFileName); | |
568 } | |
569 | |
570 bool SandboxFileSystemBackend::IsAllowedScheme(const GURL& url) const { | |
571 // Basically we only accept http or https. We allow file:// URLs | |
572 // only if --allow-file-access-from-files flag is given. | |
573 if (url.SchemeIs("http") || url.SchemeIs("https")) | |
574 return true; | |
575 if (url.SchemeIsFileSystem()) | |
576 return url.inner_url() && IsAllowedScheme(*url.inner_url()); | |
577 | |
578 for (size_t i = 0; | |
579 i < file_system_options_.additional_allowed_schemes().size(); | |
580 ++i) { | |
581 if (url.SchemeIs( | |
582 file_system_options_.additional_allowed_schemes()[i].c_str())) | |
583 return true; | |
584 } | |
585 return false; | |
586 } | |
587 | |
588 ObfuscatedFileUtil* SandboxFileSystemBackend::sandbox_sync_file_util() { | |
589 DCHECK(sandbox_context_); | |
590 return sandbox_context_->sync_file_util(); | |
591 } | |
592 | |
593 FileSystemUsageCache* SandboxFileSystemBackend::usage_cache() { | |
594 DCHECK(sandbox_context_); | |
595 return sandbox_context_->usage_cache(); | |
596 } | |
597 | |
598 int64 SandboxFileSystemBackend::RecalculateUsage(FileSystemContext* context, | |
599 const GURL& origin, | |
600 FileSystemType type) { | |
601 FileSystemOperationContext operation_context(context); | |
602 FileSystemURL url = context->CreateCrackedFileSystemURL( | |
603 origin, type, base::FilePath()); | |
604 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator( | |
605 sandbox_sync_file_util()->CreateFileEnumerator( | |
606 &operation_context, url, true)); | |
607 | |
608 base::FilePath file_path_each; | |
609 int64 usage = 0; | |
610 | |
611 while (!(file_path_each = enumerator->Next()).empty()) { | |
612 usage += enumerator->Size(); | |
613 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each); | |
614 } | |
615 | |
616 return usage; | |
617 } | |
618 | |
619 } // namespace fileapi | 412 } // namespace fileapi |
OLD | NEW |