OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h" | 5 #include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h" |
6 | 6 |
7 #include "apps/launcher.h" | 7 #include "apps/launcher.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/prefs/pref_service.h" | 9 #include "base/prefs/pref_service.h" |
10 #include "base/strings/stringprintf.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" |
11 #include "chrome/browser/chromeos/drive/file_task_executor.h" | 13 #include "chrome/browser/chromeos/drive/file_task_executor.h" |
12 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.
h" | 14 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.
h" |
13 #include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h" | 15 #include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h" |
14 #include "chrome/browser/chromeos/extensions/file_manager/open_util.h" | 16 #include "chrome/browser/chromeos/extensions/file_manager/open_util.h" |
15 #include "chrome/browser/chromeos/fileapi/file_system_backend.h" | 17 #include "chrome/browser/chromeos/fileapi/file_system_backend.h" |
16 #include "chrome/browser/extensions/extension_host.h" | 18 #include "chrome/browser/extensions/extension_host.h" |
17 #include "chrome/browser/extensions/extension_service.h" | 19 #include "chrome/browser/extensions/extension_service.h" |
| 20 #include "chrome/browser/extensions/extension_service.h" |
| 21 #include "chrome/browser/extensions/extension_system.h" |
18 #include "chrome/browser/extensions/extension_system.h" | 22 #include "chrome/browser/extensions/extension_system.h" |
19 #include "chrome/browser/extensions/extension_tab_util.h" | 23 #include "chrome/browser/extensions/extension_tab_util.h" |
20 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" |
| 26 #include "chrome/common/extensions/api/file_browser_handlers/file_browser_handle
r.h" |
21 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
22 #include "webkit/browser/fileapi/file_system_context.h" | 28 #include "webkit/browser/fileapi/file_system_context.h" |
23 #include "webkit/browser/fileapi/file_system_url.h" | 29 #include "webkit/browser/fileapi/file_system_url.h" |
24 | 30 |
25 using extensions::Extension; | 31 using extensions::Extension; |
| 32 using extensions::app_file_handler_util::FindFileHandlersForFiles; |
26 using fileapi::FileSystemURL; | 33 using fileapi::FileSystemURL; |
27 | 34 |
28 namespace file_manager { | 35 namespace file_manager { |
29 namespace file_tasks { | 36 namespace file_tasks { |
30 | 37 |
31 namespace { | 38 namespace { |
32 | 39 |
33 // The values "file" and "app" are confusing, but cannot be changed easily as | 40 // The values "file" and "app" are confusing, but cannot be changed easily as |
34 // these are used in default task IDs stored in preferences. | 41 // these are used in default task IDs stored in preferences. |
35 // | 42 // |
36 // TODO(satorux): We should rename them to "file_browser_handler" and | 43 // TODO(satorux): We should rename them to "file_browser_handler" and |
37 // "file_handler" respectively when switching from preferences to | 44 // "file_handler" respectively when switching from preferences to |
38 // chrome.storage crbug.com/267359 | 45 // chrome.storage crbug.com/267359 |
39 const char kFileBrowserHandlerTaskType[] = "file"; | 46 const char kFileBrowserHandlerTaskType[] = "file"; |
40 const char kFileHandlerTaskType[] = "app"; | 47 const char kFileHandlerTaskType[] = "app"; |
41 const char kDriveAppTaskType[] = "drive"; | 48 const char kDriveAppTaskType[] = "drive"; |
42 | 49 |
| 50 // Default icon path for drive docs. |
| 51 const char kDefaultIcon[] = "images/filetype_generic.png"; |
| 52 |
43 // Converts a TaskType to a string. | 53 // Converts a TaskType to a string. |
44 std::string TaskTypeToString(TaskType task_type) { | 54 std::string TaskTypeToString(TaskType task_type) { |
45 switch (task_type) { | 55 switch (task_type) { |
46 case TASK_TYPE_FILE_BROWSER_HANDLER: | 56 case TASK_TYPE_FILE_BROWSER_HANDLER: |
47 return kFileBrowserHandlerTaskType; | 57 return kFileBrowserHandlerTaskType; |
48 case TASK_TYPE_FILE_HANDLER: | 58 case TASK_TYPE_FILE_HANDLER: |
49 return kFileHandlerTaskType; | 59 return kFileHandlerTaskType; |
50 case TASK_TYPE_DRIVE_APP: | 60 case TASK_TYPE_DRIVE_APP: |
51 return kDriveAppTaskType; | 61 return kDriveAppTaskType; |
52 case TASK_TYPE_UNKNOWN: | 62 case TASK_TYPE_UNKNOWN: |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 } | 265 } |
256 | 266 |
257 if (!done.is_null()) | 267 if (!done.is_null()) |
258 done.Run(true); | 268 done.Run(true); |
259 return true; | 269 return true; |
260 } | 270 } |
261 NOTREACHED(); | 271 NOTREACHED(); |
262 return false; | 272 return false; |
263 } | 273 } |
264 | 274 |
| 275 struct TaskInfo { |
| 276 TaskInfo(const std::string& app_name, const GURL& icon_url) |
| 277 : app_name(app_name), icon_url(icon_url) { |
| 278 } |
| 279 |
| 280 std::string app_name; |
| 281 GURL icon_url; |
| 282 }; |
| 283 |
| 284 void GetAvailableDriveTasks( |
| 285 const drive::DriveAppRegistry& drive_app_registry, |
| 286 const PathAndMimeTypeSet& path_mime_set, |
| 287 TaskInfoMap* task_info_map) { |
| 288 DCHECK(task_info_map); |
| 289 DCHECK(task_info_map->empty()); |
| 290 |
| 291 bool is_first = true; |
| 292 for (PathAndMimeTypeSet::const_iterator it = path_mime_set.begin(); |
| 293 it != path_mime_set.end(); ++it) { |
| 294 const base::FilePath& file_path = it->first; |
| 295 const std::string& mime_type = it->second; |
| 296 if (file_path.empty()) |
| 297 continue; |
| 298 |
| 299 ScopedVector<drive::DriveAppInfo> app_info_list; |
| 300 drive_app_registry.GetAppsForFile(file_path, mime_type, &app_info_list); |
| 301 |
| 302 if (is_first) { |
| 303 // For the first file, we store all the info. |
| 304 for (size_t j = 0; j < app_info_list.size(); ++j) { |
| 305 const drive::DriveAppInfo& app_info = *app_info_list[j]; |
| 306 GURL icon_url = drive::util::FindPreferredIcon( |
| 307 app_info.app_icons, |
| 308 drive::util::kPreferredIconSize); |
| 309 task_info_map->insert(std::pair<std::string, TaskInfo>( |
| 310 file_tasks::MakeDriveAppTaskId(app_info.app_id), |
| 311 TaskInfo(app_info.app_name, icon_url))); |
| 312 } |
| 313 } else { |
| 314 // For remaining files, take the intersection with the current result, |
| 315 // based on the task id. |
| 316 std::set<std::string> task_id_set; |
| 317 for (size_t j = 0; j < app_info_list.size(); ++j) { |
| 318 task_id_set.insert( |
| 319 file_tasks::MakeDriveAppTaskId(app_info_list[j]->app_id)); |
| 320 } |
| 321 for (TaskInfoMap::iterator iter = task_info_map->begin(); |
| 322 iter != task_info_map->end(); ) { |
| 323 if (task_id_set.find(iter->first) == task_id_set.end()) { |
| 324 task_info_map->erase(iter++); |
| 325 } else { |
| 326 ++iter; |
| 327 } |
| 328 } |
| 329 } |
| 330 |
| 331 is_first = false; |
| 332 } |
| 333 } |
| 334 |
| 335 void FindDefaultDriveTasks( |
| 336 const PrefService& pref_service, |
| 337 const PathAndMimeTypeSet& path_mime_set, |
| 338 const TaskInfoMap& task_info_map, |
| 339 std::set<std::string>* default_tasks) { |
| 340 DCHECK(default_tasks); |
| 341 |
| 342 for (PathAndMimeTypeSet::const_iterator it = path_mime_set.begin(); |
| 343 it != path_mime_set.end(); ++it) { |
| 344 const base::FilePath& file_path = it->first; |
| 345 const std::string& mime_type = it->second; |
| 346 std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs( |
| 347 pref_service, mime_type, file_path.Extension()); |
| 348 if (task_info_map.find(task_id) != task_info_map.end()) |
| 349 default_tasks->insert(task_id); |
| 350 } |
| 351 } |
| 352 |
| 353 void CreateDriveTasks( |
| 354 const TaskInfoMap& task_info_map, |
| 355 const std::set<std::string>& default_tasks, |
| 356 ListValue* result_list, |
| 357 bool* default_already_set) { |
| 358 DCHECK(result_list); |
| 359 DCHECK(default_already_set); |
| 360 |
| 361 for (TaskInfoMap::const_iterator iter = task_info_map.begin(); |
| 362 iter != task_info_map.end(); ++iter) { |
| 363 DictionaryValue* task = new DictionaryValue; |
| 364 task->SetString("taskId", iter->first); |
| 365 task->SetString("title", iter->second.app_name); |
| 366 |
| 367 const GURL& icon_url = iter->second.icon_url; |
| 368 if (!icon_url.is_empty()) |
| 369 task->SetString("iconUrl", icon_url.spec()); |
| 370 |
| 371 task->SetBoolean("driveApp", true); |
| 372 |
| 373 // Once we set a default app, we don't want to set any more. |
| 374 if (!(*default_already_set) && |
| 375 default_tasks.find(iter->first) != default_tasks.end()) { |
| 376 task->SetBoolean("isDefault", true); |
| 377 *default_already_set = true; |
| 378 } else { |
| 379 task->SetBoolean("isDefault", false); |
| 380 } |
| 381 result_list->Append(task); |
| 382 } |
| 383 } |
| 384 |
| 385 void FindDriveAppTasks( |
| 386 Profile* profile, |
| 387 const PathAndMimeTypeSet& path_mime_set, |
| 388 ListValue* result_list, |
| 389 bool* default_already_set) { |
| 390 DCHECK(!path_mime_set.empty()); |
| 391 DCHECK(result_list); |
| 392 DCHECK(default_already_set); |
| 393 |
| 394 drive::DriveIntegrationService* integration_service = |
| 395 drive::DriveIntegrationServiceFactory::GetForProfile(profile); |
| 396 // |integration_service| is NULL if Drive is disabled. |
| 397 if (!integration_service || !integration_service->drive_app_registry()) |
| 398 return; |
| 399 |
| 400 // Map of task_id to TaskInfo of available tasks. |
| 401 TaskInfoMap task_info_map; |
| 402 GetAvailableDriveTasks(*integration_service->drive_app_registry(), |
| 403 path_mime_set, |
| 404 &task_info_map); |
| 405 |
| 406 std::set<std::string> default_tasks; |
| 407 FindDefaultDriveTasks(*profile->GetPrefs(), |
| 408 path_mime_set, |
| 409 task_info_map, |
| 410 &default_tasks); |
| 411 CreateDriveTasks( |
| 412 task_info_map, default_tasks, result_list, default_already_set); |
| 413 } |
| 414 |
| 415 void FindFileHandlerTasks( |
| 416 Profile* profile, |
| 417 const PathAndMimeTypeSet& path_mime_set, |
| 418 ListValue* result_list, |
| 419 bool* default_already_set) { |
| 420 DCHECK(!path_mime_set.empty()); |
| 421 DCHECK(result_list); |
| 422 DCHECK(default_already_set); |
| 423 |
| 424 ExtensionService* service = profile->GetExtensionService(); |
| 425 if (!service) |
| 426 return; |
| 427 |
| 428 std::set<std::string> default_tasks; |
| 429 for (PathAndMimeTypeSet::iterator it = path_mime_set.begin(); |
| 430 it != path_mime_set.end(); ++it) { |
| 431 default_tasks.insert(file_tasks::GetDefaultTaskIdFromPrefs( |
| 432 *profile->GetPrefs(), it->second, it->first.Extension())); |
| 433 } |
| 434 |
| 435 for (ExtensionSet::const_iterator iter = service->extensions()->begin(); |
| 436 iter != service->extensions()->end(); |
| 437 ++iter) { |
| 438 const Extension* extension = iter->get(); |
| 439 |
| 440 // We don't support using hosted apps to open files. |
| 441 if (!extension->is_platform_app()) |
| 442 continue; |
| 443 |
| 444 if (profile->IsOffTheRecord() && |
| 445 !service->IsIncognitoEnabled(extension->id())) |
| 446 continue; |
| 447 |
| 448 typedef std::vector<const extensions::FileHandlerInfo*> FileHandlerList; |
| 449 FileHandlerList file_handlers = |
| 450 FindFileHandlersForFiles(*extension, path_mime_set); |
| 451 if (file_handlers.empty()) |
| 452 continue; |
| 453 |
| 454 for (FileHandlerList::iterator i = file_handlers.begin(); |
| 455 i != file_handlers.end(); ++i) { |
| 456 DictionaryValue* task = new DictionaryValue; |
| 457 std::string task_id = file_tasks::MakeTaskID( |
| 458 extension->id(), file_tasks::TASK_TYPE_FILE_HANDLER, (*i)->id); |
| 459 task->SetString("taskId", task_id); |
| 460 task->SetString("title", (*i)->title); |
| 461 if (!(*default_already_set) && ContainsKey(default_tasks, task_id)) { |
| 462 task->SetBoolean("isDefault", true); |
| 463 *default_already_set = true; |
| 464 } else { |
| 465 task->SetBoolean("isDefault", false); |
| 466 } |
| 467 |
| 468 GURL best_icon = extensions::ExtensionIconSource::GetIconURL( |
| 469 extension, |
| 470 drive::util::kPreferredIconSize, |
| 471 ExtensionIconSet::MATCH_BIGGER, |
| 472 false, // grayscale |
| 473 NULL); // exists |
| 474 if (!best_icon.is_empty()) |
| 475 task->SetString("iconUrl", best_icon.spec()); |
| 476 else |
| 477 task->SetString("iconUrl", kDefaultIcon); |
| 478 |
| 479 task->SetBoolean("driveApp", false); |
| 480 result_list->Append(task); |
| 481 } |
| 482 } |
| 483 } |
| 484 |
| 485 void FindFileBrowserHandlerTasks( |
| 486 Profile* profile, |
| 487 const std::vector<GURL>& file_urls, |
| 488 const std::vector<base::FilePath>& file_paths, |
| 489 ListValue* result_list, |
| 490 bool* default_already_set) { |
| 491 DCHECK(!file_paths.empty()); |
| 492 DCHECK(!file_urls.empty()); |
| 493 DCHECK(result_list); |
| 494 DCHECK(default_already_set); |
| 495 |
| 496 file_browser_handlers::FileBrowserHandlerList common_tasks = |
| 497 file_browser_handlers::FindCommonFileBrowserHandlers(profile, file_urls); |
| 498 if (common_tasks.empty()) |
| 499 return; |
| 500 file_browser_handlers::FileBrowserHandlerList default_tasks = |
| 501 file_browser_handlers::FindDefaultFileBrowserHandlers( |
| 502 *profile->GetPrefs(), file_paths, common_tasks); |
| 503 |
| 504 ExtensionService* service = |
| 505 extensions::ExtensionSystem::Get(profile)->extension_service(); |
| 506 for (file_browser_handlers::FileBrowserHandlerList::const_iterator iter = |
| 507 common_tasks.begin(); |
| 508 iter != common_tasks.end(); |
| 509 ++iter) { |
| 510 const FileBrowserHandler* handler = *iter; |
| 511 const std::string extension_id = handler->extension_id(); |
| 512 const Extension* extension = service->GetExtensionById(extension_id, false); |
| 513 CHECK(extension); |
| 514 DictionaryValue* task = new DictionaryValue; |
| 515 task->SetString("taskId", file_tasks::MakeTaskID( |
| 516 extension_id, |
| 517 file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER, |
| 518 handler->id())); |
| 519 task->SetString("title", handler->title()); |
| 520 // TODO(zelidrag): Figure out how to expose icon URL that task defined in |
| 521 // manifest instead of the default extension icon. |
| 522 GURL icon = extensions::ExtensionIconSource::GetIconURL( |
| 523 extension, |
| 524 extension_misc::EXTENSION_ICON_BITTY, |
| 525 ExtensionIconSet::MATCH_BIGGER, |
| 526 false, // grayscale |
| 527 NULL); // exists |
| 528 task->SetString("iconUrl", icon.spec()); |
| 529 task->SetBoolean("driveApp", false); |
| 530 |
| 531 // Only set the default if there isn't already a default set. |
| 532 if (!*default_already_set && |
| 533 std::find(default_tasks.begin(), default_tasks.end(), *iter) != |
| 534 default_tasks.end()) { |
| 535 task->SetBoolean("isDefault", true); |
| 536 *default_already_set = true; |
| 537 } else { |
| 538 task->SetBoolean("isDefault", false); |
| 539 } |
| 540 |
| 541 result_list->Append(task); |
| 542 } |
| 543 } |
| 544 |
| 545 void FindAllTypesOfTasks( |
| 546 Profile* profile, |
| 547 const PathAndMimeTypeSet& path_mime_set, |
| 548 const std::vector<GURL>& file_urls, |
| 549 const std::vector<base::FilePath>& file_paths, |
| 550 ListValue* result_list) { |
| 551 // Check if file_paths contain a google document. |
| 552 bool has_google_document = false; |
| 553 for (size_t i = 0; i < file_paths.size(); ++i) { |
| 554 if (google_apis::ResourceEntry::ClassifyEntryKindByFileExtension( |
| 555 file_paths[i]) & |
| 556 google_apis::ResourceEntry::KIND_OF_GOOGLE_DOCUMENT) { |
| 557 has_google_document = true; |
| 558 break; |
| 559 } |
| 560 } |
| 561 |
| 562 // Find the Drive app tasks first, because we want them to take precedence |
| 563 // when setting the default app. |
| 564 bool default_already_set = false; |
| 565 // Google document are not opened by drive apps but file manager. |
| 566 if (!has_google_document) { |
| 567 FindDriveAppTasks(profile, |
| 568 path_mime_set, |
| 569 result_list, |
| 570 &default_already_set); |
| 571 } |
| 572 |
| 573 // Find and append file handler tasks. We know there aren't duplicates |
| 574 // because Drive apps and platform apps are entirely different kinds of |
| 575 // tasks. |
| 576 FindFileHandlerTasks(profile, |
| 577 path_mime_set, |
| 578 result_list, |
| 579 &default_already_set); |
| 580 |
| 581 // Find and append file browser handler tasks. We know there aren't |
| 582 // duplicates because "file_browser_handlers" and "file_handlers" shouldn't |
| 583 // be used in the same manifest.json. |
| 584 FindFileBrowserHandlerTasks(profile, |
| 585 file_urls, |
| 586 file_paths, |
| 587 result_list, |
| 588 &default_already_set); |
| 589 } |
| 590 |
265 } // namespace file_tasks | 591 } // namespace file_tasks |
266 } // namespace file_manager | 592 } // namespace file_manager |
OLD | NEW |