Home | History | Annotate | Download | only in fileapi
      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:
     29   explicit FileSystemIDToPluginMap(base::SequencedTaskRunner* task_runner)
     30       : task_runner_(task_runner) {}
     31   ~FileSystemIDToPluginMap() {}
     32 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    139 bool PluginPrivateFileSystemBackend::CanHandleType(FileSystemType type) const {
    140   return type == kFileSystemTypePluginPrivate;
    141 }
    142 
    143 void PluginPrivateFileSystemBackend::Initialize(FileSystemContext* context) {
    144 }
    145 
    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*
    159 PluginPrivateFileSystemBackend::GetAsyncFileUtil(FileSystemType type) {
    160   return file_util_.get();
    161 }
    162 
    163 CopyOrMoveFileValidatorFactory*
    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 
    172 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 
    181 bool PluginPrivateFileSystemBackend::SupportsStreaming(
    182     const fileapi::FileSystemURL& url) const {
    183   return false;
    184 }
    185 
    186 scoped_ptr<webkit_blob::FileStreamReader>
    187 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>
    196 PluginPrivateFileSystemBackend::CreateFileStreamWriter(
    197     const FileSystemURL& url,
    198     int64 offset,
    199     FileSystemContext* context) const {
    200   return scoped_ptr<FileStreamWriter>();
    201 }
    202 
    203 FileSystemQuotaUtil* PluginPrivateFileSystemBackend::GetQuotaUtil() {
    204   return this;
    205 }
    206 
    207 base::File::Error
    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 
    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 
    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 
    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>
    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 
    266 void PluginPrivateFileSystemBackend::AddFileUpdateObserver(
    267     FileSystemType type,
    268     FileUpdateObserver* observer,
    269     base::SequencedTaskRunner* task_runner) {}
    270 
    271 void PluginPrivateFileSystemBackend::AddFileChangeObserver(
    272     FileSystemType type,
    273     FileChangeObserver* observer,
    274     base::SequencedTaskRunner* task_runner) {}
    275 
    276 void PluginPrivateFileSystemBackend::AddFileAccessObserver(
    277     FileSystemType type,
    278     FileAccessObserver* observer,
    279     base::SequencedTaskRunner* task_runner) {}
    280 
    281 const UpdateObserverList* PluginPrivateFileSystemBackend::GetUpdateObservers(
    282     FileSystemType type) const {
    283   return NULL;
    284 }
    285 
    286 const ChangeObserverList* PluginPrivateFileSystemBackend::GetChangeObservers(
    287     FileSystemType type) const {
    288   return NULL;
    289 }
    290 
    291 const AccessObserverList* PluginPrivateFileSystemBackend::GetAccessObservers(
    292     FileSystemType type) const {
    293   return NULL;
    294 }
    295 
    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