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.
5 #include "chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h"
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 "chrome/common/extensions/api/file_manager_private.h"
17 #include "chrome/common/extensions/api/file_manager_private_internal.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "net/base/filename_util.h"
20 #include "storage/browser/fileapi/file_system_context.h"
21 #include "storage/browser/fileapi/file_system_url.h"
23 using content::BrowserThread
;
24 using storage::FileSystemURL
;
26 namespace extensions
{
30 const char kInvalidTask
[] = "Invalid task: ";
31 const char kInvalidFileUrl
[] = "Invalid file URL";
33 // Make a set of unique filename suffixes out of the list of file URLs.
34 std::set
<std::string
> GetUniqueSuffixes(
35 const std::vector
<std::string
>& url_list
,
36 const storage::FileSystemContext
* context
) {
37 std::set
<std::string
> suffixes
;
38 for (size_t i
= 0; i
< url_list
.size(); ++i
) {
39 const FileSystemURL url
= context
->CrackURL(GURL(url_list
[i
]));
40 if (!url
.is_valid() || url
.path().empty())
41 return std::set
<std::string
>();
42 // We'll skip empty suffixes.
43 if (!url
.path().Extension().empty())
44 suffixes
.insert(url
.path().Extension());
49 // Make a set of unique MIME types out of the list of MIME types.
50 std::set
<std::string
> GetUniqueMimeTypes(
51 const std::vector
<std::string
>& mime_type_list
) {
52 std::set
<std::string
> mime_types
;
53 for (size_t i
= 0; i
< mime_type_list
.size(); ++i
) {
54 const std::string mime_type
= mime_type_list
[i
];
55 // We'll skip empty MIME types and existing MIME types.
56 if (!mime_type
.empty())
57 mime_types
.insert(mime_type
);
64 bool FileManagerPrivateInternalExecuteTaskFunction::RunAsync() {
65 using extensions::api::file_manager_private_internal::ExecuteTask::Params
;
66 using extensions::api::file_manager_private_internal::ExecuteTask::Results::
68 const scoped_ptr
<Params
> params(Params::Create(*args_
));
69 EXTENSION_FUNCTION_VALIDATE(params
);
71 file_manager::file_tasks::TaskDescriptor task
;
72 if (!file_manager::file_tasks::ParseTaskID(params
->task_id
, &task
)) {
73 SetError(kInvalidTask
+ params
->task_id
);
75 Create(extensions::api::file_manager_private::TASK_RESULT_FAILED
);
79 if (params
->urls
.empty()) {
80 results_
= Create(extensions::api::file_manager_private::TASK_RESULT_EMPTY
);
85 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
86 file_manager::util::GetFileSystemContextForRenderFrameHost(
87 GetProfile(), render_frame_host());
89 std::vector
<FileSystemURL
> urls
;
90 for (size_t i
= 0; i
< params
->urls
.size(); i
++) {
91 const FileSystemURL url
=
92 file_system_context
->CrackURL(GURL(params
->urls
[i
]));
93 if (!chromeos::FileSystemBackend::CanHandleURL(url
)) {
94 SetError(kInvalidFileUrl
);
96 Create(extensions::api::file_manager_private::TASK_RESULT_FAILED
);
102 const bool result
= file_manager::file_tasks::ExecuteFileTask(
103 GetProfile(), source_url(), task
, urls
,
104 base::Bind(&FileManagerPrivateInternalExecuteTaskFunction::OnTaskExecuted
,
108 Create(extensions::api::file_manager_private::TASK_RESULT_FAILED
);
113 void FileManagerPrivateInternalExecuteTaskFunction::OnTaskExecuted(
114 extensions::api::file_manager_private::TaskResult result
) {
115 results_
= extensions::api::file_manager_private_internal::ExecuteTask::
116 Results::Create(result
);
117 SendResponse(result
!=
118 extensions::api::file_manager_private::TASK_RESULT_FAILED
);
121 FileManagerPrivateInternalGetFileTasksFunction::
122 FileManagerPrivateInternalGetFileTasksFunction() {}
124 FileManagerPrivateInternalGetFileTasksFunction::
125 ~FileManagerPrivateInternalGetFileTasksFunction() {}
127 bool FileManagerPrivateInternalGetFileTasksFunction::RunAsync() {
128 using extensions::api::file_manager_private_internal::GetFileTasks::Params
;
129 const scoped_ptr
<Params
> params(Params::Create(*args_
));
130 EXTENSION_FUNCTION_VALIDATE(params
);
132 if (params
->urls
.empty())
135 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
136 file_manager::util::GetFileSystemContextForRenderFrameHost(
137 GetProfile(), render_frame_host());
139 // Collect all the URLs, convert them to GURLs, and crack all the urls into
141 for (size_t i
= 0; i
< params
->urls
.size(); ++i
) {
142 const GURL
url(params
->urls
[i
]);
143 storage::FileSystemURL
file_system_url(file_system_context
->CrackURL(url
));
144 if (!chromeos::FileSystemBackend::CanHandleURL(file_system_url
))
146 urls_
.push_back(url
);
147 local_paths_
.push_back(file_system_url
.path());
150 collector_
.reset(new app_file_handler_util::MimeTypeCollector(GetProfile()));
151 collector_
->CollectForLocalPaths(
154 &FileManagerPrivateInternalGetFileTasksFunction::OnMimeTypesCollected
,
160 void FileManagerPrivateInternalGetFileTasksFunction::OnMimeTypesCollected(
161 scoped_ptr
<std::vector
<std::string
>> mime_types
) {
162 app_file_handler_util::PathAndMimeTypeSet path_mime_set
;
163 for (size_t i
= 0; i
< local_paths_
.size(); ++i
) {
164 path_mime_set
.insert(std::make_pair(local_paths_
[i
], (*mime_types
)[i
]));
167 std::vector
<file_manager::file_tasks::FullTaskDescriptor
> tasks
;
168 file_manager::file_tasks::FindAllTypesOfTasks(
169 GetProfile(), drive::util::GetDriveAppRegistryByProfile(GetProfile()),
170 path_mime_set
, urls_
, &tasks
);
172 // Convert the tasks into JSON compatible objects.
173 using api::file_manager_private::FileTask
;
174 std::vector
<linked_ptr
<FileTask
> > results
;
175 for (size_t i
= 0; i
< tasks
.size(); ++i
) {
176 const file_manager::file_tasks::FullTaskDescriptor
& task
= tasks
[i
];
177 const linked_ptr
<FileTask
> converted(new FileTask
);
178 converted
->task_id
= file_manager::file_tasks::TaskDescriptorToId(
179 task
.task_descriptor());
180 if (!task
.icon_url().is_empty())
181 converted
->icon_url
= task
.icon_url().spec();
182 converted
->title
= task
.task_title();
183 converted
->is_default
= task
.is_default();
184 converted
->is_generic_file_handler
= task
.is_generic_file_handler();
185 results
.push_back(converted
);
188 results_
= extensions::api::file_manager_private_internal::GetFileTasks::
189 Results::Create(results
);
193 bool FileManagerPrivateInternalSetDefaultTaskFunction::RunSync() {
194 using extensions::api::file_manager_private_internal::SetDefaultTask::Params
;
195 const scoped_ptr
<Params
> params(Params::Create(*args_
));
196 EXTENSION_FUNCTION_VALIDATE(params
);
198 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
199 file_manager::util::GetFileSystemContextForRenderFrameHost(
200 GetProfile(), render_frame_host());
202 const std::set
<std::string
> suffixes
=
203 GetUniqueSuffixes(params
->urls
, file_system_context
.get());
204 const std::set
<std::string
> mime_types
=
205 GetUniqueMimeTypes(params
->mime_types
);
207 // If there weren't any mime_types, and all the suffixes were blank,
208 // then we "succeed", but don't actually associate with anything.
209 // Otherwise, any time we set the default on a file with no extension
210 // on the local drive, we'd fail.
211 // TODO(gspencer): Fix file manager so that it never tries to set default in
212 // cases where extensionless local files are part of the selection.
213 if (suffixes
.empty() && mime_types
.empty()) {
214 SetResult(new base::FundamentalValue(true));
218 file_manager::file_tasks::UpdateDefaultTask(
219 GetProfile()->GetPrefs(), params
->task_id
, suffixes
, mime_types
);
223 } // namespace extensions