| 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_browser_private_api.h" | 5 #include "chrome/browser/chromeos/extensions/file_browser_private_api.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/file_path.h" |
| 12 #include "base/file_util.h" |
| 13 #include "base/i18n/case_conversion.h" |
| 11 #include "base/logging.h" | 14 #include "base/logging.h" |
| 12 #include "base/memory/scoped_vector.h" | 15 #include "base/memory/scoped_vector.h" |
| 13 #include "base/memory/singleton.h" | 16 #include "base/memory/singleton.h" |
| 14 #include "base/string_split.h" | 17 #include "base/string_split.h" |
| 15 #include "base/stringprintf.h" | 18 #include "base/stringprintf.h" |
| 16 #include "base/time.h" | 19 #include "base/time.h" |
| 17 #include "base/values.h" | 20 #include "base/values.h" |
| 21 #include "base/utf_string_conversions.h" |
| 18 #include "chrome/browser/chromeos/cros/cros_library.h" | 22 #include "chrome/browser/chromeos/cros/cros_library.h" |
| 19 #include "chrome/browser/chromeos/cros/network_library.h" | 23 #include "chrome/browser/chromeos/cros/network_library.h" |
| 20 #include "chrome/browser/chromeos/disks/disk_mount_manager.h" | 24 #include "chrome/browser/chromeos/disks/disk_mount_manager.h" |
| 21 #include "chrome/browser/chromeos/extensions/file_handler_util.h" | 25 #include "chrome/browser/chromeos/extensions/file_handler_util.h" |
| 22 #include "chrome/browser/chromeos/extensions/file_manager_util.h" | 26 #include "chrome/browser/chromeos/extensions/file_manager_util.h" |
| 23 #include "chrome/browser/chromeos/gdata/drive_webapps_registry.h" | 27 #include "chrome/browser/chromeos/gdata/drive_webapps_registry.h" |
| 24 #include "chrome/browser/chromeos/gdata/gdata.pb.h" | 28 #include "chrome/browser/chromeos/gdata/gdata.pb.h" |
| 25 #include "chrome/browser/chromeos/gdata/gdata_documents_service.h" | 29 #include "chrome/browser/chromeos/gdata/gdata_documents_service.h" |
| 26 #include "chrome/browser/chromeos/gdata/gdata_operation_registry.h" | 30 #include "chrome/browser/chromeos/gdata/gdata_operation_registry.h" |
| 27 #include "chrome/browser/chromeos/gdata/gdata_system_service.h" | 31 #include "chrome/browser/chromeos/gdata/gdata_system_service.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 43 #include "chrome/common/extensions/extension_icon_set.h" | 47 #include "chrome/common/extensions/extension_icon_set.h" |
| 44 #include "chrome/common/extensions/file_browser_handler.h" | 48 #include "chrome/common/extensions/file_browser_handler.h" |
| 45 #include "chrome/common/pref_names.h" | 49 #include "chrome/common/pref_names.h" |
| 46 #include "content/public/browser/child_process_security_policy.h" | 50 #include "content/public/browser/child_process_security_policy.h" |
| 47 #include "content/public/browser/render_process_host.h" | 51 #include "content/public/browser/render_process_host.h" |
| 48 #include "content/public/browser/render_view_host.h" | 52 #include "content/public/browser/render_view_host.h" |
| 49 #include "googleurl/src/gurl.h" | 53 #include "googleurl/src/gurl.h" |
| 50 #include "grit/generated_resources.h" | 54 #include "grit/generated_resources.h" |
| 51 #include "grit/platform_locale_settings.h" | 55 #include "grit/platform_locale_settings.h" |
| 52 #include "net/base/escape.h" | 56 #include "net/base/escape.h" |
| 57 #include "net/base/mime_util.h" |
| 53 #include "ui/base/dialogs/selected_file_info.h" | 58 #include "ui/base/dialogs/selected_file_info.h" |
| 54 #include "ui/base/l10n/l10n_util.h" | 59 #include "ui/base/l10n/l10n_util.h" |
| 55 #include "webkit/fileapi/file_system_context.h" | 60 #include "webkit/fileapi/file_system_context.h" |
| 56 #include "webkit/fileapi/file_system_file_util.h" | 61 #include "webkit/fileapi/file_system_file_util.h" |
| 57 #include "webkit/fileapi/file_system_mount_point_provider.h" | 62 #include "webkit/fileapi/file_system_mount_point_provider.h" |
| 58 #include "webkit/fileapi/file_system_operation_context.h" | 63 #include "webkit/fileapi/file_system_operation_context.h" |
| 59 #include "webkit/fileapi/file_system_types.h" | 64 #include "webkit/fileapi/file_system_types.h" |
| 60 #include "webkit/fileapi/file_system_util.h" | 65 #include "webkit/fileapi/file_system_util.h" |
| 66 #include "webkit/glue/web_intent_service_data.h" |
| 61 | 67 |
| 62 using chromeos::disks::DiskMountManager; | 68 using chromeos::disks::DiskMountManager; |
| 63 using content::BrowserContext; | 69 using content::BrowserContext; |
| 64 using content::BrowserThread; | 70 using content::BrowserThread; |
| 65 using content::ChildProcessSecurityPolicy; | 71 using content::ChildProcessSecurityPolicy; |
| 66 using content::SiteInstance; | 72 using content::SiteInstance; |
| 67 using content::WebContents; | 73 using content::WebContents; |
| 68 using extensions::Extension; | 74 using extensions::Extension; |
| 69 using file_handler_util::FileTaskExecutor; | 75 using file_handler_util::FileTaskExecutor; |
| 70 using gdata::GDataOperationRegistry; | 76 using gdata::GDataOperationRegistry; |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 GURL best_icon = FindPreferredIcon(info->app_icons, | 344 GURL best_icon = FindPreferredIcon(info->app_icons, |
| 339 kPreferredIconSize); | 345 kPreferredIconSize); |
| 340 if (!best_icon.is_empty()) { | 346 if (!best_icon.is_empty()) { |
| 341 task->SetString("iconUrl", best_icon.spec()); | 347 task->SetString("iconUrl", best_icon.spec()); |
| 342 } | 348 } |
| 343 task->SetBoolean("driveApp", true); | 349 task->SetBoolean("driveApp", true); |
| 344 result_list->Append(task); | 350 result_list->Append(task); |
| 345 } | 351 } |
| 346 } | 352 } |
| 347 | 353 |
| 354 typedef std::vector<webkit_glue::WebIntentServiceData> ServiceList; |
| 355 |
| 356 // Returns the set Web Intent actions for which the given |mime_type| is |
| 357 // allowed. |
| 358 std::set<std::string> ActionsForType(const std::string& mime_type, |
| 359 const ServiceList& services) { |
| 360 std::set<std::string> actions; |
| 361 for (ServiceList::const_iterator i = services.begin(); |
| 362 i != services.end(); ++i) { |
| 363 if (net::MatchesMimeType(UTF16ToUTF8(i->type), mime_type)) |
| 364 actions.insert(UTF16ToUTF8(i->action)); |
| 365 } |
| 366 return actions; |
| 367 } |
| 368 |
| 369 // Given an extension and a set of |mime_types|, return the set of Web Intent |
| 370 // actions that are supported on every type within the set. This set may be |
| 371 // empty, in which case no actions are supported. |
| 372 std::set<std::string> ActionsForExtension(const Extension* extension, |
| 373 const std::set<std::string>& mime_types) { |
| 374 std::set<std::string> actions; |
| 375 |
| 376 // TODO(thorogood): Test this! |
| 377 |
| 378 for (std::set<std::string>::const_iterator i = mime_types.begin(); |
| 379 i != mime_types.end(); ++i) { |
| 380 std::set<std::string> inner = |
| 381 ActionsForType(*i, extension->intents_services()); |
| 382 |
| 383 if (i == mime_types.begin()) { |
| 384 actions = inner; |
| 385 } else { |
| 386 std::set<std::string> tmp; |
| 387 std::set_intersection(actions.begin(), |
| 388 actions.end(), |
| 389 inner.begin(), |
| 390 inner.end(), |
| 391 std::inserter(tmp, tmp.begin())); |
| 392 actions = tmp; |
| 393 } |
| 394 |
| 395 if (actions.empty()) |
| 396 break; // fall-out early, this set will never grow |
| 397 } |
| 398 |
| 399 return actions; |
| 400 } |
| 401 |
| 402 // Retrieves the title for the given Extension and action pair, returning true |
| 403 // if it could be found. |
| 404 bool TitleForExtensionAction(const Extension* extension, |
| 405 const std::string& action, std::string* title) { |
| 406 for (ServiceList::const_iterator i = extension->intents_services().begin(); |
| 407 i != extension->intents_services().end(); ++i) { |
| 408 if (action == UTF16ToUTF8(i->action)) { |
| 409 *title = UTF16ToUTF8(i->title); |
| 410 return true; |
| 411 } |
| 412 } |
| 413 return false; |
| 414 } |
| 415 |
| 348 } // namespace | 416 } // namespace |
| 349 | 417 |
| 350 class RequestLocalFileSystemFunction::LocalFileSystemCallbackDispatcher { | 418 class RequestLocalFileSystemFunction::LocalFileSystemCallbackDispatcher { |
| 351 public: | 419 public: |
| 352 static fileapi::FileSystemContext::OpenFileSystemCallback CreateCallback( | 420 static fileapi::FileSystemContext::OpenFileSystemCallback CreateCallback( |
| 353 RequestLocalFileSystemFunction* function, | 421 RequestLocalFileSystemFunction* function, |
| 354 scoped_refptr<fileapi::FileSystemContext> file_system_context, | 422 scoped_refptr<fileapi::FileSystemContext> file_system_context, |
| 355 int child_id, | 423 int child_id, |
| 356 scoped_refptr<const Extension> extension) { | 424 scoped_refptr<const Extension> extension) { |
| 357 return base::Bind( | 425 return base::Bind( |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 } | 696 } |
| 629 | 697 |
| 630 gdata::GDataSystemService* system_service = | 698 gdata::GDataSystemService* system_service = |
| 631 gdata::GDataSystemServiceFactory::GetForProfile(profile_); | 699 gdata::GDataSystemServiceFactory::GetForProfile(profile_); |
| 632 // |system_service| is NULL if incognito window / guest login. We return true | 700 // |system_service| is NULL if incognito window / guest login. We return true |
| 633 // in this case because there might be other extension tasks, even if we don't | 701 // in this case because there might be other extension tasks, even if we don't |
| 634 // have any to add. | 702 // have any to add. |
| 635 if (!system_service || !system_service->webapps_registry()) | 703 if (!system_service || !system_service->webapps_registry()) |
| 636 return true; | 704 return true; |
| 637 | 705 |
| 638 | |
| 639 gdata::DriveWebAppsRegistry* registry = system_service->webapps_registry(); | 706 gdata::DriveWebAppsRegistry* registry = system_service->webapps_registry(); |
| 640 | 707 |
| 641 // Map of app_id to DriveWebAppInfo so we can look up the apps we've found | 708 // Map of app_id to DriveWebAppInfo so we can look up the apps we've found |
| 642 // after taking the intersection of available apps. | 709 // after taking the intersection of available apps. |
| 643 std::map<std::string, gdata::DriveWebAppInfo*> app_info; | 710 std::map<std::string, gdata::DriveWebAppInfo*> app_info; |
| 644 // Set of application IDs. This will end up with the intersection of the | 711 // Set of application IDs. This will end up with the intersection of the |
| 645 // application IDs that apply to the paths in |file_paths|. | 712 // application IDs that apply to the paths in |file_paths|. |
| 646 std::set<std::string> available_apps; | 713 std::set<std::string> available_apps; |
| 647 | 714 |
| 648 IntersectAvailableDriveTasks(registry, file_paths, | 715 IntersectAvailableDriveTasks(registry, file_paths, |
| 649 &app_info, &available_apps); | 716 &app_info, &available_apps); |
| 650 CreateDriveTasks(registry, app_info, available_apps, result_list); | 717 CreateDriveTasks(registry, app_info, available_apps, result_list); |
| 651 | 718 |
| 652 // We own the pointers in |app_info|, so we need to delete them. | 719 // We own the pointers in |app_info|, so we need to delete them. |
| 653 STLDeleteContainerPairSecondPointers(app_info.begin(), app_info.end()); | 720 STLDeleteContainerPairSecondPointers(app_info.begin(), app_info.end()); |
| 654 return true; | 721 return true; |
| 655 } | 722 } |
| 656 | 723 |
| 724 // Find special tasks here for Web Intent platform apps. Iterate through |
| 725 // matching apps and add them. These tasks will be identified by the "http" |
| 726 // prefix found on the task action. |
| 727 bool GetFileTasksFileBrowserFunction::FindWebIntentTasks( |
| 728 const std::vector<GURL>& file_urls, |
| 729 ListValue* result_list) { |
| 730 DCHECK(!file_urls.empty()); |
| 731 ExtensionService* service = profile_->GetExtensionService(); |
| 732 if (!service) |
| 733 return false; |
| 734 |
| 735 std::set<std::string> mime_types; |
| 736 for (std::vector<GURL>::const_iterator iter = file_urls.begin(); |
| 737 iter != file_urls.end(); ++iter) { |
| 738 const FilePath file = FilePath(GURL(iter->spec()).ExtractFileName()); |
| 739 const FilePath::StringType file_extension = |
| 740 StringToLowerASCII(file.Extension()); |
| 741 |
| 742 // TODO(thorogood): Rearchitect this call so it can run on the File thread; |
| 743 // GetMimeTypeFromFile requires this on Linux. Right now, we use |
| 744 // Chrome-level knowledge only. |
| 745 std::string mime_type; |
| 746 if (!file_extension.empty() && !net::GetWellKnownMimeTypeFromExtension( |
| 747 file_extension.substr(1), &mime_type)) |
| 748 mime_type = std::string(); // There was no mime-type available from |
| 749 // this file, but we'll still match "*". |
| 750 mime_types.insert(mime_type); |
| 751 } |
| 752 |
| 753 for (ExtensionSet::const_iterator iter = service->extensions()->begin(); |
| 754 iter != service->extensions()->end(); |
| 755 ++iter) { |
| 756 const Extension* extension = *iter; |
| 757 |
| 758 // We can't use hosted apps to open files. |
| 759 if (!extension->is_platform_app() || !extension->has_background_page()) |
| 760 continue; |
| 761 |
| 762 if (profile_->IsOffTheRecord() && |
| 763 !service->IsIncognitoEnabled(extension->id())) |
| 764 continue; |
| 765 |
| 766 const std::set<std::string> actions = |
| 767 ActionsForExtension(extension, mime_types); |
| 768 for (std::set<std::string>::iterator ai = actions.begin(); |
| 769 ai != actions.end(); ++ai) { |
| 770 std::string title; |
| 771 DCHECK(TitleForExtensionAction(extension, *ai, &title)); |
| 772 |
| 773 DictionaryValue* task = new DictionaryValue; |
| 774 std::string task_id = |
| 775 file_handler_util::MakeTaskID(extension->id(), *ai); |
| 776 task->SetString("taskId", task_id); |
| 777 task->SetString("title", title); |
| 778 |
| 779 // TODO(thorogood): Expand mime-types. Is this even important? We're |
| 780 // already only serving this task if it satisfies the pattern list. |
| 781 ListValue* pattern_list = new ListValue; |
| 782 pattern_list->Append(new StringValue("filesystem:*")); |
| 783 task->Set("patterns", pattern_list); |
| 784 |
| 785 GURL best_icon = extension->GetIconURL(kPreferredIconSize, |
| 786 ExtensionIconSet::MATCH_BIGGER); |
| 787 task->SetString("iconUrl", best_icon.spec()); |
| 788 |
| 789 task->SetBoolean("driveApp", false); |
| 790 result_list->Append(task); |
| 791 } |
| 792 } |
| 793 |
| 794 return true; |
| 795 } |
| 657 | 796 |
| 658 bool GetFileTasksFileBrowserFunction::RunImpl() { | 797 bool GetFileTasksFileBrowserFunction::RunImpl() { |
| 659 ListValue* files_list = NULL; | 798 ListValue* files_list = NULL; |
| 660 if (!args_->GetList(0, &files_list)) | 799 if (!args_->GetList(0, &files_list)) |
| 661 return false; | 800 return false; |
| 662 | 801 |
| 663 std::vector<GURL> file_urls; | 802 std::vector<GURL> file_urls; |
| 664 for (size_t i = 0; i < files_list->GetSize(); ++i) { | 803 for (size_t i = 0; i < files_list->GetSize(); ++i) { |
| 665 std::string file_url; | 804 std::string file_url; |
| 666 if (!files_list->GetString(i, &file_url)) | 805 if (!files_list->GetString(i, &file_url)) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 | 842 |
| 704 // Take the union of Drive and extension tasks: Because any extension tasks we | 843 // Take the union of Drive and extension tasks: Because any extension tasks we |
| 705 // found must apply to all of the files (intersection), and because the same | 844 // found must apply to all of the files (intersection), and because the same |
| 706 // is true of the drive apps, we simply take the union of two lists by adding | 845 // is true of the drive apps, we simply take the union of two lists by adding |
| 707 // the drive tasks to the extension task list. We know there aren't duplicates | 846 // the drive tasks to the extension task list. We know there aren't duplicates |
| 708 // because they're entirely different kinds of tasks, but there could be both | 847 // because they're entirely different kinds of tasks, but there could be both |
| 709 // kinds of tasks for a file type (an image file, for instance). | 848 // kinds of tasks for a file type (an image file, for instance). |
| 710 if (!FindDriveAppTasks(file_urls, result_list)) | 849 if (!FindDriveAppTasks(file_urls, result_list)) |
| 711 return false; | 850 return false; |
| 712 | 851 |
| 713 // TODO(zelidrag, serya): Add intent content tasks to result_list once we | 852 // Take the union of Web Intents (that platform apps may accept) and all |
| 714 // implement that API. | 853 // previous Drive and extension tasks. As above, we know there aren't |
| 854 // duplicates because they're entirely different kinds of tasks. |
| 855 if (!FindWebIntentTasks(file_urls, result_list)) |
| 856 return false; |
| 857 |
| 715 SendResponse(true); | 858 SendResponse(true); |
| 716 return true; | 859 return true; |
| 717 } | 860 } |
| 718 | 861 |
| 719 ExecuteTasksFileBrowserFunction::ExecuteTasksFileBrowserFunction() {} | 862 ExecuteTasksFileBrowserFunction::ExecuteTasksFileBrowserFunction() {} |
| 720 | 863 |
| 721 void ExecuteTasksFileBrowserFunction::OnTaskExecuted(bool success) { | 864 void ExecuteTasksFileBrowserFunction::OnTaskExecuted(bool success) { |
| 722 SendResponse(success); | 865 SendResponse(success); |
| 723 } | 866 } |
| 724 | 867 |
| (...skipping 1706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2431 gdata::GDataSystemService* system_service = | 2574 gdata::GDataSystemService* system_service = |
| 2432 gdata::GDataSystemServiceFactory::GetForProfile(profile_); | 2575 gdata::GDataSystemServiceFactory::GetForProfile(profile_); |
| 2433 if (!system_service || !system_service->file_system()) | 2576 if (!system_service || !system_service->file_system()) |
| 2434 return false; | 2577 return false; |
| 2435 | 2578 |
| 2436 FilePath directory_path = GetVirtualPathFromURL(GURL(file_url_as_string)); | 2579 FilePath directory_path = GetVirtualPathFromURL(GURL(file_url_as_string)); |
| 2437 system_service->file_system()->RequestDirectoryRefresh(directory_path); | 2580 system_service->file_system()->RequestDirectoryRefresh(directory_path); |
| 2438 | 2581 |
| 2439 return true; | 2582 return true; |
| 2440 } | 2583 } |
| OLD | NEW |