browser_file_system_helper.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
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 "content/browser/fileapi/browser_file_system_helper.h"
6
7#include <string>
8#include <vector>
9
10#include "base/command_line.h"
11#include "base/files/file_path.h"
12#include "base/sequenced_task_runner.h"
13#include "base/threading/sequenced_worker_pool.h"
14#include "content/browser/child_process_security_policy_impl.h"
15#include "content/public/browser/browser_context.h"
16#include "content/public/browser/browser_thread.h"
17#include "content/public/browser/content_browser_client.h"
18#include "content/public/common/content_client.h"
19#include "content/public/common/content_switches.h"
20#include "content/public/common/url_constants.h"
21#include "webkit/browser/fileapi/external_mount_points.h"
22#include "webkit/browser/fileapi/file_permission_policy.h"
23#include "webkit/browser/fileapi/file_system_backend.h"
24#include "webkit/browser/fileapi/file_system_operation_runner.h"
25#include "webkit/browser/fileapi/file_system_options.h"
26#include "webkit/browser/quota/quota_manager.h"
27
28namespace content {
29
30namespace {
31
32using fileapi::FileSystemOptions;
33
34FileSystemOptions CreateBrowserFileSystemOptions(bool is_incognito) {
35  FileSystemOptions::ProfileMode profile_mode =
36      is_incognito ? FileSystemOptions::PROFILE_MODE_INCOGNITO
37                   : FileSystemOptions::PROFILE_MODE_NORMAL;
38  std::vector<std::string> additional_allowed_schemes;
39  GetContentClient()->browser()->GetAdditionalAllowedSchemesForFileSystem(
40      &additional_allowed_schemes);
41  if (CommandLine::ForCurrentProcess()->HasSwitch(
42          switches::kAllowFileAccessFromFiles)) {
43    additional_allowed_schemes.push_back(chrome::kFileScheme);
44  }
45  return FileSystemOptions(profile_mode, additional_allowed_schemes);
46}
47
48}  // namespace
49
50scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext(
51    BrowserContext* browser_context,
52    const base::FilePath& profile_path,
53    bool is_incognito,
54    quota::QuotaManagerProxy* quota_manager_proxy) {
55
56  base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
57  scoped_refptr<base::SequencedTaskRunner> file_task_runner =
58      pool->GetSequencedTaskRunner(pool->GetNamedSequenceToken("FileAPI"));
59
60  // Setting up additional filesystem backends.
61  ScopedVector<fileapi::FileSystemBackend> additional_backends;
62  GetContentClient()->browser()->GetAdditionalFileSystemBackends(
63      browser_context,
64      profile_path,
65      &additional_backends);
66
67  scoped_refptr<fileapi::FileSystemContext> file_system_context =
68      new fileapi::FileSystemContext(
69          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(),
70          file_task_runner.get(),
71          BrowserContext::GetMountPoints(browser_context),
72          browser_context->GetSpecialStoragePolicy(),
73          quota_manager_proxy,
74          additional_backends.Pass(),
75          profile_path,
76          CreateBrowserFileSystemOptions(is_incognito));
77
78  std::vector<fileapi::FileSystemType> types;
79  file_system_context->GetFileSystemTypes(&types);
80  for (size_t i = 0; i < types.size(); ++i) {
81    ChildProcessSecurityPolicyImpl::GetInstance()->
82        RegisterFileSystemPermissionPolicy(
83            types[i],
84            fileapi::FileSystemContext::GetPermissionPolicy(types[i]));
85  }
86
87  return file_system_context;
88}
89
90bool FileSystemURLIsValid(
91    fileapi::FileSystemContext* context,
92    const fileapi::FileSystemURL& url) {
93  if (!url.is_valid())
94    return false;
95
96  return context->GetFileSystemBackend(url.type()) != NULL;
97}
98
99bool CheckFileSystemPermissionsForProcess(
100    fileapi::FileSystemContext* context, int process_id,
101    const fileapi::FileSystemURL& url, int permissions,
102    base::PlatformFileError* error) {
103  DCHECK(error);
104
105  if (!FileSystemURLIsValid(context, url)) {
106    *error = base::PLATFORM_FILE_ERROR_INVALID_URL;
107    return false;
108  }
109
110  if (!ChildProcessSecurityPolicyImpl::GetInstance()->
111          HasPermissionsForFileSystemFile(process_id, url, permissions)) {
112    *error = base::PLATFORM_FILE_ERROR_SECURITY;
113    return false;
114  }
115
116  *error = base::PLATFORM_FILE_OK;
117  return true;
118}
119
120void SyncGetPlatformPath(fileapi::FileSystemContext* context,
121                         int process_id,
122                         const GURL& path,
123                         base::FilePath* platform_path) {
124  DCHECK(context->default_file_task_runner()->
125         RunsTasksOnCurrentThread());
126  DCHECK(platform_path);
127  *platform_path = base::FilePath();
128  fileapi::FileSystemURL url(context->CrackURL(path));
129  if (!FileSystemURLIsValid(context, url))
130    return;
131
132  // Make sure if this file is ok to be read (in the current architecture
133  // which means roughly same as the renderer is allowed to get the platform
134  // path to the file).
135  ChildProcessSecurityPolicyImpl* policy =
136      ChildProcessSecurityPolicyImpl::GetInstance();
137  if (!policy->CanReadFileSystemFile(process_id, url))
138    return;
139
140  context->operation_runner()->SyncGetPlatformPath(url, platform_path);
141
142  // The path is to be attached to URLLoader so we grant read permission
143  // for the file. (We need to check first because a parent directory may
144  // already have the permissions and we don't need to grant it to the file.)
145  if (!policy->CanReadFile(process_id, *platform_path))
146    policy->GrantReadFile(process_id, *platform_path);
147}
148
149}  // namespace content
150