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_FILE_MANAGER_FILE_TASKS_H_ 111 #define CHROME_BROWSER_CHROMEOS_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 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h" 120 #include "url/gurl.h" 121 122 class PrefService; 123 class Profile; 124 125 namespace drive { 126 class DriveAppRegistry; 127 } 128 129 namespace fileapi { 130 class FileSystemURL; 131 } 132 133 namespace file_manager { 134 namespace file_tasks { 135 136 // Task types as explained in the comment above. Search for <task-type>. 137 enum TaskType { 138 TASK_TYPE_FILE_BROWSER_HANDLER, 139 TASK_TYPE_FILE_HANDLER, 140 TASK_TYPE_DRIVE_APP, 141 TASK_TYPE_UNKNOWN, // Used only for handling errors. 142 }; 143 144 // Describes a task. 145 // See the comment above for <app-id>, <task-type>, and <action-id>. 146 struct TaskDescriptor { 147 TaskDescriptor(const std::string& in_app_id, 148 TaskType in_task_type, 149 const std::string& in_action_id) 150 : app_id(in_app_id), 151 task_type(in_task_type), 152 action_id(in_action_id) { 153 } 154 TaskDescriptor() { 155 } 156 157 std::string app_id; 158 TaskType task_type; 159 std::string action_id; 160 }; 161 162 // Describes a task with extra information such as icon URL. 163 class FullTaskDescriptor { 164 public: 165 FullTaskDescriptor(const TaskDescriptor& task_descriptor, 166 const std::string& task_title, 167 const GURL& icon_url, 168 bool is_default); 169 const TaskDescriptor& task_descriptor() const { return task_descriptor_; } 170 171 // The title of the task. 172 const std::string& task_title() const { return task_title_; } 173 // The icon URL for the task (ex. app icon) 174 const GURL& icon_url() const { return icon_url_; } 175 176 // True if this task is set as default. 177 bool is_default() const { return is_default_; } 178 void set_is_default(bool is_default) { is_default_ = is_default; } 179 180 private: 181 TaskDescriptor task_descriptor_; 182 std::string task_title_; 183 GURL icon_url_; 184 bool is_default_; 185 }; 186 187 // Update the default file handler for the given sets of suffixes and MIME 188 // types. 189 void UpdateDefaultTask(PrefService* pref_service, 190 const std::string& task_id, 191 const std::set<std::string>& suffixes, 192 const std::set<std::string>& mime_types); 193 194 // Returns the task ID of the default task for the given |mime_type|/|suffix| 195 // combination. If it finds a MIME type match, then it prefers that over a 196 // suffix match. If it a default can't be found, then it returns the empty 197 // string. 198 std::string GetDefaultTaskIdFromPrefs(const PrefService& pref_service, 199 const std::string& mime_type, 200 const std::string& suffix); 201 202 // Generates task id for the task specified by |app_id|, |task_type| and 203 // |action_id|. 204 // 205 // |app_id| is either of Chrome Extension/App ID or Drive App ID. 206 // |action_id| is a free-form string ID for the action. 207 std::string MakeTaskID(const std::string& app_id, 208 TaskType task_type, 209 const std::string& action_id); 210 211 // Returns a task id for the Drive app with |app_id|. 212 // TODO(gspencer): For now, the action id is always "open-with", but we 213 // could add any actions that the drive app supports. 214 std::string MakeDriveAppTaskId(const std::string& app_id); 215 216 // Converts |task_descriptor| to a task ID. 217 std::string TaskDescriptorToId(const TaskDescriptor& task_descriptor); 218 219 // Parses the task ID and extracts app ID, task type, and action ID into 220 // |task|. On failure, returns false, and the contents of |task| are 221 // undefined. 222 // 223 // See also the comment at the beginning of the file for details for how 224 // "task_id" looks like. 225 bool ParseTaskID(const std::string& task_id, TaskDescriptor* task); 226 227 // The callback is used for ExecuteFileTask(). Will be called with true if 228 // the file task execution is successful, or false if unsuccessful. 229 typedef base::Callback<void(bool success)> FileTaskFinishedCallback; 230 231 // Executes file handler task for each element of |file_urls|. 232 // Returns |false| if the execution cannot be initiated. Otherwise returns 233 // |true| and then eventually calls |done| when all the files have been handled. 234 // |done| can be a null callback. 235 // 236 // Parameters: 237 // profile - The profile used for making this function call. 238 // app_id - The ID of the app requesting the file task execution. 239 // source_url - The source URL which originates this function call. 240 // task - See the comment at TaskDescriptor struct. 241 // file_urls - URLs of the target files. 242 // done - The callback which will be called on completion. 243 // The callback won't be called if the function returns 244 // false. 245 bool ExecuteFileTask(Profile* profile, 246 const GURL& source_url, 247 const std::string& app_id, 248 const TaskDescriptor& task, 249 const std::vector<fileapi::FileSystemURL>& file_urls, 250 const FileTaskFinishedCallback& done); 251 252 typedef extensions::app_file_handler_util::PathAndMimeTypeSet 253 PathAndMimeTypeSet; 254 255 // Finds the Drive app tasks that can be used with the given |path_mime_set| 256 // from |drive_app_registry|, and append them to the |result_list|. 257 // Drive app tasks will be found only if all of the files are on Drive. 258 void FindDriveAppTasks(const drive::DriveAppRegistry& drive_app_registry, 259 const PathAndMimeTypeSet& path_mime_set, 260 std::vector<FullTaskDescriptor>* result_list); 261 262 // Finds the file handler tasks (apps declaring "file_handlers" in 263 // manifest.json) that can be used with the given files, appending them to 264 // the |result_list|. 265 void FindFileHandlerTasks(Profile* profile, 266 const PathAndMimeTypeSet& path_mime_set, 267 std::vector<FullTaskDescriptor>* result_list); 268 269 // Finds the file browser handler tasks (app/extensions declaring 270 // "file_browser_handlers" in manifest.json) that can be used with the 271 // given files, appending them to the |result_list|. 272 void FindFileBrowserHandlerTasks( 273 Profile* profile, 274 const std::vector<GURL>& file_urls, 275 std::vector<FullTaskDescriptor>* result_list); 276 277 // Finds all types (drive, file handlers, file browser handlers) of 278 // tasks. See the comment at FindDriveAppTasks() about |result_list|. 279 // Drive app tasks will be found only if all of the files are on Drive. 280 // |drive_app_registry| can be NULL if the drive app registry is not 281 // present. 282 // 283 // If |path_mime_set| contains a Google document, only the internal tasks of 284 // Files.app (i.e., tasks having the app ID of Files.app) are listed. 285 // This is to avoid dups between Drive app tasks and an internal handler that 286 // Files.app provides, and to avoid listing normal file handler and file browser 287 // handler tasks, which can handle only normal files. 288 void FindAllTypesOfTasks( 289 Profile* profile, 290 const drive::DriveAppRegistry* drive_app_registry, 291 const PathAndMimeTypeSet& path_mime_set, 292 const std::vector<GURL>& file_urls, 293 std::vector<FullTaskDescriptor>* result_list); 294 295 // Chooses the default task in |tasks| and sets it as default, if the default 296 // task is found (i.e. the default task may not exist in |tasks|). No tasks 297 // should be set as default before calling this function. 298 void ChooseAndSetDefaultTask(const PrefService& pref_service, 299 const PathAndMimeTypeSet& path_mime_set, 300 std::vector<FullTaskDescriptor>* tasks); 301 302 } // namespace file_tasks 303 } // namespace file_manager 304 305 #endif // CHROME_BROWSER_CHROMEOS_FILE_MANAGER_FILE_TASKS_H_ 306