Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(122)

Side by Side Diff: webkit/browser/fileapi/sandbox_context.cc

Issue 21116008: FileAPI: Move FileSystemQuotaUtil related functions into SandboxContext (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_context.h" 5 #include "webkit/browser/fileapi/sandbox_context.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/metrics/histogram.h"
10 #include "base/stl_util.h"
8 #include "base/task_runner_util.h" 11 #include "base/task_runner_util.h"
12 #include "net/base/net_util.h"
9 #include "webkit/browser/fileapi/async_file_util_adapter.h" 13 #include "webkit/browser/fileapi/async_file_util_adapter.h"
14 #include "webkit/browser/fileapi/file_system_context.h"
15 #include "webkit/browser/fileapi/file_system_operation_context.h"
16 #include "webkit/browser/fileapi/file_system_url.h"
10 #include "webkit/browser/fileapi/file_system_usage_cache.h" 17 #include "webkit/browser/fileapi/file_system_usage_cache.h"
11 #include "webkit/browser/fileapi/obfuscated_file_util.h" 18 #include "webkit/browser/fileapi/obfuscated_file_util.h"
12 #include "webkit/browser/fileapi/sandbox_quota_observer.h" 19 #include "webkit/browser/fileapi/sandbox_quota_observer.h"
13 #include "webkit/browser/quota/quota_manager.h" 20 #include "webkit/browser/quota/quota_manager.h"
21 #include "webkit/common/fileapi/file_system_util.h"
14 22
15 namespace fileapi { 23 namespace fileapi {
16 24
17 namespace { 25 namespace {
26
18 // A command line switch to disable usage tracking. 27 // A command line switch to disable usage tracking.
19 const char kDisableUsageTracking[] = "disable-file-system-usage-tracking"; 28 const char kDisableUsageTracking[] = "disable-file-system-usage-tracking";
29
30 // Restricted names.
31 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
32 const base::FilePath::CharType* const kRestrictedNames[] = {
33 FILE_PATH_LITERAL("."), FILE_PATH_LITERAL(".."),
34 };
35
36 // Restricted chars.
37 const base::FilePath::CharType kRestrictedChars[] = {
38 FILE_PATH_LITERAL('/'), FILE_PATH_LITERAL('\\'),
39 };
40
41 class ObfuscatedOriginEnumerator
42 : public SandboxContext::OriginEnumerator {
43 public:
44 explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) {
45 enum_.reset(file_util->CreateOriginEnumerator());
46 }
47 virtual ~ObfuscatedOriginEnumerator() {}
48
49 virtual GURL Next() OVERRIDE {
50 return enum_->Next();
51 }
52
53 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE {
54 return enum_->HasFileSystemType(type);
55 }
56
57 private:
58 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_;
59 };
60
61 bool IsValidType(fileapi::FileSystemType type) {
62 if (type == kFileSystemTypeTemporary ||
63 type == kFileSystemTypePersistent ||
64 type == kFileSystemTypeSyncable ||
65 type == kFileSystemTypeSyncableForInternalSync)
66 return true;
67 return false;
20 } 68 }
kinuko 2013/07/30 08:22:20 This method probably shouldn't be here. For IsAcc
nhiroki 2013/07/30 11:56:44 Done.
21 69
70 } // namespace
71
22 const base::FilePath::CharType 72 const base::FilePath::CharType
23 SandboxContext::kFileSystemDirectory[] = FILE_PATH_LITERAL("File System"); 73 SandboxContext::kFileSystemDirectory[] = FILE_PATH_LITERAL("File System");
24 74
25 SandboxContext::SandboxContext( 75 SandboxContext::SandboxContext(
26 quota::QuotaManagerProxy* quota_manager_proxy, 76 quota::QuotaManagerProxy* quota_manager_proxy,
27 base::SequencedTaskRunner* file_task_runner, 77 base::SequencedTaskRunner* file_task_runner,
28 const base::FilePath& profile_path, 78 const base::FilePath& profile_path,
29 quota::SpecialStoragePolicy* special_storage_policy) 79 quota::SpecialStoragePolicy* special_storage_policy,
80 const FileSystemOptions& file_system_options)
30 : file_task_runner_(file_task_runner), 81 : file_task_runner_(file_task_runner),
31 sandbox_file_util_(new AsyncFileUtilAdapter( 82 sandbox_file_util_(new AsyncFileUtilAdapter(
32 new ObfuscatedFileUtil( 83 new ObfuscatedFileUtil(
33 special_storage_policy, 84 special_storage_policy,
34 profile_path.Append(kFileSystemDirectory), 85 profile_path.Append(kFileSystemDirectory),
35 file_task_runner))), 86 file_task_runner))),
36 file_system_usage_cache_(new FileSystemUsageCache(file_task_runner)), 87 file_system_usage_cache_(new FileSystemUsageCache(file_task_runner)),
37 quota_observer_(new SandboxQuotaObserver( 88 quota_observer_(new SandboxQuotaObserver(
38 quota_manager_proxy, 89 quota_manager_proxy,
39 file_task_runner, 90 file_task_runner,
40 sync_file_util(), 91 sync_file_util(),
41 usage_cache())), 92 usage_cache())),
93 special_storage_policy_(special_storage_policy),
94 file_system_options_(file_system_options),
42 is_usage_tracking_enabled_( 95 is_usage_tracking_enabled_(
43 !CommandLine::ForCurrentProcess()->HasSwitch( 96 !CommandLine::ForCurrentProcess()->HasSwitch(
44 kDisableUsageTracking)) { 97 kDisableUsageTracking)) {
45 } 98 }
46 99
47 SandboxContext::~SandboxContext() { 100 SandboxContext::~SandboxContext() {
48 if (!file_task_runner_->RunsTasksOnCurrentThread()) { 101 if (!file_task_runner_->RunsTasksOnCurrentThread()) {
49 AsyncFileUtilAdapter* sandbox_file_util = sandbox_file_util_.release(); 102 AsyncFileUtilAdapter* sandbox_file_util = sandbox_file_util_.release();
50 SandboxQuotaObserver* quota_observer = quota_observer_.release(); 103 SandboxQuotaObserver* quota_observer = quota_observer_.release();
51 FileSystemUsageCache* file_system_usage_cache = 104 FileSystemUsageCache* file_system_usage_cache =
52 file_system_usage_cache_.release(); 105 file_system_usage_cache_.release();
53 if (!file_task_runner_->DeleteSoon(FROM_HERE, sandbox_file_util)) 106 if (!file_task_runner_->DeleteSoon(FROM_HERE, sandbox_file_util))
54 delete sandbox_file_util; 107 delete sandbox_file_util;
55 if (!file_task_runner_->DeleteSoon(FROM_HERE, quota_observer)) 108 if (!file_task_runner_->DeleteSoon(FROM_HERE, quota_observer))
56 delete quota_observer; 109 delete quota_observer;
57 if (!file_task_runner_->DeleteSoon(FROM_HERE, file_system_usage_cache)) 110 if (!file_task_runner_->DeleteSoon(FROM_HERE, file_system_usage_cache))
58 delete file_system_usage_cache; 111 delete file_system_usage_cache;
59 } 112 }
60 } 113 }
61 114
115 bool SandboxContext::IsAccessValid(const FileSystemURL& url) const {
116 if (!IsAllowedScheme(url.origin()))
117 return false;
118
119 if (!IsValidType(url.type()))
120 return false;
121
122 if (url.path().ReferencesParent())
123 return false;
124
125 // Return earlier if the path is '/', because VirtualPath::BaseName()
126 // returns '/' for '/' and we fail the "basename != '/'" check below.
127 // (We exclude '.' because it's disallowed by spec.)
128 if (VirtualPath::IsRootPath(url.path()) &&
129 url.path() != base::FilePath(base::FilePath::kCurrentDirectory))
130 return true;
131
132 // Restricted names specified in
133 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restriction s
134 base::FilePath filename = VirtualPath::BaseName(url.path());
135 // See if the name is allowed to create.
136 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
137 if (filename.value() == kRestrictedNames[i])
138 return false;
139 }
140 for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
141 if (filename.value().find(kRestrictedChars[i]) !=
142 base::FilePath::StringType::npos)
143 return false;
144 }
145
146 return true;
147 }
148
149 bool SandboxContext::IsAllowedScheme(const GURL& url) const {
150 // Basically we only accept http or https. We allow file:// URLs
151 // only if --allow-file-access-from-files flag is given.
152 if (url.SchemeIs("http") || url.SchemeIs("https"))
153 return true;
154 if (url.SchemeIsFileSystem())
155 return url.inner_url() && IsAllowedScheme(*url.inner_url());
156
157 for (size_t i = 0;
158 i < file_system_options_.additional_allowed_schemes().size();
159 ++i) {
160 if (url.SchemeIs(
161 file_system_options_.additional_allowed_schemes()[i].c_str()))
162 return true;
163 }
164 return false;
165 }
166
167 SandboxContext::OriginEnumerator* SandboxContext::CreateOriginEnumerator() {
168 return new ObfuscatedOriginEnumerator(sync_file_util());
169 }
170
171 base::FilePath SandboxContext::GetBaseDirectoryForOriginAndType(
172 const GURL& origin_url, fileapi::FileSystemType type, bool create) {
173 base::PlatformFileError error = base::PLATFORM_FILE_OK;
174 base::FilePath path = sync_file_util()->GetDirectoryForOriginAndType(
175 origin_url, type, create, &error);
176 if (error != base::PLATFORM_FILE_OK)
177 return base::FilePath();
178 return path;
179 }
180
181 base::PlatformFileError SandboxContext::DeleteOriginDataOnFileThreadImpl(
182 FileSystemContext* file_system_context,
183 quota::QuotaManagerProxy* proxy,
184 const GURL& origin_url,
185 fileapi::FileSystemType type) {
186 int64 usage = GetOriginUsageOnFileThreadImpl(file_system_context,
187 origin_url, type);
188 usage_cache()->CloseCacheFiles();
189 bool result = sync_file_util()->DeleteDirectoryForOriginAndType(
190 origin_url, type);
191 if (result && proxy) {
192 proxy->NotifyStorageModified(
193 quota::QuotaClient::kFileSystem,
194 origin_url,
195 FileSystemTypeToQuotaStorageType(type),
196 -usage);
197 }
198
199 if (result)
200 return base::PLATFORM_FILE_OK;
201 return base::PLATFORM_FILE_ERROR_FAILED;
202 }
203
204 void SandboxContext::GetOriginsForTypeOnFileThreadImpl(
205 fileapi::FileSystemType type, std::set<GURL>* origins) {
206 DCHECK(IsValidType(type));
207 DCHECK(origins);
208 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator());
209 GURL origin;
210 while (!(origin = enumerator->Next()).is_empty()) {
211 if (enumerator->HasFileSystemType(type))
212 origins->insert(origin);
213 }
214 }
215
216 void SandboxContext::GetOriginsForHostOnFileThreadImpl(
217 fileapi::FileSystemType type, const std::string& host,
218 std::set<GURL>* origins) {
219 DCHECK(IsValidType(type));
220 DCHECK(origins);
221 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator());
222 GURL origin;
223 while (!(origin = enumerator->Next()).is_empty()) {
224 if (host == net::GetHostOrSpecFromURL(origin) &&
225 enumerator->HasFileSystemType(type))
226 origins->insert(origin);
227 }
228 }
229
230 int64 SandboxContext::GetOriginUsageOnFileThreadImpl(
231 FileSystemContext* file_system_context,
232 const GURL& origin_url,
233 fileapi::FileSystemType type) {
234 DCHECK(IsValidType(type));
235 if (!is_usage_tracking_enabled())
236 return 0;
237
238 // Don't use usage cache and return recalculated usage for sticky invalidated
239 // origins.
240 if (ContainsKey(sticky_dirty_origins_, std::make_pair(origin_url, type)))
241 return RecalculateUsage(file_system_context, origin_url, type);
242
243 base::FilePath base_path =
244 GetBaseDirectoryForOriginAndType(origin_url, type, false);
245 if (base_path.empty() || !base::DirectoryExists(base_path))
246 return 0;
247 base::FilePath usage_file_path =
248 base_path.Append(FileSystemUsageCache::kUsageFileName);
249
250 bool is_valid = usage_cache()->IsValid(usage_file_path);
251 uint32 dirty_status = 0;
252 bool dirty_status_available =
253 usage_cache()->GetDirty(usage_file_path, &dirty_status);
254 bool visited = !visited_origins_.insert(origin_url).second;
255 if (is_valid && (dirty_status == 0 || (dirty_status_available && visited))) {
256 // The usage cache is clean (dirty == 0) or the origin is already
257 // initialized and running. Read the cache file to get the usage.
258 int64 usage = 0;
259 return usage_cache()->GetUsage(usage_file_path, &usage) ? usage : -1;
260 }
261 // The usage cache has not been initialized or the cache is dirty.
262 // Get the directory size now and update the cache.
263 usage_cache()->Delete(usage_file_path);
264
265 int64 usage = RecalculateUsage(file_system_context, origin_url, type);
266
267 // This clears the dirty flag too.
268 usage_cache()->UpdateUsage(usage_file_path, usage);
269 return usage;
270 }
271
272 void SandboxContext::InvalidateUsageCacheImpl(
273 const GURL& origin,
274 fileapi::FileSystemType type) {
275 DCHECK(IsValidType(type));
276 base::PlatformFileError error = base::PLATFORM_FILE_OK;
277 base::FilePath usage_file_path = GetUsageCachePathForOriginAndType(
278 sync_file_util(), origin, type, &error);
279 if (error != base::PLATFORM_FILE_OK)
280 return;
281 usage_cache()->IncrementDirty(usage_file_path);
282 }
283
284 void SandboxContext::StickyInvalidateUsageCacheImpl(
285 const GURL& origin,
286 fileapi::FileSystemType type) {
287 DCHECK(IsValidType(type));
288 sticky_dirty_origins_.insert(std::make_pair(origin, type));
289 quota_observer()->SetUsageCacheEnabled(origin, type, false);
290 InvalidateUsageCacheImpl(origin, type);
291 }
292
293 base::FilePath SandboxContext::GetUsageCachePathForOriginAndType(
294 const GURL& origin_url,
295 FileSystemType type) {
296 base::PlatformFileError error;
297 base::FilePath path = GetUsageCachePathForOriginAndType(
298 sync_file_util(), origin_url, type, &error);
299 if (error != base::PLATFORM_FILE_OK)
300 return base::FilePath();
301 return path;
302 }
303
304 // static
305 base::FilePath SandboxContext::GetUsageCachePathForOriginAndType(
306 ObfuscatedFileUtil* sandbox_file_util,
307 const GURL& origin_url,
308 fileapi::FileSystemType type,
309 base::PlatformFileError* error_out) {
310 DCHECK(error_out);
311 *error_out = base::PLATFORM_FILE_OK;
312 base::FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType(
313 origin_url, type, false /* create */, error_out);
314 if (*error_out != base::PLATFORM_FILE_OK)
315 return base::FilePath();
316 return base_path.Append(FileSystemUsageCache::kUsageFileName);
317 }
318
319 int64 SandboxContext::RecalculateUsage(FileSystemContext* context,
320 const GURL& origin,
321 FileSystemType type) {
322 FileSystemOperationContext operation_context(context);
323 FileSystemURL url = context->CreateCrackedFileSystemURL(
324 origin, type, base::FilePath());
325 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator(
326 sync_file_util()->CreateFileEnumerator(&operation_context, url, true));
327
328 base::FilePath file_path_each;
329 int64 usage = 0;
330
331 while (!(file_path_each = enumerator->Next()).empty()) {
332 usage += enumerator->Size();
333 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each);
334 }
335
336 return usage;
337 }
338
62 ObfuscatedFileUtil* SandboxContext::sync_file_util() { 339 ObfuscatedFileUtil* SandboxContext::sync_file_util() {
63 return static_cast<ObfuscatedFileUtil*>(file_util()->sync_file_util()); 340 return static_cast<ObfuscatedFileUtil*>(file_util()->sync_file_util());
64 } 341 }
65 342
66 } // namespace fileapi 343 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698