• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "webkit/browser/fileapi/plugin_private_file_system_backend.h"
6 
7 #include <map>
8 
9 #include "base/stl_util.h"
10 #include "base/synchronization/lock.h"
11 #include "base/task_runner_util.h"
12 #include "net/base/net_util.h"
13 #include "webkit/browser/blob/file_stream_reader.h"
14 #include "webkit/browser/fileapi/async_file_util_adapter.h"
15 #include "webkit/browser/fileapi/file_stream_writer.h"
16 #include "webkit/browser/fileapi/file_system_context.h"
17 #include "webkit/browser/fileapi/file_system_operation.h"
18 #include "webkit/browser/fileapi/file_system_operation_context.h"
19 #include "webkit/browser/fileapi/file_system_options.h"
20 #include "webkit/browser/fileapi/isolated_context.h"
21 #include "webkit/browser/fileapi/obfuscated_file_util.h"
22 #include "webkit/browser/fileapi/quota/quota_reservation.h"
23 #include "webkit/common/fileapi/file_system_util.h"
24 
25 namespace fileapi {
26 
27 class PluginPrivateFileSystemBackend::FileSystemIDToPluginMap {
28  public:
FileSystemIDToPluginMap(base::SequencedTaskRunner * task_runner)29   explicit FileSystemIDToPluginMap(base::SequencedTaskRunner* task_runner)
30       : task_runner_(task_runner) {}
~FileSystemIDToPluginMap()31   ~FileSystemIDToPluginMap() {}
32 
GetPluginIDForURL(const FileSystemURL & url)33   std::string GetPluginIDForURL(const FileSystemURL& url) {
34     DCHECK(task_runner_->RunsTasksOnCurrentThread());
35     Map::iterator found = map_.find(url.filesystem_id());
36     if (url.type() != kFileSystemTypePluginPrivate || found == map_.end()) {
37       NOTREACHED() << "Unsupported url is given: " << url.DebugString();
38       return std::string();
39     }
40     return found->second;
41   }
42 
RegisterFileSystem(const std::string & filesystem_id,const std::string & plugin_id)43   void RegisterFileSystem(const std::string& filesystem_id,
44                           const std::string& plugin_id) {
45     DCHECK(task_runner_->RunsTasksOnCurrentThread());
46     DCHECK(!filesystem_id.empty());
47     DCHECK(!ContainsKey(map_, filesystem_id)) << filesystem_id;
48     map_[filesystem_id] = plugin_id;
49   }
50 
RemoveFileSystem(const std::string & filesystem_id)51   void RemoveFileSystem(const std::string& filesystem_id) {
52     DCHECK(task_runner_->RunsTasksOnCurrentThread());
53     map_.erase(filesystem_id);
54   }
55 
56  private:
57   typedef std::map<std::string, std::string> Map;
58   scoped_refptr<base::SequencedTaskRunner> task_runner_;
59   Map map_;
60 };
61 
62 namespace {
63 
64 const base::FilePath::CharType* kFileSystemDirectory =
65     SandboxFileSystemBackendDelegate::kFileSystemDirectory;
66 const base::FilePath::CharType* kPluginPrivateDirectory =
67     FILE_PATH_LITERAL("Plugins");
68 
OpenFileSystemOnFileTaskRunner(ObfuscatedFileUtil * file_util,PluginPrivateFileSystemBackend::FileSystemIDToPluginMap * plugin_map,const GURL & origin_url,const std::string & filesystem_id,const std::string & plugin_id,OpenFileSystemMode mode)69 base::File::Error OpenFileSystemOnFileTaskRunner(
70     ObfuscatedFileUtil* file_util,
71     PluginPrivateFileSystemBackend::FileSystemIDToPluginMap* plugin_map,
72     const GURL& origin_url,
73     const std::string& filesystem_id,
74     const std::string& plugin_id,
75     OpenFileSystemMode mode) {
76   base::File::Error error = base::File::FILE_ERROR_FAILED;
77   const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT);
78   file_util->GetDirectoryForOriginAndType(
79       origin_url, plugin_id, create, &error);
80   if (error == base::File::FILE_OK)
81     plugin_map->RegisterFileSystem(filesystem_id, plugin_id);
82   return error;
83 }
84 
85 }  // namespace
86 
PluginPrivateFileSystemBackend(base::SequencedTaskRunner * file_task_runner,const base::FilePath & profile_path,quota::SpecialStoragePolicy * special_storage_policy,const FileSystemOptions & file_system_options)87 PluginPrivateFileSystemBackend::PluginPrivateFileSystemBackend(
88     base::SequencedTaskRunner* file_task_runner,
89     const base::FilePath& profile_path,
90     quota::SpecialStoragePolicy* special_storage_policy,
91     const FileSystemOptions& file_system_options)
92     : file_task_runner_(file_task_runner),
93       file_system_options_(file_system_options),
94       base_path_(profile_path.Append(
95           kFileSystemDirectory).Append(kPluginPrivateDirectory)),
96       plugin_map_(new FileSystemIDToPluginMap(file_task_runner)),
97       weak_factory_(this) {
98   file_util_.reset(
99       new AsyncFileUtilAdapter(new ObfuscatedFileUtil(
100           special_storage_policy,
101           base_path_, file_system_options.env_override(),
102           file_task_runner,
103           base::Bind(&FileSystemIDToPluginMap::GetPluginIDForURL,
104                      base::Owned(plugin_map_)),
105           std::set<std::string>(),
106           NULL)));
107 }
108 
~PluginPrivateFileSystemBackend()109 PluginPrivateFileSystemBackend::~PluginPrivateFileSystemBackend() {
110   if (!file_task_runner_->RunsTasksOnCurrentThread()) {
111     AsyncFileUtil* file_util = file_util_.release();
112     if (!file_task_runner_->DeleteSoon(FROM_HERE, file_util))
113       delete file_util;
114   }
115 }
116 
OpenPrivateFileSystem(const GURL & origin_url,FileSystemType type,const std::string & filesystem_id,const std::string & plugin_id,OpenFileSystemMode mode,const StatusCallback & callback)117 void PluginPrivateFileSystemBackend::OpenPrivateFileSystem(
118     const GURL& origin_url,
119     FileSystemType type,
120     const std::string& filesystem_id,
121     const std::string& plugin_id,
122     OpenFileSystemMode mode,
123     const StatusCallback& callback) {
124   if (!CanHandleType(type) || file_system_options_.is_incognito()) {
125     base::MessageLoopProxy::current()->PostTask(
126         FROM_HERE, base::Bind(callback, base::File::FILE_ERROR_SECURITY));
127     return;
128   }
129 
130   PostTaskAndReplyWithResult(
131       file_task_runner_.get(),
132       FROM_HERE,
133       base::Bind(&OpenFileSystemOnFileTaskRunner,
134                  obfuscated_file_util(), plugin_map_,
135                  origin_url, filesystem_id, plugin_id, mode),
136       callback);
137 }
138 
CanHandleType(FileSystemType type) const139 bool PluginPrivateFileSystemBackend::CanHandleType(FileSystemType type) const {
140   return type == kFileSystemTypePluginPrivate;
141 }
142 
Initialize(FileSystemContext * context)143 void PluginPrivateFileSystemBackend::Initialize(FileSystemContext* context) {
144 }
145 
ResolveURL(const FileSystemURL & url,OpenFileSystemMode mode,const OpenFileSystemCallback & callback)146 void PluginPrivateFileSystemBackend::ResolveURL(
147     const FileSystemURL& url,
148     OpenFileSystemMode mode,
149     const OpenFileSystemCallback& callback) {
150   // We never allow opening a new plugin-private filesystem via usual
151   // ResolveURL.
152   base::MessageLoopProxy::current()->PostTask(
153       FROM_HERE,
154       base::Bind(callback, GURL(), std::string(),
155                  base::File::FILE_ERROR_SECURITY));
156 }
157 
158 AsyncFileUtil*
GetAsyncFileUtil(FileSystemType type)159 PluginPrivateFileSystemBackend::GetAsyncFileUtil(FileSystemType type) {
160   return file_util_.get();
161 }
162 
163 CopyOrMoveFileValidatorFactory*
GetCopyOrMoveFileValidatorFactory(FileSystemType type,base::File::Error * error_code)164 PluginPrivateFileSystemBackend::GetCopyOrMoveFileValidatorFactory(
165     FileSystemType type,
166     base::File::Error* error_code) {
167   DCHECK(error_code);
168   *error_code = base::File::FILE_OK;
169   return NULL;
170 }
171 
CreateFileSystemOperation(const FileSystemURL & url,FileSystemContext * context,base::File::Error * error_code) const172 FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation(
173     const FileSystemURL& url,
174     FileSystemContext* context,
175     base::File::Error* error_code) const {
176   scoped_ptr<FileSystemOperationContext> operation_context(
177       new FileSystemOperationContext(context));
178   return FileSystemOperation::Create(url, context, operation_context.Pass());
179 }
180 
SupportsStreaming(const fileapi::FileSystemURL & url) const181 bool PluginPrivateFileSystemBackend::SupportsStreaming(
182     const fileapi::FileSystemURL& url) const {
183   return false;
184 }
185 
186 scoped_ptr<webkit_blob::FileStreamReader>
CreateFileStreamReader(const FileSystemURL & url,int64 offset,const base::Time & expected_modification_time,FileSystemContext * context) const187 PluginPrivateFileSystemBackend::CreateFileStreamReader(
188     const FileSystemURL& url,
189     int64 offset,
190     const base::Time& expected_modification_time,
191     FileSystemContext* context) const {
192   return scoped_ptr<webkit_blob::FileStreamReader>();
193 }
194 
195 scoped_ptr<FileStreamWriter>
CreateFileStreamWriter(const FileSystemURL & url,int64 offset,FileSystemContext * context) const196 PluginPrivateFileSystemBackend::CreateFileStreamWriter(
197     const FileSystemURL& url,
198     int64 offset,
199     FileSystemContext* context) const {
200   return scoped_ptr<FileStreamWriter>();
201 }
202 
GetQuotaUtil()203 FileSystemQuotaUtil* PluginPrivateFileSystemBackend::GetQuotaUtil() {
204   return this;
205 }
206 
207 base::File::Error
DeleteOriginDataOnFileTaskRunner(FileSystemContext * context,quota::QuotaManagerProxy * proxy,const GURL & origin_url,FileSystemType type)208 PluginPrivateFileSystemBackend::DeleteOriginDataOnFileTaskRunner(
209     FileSystemContext* context,
210     quota::QuotaManagerProxy* proxy,
211     const GURL& origin_url,
212     FileSystemType type) {
213   if (!CanHandleType(type))
214     return base::File::FILE_ERROR_SECURITY;
215   bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType(
216       origin_url, std::string());
217   if (result)
218     return base::File::FILE_OK;
219   return base::File::FILE_ERROR_FAILED;
220 }
221 
GetOriginsForTypeOnFileTaskRunner(FileSystemType type,std::set<GURL> * origins)222 void PluginPrivateFileSystemBackend::GetOriginsForTypeOnFileTaskRunner(
223     FileSystemType type,
224     std::set<GURL>* origins) {
225   if (!CanHandleType(type))
226     return;
227   scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator(
228       obfuscated_file_util()->CreateOriginEnumerator());
229   GURL origin;
230   while (!(origin = enumerator->Next()).is_empty())
231     origins->insert(origin);
232 }
233 
GetOriginsForHostOnFileTaskRunner(FileSystemType type,const std::string & host,std::set<GURL> * origins)234 void PluginPrivateFileSystemBackend::GetOriginsForHostOnFileTaskRunner(
235     FileSystemType type,
236     const std::string& host,
237     std::set<GURL>* origins) {
238   if (!CanHandleType(type))
239     return;
240   scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator(
241       obfuscated_file_util()->CreateOriginEnumerator());
242   GURL origin;
243   while (!(origin = enumerator->Next()).is_empty()) {
244     if (host == net::GetHostOrSpecFromURL(origin))
245       origins->insert(origin);
246   }
247 }
248 
GetOriginUsageOnFileTaskRunner(FileSystemContext * context,const GURL & origin_url,FileSystemType type)249 int64 PluginPrivateFileSystemBackend::GetOriginUsageOnFileTaskRunner(
250     FileSystemContext* context,
251     const GURL& origin_url,
252     FileSystemType type) {
253   // We don't track usage on this filesystem.
254   return 0;
255 }
256 
257 scoped_refptr<QuotaReservation>
CreateQuotaReservationOnFileTaskRunner(const GURL & origin_url,FileSystemType type)258 PluginPrivateFileSystemBackend::CreateQuotaReservationOnFileTaskRunner(
259     const GURL& origin_url,
260     FileSystemType type) {
261   // We don't track usage on this filesystem.
262   NOTREACHED();
263   return scoped_refptr<QuotaReservation>();
264 }
265 
AddFileUpdateObserver(FileSystemType type,FileUpdateObserver * observer,base::SequencedTaskRunner * task_runner)266 void PluginPrivateFileSystemBackend::AddFileUpdateObserver(
267     FileSystemType type,
268     FileUpdateObserver* observer,
269     base::SequencedTaskRunner* task_runner) {}
270 
AddFileChangeObserver(FileSystemType type,FileChangeObserver * observer,base::SequencedTaskRunner * task_runner)271 void PluginPrivateFileSystemBackend::AddFileChangeObserver(
272     FileSystemType type,
273     FileChangeObserver* observer,
274     base::SequencedTaskRunner* task_runner) {}
275 
AddFileAccessObserver(FileSystemType type,FileAccessObserver * observer,base::SequencedTaskRunner * task_runner)276 void PluginPrivateFileSystemBackend::AddFileAccessObserver(
277     FileSystemType type,
278     FileAccessObserver* observer,
279     base::SequencedTaskRunner* task_runner) {}
280 
GetUpdateObservers(FileSystemType type) const281 const UpdateObserverList* PluginPrivateFileSystemBackend::GetUpdateObservers(
282     FileSystemType type) const {
283   return NULL;
284 }
285 
GetChangeObservers(FileSystemType type) const286 const ChangeObserverList* PluginPrivateFileSystemBackend::GetChangeObservers(
287     FileSystemType type) const {
288   return NULL;
289 }
290 
GetAccessObservers(FileSystemType type) const291 const AccessObserverList* PluginPrivateFileSystemBackend::GetAccessObservers(
292     FileSystemType type) const {
293   return NULL;
294 }
295 
obfuscated_file_util()296 ObfuscatedFileUtil* PluginPrivateFileSystemBackend::obfuscated_file_util() {
297   return static_cast<ObfuscatedFileUtil*>(
298       static_cast<AsyncFileUtilAdapter*>(file_util_.get())->sync_file_util());
299 }
300 
301 }  // namespace fileapi
302