Home | History | Annotate | Download | only in file_manager
      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