private_api_tasks.cc revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
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 "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
8#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
9#include "chrome/browser/chromeos/extensions/file_manager/mime_util.h"
10#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
11#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
12#include "chrome/browser/profiles/profile.h"
13#include "content/public/browser/render_view_host.h"
14#include "webkit/browser/fileapi/file_system_context.h"
15#include "webkit/browser/fileapi/file_system_url.h"
16
17using extensions::app_file_handler_util::PathAndMimeTypeSet;
18using extensions::Extension;
19using fileapi::FileSystemURL;
20
21namespace extensions {
22namespace {
23
24// Error messages.
25const char kInvalidFileUrl[] = "Invalid file URL";
26
27// Make a set of unique filename suffixes out of the list of file URLs.
28std::set<std::string> GetUniqueSuffixes(base::ListValue* file_url_list,
29                                        fileapi::FileSystemContext* context) {
30  std::set<std::string> suffixes;
31  for (size_t i = 0; i < file_url_list->GetSize(); ++i) {
32    std::string url_str;
33    if (!file_url_list->GetString(i, &url_str))
34      return std::set<std::string>();
35    FileSystemURL url = context->CrackURL(GURL(url_str));
36    if (!url.is_valid() || url.path().empty())
37      return std::set<std::string>();
38    // We'll skip empty suffixes.
39    if (!url.path().Extension().empty())
40      suffixes.insert(url.path().Extension());
41  }
42  return suffixes;
43}
44
45// Make a set of unique MIME types out of the list of MIME types.
46std::set<std::string> GetUniqueMimeTypes(base::ListValue* mime_type_list) {
47  std::set<std::string> mime_types;
48  for (size_t i = 0; i < mime_type_list->GetSize(); ++i) {
49    std::string mime_type;
50    if (!mime_type_list->GetString(i, &mime_type))
51      return std::set<std::string>();
52    // We'll skip empty MIME types.
53    if (!mime_type.empty())
54      mime_types.insert(mime_type);
55  }
56  return mime_types;
57}
58
59}  // namespace
60
61FileBrowserPrivateExecuteTaskFunction::FileBrowserPrivateExecuteTaskFunction() {
62}
63
64FileBrowserPrivateExecuteTaskFunction::
65    ~FileBrowserPrivateExecuteTaskFunction() {
66}
67
68bool FileBrowserPrivateExecuteTaskFunction::RunImpl() {
69  // First param is task id that was to the extension with getFileTasks call.
70  std::string task_id;
71  if (!args_->GetString(0, &task_id) || !task_id.size())
72    return false;
73
74  // TODO(kaznacheev): Crack the task_id here, store it in the Executor
75  // and avoid passing it around.
76
77  // The second param is the list of files that need to be executed with this
78  // task.
79  ListValue* files_list = NULL;
80  if (!args_->GetList(1, &files_list))
81    return false;
82
83  file_manager::file_tasks::TaskDescriptor task;
84  if (!file_manager::file_tasks::ParseTaskID(task_id, &task)) {
85    LOG(WARNING) << "Invalid task " << task_id;
86    return false;
87  }
88
89  if (!files_list->GetSize())
90    return true;
91
92  scoped_refptr<fileapi::FileSystemContext> file_system_context =
93      file_manager::util::GetFileSystemContextForRenderViewHost(
94          profile(), render_view_host());
95
96  std::vector<FileSystemURL> file_urls;
97  for (size_t i = 0; i < files_list->GetSize(); i++) {
98    std::string file_url_str;
99    if (!files_list->GetString(i, &file_url_str)) {
100      error_ = kInvalidFileUrl;
101      return false;
102    }
103    FileSystemURL url = file_system_context->CrackURL(GURL(file_url_str));
104    if (!chromeos::FileSystemBackend::CanHandleURL(url)) {
105      error_ = kInvalidFileUrl;
106      return false;
107    }
108    file_urls.push_back(url);
109  }
110
111  int32 tab_id = file_manager::util::GetTabId(dispatcher());
112  return file_manager::file_tasks::ExecuteFileTask(
113      profile(),
114      source_url(),
115      extension_->id(),
116      tab_id,
117      task,
118      file_urls,
119      base::Bind(&FileBrowserPrivateExecuteTaskFunction::OnTaskExecuted, this));
120}
121
122void FileBrowserPrivateExecuteTaskFunction::OnTaskExecuted(bool success) {
123  SetResult(new base::FundamentalValue(success));
124  SendResponse(true);
125}
126
127FileBrowserPrivateGetFileTasksFunction::
128    FileBrowserPrivateGetFileTasksFunction() {
129}
130
131FileBrowserPrivateGetFileTasksFunction::
132    ~FileBrowserPrivateGetFileTasksFunction() {
133}
134
135bool FileBrowserPrivateGetFileTasksFunction::RunImpl() {
136  // First argument is the list of files to get tasks for.
137  ListValue* files_list = NULL;
138  if (!args_->GetList(0, &files_list))
139    return false;
140
141  if (files_list->GetSize() == 0)
142    return false;
143
144  // Second argument is the list of mime types of each of the files in the list.
145  ListValue* mime_types_list = NULL;
146  if (!args_->GetList(1, &mime_types_list))
147    return false;
148
149  // MIME types can either be empty, or there needs to be one for each file.
150  if (mime_types_list->GetSize() != files_list->GetSize() &&
151      mime_types_list->GetSize() != 0)
152    return false;
153
154  scoped_refptr<fileapi::FileSystemContext> file_system_context =
155      file_manager::util::GetFileSystemContextForRenderViewHost(
156          profile(), render_view_host());
157
158  // Collect all the URLs, convert them to GURLs, and crack all the urls into
159  // file paths.
160  PathAndMimeTypeSet path_mime_set;
161  std::vector<GURL> file_urls;
162  std::vector<base::FilePath> file_paths;
163  for (size_t i = 0; i < files_list->GetSize(); ++i) {
164    std::string file_url_str;
165    if (!files_list->GetString(i, &file_url_str))
166      return false;
167
168    std::string mime_type;
169    if (mime_types_list->GetSize() != 0 &&
170        !mime_types_list->GetString(i, &mime_type))
171      return false;
172
173    GURL file_url(file_url_str);
174    fileapi::FileSystemURL file_system_url(
175        file_system_context->CrackURL(file_url));
176    if (!chromeos::FileSystemBackend::CanHandleURL(file_system_url))
177      continue;
178    const base::FilePath file_path = file_system_url.path();
179
180    file_urls.push_back(file_url);
181    file_paths.push_back(file_path);
182
183    // If MIME type is not provided, guess it from the file path.
184    if (mime_type.empty())
185      mime_type = file_manager::util::GetMimeTypeForPath(file_path);
186
187    path_mime_set.insert(std::make_pair(file_path, mime_type));
188  }
189
190  std::vector<file_manager::file_tasks::FullTaskDescriptor> tasks;
191  file_manager::file_tasks::FindAllTypesOfTasks(profile_,
192                                                path_mime_set,
193                                                file_urls,
194                                                file_paths,
195                                                &tasks);
196  // Convert the tasks into JSON format.
197  ListValue* result_list = new ListValue();
198  for (size_t i = 0; i < tasks.size(); ++i)
199    result_list->Append(tasks[i].AsDictionaryValue().release());
200
201  SetResult(result_list);
202  SendResponse(true);
203  return true;
204}
205
206FileBrowserPrivateSetDefaultTaskFunction::
207    FileBrowserPrivateSetDefaultTaskFunction() {
208}
209
210FileBrowserPrivateSetDefaultTaskFunction::
211    ~FileBrowserPrivateSetDefaultTaskFunction() {
212}
213
214bool FileBrowserPrivateSetDefaultTaskFunction::RunImpl() {
215  // First param is task id that was to the extension with setDefaultTask call.
216  std::string task_id;
217  if (!args_->GetString(0, &task_id) || !task_id.size())
218    return false;
219
220  base::ListValue* file_url_list;
221  if (!args_->GetList(1, &file_url_list))
222    return false;
223
224  scoped_refptr<fileapi::FileSystemContext> file_system_context =
225      file_manager::util::GetFileSystemContextForRenderViewHost(
226          profile(), render_view_host());
227
228  std::set<std::string> suffixes =
229      GetUniqueSuffixes(file_url_list, file_system_context.get());
230
231  // MIME types are an optional parameter.
232  base::ListValue* mime_type_list;
233  std::set<std::string> mime_types;
234  if (args_->GetList(2, &mime_type_list) && !mime_type_list->empty()) {
235    if (mime_type_list->GetSize() != file_url_list->GetSize())
236      return false;
237    mime_types = GetUniqueMimeTypes(mime_type_list);
238  }
239
240  // If there weren't any mime_types, and all the suffixes were blank,
241  // then we "succeed", but don't actually associate with anything.
242  // Otherwise, any time we set the default on a file with no extension
243  // on the local drive, we'd fail.
244  // TODO(gspencer): Fix file manager so that it never tries to set default in
245  // cases where extensionless local files are part of the selection.
246  if (suffixes.empty() && mime_types.empty()) {
247    SetResult(new base::FundamentalValue(true));
248    return true;
249  }
250
251  file_manager::file_tasks::UpdateDefaultTask(profile_->GetPrefs(),
252                                              task_id,
253                                              suffixes,
254                                              mime_types);
255  return true;
256}
257
258}  // namespace extensions
259