file_tasks.h revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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 representation 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", "mount-archive". These built-in 22// handlers are often handled in special manners inside Files.app. 23// This information also comes from FileBrowserHandler::GetHandlers(). 24// 25// See also: 26// ui/file_manager/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// awkward. 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 following 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 former 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" are handled internally in Files.app. 103// "mount-archive" is handled very differently. The task execution business 104// should be simplified: crbug.com/267313 105// 106// See also: 107// ui/file_manager/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 "chrome/common/extensions/api/file_browser_private.h" 121#include "url/gurl.h" 122 123class PrefService; 124class Profile; 125 126namespace drive { 127class DriveAppRegistry; 128} 129 130namespace fileapi { 131class FileSystemURL; 132} 133 134namespace file_manager { 135namespace file_tasks { 136 137// Task types as explained in the comment above. Search for <task-type>. 138enum TaskType { 139 TASK_TYPE_FILE_BROWSER_HANDLER, 140 TASK_TYPE_FILE_HANDLER, 141 TASK_TYPE_DRIVE_APP, 142 TASK_TYPE_UNKNOWN, // Used only for handling errors. 143}; 144 145// Describes a task. 146// See the comment above for <app-id>, <task-type>, and <action-id>. 147struct TaskDescriptor { 148 TaskDescriptor(const std::string& in_app_id, 149 TaskType in_task_type, 150 const std::string& in_action_id) 151 : app_id(in_app_id), 152 task_type(in_task_type), 153 action_id(in_action_id) { 154 } 155 TaskDescriptor() { 156 } 157 158 std::string app_id; 159 TaskType task_type; 160 std::string action_id; 161}; 162 163// Describes a task with extra information such as icon URL. 164class FullTaskDescriptor { 165 public: 166 FullTaskDescriptor(const TaskDescriptor& task_descriptor, 167 const std::string& task_title, 168 const GURL& icon_url, 169 bool is_default); 170 const TaskDescriptor& task_descriptor() const { return task_descriptor_; } 171 172 // The title of the task. 173 const std::string& task_title() const { return task_title_; } 174 // The icon URL for the task (ex. app icon) 175 const GURL& icon_url() const { return icon_url_; } 176 177 // True if this task is set as default. 178 bool is_default() const { return is_default_; } 179 void set_is_default(bool is_default) { is_default_ = is_default; } 180 181 private: 182 TaskDescriptor task_descriptor_; 183 std::string task_title_; 184 GURL icon_url_; 185 bool is_default_; 186}; 187 188// Update the default file handler for the given sets of suffixes and MIME 189// types. 190void UpdateDefaultTask(PrefService* pref_service, 191 const std::string& task_id, 192 const std::set<std::string>& suffixes, 193 const std::set<std::string>& mime_types); 194 195// Returns the task ID of the default task for the given |mime_type|/|suffix| 196// combination. If it finds a MIME type match, then it prefers that over a 197// suffix match. If it a default can't be found, then it returns the empty 198// string. 199std::string GetDefaultTaskIdFromPrefs(const PrefService& pref_service, 200 const std::string& mime_type, 201 const std::string& suffix); 202 203// Generates task id for the task specified by |app_id|, |task_type| and 204// |action_id|. 205// 206// |app_id| is either of Chrome Extension/App ID or Drive App ID. 207// |action_id| is a free-form string ID for the action. 208std::string MakeTaskID(const std::string& app_id, 209 TaskType task_type, 210 const std::string& action_id); 211 212// Returns a task id for the Drive app with |app_id|. 213// TODO(gspencer): For now, the action id is always "open-with", but we 214// could add any actions that the drive app supports. 215std::string MakeDriveAppTaskId(const std::string& app_id); 216 217// Converts |task_descriptor| to a task ID. 218std::string TaskDescriptorToId(const TaskDescriptor& task_descriptor); 219 220// Parses the task ID and extracts app ID, task type, and action ID into 221// |task|. On failure, returns false, and the contents of |task| are 222// undefined. 223// 224// See also the comment at the beginning of the file for details for how 225// "task_id" looks like. 226bool ParseTaskID(const std::string& task_id, TaskDescriptor* task); 227 228// The callback is used for ExecuteFileTask(). Will be called with true if 229// the file task execution is successful, or false if unsuccessful. 230typedef base::Callback<void(extensions::api::file_browser_private::TaskResult 231 result)> FileTaskFinishedCallback; 232 233// Executes file handler task for each element of |file_urls|. 234// Returns |false| if the execution cannot be initiated. Otherwise returns 235// |true| and then eventually calls |done| when all the files have been handled. 236// |done| can be a null callback. 237// 238// Parameters: 239// profile - The profile used for making this function call. 240// source_url - The source URL which originates this function call. 241// task - See the comment at TaskDescriptor struct. 242// file_urls - URLs of the target files. 243// done - The callback which will be called on completion. 244// The callback won't be called if the function returns 245// false. 246bool ExecuteFileTask(Profile* profile, 247 const GURL& source_url, 248 const TaskDescriptor& task, 249 const std::vector<fileapi::FileSystemURL>& file_urls, 250 const FileTaskFinishedCallback& done); 251 252typedef 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. 258void 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|. 265void 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|. 272void 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. 288void 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. 298void 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