Home | History | Annotate | Download | only in file_manager
      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 "chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h"
      6 
      7 #include <set>
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "chrome/browser/chromeos/drive/file_system_util.h"
     12 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
     13 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
     14 #include "chrome/browser/extensions/api/file_handlers/mime_util.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "content/public/browser/browser_thread.h"
     17 #include "net/base/filename_util.h"
     18 #include "storage/browser/fileapi/file_system_context.h"
     19 #include "storage/browser/fileapi/file_system_url.h"
     20 
     21 using content::BrowserThread;
     22 using storage::FileSystemURL;
     23 
     24 namespace extensions {
     25 namespace {
     26 
     27 // Error messages.
     28 const char kInvalidTask[] = "Invalid task: ";
     29 const char kInvalidFileUrl[] = "Invalid file URL";
     30 
     31 // Make a set of unique filename suffixes out of the list of file URLs.
     32 std::set<std::string> GetUniqueSuffixes(
     33     const std::vector<std::string>& file_url_list,
     34     const storage::FileSystemContext* context) {
     35   std::set<std::string> suffixes;
     36   for (size_t i = 0; i < file_url_list.size(); ++i) {
     37     const FileSystemURL url = context->CrackURL(GURL(file_url_list[i]));
     38     if (!url.is_valid() || url.path().empty())
     39       return std::set<std::string>();
     40     // We'll skip empty suffixes.
     41     if (!url.path().Extension().empty())
     42       suffixes.insert(url.path().Extension());
     43   }
     44   return suffixes;
     45 }
     46 
     47 // Make a set of unique MIME types out of the list of MIME types.
     48 std::set<std::string> GetUniqueMimeTypes(
     49     const std::vector<std::string>& mime_type_list) {
     50   std::set<std::string> mime_types;
     51   for (size_t i = 0; i < mime_type_list.size(); ++i) {
     52     const std::string mime_type = mime_type_list[i];
     53     // We'll skip empty MIME types and existing MIME types.
     54     if (!mime_type.empty())
     55       mime_types.insert(mime_type);
     56   }
     57   return mime_types;
     58 }
     59 
     60 }  // namespace
     61 
     62 bool FileManagerPrivateExecuteTaskFunction::RunAsync() {
     63   using extensions::api::file_manager_private::ExecuteTask::Params;
     64   using extensions::api::file_manager_private::ExecuteTask::Results::Create;
     65   const scoped_ptr<Params> params(Params::Create(*args_));
     66   EXTENSION_FUNCTION_VALIDATE(params);
     67 
     68   file_manager::file_tasks::TaskDescriptor task;
     69   if (!file_manager::file_tasks::ParseTaskID(params->task_id, &task)) {
     70     SetError(kInvalidTask + params->task_id);
     71     results_ =
     72         Create(extensions::api::file_manager_private::TASK_RESULT_FAILED);
     73     return false;
     74   }
     75 
     76   if (params->file_urls.empty()) {
     77     results_ = Create(extensions::api::file_manager_private::TASK_RESULT_EMPTY);
     78     SendResponse(true);
     79     return true;
     80   }
     81 
     82   const scoped_refptr<storage::FileSystemContext> file_system_context =
     83       file_manager::util::GetFileSystemContextForRenderViewHost(
     84           GetProfile(), render_view_host());
     85 
     86   std::vector<FileSystemURL> file_urls;
     87   for (size_t i = 0; i < params->file_urls.size(); i++) {
     88     const FileSystemURL url =
     89         file_system_context->CrackURL(GURL(params->file_urls[i]));
     90     if (!chromeos::FileSystemBackend::CanHandleURL(url)) {
     91       SetError(kInvalidFileUrl);
     92       results_ =
     93           Create(extensions::api::file_manager_private::TASK_RESULT_FAILED);
     94       return false;
     95     }
     96     file_urls.push_back(url);
     97   }
     98 
     99   const bool result = file_manager::file_tasks::ExecuteFileTask(
    100       GetProfile(),
    101       source_url(),
    102       task,
    103       file_urls,
    104       base::Bind(&FileManagerPrivateExecuteTaskFunction::OnTaskExecuted, this));
    105   if (!result) {
    106     results_ =
    107         Create(extensions::api::file_manager_private::TASK_RESULT_FAILED);
    108   }
    109   return result;
    110 }
    111 
    112 void FileManagerPrivateExecuteTaskFunction::OnTaskExecuted(
    113     extensions::api::file_manager_private::TaskResult result) {
    114   results_ =
    115       extensions::api::file_manager_private::ExecuteTask::Results::Create(
    116           result);
    117   SendResponse(result !=
    118                extensions::api::file_manager_private::TASK_RESULT_FAILED);
    119 }
    120 
    121 FileManagerPrivateGetFileTasksFunction::
    122     FileManagerPrivateGetFileTasksFunction() {
    123 }
    124 
    125 FileManagerPrivateGetFileTasksFunction::
    126     ~FileManagerPrivateGetFileTasksFunction() {
    127 }
    128 
    129 bool FileManagerPrivateGetFileTasksFunction::RunAsync() {
    130   using extensions::api::file_manager_private::GetFileTasks::Params;
    131   const scoped_ptr<Params> params(Params::Create(*args_));
    132   EXTENSION_FUNCTION_VALIDATE(params);
    133 
    134   if (params->file_urls.empty())
    135     return false;
    136 
    137   const scoped_refptr<storage::FileSystemContext> file_system_context =
    138       file_manager::util::GetFileSystemContextForRenderViewHost(
    139           GetProfile(), render_view_host());
    140 
    141   // Collect all the URLs, convert them to GURLs, and crack all the urls into
    142   // file paths.
    143   for (size_t i = 0; i < params->file_urls.size(); ++i) {
    144     const GURL file_url(params->file_urls[i]);
    145     storage::FileSystemURL file_system_url(
    146         file_system_context->CrackURL(file_url));
    147     if (!chromeos::FileSystemBackend::CanHandleURL(file_system_url))
    148       continue;
    149     file_urls_.push_back(file_url);
    150     local_paths_.push_back(file_system_url.path());
    151   }
    152 
    153   collector_.reset(new app_file_handler_util::MimeTypeCollector(GetProfile()));
    154   collector_->CollectForLocalPaths(
    155       local_paths_,
    156       base::Bind(&FileManagerPrivateGetFileTasksFunction::OnMimeTypesCollected,
    157                  this));
    158 
    159   return true;
    160 }
    161 
    162 void FileManagerPrivateGetFileTasksFunction::OnMimeTypesCollected(
    163     scoped_ptr<std::vector<std::string> > mime_types) {
    164   app_file_handler_util::PathAndMimeTypeSet path_mime_set;
    165   for (size_t i = 0; i < local_paths_.size(); ++i) {
    166     path_mime_set.insert(std::make_pair(local_paths_[i], (*mime_types)[i]));
    167   }
    168 
    169   std::vector<file_manager::file_tasks::FullTaskDescriptor> tasks;
    170   file_manager::file_tasks::FindAllTypesOfTasks(
    171       GetProfile(),
    172       drive::util::GetDriveAppRegistryByProfile(GetProfile()),
    173       path_mime_set,
    174       file_urls_,
    175       &tasks);
    176 
    177   // Convert the tasks into JSON compatible objects.
    178   using api::file_manager_private::FileTask;
    179   std::vector<linked_ptr<FileTask> > results;
    180   for (size_t i = 0; i < tasks.size(); ++i) {
    181     const file_manager::file_tasks::FullTaskDescriptor& task = tasks[i];
    182     const linked_ptr<FileTask> converted(new FileTask);
    183     converted->task_id = file_manager::file_tasks::TaskDescriptorToId(
    184         task.task_descriptor());
    185     if (!task.icon_url().is_empty())
    186       converted->icon_url = task.icon_url().spec();
    187     converted->title = task.task_title();
    188     converted->is_default = task.is_default();
    189     results.push_back(converted);
    190   }
    191 
    192   results_ = extensions::api::file_manager_private::GetFileTasks::Results::
    193       Create(results);
    194   SendResponse(true);
    195 }
    196 
    197 bool FileManagerPrivateSetDefaultTaskFunction::RunSync() {
    198   using extensions::api::file_manager_private::SetDefaultTask::Params;
    199   const scoped_ptr<Params> params(Params::Create(*args_));
    200   EXTENSION_FUNCTION_VALIDATE(params);
    201 
    202   const scoped_refptr<storage::FileSystemContext> file_system_context =
    203       file_manager::util::GetFileSystemContextForRenderViewHost(
    204           GetProfile(), render_view_host());
    205 
    206   const std::set<std::string> suffixes =
    207       GetUniqueSuffixes(params->file_urls, file_system_context.get());
    208 
    209   // MIME types are an optional parameter.
    210   std::set<std::string> mime_types;
    211   if (params->mime_types && !params->mime_types->empty()) {
    212     if (params->mime_types->size() != params->file_urls.size())
    213       return false;
    214     mime_types = GetUniqueMimeTypes(*params->mime_types);
    215   }
    216 
    217   // If there weren't any mime_types, and all the suffixes were blank,
    218   // then we "succeed", but don't actually associate with anything.
    219   // Otherwise, any time we set the default on a file with no extension
    220   // on the local drive, we'd fail.
    221   // TODO(gspencer): Fix file manager so that it never tries to set default in
    222   // cases where extensionless local files are part of the selection.
    223   if (suffixes.empty() && mime_types.empty()) {
    224     SetResult(new base::FundamentalValue(true));
    225     return true;
    226   }
    227 
    228   file_manager::file_tasks::UpdateDefaultTask(
    229       GetProfile()->GetPrefs(), params->task_id, suffixes, mime_types);
    230   return true;
    231 }
    232 
    233 }  // namespace extensions
    234