1 // Copyright (c) 2012 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 // This file provides utility functions for "file tasks".
7 // WHAT ARE FILE TASKS?
9 // File tasks are representation of actions that can be performed over the
10 // currently selected files from Files.app. A task can be either of:
12 // 1) Chrome extension or app, registered via "file_handlers" or
13 // "file_browser_handlers" in manifest.json (ex. Text.app). This information
14 // comes from FileBrowserHandler::GetHandlers()
17 // https://developer.chrome.com/extensions/manifest.html#file_handlers
18 // https://developer.chrome.com/extensions/fileBrowserHandler.html
20 // 2) Built-in handlers provided from Files.app. Files.app provides lots of
21 // file_browser_handlers, such as "play", "mount-archive". These built-in
22 // handlers are often handled in special manners inside Files.app.
23 // This information also comes from FileBrowserHandler::GetHandlers().
26 // ui/file_manager/file_manager/manifest.json
28 // 3) Drive app, which is a hosted app (i.e. just web site), that can work
29 // with Drive (ex. Pixlr Editor). This information comes from
30 // drive::DriveAppRegistry.
33 // https://chrome.google.com/webstore/category/collection/drive_apps
35 // For example, if the user is now selecting a JPEG file, Files.app will
36 // receive file tasks represented as a JSON object via
37 // chrome.fileManagerPrivate.getFileTasks() API, which look like:
42 // "iconUrl": "<app_icon_url>",
43 // "isDefault": false,
44 // "taskId": "<drive_app_id>|drive|open-with",
45 // "title": "Drive App Name (ex. Pixlr Editor)"
49 // "iconUrl": "chrome://extension-icon/hhaomjibdihmijegdhdafkllkbggdgoj/16/1",
51 // "taskId": "hhaomjibdihmijegdhdafkllkbggdgoj|file|gallery",
52 // "title": "__MSG_OPEN_ACTION__"
56 // The first file task is a Drive app. The second file task is a built-in
57 // handler from Files.app.
61 // You may have noticed that "taskId" fields in the above example look
62 // awkward. Apparently "taskId" encodes three types of information delimited
63 // by "|". This is a weird format for something called as an ID.
65 // 1) Why are the three types information encoded in this way?
67 // It's just a historical reason. The reason is that a simple string can be
68 // easily stored in user's preferences. We should stop doing this, by storing
69 // this information in chrome.storage instead. crbug.com/267359.
71 // 2) OK, then what are the three types of information encoded here?
73 // The task ID encodes the following structure:
75 // <app-id>|<task-type>|<task-action-id>
77 // <app-id> is either of Chrome Extension/App ID or Drive App ID. For some
78 // reason, Chrome Extension/App IDs and Drive App IDs look differently. As of
79 // writing, the former looks like "hhaomjibdihmijegdhdafkllkbggdgoj"
80 // (Files.app) and the latter looks like "419782477519" (Pixlr Editor).
82 // <task-type> is either of
83 // - "file" - File browser handler - app/extension declaring
84 // "file_browser_handlers" in manifest.
85 // - "app" - File handler - app declaring "file_handlers" in manifest.json.
86 // - "drive" - Drive App
88 // <task-action-id> is an ID string used for identifying actions provided
89 // from a single Chrome Extension/App. In other words, a single
90 // Chrome/Extension can provide multiple file handlers hence each of them
91 // needs to have a unique action ID. For Drive apps, <task-action-id> is
92 // always "open-with".
94 // HOW TASKS ARE EXECUTED?
96 // chrome.fileManagerPrivate.viewFiles() is used to open a file in a browser,
97 // without any handler. Browser will take care of handling the file (ex. PDF).
99 // chrome.fileManagerPrivate.executeTasks() is used to open a file with a
100 // handler (Chrome Extension/App or Drive App).
102 // Some built-in handlers such as "play" are handled internally in Files.app.
103 // "mount-archive" is handled very differently. The task execution business
104 // should be simplified: crbug.com/267313
107 // ui/file_manager/file_manager/foreground/js/file_tasks.js
110 #ifndef CHROME_BROWSER_CHROMEOS_FILE_MANAGER_FILE_TASKS_H_
111 #define CHROME_BROWSER_CHROMEOS_FILE_MANAGER_FILE_TASKS_H_
117 #include "base/basictypes.h"
118 #include "base/callback_forward.h"
119 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
120 #include "chrome/common/extensions/api/file_manager_private.h"
121 #include "url/gurl.h"
127 class DriveAppRegistry
;
134 namespace file_manager
{
135 namespace file_tasks
{
137 // Task types as explained in the comment above. Search for <task-type>.
139 TASK_TYPE_FILE_BROWSER_HANDLER
,
140 TASK_TYPE_FILE_HANDLER
,
142 TASK_TYPE_UNKNOWN
, // Used only for handling errors.
146 // See the comment above for <app-id>, <task-type>, and <action-id>.
147 struct TaskDescriptor
{
148 TaskDescriptor(const std::string
& in_app_id
,
149 TaskType in_task_type
,
150 const std::string
& in_action_id
)
152 task_type(in_task_type
),
153 action_id(in_action_id
) {
160 std::string action_id
;
163 // Describes a task with extra information such as icon URL.
164 class FullTaskDescriptor
{
166 FullTaskDescriptor(const TaskDescriptor
& task_descriptor
,
167 const std::string
& task_title
,
168 const GURL
& icon_url
,
170 bool is_generic_file_handler
);
171 const TaskDescriptor
& task_descriptor() const { return task_descriptor_
; }
173 // The title of the task.
174 const std::string
& task_title() const { return task_title_
; }
175 // The icon URL for the task (ex. app icon)
176 const GURL
& icon_url() const { return icon_url_
; }
178 // True if this task is set as default.
179 bool is_default() const { return is_default_
; }
180 void set_is_default(bool is_default
) { is_default_
= is_default
; }
182 // True if this task is from generic file handler. Generic file handler is a
183 // file handler which handles any type of files (e.g. extensions: ["*"],
184 // types: ["*/*"]). Partial wild card (e.g. types: ["image/*"]) is not
185 // generic file handler.
186 bool is_generic_file_handler() const { return is_generic_file_handler_
; }
187 void set_is_generic_file_handler(bool is_generic_file_handler
) {
188 is_generic_file_handler_
= is_generic_file_handler
;
192 TaskDescriptor task_descriptor_
;
193 std::string task_title_
;
196 bool is_generic_file_handler_
;
199 // Update the default file handler for the given sets of suffixes and MIME
201 void UpdateDefaultTask(PrefService
* pref_service
,
202 const std::string
& task_id
,
203 const std::set
<std::string
>& suffixes
,
204 const std::set
<std::string
>& mime_types
);
206 // Returns the task ID of the default task for the given |mime_type|/|suffix|
207 // combination. If it finds a MIME type match, then it prefers that over a
208 // suffix match. If it a default can't be found, then it returns the empty
210 std::string
GetDefaultTaskIdFromPrefs(const PrefService
& pref_service
,
211 const std::string
& mime_type
,
212 const std::string
& suffix
);
214 // Generates task id for the task specified by |app_id|, |task_type| and
217 // |app_id| is either of Chrome Extension/App ID or Drive App ID.
218 // |action_id| is a free-form string ID for the action.
219 std::string
MakeTaskID(const std::string
& app_id
,
221 const std::string
& action_id
);
223 // Converts |task_descriptor| to a task ID.
224 std::string
TaskDescriptorToId(const TaskDescriptor
& task_descriptor
);
226 // Parses the task ID and extracts app ID, task type, and action ID into
227 // |task|. On failure, returns false, and the contents of |task| are
230 // See also the comment at the beginning of the file for details for how
231 // "task_id" looks like.
232 bool ParseTaskID(const std::string
& task_id
, TaskDescriptor
* task
);
234 // The callback is used for ExecuteFileTask(). Will be called with true if
235 // the file task execution is successful, or false if unsuccessful.
236 typedef base::Callback
<void(extensions::api::file_manager_private::TaskResult
237 result
)> FileTaskFinishedCallback
;
239 // Executes file handler task for each element of |file_urls|.
240 // Returns |false| if the execution cannot be initiated. Otherwise returns
241 // |true| and then eventually calls |done| when all the files have been handled.
242 // |done| can be a null callback.
245 // profile - The profile used for making this function call.
246 // source_url - The source URL which originates this function call.
247 // task - See the comment at TaskDescriptor struct.
248 // file_urls - URLs of the target files.
249 // done - The callback which will be called on completion.
250 // The callback won't be called if the function returns
252 bool ExecuteFileTask(Profile
* profile
,
253 const GURL
& source_url
,
254 const TaskDescriptor
& task
,
255 const std::vector
<storage::FileSystemURL
>& file_urls
,
256 const FileTaskFinishedCallback
& done
);
258 typedef extensions::app_file_handler_util::PathAndMimeTypeSet
261 // Finds the Drive app tasks that can be used with the given |path_mime_set|
262 // from |drive_app_registry|, and append them to the |result_list|.
263 // Drive app tasks will be found only if all of the files are on Drive.
264 void FindDriveAppTasks(const drive::DriveAppRegistry
& drive_app_registry
,
265 const PathAndMimeTypeSet
& path_mime_set
,
266 std::vector
<FullTaskDescriptor
>* result_list
);
268 // Returns whether a file handler info is a generic file handler or not.
269 bool IsGenericFileHandler(const extensions::FileHandlerInfo
& file_handler_info
);
271 // Finds the file handler tasks (apps declaring "file_handlers" in
272 // manifest.json) that can be used with the given files, appending them to
273 // the |result_list|.
274 void FindFileHandlerTasks(Profile
* profile
,
275 const PathAndMimeTypeSet
& path_mime_set
,
276 std::vector
<FullTaskDescriptor
>* result_list
);
278 // Finds the file browser handler tasks (app/extensions declaring
279 // "file_browser_handlers" in manifest.json) that can be used with the
280 // given files, appending them to the |result_list|.
281 void FindFileBrowserHandlerTasks(
283 const std::vector
<GURL
>& file_urls
,
284 std::vector
<FullTaskDescriptor
>* result_list
);
286 // Finds all types (drive, file handlers, file browser handlers) of
287 // tasks. See the comment at FindDriveAppTasks() about |result_list|.
288 // Drive app tasks will be found only if all of the files are on Drive.
289 // |drive_app_registry| can be NULL if the drive app registry is not
292 // If |path_mime_set| contains a Google document, only the internal tasks of
293 // Files.app (i.e., tasks having the app ID of Files.app) are listed.
294 // This is to avoid dups between Drive app tasks and an internal handler that
295 // Files.app provides, and to avoid listing normal file handler and file browser
296 // handler tasks, which can handle only normal files.
297 void FindAllTypesOfTasks(
299 const drive::DriveAppRegistry
* drive_app_registry
,
300 const PathAndMimeTypeSet
& path_mime_set
,
301 const std::vector
<GURL
>& file_urls
,
302 std::vector
<FullTaskDescriptor
>* result_list
);
304 // Chooses the default task in |tasks| and sets it as default, if the default
305 // task is found (i.e. the default task may not exist in |tasks|). No tasks
306 // should be set as default before calling this function.
307 void ChooseAndSetDefaultTask(const PrefService
& pref_service
,
308 const PathAndMimeTypeSet
& path_mime_set
,
309 std::vector
<FullTaskDescriptor
>* tasks
);
311 } // namespace file_tasks
312 } // namespace file_manager
314 #endif // CHROME_BROWSER_CHROMEOS_FILE_MANAGER_FILE_TASKS_H_