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.
4//
5// This file provides utility functions for "file tasks".
6//
7// WHAT ARE FILE TASKS?
8//
9// File tasks are representatiosn of actions that can be performed over the
10// currently selected files from Files.app. A task can be either of:
11//
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()
15//
16// See also:
17// https://developer.chrome.com/extensions/manifest.html#file_handlers
18// https://developer.chrome.com/extensions/fileBrowserHandler.html
19//
20// 2) Built-in handlers provided from Files.app. Files.app provides lots of
21// file_browser_handlers, such as "play", "watch", "mount-archive".  These
22// built-in handlers are often handled in special manners inside Files.app.
23// This information also comes from FileBrowserHandler::GetHandlers().
24//
25// See also:
26// chrome/browser/resources/file_manager/manifest.json
27//
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.
31//
32// See also:
33// https://chrome.google.com/webstore/category/collection/drive_apps
34//
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.fileBrowserPrivate.getFileTasks() API, which look like:
38//
39// [
40//   {
41//     "driveApp": true,
42//     "iconUrl": "<app_icon_url>",
43//     "isDefault": false,
44//     "taskId": "<drive_app_id>|drive|open-with",
45//     "title": "Drive App Name (ex. Pixlr Editor)"
46//   },
47//   {
48//     "driveApp": false,
49//     "iconUrl": "chrome://extension-icon/hhaomjibdihmijegdhdafkllkbggdgoj/16/1",
50//     "isDefault": true,
51//     "taskId": "hhaomjibdihmijegdhdafkllkbggdgoj|file|gallery",
52//     "title": "__MSG_OPEN_ACTION__"
53//   }
54// ]
55//
56// The first file task is a Drive app. The second file task is a built-in
57// handler from Files.app.
58//
59// WHAT ARE TASK IDS?
60//
61// You may have noticed that "taskId" fields in the above example look
62// awakard. Apparently "taskId" encodes three types of information delimited
63// by "|". This is a weird format for something called as an ID.
64//
65// 1) Why are the three types information encoded in this way?
66//
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.
70//
71// 2) OK, then what are the three types of information encoded here?
72//
73// The task ID encodes the folloing structure:
74//
75//     <app-id>|<task-type>|<task-action-id>
76//
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 fomer looks like "hhaomjibdihmijegdhdafkllkbggdgoj"
80// (Files.app) and the latter looks like "419782477519" (Pixlr Editor).
81//
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
87//
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".
93//
94// HOW TASKS ARE EXECUTED?
95//
96// chrome.fileBrowserPrivate.viewFiles() is used to open a file in a browser,
97// without any handler. Browser will take care of handling the file (ex. PDF).
98//
99// chrome.fileBrowserPrivate.executeTasks() is used to open a file with a
100// handler (Chrome Extension/App or Drive App).
101//
102// Some built-in handlers such as "play" and "watch" are handled internally
103// in Files.app. "mount-archive" is handled very differently. The task
104// execution business should be simplified: crbug.com/267313
105//
106// See also:
107// chrome/browser/resources/file_manager/js/file_tasks.js
108//
109
110#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_TASKS_H_
111#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_TASKS_H_
112
113#include <set>
114#include <string>
115#include <vector>
116
117#include "base/basictypes.h"
118#include "base/callback_forward.h"
119
120class GURL;
121class Profile;
122
123namespace fileapi {
124class FileSystemURL;
125}
126
127namespace file_manager {
128namespace file_tasks {
129
130// Task types encoded in task IDs. See also the comment at the beginning of
131// the file about <task-type>.
132extern const char kFileBrowserHandlerTaskType[];
133extern const char kFileHandlerTaskType[];
134extern const char kDriveTaskType[];
135
136// Describes a task.
137// See the comment above for <app-id>, <task-type>, and <action-id>.
138struct TaskDescriptor {
139  TaskDescriptor(const std::string& in_app_id,
140                 const std::string& in_task_type,
141                 const std::string& in_action_id)
142      : app_id(in_app_id),
143        task_type(in_task_type),
144        action_id(in_action_id) {
145  }
146  TaskDescriptor() {
147  }
148
149  std::string app_id;
150  std::string task_type;
151  std::string action_id;
152};
153
154// Update the default file handler for the given sets of suffixes and MIME
155// types.
156void UpdateDefaultTask(Profile* profile,
157                       const std::string& task_id,
158                       const std::set<std::string>& suffixes,
159                       const std::set<std::string>& mime_types);
160
161// Returns the task ID of the default task for the given |mime_type|/|suffix|
162// combination. If it finds a MIME type match, then it prefers that over a
163// suffix match. If it a default can't be found, then it returns the empty
164// string.
165std::string GetDefaultTaskIdFromPrefs(Profile* profile,
166                                      const std::string& mime_type,
167                                      const std::string& suffix);
168
169// Generates task id for the task specified by |app_id|, |task_type| and
170// |action_id|. The |task_type| must be one of kFileBrowserHandlerTaskType,
171// kDriveTaskType or kFileHandlerTaskType.
172// <app-id> is either of Chrome Extension/App ID or Drive App ID.
173std::string MakeTaskID(const std::string& extension_id,
174                       const std::string& task_type,
175                       const std::string& action_id);
176
177// Returns a task id for the Drive app with |app_id|.
178// TODO(gspencer): For now, the action id is always "open-with", but we
179// could add any actions that the drive app supports.
180std::string MakeDriveAppTaskId(const std::string& app_id);
181
182// Parses the task ID and extracts app ID, task type, and action ID into
183// |task|. On failure, returns false, and the contents of |task| are
184// undefined.
185//
186// See also the comment at the beginning of the file for details for how
187// "task_id" looks like.
188bool ParseTaskID(const std::string& task_id, TaskDescriptor* task);
189
190// The callback is used for ExecuteFileTask(). Will be called with true if
191// the file task execution is successful, or false if unsuccessful.
192typedef base::Callback<void(bool success)> FileTaskFinishedCallback;
193
194// Executes file handler task for each element of |file_urls|.
195// Returns |false| if the execution cannot be initiated. Otherwise returns
196// |true| and then eventually calls |done| when all the files have been handled.
197// |done| can be a null callback.
198//
199// Parameters:
200// profile    - The profile used for making this function call.
201// source_url - The source URL which originates this function call.
202// tab_id     - The ID of the tab which originates this function call.
203//              This can be 0 if no tab is associated.
204// task       - See the comment at TaskDescriptor struct.
205// file_urls  - URLs of the target files.
206// done       - The callback which will be called on completion.
207//              The callback won't be called if the function returns
208//              false.
209bool ExecuteFileTask(Profile* profile,
210                     const GURL& source_url,
211                     const std::string& file_browser_id,
212                     int32 tab_id,
213                     const TaskDescriptor& task,
214                     const std::vector<fileapi::FileSystemURL>& file_urls,
215                     const FileTaskFinishedCallback& done);
216
217}  // namespace file_tasks
218}  // namespace file_manager
219
220#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_TASKS_H_
221