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 "storage/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 "storage/browser/blob/file_stream_reader.h"
     14 #include "storage/browser/fileapi/async_file_util_adapter.h"
     15 #include "storage/browser/fileapi/file_stream_writer.h"
     16 #include "storage/browser/fileapi/file_system_context.h"
     17 #include "storage/browser/fileapi/file_system_operation.h"
     18 #include "storage/browser/fileapi/file_system_operation_context.h"
     19 #include "storage/browser/fileapi/file_system_options.h"
     20 #include "storage/browser/fileapi/isolated_context.h"
     21 #include "storage/browser/fileapi/obfuscated_file_util.h"
     22 #include "storage/browser/fileapi/quota/quota_reservation.h"
     23 #include "storage/common/fileapi/file_system_util.h"
     24 
     25 namespace storage {
     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     storage::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(kFileSystemDirectory)
     95                      .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 WatcherManager* PluginPrivateFileSystemBackend::GetWatcherManager(
    164     FileSystemType type) {
    165   return NULL;
    166 }
    167 
    168 CopyOrMoveFileValidatorFactory*
    169 PluginPrivateFileSystemBackend::GetCopyOrMoveFileValidatorFactory(
    170     FileSystemType type,
    171     base::File::Error* error_code) {
    172   DCHECK(error_code);
    173   *error_code = base::File::FILE_OK;
    174   return NULL;
    175 }
    176 
    177 FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation(
    178     const FileSystemURL& url,
    179     FileSystemContext* context,
    180     base::File::Error* error_code) const {
    181   scoped_ptr<FileSystemOperationContext> operation_context(
    182       new FileSystemOperationContext(context));
    183   return FileSystemOperation::Create(url, context, operation_context.Pass());
    184 }
    185 
    186 bool PluginPrivateFileSystemBackend::SupportsStreaming(
    187     const storage::FileSystemURL& url) const {
    188   return false;
    189 }
    190 
    191 bool PluginPrivateFileSystemBackend::HasInplaceCopyImplementation(
    192     storage::FileSystemType type) const {
    193   return false;
    194 }
    195 
    196 scoped_ptr<storage::FileStreamReader>
    197 PluginPrivateFileSystemBackend::CreateFileStreamReader(
    198     const FileSystemURL& url,
    199     int64 offset,
    200     int64 max_bytes_to_read,
    201     const base::Time& expected_modification_time,
    202     FileSystemContext* context) const {
    203   return scoped_ptr<storage::FileStreamReader>();
    204 }
    205 
    206 scoped_ptr<FileStreamWriter>
    207 PluginPrivateFileSystemBackend::CreateFileStreamWriter(
    208     const FileSystemURL& url,
    209     int64 offset,
    210     FileSystemContext* context) const {
    211   return scoped_ptr<FileStreamWriter>();
    212 }
    213 
    214 FileSystemQuotaUtil* PluginPrivateFileSystemBackend::GetQuotaUtil() {
    215   return this;
    216 }
    217 
    218 base::File::Error
    219 PluginPrivateFileSystemBackend::DeleteOriginDataOnFileTaskRunner(
    220     FileSystemContext* context,
    221     storage::QuotaManagerProxy* proxy,
    222     const GURL& origin_url,
    223     FileSystemType type) {
    224   if (!CanHandleType(type))
    225     return base::File::FILE_ERROR_SECURITY;
    226   bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType(
    227       origin_url, std::string());
    228   if (result)
    229     return base::File::FILE_OK;
    230   return base::File::FILE_ERROR_FAILED;
    231 }
    232 
    233 void PluginPrivateFileSystemBackend::GetOriginsForTypeOnFileTaskRunner(
    234     FileSystemType type,
    235     std::set<GURL>* origins) {
    236   if (!CanHandleType(type))
    237     return;
    238   scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator(
    239       obfuscated_file_util()->CreateOriginEnumerator());
    240   GURL origin;
    241   while (!(origin = enumerator->Next()).is_empty())
    242     origins->insert(origin);
    243 }
    244 
    245 void PluginPrivateFileSystemBackend::GetOriginsForHostOnFileTaskRunner(
    246     FileSystemType type,
    247     const std::string& host,
    248     std::set<GURL>* origins) {
    249   if (!CanHandleType(type))
    250     return;
    251   scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator(
    252       obfuscated_file_util()->CreateOriginEnumerator());
    253   GURL origin;
    254   while (!(origin = enumerator->Next()).is_empty()) {
    255     if (host == net::GetHostOrSpecFromURL(origin))
    256       origins->insert(origin);
    257   }
    258 }
    259 
    260 int64 PluginPrivateFileSystemBackend::GetOriginUsageOnFileTaskRunner(
    261     FileSystemContext* context,
    262     const GURL& origin_url,
    263     FileSystemType type) {
    264   // We don't track usage on this filesystem.
    265   return 0;
    266 }
    267 
    268 scoped_refptr<QuotaReservation>
    269 PluginPrivateFileSystemBackend::CreateQuotaReservationOnFileTaskRunner(
    270     const GURL& origin_url,
    271     FileSystemType type) {
    272   // We don't track usage on this filesystem.
    273   NOTREACHED();
    274   return scoped_refptr<QuotaReservation>();
    275 }
    276 
    277 const UpdateObserverList* PluginPrivateFileSystemBackend::GetUpdateObservers(
    278     FileSystemType type) const {
    279   return NULL;
    280 }
    281 
    282 const ChangeObserverList* PluginPrivateFileSystemBackend::GetChangeObservers(
    283     FileSystemType type) const {
    284   return NULL;
    285 }
    286 
    287 const AccessObserverList* PluginPrivateFileSystemBackend::GetAccessObservers(
    288     FileSystemType type) const {
    289   return NULL;
    290 }
    291 
    292 ObfuscatedFileUtil* PluginPrivateFileSystemBackend::obfuscated_file_util() {
    293   return static_cast<ObfuscatedFileUtil*>(
    294       static_cast<AsyncFileUtilAdapter*>(file_util_.get())->sync_file_util());
    295 }
    296 
    297 }  // namespace storage
    298