private_api_tasks.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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
21using content::BrowserThread;
22using storage::FileSystemURL;
23
24namespace extensions {
25namespace {
26
27// Error messages.
28const char kInvalidTask[] = "Invalid task: ";
29const char kInvalidFileUrl[] = "Invalid file URL";
30
31// Make a set of unique filename suffixes out of the list of file URLs.
32std::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.
48std::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
62bool 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
112void 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
121FileManagerPrivateGetFileTasksFunction::
122    FileManagerPrivateGetFileTasksFunction() {
123}
124
125FileManagerPrivateGetFileTasksFunction::
126    ~FileManagerPrivateGetFileTasksFunction() {
127}
128
129bool 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
162void 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
197bool 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