15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/file_tasks.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "apps/launcher.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/prefs/pref_service.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_task_executor.h"
148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/app_id.h"
1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/file_browser_handlers.h"
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/open_util.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/drive/drive_api_util.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/drive/drive_app_registry.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h"
218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
2334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "chrome/browser/ui/extensions/application_launch.h"
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/common/extensions/api/file_manager_private.h"
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/extension_constants.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h"
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/extension_registry.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/extension_util.h"
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/constants.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h"
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_url.h"
36ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension;
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using extensions::app_file_handler_util::FindFileHandlersForFiles;
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURL;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace file_manager {
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace file_tasks {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace {
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// The values "file" and "app" are confusing, but cannot be changed easily as
47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// these are used in default task IDs stored in preferences.
48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst char kFileBrowserHandlerTaskType[] = "file";
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst char kFileHandlerTaskType[] = "app";
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kDriveAppTaskType[] = "drive";
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Drive apps always use the action ID.
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kDriveAppActionID[] = "open-with";
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Converts a TaskType to a string.
563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)std::string TaskTypeToString(TaskType task_type) {
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (task_type) {
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case TASK_TYPE_FILE_BROWSER_HANDLER:
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return kFileBrowserHandlerTaskType;
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case TASK_TYPE_FILE_HANDLER:
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return kFileHandlerTaskType;
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case TASK_TYPE_DRIVE_APP:
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return kDriveAppTaskType;
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case TASK_TYPE_UNKNOWN:
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NOTREACHED();
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return "";
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Converts a string to a TaskType. Returns TASK_TYPE_UNKNOWN on error.
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TaskType StringToTaskType(const std::string& str) {
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (str == kFileBrowserHandlerTaskType)
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return TASK_TYPE_FILE_BROWSER_HANDLER;
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (str == kFileHandlerTaskType)
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return TASK_TYPE_FILE_HANDLER;
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (str == kDriveAppTaskType)
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return TASK_TYPE_DRIVE_APP;
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return TASK_TYPE_UNKNOWN;
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Legacy Drive task extension prefix, used by CrackTaskID.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDriveTaskExtensionPrefix[] = "drive-app:";
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kDriveTaskExtensionPrefixLength =
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kDriveTaskExtensionPrefix) - 1;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Returns true if path_mime_set contains a Google document.
888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ContainsGoogleDocument(const PathAndMimeTypeSet& path_mime_set) {
898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (PathAndMimeTypeSet::const_iterator iter = path_mime_set.begin();
908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       iter != path_mime_set.end(); ++iter) {
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (drive::util::HasHostedDocumentExtension(iter->first))
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return true;
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return false;
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Leaves tasks handled by the file manger itself as is and removes all others.
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void KeepOnlyFileManagerInternalTasks(std::vector<FullTaskDescriptor>* tasks) {
998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::vector<FullTaskDescriptor> filtered;
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (size_t i = 0; i < tasks->size(); ++i) {
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if ((*tasks)[i].task_descriptor().app_id == kFileManagerAppId)
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      filtered.push_back((*tasks)[i]);
1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  tasks->swap(filtered);
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Returns true if the given task is a handler by built-in apps like Files.app
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// itself or QuickOffice etc. They are used as the initial default app.
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool IsFallbackFileHandler(const file_tasks::TaskDescriptor& task) {
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (task.task_type != file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER &&
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      task.task_type != file_tasks::TASK_TYPE_FILE_HANDLER)
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const char* kBuiltInApps[] = {
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    kFileManagerAppId,
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    kVideoPlayerAppId,
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    kGalleryAppId,
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    extension_misc::kQuickOfficeComponentExtensionId,
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    extension_misc::kQuickOfficeInternalExtensionId,
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    extension_misc::kQuickOfficeExtensionId,
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < arraysize(kBuiltInApps); ++i) {
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (task.app_id == kBuiltInApps[i])
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return true;
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return false;
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FullTaskDescriptor::FullTaskDescriptor(
133424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const TaskDescriptor& task_descriptor,
134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& task_title,
135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const GURL& icon_url,
136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    bool is_default)
137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : task_descriptor_(task_descriptor),
138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      task_title_(task_title),
139424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      icon_url_(icon_url),
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      is_default_(is_default) {
141424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
142424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
143424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void UpdateDefaultTask(PrefService* pref_service,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& task_id,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::set<std::string>& suffixes,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::set<std::string>& mime_types) {
147424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!pref_service)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mime_types.empty()) {
151424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DictionaryPrefUpdate mime_type_pref(pref_service,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        prefs::kDefaultTasksByMimeType);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::set<std::string>::const_iterator iter = mime_types.begin();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iter != mime_types.end(); ++iter) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringValue* value = new base::StringValue(task_id);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mime_type_pref->SetWithoutPathExpansion(*iter, value);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!suffixes.empty()) {
161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DictionaryPrefUpdate mime_type_pref(pref_service,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        prefs::kDefaultTasksBySuffix);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::set<std::string>::const_iterator iter = suffixes.begin();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iter != suffixes.end(); ++iter) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringValue* value = new base::StringValue(task_id);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Suffixes are case insensitive.
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      std::string lower_suffix = base::StringToLowerASCII(*iter);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mime_type_pref->SetWithoutPathExpansion(lower_suffix, value);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
173424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)std::string GetDefaultTaskIdFromPrefs(const PrefService& pref_service,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& mime_type,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& suffix) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Looking for default for MIME type: " << mime_type
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << " and suffix: " << suffix;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string task_id;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mime_type.empty()) {
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* mime_task_prefs =
181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        pref_service.GetDictionary(prefs::kDefaultTasksByMimeType);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(mime_task_prefs);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(ERROR, !mime_task_prefs) << "Unable to open MIME type prefs";
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mime_task_prefs &&
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mime_task_prefs->GetStringWithoutPathExpansion(mime_type, &task_id)) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "Found MIME default handler: " << task_id;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return task_id;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* suffix_task_prefs =
192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pref_service.GetDictionary(prefs::kDefaultTasksBySuffix);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(suffix_task_prefs);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, !suffix_task_prefs) << "Unable to open suffix prefs";
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string lower_suffix = base::StringToLowerASCII(suffix);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (suffix_task_prefs)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    suffix_task_prefs->GetStringWithoutPathExpansion(lower_suffix, &task_id);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG_IF(1, !task_id.empty()) << "Found suffix default handler: " << task_id;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return task_id;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)std::string MakeTaskID(const std::string& app_id,
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                       TaskType task_type,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& action_id) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPrintf("%s|%s|%s",
206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                            app_id.c_str(),
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            TaskTypeToString(task_type).c_str(),
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            action_id.c_str());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)std::string TaskDescriptorToId(const TaskDescriptor& task_descriptor) {
212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return MakeTaskID(task_descriptor.app_id,
213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    task_descriptor.task_type,
214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    task_descriptor.action_id);
215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool ParseTaskID(const std::string& task_id, TaskDescriptor* task) {
218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(task);
219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> result;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = Tokenize(task_id, std::string("|"), &result);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Parse a legacy task ID that only contain two parts. Drive tasks are
224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // identified by a prefix "drive-app:" on the extension ID. The legacy task
225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // IDs can be stored in preferences.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (count == 2) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (StartsWithASCII(result[0], kDriveTaskExtensionPrefix, true)) {
2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      task->task_type = TASK_TYPE_DRIVE_APP;
229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      task->app_id = result[0].substr(kDriveTaskExtensionPrefixLength);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      task->task_type = TASK_TYPE_FILE_BROWSER_HANDLER;
232ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      task->app_id = result[0];
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    task->action_id = result[1];
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (count != 3)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  TaskType task_type = StringToTaskType(result[1]);
2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (task_type == TASK_TYPE_UNKNOWN)
2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  task->app_id = result[0];
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  task->task_type = task_type;
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  task->action_id = result[2];
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool ExecuteFileTask(Profile* profile,
2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     const GURL& source_url,
256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                     const TaskDescriptor& task,
2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     const std::vector<FileSystemURL>& file_urls,
2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     const FileTaskFinishedCallback& done) {
2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // drive::FileTaskExecutor is responsible to handle drive tasks.
2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (task.task_type == TASK_TYPE_DRIVE_APP) {
26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK_EQ(kDriveAppActionID, task.action_id);
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    drive::FileTaskExecutor* executor =
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        new drive::FileTaskExecutor(profile, task.app_id);
2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    executor->Execute(file_urls, done);
2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return true;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Get the extension.
269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const Extension* extension = extensions::ExtensionRegistry::Get(
270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      profile)->enabled_extensions().GetByID(task.app_id);
2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!extension)
2727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return false;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Execute the task.
2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (task.task_type == TASK_TYPE_FILE_BROWSER_HANDLER) {
276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return file_browser_handlers::ExecuteFileBrowserHandler(
277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        profile,
278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        extension,
279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        task.action_id,
280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        file_urls,
281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        done);
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (task.task_type == TASK_TYPE_FILE_HANDLER) {
28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::vector<base::FilePath> paths;
284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (size_t i = 0; i != file_urls.size(); ++i)
28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      paths.push_back(file_urls[i].path());
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    apps::LaunchPlatformAppWithFileHandler(
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        profile, extension, task.action_id, paths);
2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!done.is_null())
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      done.Run(extensions::api::file_manager_private::TASK_RESULT_MESSAGE_SENT);
2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return true;
2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  NOTREACHED();
2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return false;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void FindDriveAppTasks(
297424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const drive::DriveAppRegistry& drive_app_registry,
298424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PathAndMimeTypeSet& path_mime_set,
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<FullTaskDescriptor>* result_list) {
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(result_list);
301424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
302424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  bool is_first = true;
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  typedef std::map<std::string, drive::DriveAppInfo> DriveAppInfoMap;
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DriveAppInfoMap drive_app_map;
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (PathAndMimeTypeSet::const_iterator it = path_mime_set.begin();
307424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)       it != path_mime_set.end(); ++it) {
308424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const base::FilePath& file_path = it->first;
309424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& mime_type = it->second;
31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Return immediately if a file not on Drive is found, as Drive app tasks
31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // work only if all files are on Drive.
31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!drive::util::IsUnderDriveMountPoint(file_path))
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<drive::DriveAppInfo> app_info_list;
31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    drive_app_registry.GetAppsForFile(file_path.Extension(),
31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      mime_type,
31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      &app_info_list);
319424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
320424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (is_first) {
321424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // For the first file, we store all the info.
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (size_t j = 0; j < app_info_list.size(); ++j)
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        drive_app_map[app_info_list[j].app_id] = app_info_list[j];
324424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else {
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // For remaining files, take the intersection with the current
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // result, based on the app id.
32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      std::set<std::string> app_id_set;
32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      for (size_t j = 0; j < app_info_list.size(); ++j)
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        app_id_set.insert(app_info_list[j].app_id);
33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      for (DriveAppInfoMap::iterator iter = drive_app_map.begin();
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)           iter != drive_app_map.end();) {
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (app_id_set.count(iter->first) == 0) {
33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          drive_app_map.erase(iter++);
334424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        } else {
335424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          ++iter;
336424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        }
337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
338424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
339424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
340424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    is_first = false;
341424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
342424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (DriveAppInfoMap::const_iterator iter = drive_app_map.begin();
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)       iter != drive_app_map.end(); ++iter) {
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const drive::DriveAppInfo& app_info = iter->second;
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    TaskDescriptor descriptor(app_info.app_id,
34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              TASK_TYPE_DRIVE_APP,
34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              kDriveAppActionID);
34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    GURL icon_url = drive::util::FindPreferredIcon(
35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        app_info.app_icons,
35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        drive::util::kPreferredIconSize);
352424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    result_list->push_back(
353424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        FullTaskDescriptor(descriptor,
35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           app_info.app_name,
35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           icon_url,
35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           false /* is_default */));
357424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
358424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
359424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
360424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void FindFileHandlerTasks(
361424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    Profile* profile,
362424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PathAndMimeTypeSet& path_mime_set,
36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<FullTaskDescriptor>* result_list) {
364424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(!path_mime_set.empty());
365424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(result_list);
366424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const extensions::ExtensionSet& enabled_extensions =
368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (extensions::ExtensionSet::const_iterator iter =
370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           enabled_extensions.begin();
371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       iter != enabled_extensions.end();
372424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)       ++iter) {
373424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const Extension* extension = iter->get();
374424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
37534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    // Check that the extension can be launched via an event. This includes all
37634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    // platform apps plus whitelisted extensions.
37734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    if (!CanLaunchViaEvent(extension))
378424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      continue;
379424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Ephemeral apps cannot be file handlers.
381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (extensions::util::IsEphemeralApp(extension->id(), profile))
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      continue;
383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
384424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (profile->IsOffTheRecord() &&
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        !extensions::util::IsIncognitoEnabled(extension->id(), profile))
386424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      continue;
387424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
388424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    typedef std::vector<const extensions::FileHandlerInfo*> FileHandlerList;
389424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    FileHandlerList file_handlers =
390424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        FindFileHandlersForFiles(*extension, path_mime_set);
391424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (file_handlers.empty())
392424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      continue;
393424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Only show the first matching handler from each app.
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const extensions::FileHandlerInfo* file_handler = file_handlers.front();
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::string task_id = file_tasks::MakeTaskID(
3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extension->id(), file_tasks::TASK_TYPE_FILE_HANDLER, file_handler->id);
3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    GURL best_icon = extensions::ExtensionIconSource::GetIconURL(
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extension,
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        drive::util::kPreferredIconSize,
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ExtensionIconSet::MATCH_BIGGER,
4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        false,  // grayscale
4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        NULL);  // exists
4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    result_list->push_back(
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        FullTaskDescriptor(TaskDescriptor(extension->id(),
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          file_tasks::TASK_TYPE_FILE_HANDLER,
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          file_handler->id),
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           extension->name(),
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           best_icon,
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           false /* is_default */));
413424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
414424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
415424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
416424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void FindFileBrowserHandlerTasks(
417424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    Profile* profile,
418424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::vector<GURL>& file_urls,
41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<FullTaskDescriptor>* result_list) {
420424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(!file_urls.empty());
421424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(result_list);
422424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
423424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  file_browser_handlers::FileBrowserHandlerList common_tasks =
42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      file_browser_handlers::FindFileBrowserHandlers(profile, file_urls);
425424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (common_tasks.empty())
426424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
427424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const extensions::ExtensionSet& enabled_extensions =
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
430424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (file_browser_handlers::FileBrowserHandlerList::const_iterator iter =
431424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)           common_tasks.begin();
432424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)       iter != common_tasks.end();
433424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)       ++iter) {
434424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const FileBrowserHandler* handler = *iter;
435424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string extension_id = handler->extension_id();
436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Extension* extension = enabled_extensions.GetByID(extension_id);
437424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DCHECK(extension);
438424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
439424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // TODO(zelidrag): Figure out how to expose icon URL that task defined in
440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // manifest instead of the default extension icon.
441424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const GURL icon_url = extensions::ExtensionIconSource::GetIconURL(
442424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        extension,
443424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        extension_misc::EXTENSION_ICON_BITTY,
444424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        ExtensionIconSet::MATCH_BIGGER,
445424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        false,  // grayscale
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        NULL);  // exists
447424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    result_list->push_back(FullTaskDescriptor(
449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        TaskDescriptor(extension_id,
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                       file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                       handler->id()),
452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        handler->title(),
453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        icon_url,
45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        false /* is_default */));
455424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
458424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void FindAllTypesOfTasks(
459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    Profile* profile,
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const drive::DriveAppRegistry* drive_app_registry,
461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PathAndMimeTypeSet& path_mime_set,
462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::vector<GURL>& file_urls,
463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    std::vector<FullTaskDescriptor>* result_list) {
464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(profile);
465424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(result_list);
466424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Find Drive app tasks, if the drive app registry is present.
4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (drive_app_registry)
4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FindDriveAppTasks(*drive_app_registry, path_mime_set, result_list);
470424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
471424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Find and append file handler tasks. We know there aren't duplicates
472424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // because Drive apps and platform apps are entirely different kinds of
473424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // tasks.
4748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  FindFileHandlerTasks(profile, path_mime_set, result_list);
475424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
476424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Find and append file browser handler tasks. We know there aren't
477424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // duplicates because "file_browser_handlers" and "file_handlers" shouldn't
478424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // be used in the same manifest.json.
4798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  FindFileBrowserHandlerTasks(profile, file_urls, result_list);
4808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Google documents can only be handled by internal handlers.
4828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (ContainsGoogleDocument(path_mime_set))
4838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    KeepOnlyFileManagerInternalTasks(result_list);
48458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ChooseAndSetDefaultTask(*profile->GetPrefs(), path_mime_set, result_list);
48658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
48758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
48858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ChooseAndSetDefaultTask(const PrefService& pref_service,
48958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                             const PathAndMimeTypeSet& path_mime_set,
49058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                             std::vector<FullTaskDescriptor>* tasks) {
49158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Collect the task IDs of default tasks from the preferences into a set.
49258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::set<std::string> default_task_ids;
49358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (PathAndMimeTypeSet::const_iterator it = path_mime_set.begin();
49458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)       it != path_mime_set.end(); ++it) {
49558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const base::FilePath& file_path = it->first;
49658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& mime_type = it->second;
49758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs(
49858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        pref_service, mime_type, file_path.Extension());
49958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    default_task_ids.insert(task_id);
50058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
50158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
50258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Go through all the tasks from the beginning and see if there is any
50358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // default task. If found, pick and set it as default and return.
50458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < tasks->size(); ++i) {
50558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    FullTaskDescriptor* task = &tasks->at(i);
50658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(!task->is_default());
50758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string task_id = TaskDescriptorToId(task->task_descriptor());
50858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (ContainsKey(default_task_ids, task_id)) {
50958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      task->set_is_default(true);
51058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
51158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
51258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
51358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
51458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // No default tasks found. If there is any fallback file browser handler,
51558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // make it as default task, so it's selected by default.
51658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < tasks->size(); ++i) {
51758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    FullTaskDescriptor* task = &tasks->at(i);
51858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(!task->is_default());
519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (IsFallbackFileHandler(task->task_descriptor())) {
52058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      task->set_is_default(true);
52158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
52258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
52358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
524424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
525424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
526a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace file_tasks
527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace file_manager
528