| OLD | NEW |
| (Empty) |
| 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 #include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h" | |
| 6 | |
| 7 #include "apps/launcher.h" | |
| 8 #include "base/bind.h" | |
| 9 #include "base/prefs/pref_service.h" | |
| 10 #include "base/strings/stringprintf.h" | |
| 11 #include "chrome/browser/chromeos/drive/drive_app_registry.h" | |
| 12 #include "chrome/browser/chromeos/drive/drive_integration_service.h" | |
| 13 #include "chrome/browser/chromeos/drive/file_system_util.h" | |
| 14 #include "chrome/browser/chromeos/drive/file_task_executor.h" | |
| 15 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.
h" | |
| 16 #include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h" | |
| 17 #include "chrome/browser/chromeos/extensions/file_manager/open_util.h" | |
| 18 #include "chrome/browser/chromeos/fileapi/file_system_backend.h" | |
| 19 #include "chrome/browser/extensions/extension_host.h" | |
| 20 #include "chrome/browser/extensions/extension_service.h" | |
| 21 #include "chrome/browser/extensions/extension_service.h" | |
| 22 #include "chrome/browser/extensions/extension_system.h" | |
| 23 #include "chrome/browser/extensions/extension_system.h" | |
| 24 #include "chrome/browser/extensions/extension_tab_util.h" | |
| 25 #include "chrome/browser/profiles/profile.h" | |
| 26 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" | |
| 27 #include "chrome/common/extensions/api/file_browser_handlers/file_browser_handle
r.h" | |
| 28 #include "chrome/common/pref_names.h" | |
| 29 #include "webkit/browser/fileapi/file_system_context.h" | |
| 30 #include "webkit/browser/fileapi/file_system_url.h" | |
| 31 | |
| 32 using extensions::Extension; | |
| 33 using extensions::app_file_handler_util::FindFileHandlersForFiles; | |
| 34 using fileapi::FileSystemURL; | |
| 35 | |
| 36 namespace file_manager { | |
| 37 namespace file_tasks { | |
| 38 | |
| 39 namespace { | |
| 40 | |
| 41 // The values "file" and "app" are confusing, but cannot be changed easily as | |
| 42 // these are used in default task IDs stored in preferences. | |
| 43 // | |
| 44 // TODO(satorux): We should rename them to "file_browser_handler" and | |
| 45 // "file_handler" respectively when switching from preferences to | |
| 46 // chrome.storage crbug.com/267359 | |
| 47 const char kFileBrowserHandlerTaskType[] = "file"; | |
| 48 const char kFileHandlerTaskType[] = "app"; | |
| 49 const char kDriveAppTaskType[] = "drive"; | |
| 50 | |
| 51 // Drive apps always use the action ID. | |
| 52 const char kDriveAppActionID[] = "open-with"; | |
| 53 | |
| 54 // Default icon path for drive docs. | |
| 55 const char kDefaultIcon[] = "images/filetype_generic.png"; | |
| 56 | |
| 57 // Converts a TaskType to a string. | |
| 58 std::string TaskTypeToString(TaskType task_type) { | |
| 59 switch (task_type) { | |
| 60 case TASK_TYPE_FILE_BROWSER_HANDLER: | |
| 61 return kFileBrowserHandlerTaskType; | |
| 62 case TASK_TYPE_FILE_HANDLER: | |
| 63 return kFileHandlerTaskType; | |
| 64 case TASK_TYPE_DRIVE_APP: | |
| 65 return kDriveAppTaskType; | |
| 66 case TASK_TYPE_UNKNOWN: | |
| 67 break; | |
| 68 } | |
| 69 NOTREACHED(); | |
| 70 return ""; | |
| 71 } | |
| 72 | |
| 73 // Converts a string to a TaskType. Returns TASK_TYPE_UNKNOWN on error. | |
| 74 TaskType StringToTaskType(const std::string& str) { | |
| 75 if (str == kFileBrowserHandlerTaskType) | |
| 76 return TASK_TYPE_FILE_BROWSER_HANDLER; | |
| 77 if (str == kFileHandlerTaskType) | |
| 78 return TASK_TYPE_FILE_HANDLER; | |
| 79 if (str == kDriveAppTaskType) | |
| 80 return TASK_TYPE_DRIVE_APP; | |
| 81 return TASK_TYPE_UNKNOWN; | |
| 82 } | |
| 83 | |
| 84 // Legacy Drive task extension prefix, used by CrackTaskID. | |
| 85 const char kDriveTaskExtensionPrefix[] = "drive-app:"; | |
| 86 const size_t kDriveTaskExtensionPrefixLength = | |
| 87 arraysize(kDriveTaskExtensionPrefix) - 1; | |
| 88 | |
| 89 // Checks if the file browser extension has permissions for the files in its | |
| 90 // file system context. | |
| 91 bool FileBrowserHasAccessPermissionForFiles( | |
| 92 Profile* profile, | |
| 93 const GURL& source_url, | |
| 94 const std::string& file_browser_id, | |
| 95 const std::vector<FileSystemURL>& files) { | |
| 96 fileapi::ExternalFileSystemBackend* backend = | |
| 97 util::GetFileSystemContextForExtensionId( | |
| 98 profile, file_browser_id)->external_backend(); | |
| 99 if (!backend) | |
| 100 return false; | |
| 101 | |
| 102 for (size_t i = 0; i < files.size(); ++i) { | |
| 103 // Make sure this url really being used by the right caller extension. | |
| 104 if (source_url.GetOrigin() != files[i].origin()) | |
| 105 return false; | |
| 106 | |
| 107 if (!chromeos::FileSystemBackend::CanHandleURL(files[i]) || | |
| 108 !backend->IsAccessAllowed(files[i])) { | |
| 109 return false; | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 return true; | |
| 114 } | |
| 115 | |
| 116 } // namespace | |
| 117 | |
| 118 FullTaskDescriptor::FullTaskDescriptor( | |
| 119 const TaskDescriptor& task_descriptor, | |
| 120 const std::string& task_title, | |
| 121 const GURL& icon_url, | |
| 122 bool is_default) | |
| 123 : task_descriptor_(task_descriptor), | |
| 124 task_title_(task_title), | |
| 125 icon_url_(icon_url), | |
| 126 is_default_(is_default){ | |
| 127 } | |
| 128 | |
| 129 scoped_ptr<base::DictionaryValue> | |
| 130 FullTaskDescriptor::AsDictionaryValue() const { | |
| 131 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue); | |
| 132 dictionary->SetString("taskId", TaskDescriptorToId(task_descriptor_)); | |
| 133 if (!icon_url_.is_empty()) | |
| 134 dictionary->SetString("iconUrl", icon_url_.spec()); | |
| 135 dictionary->SetString("title", task_title_); | |
| 136 dictionary->SetBoolean("isDefault", is_default_); | |
| 137 return dictionary.Pass(); | |
| 138 } | |
| 139 | |
| 140 void UpdateDefaultTask(PrefService* pref_service, | |
| 141 const std::string& task_id, | |
| 142 const std::set<std::string>& suffixes, | |
| 143 const std::set<std::string>& mime_types) { | |
| 144 if (!pref_service) | |
| 145 return; | |
| 146 | |
| 147 if (!mime_types.empty()) { | |
| 148 DictionaryPrefUpdate mime_type_pref(pref_service, | |
| 149 prefs::kDefaultTasksByMimeType); | |
| 150 for (std::set<std::string>::const_iterator iter = mime_types.begin(); | |
| 151 iter != mime_types.end(); ++iter) { | |
| 152 base::StringValue* value = new base::StringValue(task_id); | |
| 153 mime_type_pref->SetWithoutPathExpansion(*iter, value); | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 if (!suffixes.empty()) { | |
| 158 DictionaryPrefUpdate mime_type_pref(pref_service, | |
| 159 prefs::kDefaultTasksBySuffix); | |
| 160 for (std::set<std::string>::const_iterator iter = suffixes.begin(); | |
| 161 iter != suffixes.end(); ++iter) { | |
| 162 base::StringValue* value = new base::StringValue(task_id); | |
| 163 // Suffixes are case insensitive. | |
| 164 std::string lower_suffix = StringToLowerASCII(*iter); | |
| 165 mime_type_pref->SetWithoutPathExpansion(lower_suffix, value); | |
| 166 } | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 std::string GetDefaultTaskIdFromPrefs(const PrefService& pref_service, | |
| 171 const std::string& mime_type, | |
| 172 const std::string& suffix) { | |
| 173 VLOG(1) << "Looking for default for MIME type: " << mime_type | |
| 174 << " and suffix: " << suffix; | |
| 175 std::string task_id; | |
| 176 if (!mime_type.empty()) { | |
| 177 const DictionaryValue* mime_task_prefs = | |
| 178 pref_service.GetDictionary(prefs::kDefaultTasksByMimeType); | |
| 179 DCHECK(mime_task_prefs); | |
| 180 LOG_IF(ERROR, !mime_task_prefs) << "Unable to open MIME type prefs"; | |
| 181 if (mime_task_prefs && | |
| 182 mime_task_prefs->GetStringWithoutPathExpansion(mime_type, &task_id)) { | |
| 183 VLOG(1) << "Found MIME default handler: " << task_id; | |
| 184 return task_id; | |
| 185 } | |
| 186 } | |
| 187 | |
| 188 const DictionaryValue* suffix_task_prefs = | |
| 189 pref_service.GetDictionary(prefs::kDefaultTasksBySuffix); | |
| 190 DCHECK(suffix_task_prefs); | |
| 191 LOG_IF(ERROR, !suffix_task_prefs) << "Unable to open suffix prefs"; | |
| 192 std::string lower_suffix = StringToLowerASCII(suffix); | |
| 193 if (suffix_task_prefs) | |
| 194 suffix_task_prefs->GetStringWithoutPathExpansion(lower_suffix, &task_id); | |
| 195 VLOG_IF(1, !task_id.empty()) << "Found suffix default handler: " << task_id; | |
| 196 return task_id; | |
| 197 } | |
| 198 | |
| 199 std::string MakeTaskID(const std::string& app_id, | |
| 200 TaskType task_type, | |
| 201 const std::string& action_id) { | |
| 202 return base::StringPrintf("%s|%s|%s", | |
| 203 app_id.c_str(), | |
| 204 TaskTypeToString(task_type).c_str(), | |
| 205 action_id.c_str()); | |
| 206 } | |
| 207 | |
| 208 std::string MakeDriveAppTaskId(const std::string& app_id) { | |
| 209 return MakeTaskID(app_id, TASK_TYPE_DRIVE_APP, kDriveAppActionID); | |
| 210 } | |
| 211 | |
| 212 std::string TaskDescriptorToId(const TaskDescriptor& task_descriptor) { | |
| 213 return MakeTaskID(task_descriptor.app_id, | |
| 214 task_descriptor.task_type, | |
| 215 task_descriptor.action_id); | |
| 216 } | |
| 217 | |
| 218 bool ParseTaskID(const std::string& task_id, TaskDescriptor* task) { | |
| 219 DCHECK(task); | |
| 220 | |
| 221 std::vector<std::string> result; | |
| 222 int count = Tokenize(task_id, std::string("|"), &result); | |
| 223 | |
| 224 // Parse a legacy task ID that only contain two parts. Drive tasks are | |
| 225 // identified by a prefix "drive-app:" on the extension ID. The legacy task | |
| 226 // IDs can be stored in preferences. | |
| 227 // TODO(satorux): We should get rid of this code: crbug.com/267359. | |
| 228 if (count == 2) { | |
| 229 if (StartsWithASCII(result[0], kDriveTaskExtensionPrefix, true)) { | |
| 230 task->task_type = TASK_TYPE_DRIVE_APP; | |
| 231 task->app_id = result[0].substr(kDriveTaskExtensionPrefixLength); | |
| 232 } else { | |
| 233 task->task_type = TASK_TYPE_FILE_BROWSER_HANDLER; | |
| 234 task->app_id = result[0]; | |
| 235 } | |
| 236 | |
| 237 task->action_id = result[1]; | |
| 238 | |
| 239 return true; | |
| 240 } | |
| 241 | |
| 242 if (count != 3) | |
| 243 return false; | |
| 244 | |
| 245 TaskType task_type = StringToTaskType(result[1]); | |
| 246 if (task_type == TASK_TYPE_UNKNOWN) | |
| 247 return false; | |
| 248 | |
| 249 task->app_id = result[0]; | |
| 250 task->task_type = task_type; | |
| 251 task->action_id = result[2]; | |
| 252 | |
| 253 return true; | |
| 254 } | |
| 255 | |
| 256 bool ExecuteFileTask(Profile* profile, | |
| 257 const GURL& source_url, | |
| 258 const std::string& app_id, | |
| 259 int32 tab_id, | |
| 260 const TaskDescriptor& task, | |
| 261 const std::vector<FileSystemURL>& file_urls, | |
| 262 const FileTaskFinishedCallback& done) { | |
| 263 if (!FileBrowserHasAccessPermissionForFiles(profile, source_url, | |
| 264 app_id, file_urls)) | |
| 265 return false; | |
| 266 | |
| 267 // drive::FileTaskExecutor is responsible to handle drive tasks. | |
| 268 if (task.task_type == TASK_TYPE_DRIVE_APP) { | |
| 269 DCHECK_EQ(kDriveAppActionID, task.action_id); | |
| 270 drive::FileTaskExecutor* executor = | |
| 271 new drive::FileTaskExecutor(profile, task.app_id); | |
| 272 executor->Execute(file_urls, done); | |
| 273 return true; | |
| 274 } | |
| 275 | |
| 276 // Get the extension. | |
| 277 ExtensionService* service = | |
| 278 extensions::ExtensionSystem::Get(profile)->extension_service(); | |
| 279 const Extension* extension = service ? | |
| 280 service->GetExtensionById(task.app_id, false) : NULL; | |
| 281 if (!extension) | |
| 282 return false; | |
| 283 | |
| 284 // Execute the task. | |
| 285 if (task.task_type == TASK_TYPE_FILE_BROWSER_HANDLER) { | |
| 286 return file_browser_handlers::ExecuteFileBrowserHandler( | |
| 287 profile, | |
| 288 extension, | |
| 289 tab_id, | |
| 290 task.action_id, | |
| 291 file_urls, | |
| 292 done); | |
| 293 } else if (task.task_type == TASK_TYPE_FILE_HANDLER) { | |
| 294 for (size_t i = 0; i != file_urls.size(); ++i) { | |
| 295 apps::LaunchPlatformAppWithFileHandler( | |
| 296 profile, extension, task.action_id, file_urls[i].path()); | |
| 297 } | |
| 298 | |
| 299 if (!done.is_null()) | |
| 300 done.Run(true); | |
| 301 return true; | |
| 302 } | |
| 303 NOTREACHED(); | |
| 304 return false; | |
| 305 } | |
| 306 | |
| 307 void FindDriveAppTasks( | |
| 308 const drive::DriveAppRegistry& drive_app_registry, | |
| 309 const PathAndMimeTypeSet& path_mime_set, | |
| 310 std::vector<FullTaskDescriptor>* result_list) { | |
| 311 DCHECK(result_list); | |
| 312 | |
| 313 bool is_first = true; | |
| 314 typedef std::map<std::string, drive::DriveAppInfo> DriveAppInfoMap; | |
| 315 DriveAppInfoMap drive_app_map; | |
| 316 | |
| 317 for (PathAndMimeTypeSet::const_iterator it = path_mime_set.begin(); | |
| 318 it != path_mime_set.end(); ++it) { | |
| 319 const base::FilePath& file_path = it->first; | |
| 320 const std::string& mime_type = it->second; | |
| 321 // Return immediately if a file not on Drive is found, as Drive app tasks | |
| 322 // work only if all files are on Drive. | |
| 323 if (!drive::util::IsUnderDriveMountPoint(file_path)) | |
| 324 return; | |
| 325 | |
| 326 ScopedVector<drive::DriveAppInfo> app_info_list; | |
| 327 drive_app_registry.GetAppsForFile(file_path.Extension(), | |
| 328 mime_type, | |
| 329 &app_info_list); | |
| 330 | |
| 331 if (is_first) { | |
| 332 // For the first file, we store all the info. | |
| 333 for (size_t j = 0; j < app_info_list.size(); ++j) { | |
| 334 const drive::DriveAppInfo& app_info = *app_info_list[j]; | |
| 335 drive_app_map[app_info.app_id] = app_info; | |
| 336 } | |
| 337 } else { | |
| 338 // For remaining files, take the intersection with the current | |
| 339 // result, based on the app id. | |
| 340 std::set<std::string> app_id_set; | |
| 341 for (size_t j = 0; j < app_info_list.size(); ++j) | |
| 342 app_id_set.insert(app_info_list[j]->app_id); | |
| 343 for (DriveAppInfoMap::iterator iter = drive_app_map.begin(); | |
| 344 iter != drive_app_map.end();) { | |
| 345 if (app_id_set.count(iter->first) == 0) { | |
| 346 drive_app_map.erase(iter++); | |
| 347 } else { | |
| 348 ++iter; | |
| 349 } | |
| 350 } | |
| 351 } | |
| 352 | |
| 353 is_first = false; | |
| 354 } | |
| 355 | |
| 356 for (DriveAppInfoMap::const_iterator iter = drive_app_map.begin(); | |
| 357 iter != drive_app_map.end(); ++iter) { | |
| 358 const drive::DriveAppInfo& app_info = iter->second; | |
| 359 TaskDescriptor descriptor(app_info.app_id, | |
| 360 TASK_TYPE_DRIVE_APP, | |
| 361 kDriveAppActionID); | |
| 362 GURL icon_url = drive::util::FindPreferredIcon( | |
| 363 app_info.app_icons, | |
| 364 drive::util::kPreferredIconSize); | |
| 365 result_list->push_back( | |
| 366 FullTaskDescriptor(descriptor, | |
| 367 app_info.app_name, | |
| 368 icon_url, | |
| 369 false /* is_default */)); | |
| 370 } | |
| 371 } | |
| 372 | |
| 373 void FindFileHandlerTasks( | |
| 374 Profile* profile, | |
| 375 const PathAndMimeTypeSet& path_mime_set, | |
| 376 std::vector<FullTaskDescriptor>* result_list) { | |
| 377 DCHECK(!path_mime_set.empty()); | |
| 378 DCHECK(result_list); | |
| 379 | |
| 380 ExtensionService* service = profile->GetExtensionService(); | |
| 381 if (!service) | |
| 382 return; | |
| 383 | |
| 384 for (ExtensionSet::const_iterator iter = service->extensions()->begin(); | |
| 385 iter != service->extensions()->end(); | |
| 386 ++iter) { | |
| 387 const Extension* extension = iter->get(); | |
| 388 | |
| 389 // We don't support using hosted apps to open files. | |
| 390 if (!extension->is_platform_app()) | |
| 391 continue; | |
| 392 | |
| 393 if (profile->IsOffTheRecord() && | |
| 394 !service->IsIncognitoEnabled(extension->id())) | |
| 395 continue; | |
| 396 | |
| 397 typedef std::vector<const extensions::FileHandlerInfo*> FileHandlerList; | |
| 398 FileHandlerList file_handlers = | |
| 399 FindFileHandlersForFiles(*extension, path_mime_set); | |
| 400 if (file_handlers.empty()) | |
| 401 continue; | |
| 402 | |
| 403 for (FileHandlerList::iterator i = file_handlers.begin(); | |
| 404 i != file_handlers.end(); ++i) { | |
| 405 std::string task_id = file_tasks::MakeTaskID( | |
| 406 extension->id(), file_tasks::TASK_TYPE_FILE_HANDLER, (*i)->id); | |
| 407 | |
| 408 GURL best_icon = extensions::ExtensionIconSource::GetIconURL( | |
| 409 extension, | |
| 410 drive::util::kPreferredIconSize, | |
| 411 ExtensionIconSet::MATCH_BIGGER, | |
| 412 false, // grayscale | |
| 413 NULL); // exists | |
| 414 | |
| 415 result_list->push_back(FullTaskDescriptor( | |
| 416 TaskDescriptor(extension->id(), | |
| 417 file_tasks::TASK_TYPE_FILE_HANDLER, | |
| 418 (*i)->id), | |
| 419 (*i)->title, | |
| 420 best_icon, | |
| 421 false /* is_default */)); | |
| 422 } | |
| 423 } | |
| 424 } | |
| 425 | |
| 426 void FindFileBrowserHandlerTasks( | |
| 427 Profile* profile, | |
| 428 const std::vector<GURL>& file_urls, | |
| 429 std::vector<FullTaskDescriptor>* result_list) { | |
| 430 DCHECK(!file_urls.empty()); | |
| 431 DCHECK(result_list); | |
| 432 | |
| 433 file_browser_handlers::FileBrowserHandlerList common_tasks = | |
| 434 file_browser_handlers::FindCommonFileBrowserHandlers(profile, file_urls); | |
| 435 if (common_tasks.empty()) | |
| 436 return; | |
| 437 | |
| 438 ExtensionService* service = | |
| 439 extensions::ExtensionSystem::Get(profile)->extension_service(); | |
| 440 for (file_browser_handlers::FileBrowserHandlerList::const_iterator iter = | |
| 441 common_tasks.begin(); | |
| 442 iter != common_tasks.end(); | |
| 443 ++iter) { | |
| 444 const FileBrowserHandler* handler = *iter; | |
| 445 const std::string extension_id = handler->extension_id(); | |
| 446 const Extension* extension = service->GetExtensionById(extension_id, false); | |
| 447 DCHECK(extension); | |
| 448 | |
| 449 // TODO(zelidrag): Figure out how to expose icon URL that task defined in | |
| 450 // manifest instead of the default extension icon. | |
| 451 const GURL icon_url = extensions::ExtensionIconSource::GetIconURL( | |
| 452 extension, | |
| 453 extension_misc::EXTENSION_ICON_BITTY, | |
| 454 ExtensionIconSet::MATCH_BIGGER, | |
| 455 false, // grayscale | |
| 456 NULL); // exists | |
| 457 | |
| 458 result_list->push_back(FullTaskDescriptor( | |
| 459 TaskDescriptor(extension_id, | |
| 460 file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER, | |
| 461 handler->id()), | |
| 462 handler->title(), | |
| 463 icon_url, | |
| 464 false /* is_default */)); | |
| 465 } | |
| 466 } | |
| 467 | |
| 468 void FindAllTypesOfTasks( | |
| 469 Profile* profile, | |
| 470 const PathAndMimeTypeSet& path_mime_set, | |
| 471 const std::vector<GURL>& file_urls, | |
| 472 std::vector<FullTaskDescriptor>* result_list) { | |
| 473 DCHECK(profile); | |
| 474 DCHECK(result_list); | |
| 475 | |
| 476 // Check if file_paths contain a google document. | |
| 477 bool has_google_document = false; | |
| 478 for (PathAndMimeTypeSet::const_iterator iter = path_mime_set.begin(); | |
| 479 iter != path_mime_set.end(); ++iter) { | |
| 480 if (google_apis::ResourceEntry::ClassifyEntryKindByFileExtension( | |
| 481 iter->first) & | |
| 482 google_apis::ResourceEntry::KIND_OF_GOOGLE_DOCUMENT) { | |
| 483 has_google_document = true; | |
| 484 break; | |
| 485 } | |
| 486 } | |
| 487 | |
| 488 // Google document are not opened by drive apps but file manager. | |
| 489 if (!has_google_document) { | |
| 490 drive::DriveIntegrationService* integration_service = | |
| 491 drive::DriveIntegrationServiceFactory::GetForProfile(profile); | |
| 492 // |integration_service| is NULL if Drive is disabled. | |
| 493 if (!integration_service || !integration_service->drive_app_registry()) | |
| 494 return; | |
| 495 | |
| 496 FindDriveAppTasks(*integration_service->drive_app_registry(), | |
| 497 path_mime_set, | |
| 498 result_list); | |
| 499 } | |
| 500 | |
| 501 // Find and append file handler tasks. We know there aren't duplicates | |
| 502 // because Drive apps and platform apps are entirely different kinds of | |
| 503 // tasks. | |
| 504 FindFileHandlerTasks(profile, | |
| 505 path_mime_set, | |
| 506 result_list); | |
| 507 | |
| 508 // Find and append file browser handler tasks. We know there aren't | |
| 509 // duplicates because "file_browser_handlers" and "file_handlers" shouldn't | |
| 510 // be used in the same manifest.json. | |
| 511 FindFileBrowserHandlerTasks(profile, | |
| 512 file_urls, | |
| 513 result_list); | |
| 514 | |
| 515 ChooseAndSetDefaultTask(*profile->GetPrefs(), | |
| 516 path_mime_set, | |
| 517 result_list); | |
| 518 } | |
| 519 | |
| 520 void ChooseAndSetDefaultTask(const PrefService& pref_service, | |
| 521 const PathAndMimeTypeSet& path_mime_set, | |
| 522 std::vector<FullTaskDescriptor>* tasks) { | |
| 523 // Collect the task IDs of default tasks from the preferences into a set. | |
| 524 std::set<std::string> default_task_ids; | |
| 525 for (PathAndMimeTypeSet::const_iterator it = path_mime_set.begin(); | |
| 526 it != path_mime_set.end(); ++it) { | |
| 527 const base::FilePath& file_path = it->first; | |
| 528 const std::string& mime_type = it->second; | |
| 529 std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs( | |
| 530 pref_service, mime_type, file_path.Extension()); | |
| 531 default_task_ids.insert(task_id); | |
| 532 } | |
| 533 | |
| 534 // Go through all the tasks from the beginning and see if there is any | |
| 535 // default task. If found, pick and set it as default and return. | |
| 536 for (size_t i = 0; i < tasks->size(); ++i) { | |
| 537 FullTaskDescriptor* task = &tasks->at(i); | |
| 538 DCHECK(!task->is_default()); | |
| 539 const std::string task_id = TaskDescriptorToId(task->task_descriptor()); | |
| 540 if (ContainsKey(default_task_ids, task_id)) { | |
| 541 task->set_is_default(true); | |
| 542 return; | |
| 543 } | |
| 544 } | |
| 545 | |
| 546 // No default tasks found. If there is any fallback file browser handler, | |
| 547 // make it as default task, so it's selected by default. | |
| 548 for (size_t i = 0; i < tasks->size(); ++i) { | |
| 549 FullTaskDescriptor* task = &tasks->at(i); | |
| 550 DCHECK(!task->is_default()); | |
| 551 if (file_browser_handlers::IsFallbackFileBrowserHandler( | |
| 552 task->task_descriptor())) { | |
| 553 task->set_is_default(true); | |
| 554 return; | |
| 555 } | |
| 556 } | |
| 557 } | |
| 558 | |
| 559 } // namespace file_tasks | |
| 560 } // namespace file_manager | |
| OLD | NEW |