Chromium Code Reviews| Index: chrome/browser/chromeos/extensions/file_browser_private_api.cc |
| diff --git a/chrome/browser/chromeos/extensions/file_browser_private_api.cc b/chrome/browser/chromeos/extensions/file_browser_private_api.cc |
| index 21bb18a7771a1819c4d1d0cd719d7d41e0c89aa8..28405240075761e351e0ce662659f4ea11452389 100644 |
| --- a/chrome/browser/chromeos/extensions/file_browser_private_api.cc |
| +++ b/chrome/browser/chromeos/extensions/file_browser_private_api.cc |
| @@ -8,6 +8,9 @@ |
| #include "base/base64.h" |
| #include "base/bind.h" |
| +#include "base/file_path.h" |
| +#include "base/file_util.h" |
| +#include "base/i18n/case_conversion.h" |
| #include "base/json/json_writer.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_vector.h" |
| @@ -16,6 +19,7 @@ |
| #include "base/stringprintf.h" |
| #include "base/time.h" |
| #include "base/values.h" |
| +#include "base/utf_string_conversions.h" |
| #include "chrome/browser/chromeos/cros/cros_library.h" |
| #include "chrome/browser/chromeos/cros/network_library.h" |
| #include "chrome/browser/chromeos/disks/disk_mount_manager.h" |
| @@ -52,6 +56,7 @@ |
| #include "grit/generated_resources.h" |
| #include "grit/platform_locale_settings.h" |
| #include "net/base/escape.h" |
| +#include "net/base/mime_util.h" |
| #include "ui/base/dialogs/selected_file_info.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "webkit/chromeos/fileapi/cros_mount_point_provider.h" |
| @@ -61,6 +66,7 @@ |
| #include "webkit/fileapi/file_system_types.h" |
| #include "webkit/fileapi/file_system_url.h" |
| #include "webkit/fileapi/file_system_util.h" |
| +#include "webkit/glue/web_intent_service_data.h" |
| using chromeos::disks::DiskMountManager; |
| using content::BrowserContext; |
| @@ -253,6 +259,66 @@ GURL FindPreferredIcon(const InstalledApp::IconList& icons, |
| return result; |
| } |
| +typedef std::vector<webkit_glue::WebIntentServiceData> ServiceList; |
| + |
| +// Returns the set of Web Intent actions for which the given |mime_type| is |
| +// allowed. |
| +std::set<std::string> ActionsForType(const std::string& mime_type, |
| + const ServiceList& services) { |
| + std::set<std::string> actions; |
| + for (ServiceList::const_iterator i = services.begin(); |
| + i != services.end(); ++i) { |
| + if (net::MatchesMimeType(UTF16ToUTF8(i->type), mime_type)) |
| + actions.insert(UTF16ToUTF8(i->action)); |
| + } |
| + return actions; |
| +} |
| + |
| +// Given an extension and a set of |mime_types|, return the set of Web Intent |
| +// actions that are supported on every type within the set. This set may be |
| +// empty, in which case no actions are supported. |
| +std::set<std::string> ActionsForExtension(const Extension* extension, |
| + const std::set<std::string>& mime_types) { |
| + std::set<std::string> actions; |
| + |
| + for (std::set<std::string>::const_iterator i = mime_types.begin(); |
| + i != mime_types.end(); ++i) { |
| + std::set<std::string> inner = |
| + ActionsForType(*i, extension->intents_services()); |
| + |
| + if (i == mime_types.begin()) { |
| + actions = inner; |
| + } else { |
| + std::set<std::string> tmp; |
| + std::set_intersection(actions.begin(), |
| + actions.end(), |
| + inner.begin(), |
| + inner.end(), |
| + std::inserter(tmp, tmp.begin())); |
| + actions = tmp; |
| + } |
| + |
| + if (actions.empty()) |
| + break; // fall-out early, this set will never grow |
| + } |
| + |
| + return actions; |
| +} |
| + |
| +// Retrieves the title for the given Extension and action pair, returning true |
| +// if it could be found. |
| +bool TitleForExtensionAction(const Extension* extension, |
| + const std::string& action, std::string* title) { |
| + for (ServiceList::const_iterator i = extension->intents_services().begin(); |
| + i != extension->intents_services().end(); ++i) { |
| + if (action == UTF16ToUTF8(i->action)) { |
| + *title = UTF16ToUTF8(i->title); |
| + return true; |
| + } |
| + } |
| + return false; |
| +} |
| + |
| } // namespace |
| class RequestLocalFileSystemFunction::LocalFileSystemCallbackDispatcher { |
| @@ -600,7 +666,6 @@ bool GetFileTasksFileBrowserFunction::FindDriveAppTasks( |
| if (!system_service || !system_service->webapps_registry()) |
| return true; |
| - |
| gdata::DriveWebAppsRegistry* registry = system_service->webapps_registry(); |
| // Map of app_id to DriveWebAppInfo so we can look up the apps we've found |
| @@ -619,6 +684,74 @@ bool GetFileTasksFileBrowserFunction::FindDriveAppTasks( |
| return true; |
| } |
| +// Find special tasks here for Web Intent platform apps. Iterate through |
| +// matching apps and add them. These tasks will be identified by the "http" |
| +// prefix found on the task action. |
| +bool GetFileTasksFileBrowserFunction::FindWebIntentTasks( |
| + const std::vector<GURL>& file_urls, |
| + ListValue* result_list) { |
| + DCHECK(!file_urls.empty()); |
| + ExtensionService* service = profile_->GetExtensionService(); |
| + if (!service) |
| + return false; |
| + |
| + std::set<std::string> mime_types; |
| + for (std::vector<GURL>::const_iterator iter = file_urls.begin(); |
| + iter != file_urls.end(); ++iter) { |
| + const FilePath file = FilePath(GURL(iter->spec()).ExtractFileName()); |
| + const FilePath::StringType file_extension = |
| + StringToLowerASCII(file.Extension()); |
| + |
| + // TODO(thorogood): Rearchitect this call so it can run on the File thread; |
| + // GetMimeTypeFromFile requires this on Linux. Right now, we use |
| + // Chrome-level knowledge only. |
| + std::string mime_type; |
| + if (!file_extension.empty() && !net::GetWellKnownMimeTypeFromExtension( |
| + file_extension.substr(1), &mime_type)) |
| + mime_type = std::string(); // There was no mime-type available from this |
| + // file, but we'll still match "*". |
| + mime_types.insert(mime_type); |
| + } |
| + |
| + for (ExtensionSet::const_iterator iter = service->extensions()->begin(); |
| + iter != service->extensions()->end(); |
| + ++iter) { |
| + const Extension* extension = *iter; |
| + |
| + // We can't use hosted apps to open files. |
| + if (!extension->is_platform_app() || !extension->has_background_page()) |
|
benwells
2012/08/27 08:02:59
Don't need to check for background page here, all
thorogood
2012/08/28 00:04:04
Done.
|
| + continue; |
| + |
| + if (profile_->IsOffTheRecord() && |
| + !service->IsIncognitoEnabled(extension->id())) |
| + continue; |
| + |
| + const std::set<std::string> actions = |
| + ActionsForExtension(extension, mime_types); |
|
benwells
2012/08/27 08:02:59
I should have mentioned this, but we only care abo
thorogood
2012/08/28 00:04:04
Before I make this change, can I ask why? In my mi
thorogood
2012/08/29 06:34:46
I've updated this file to work this way now. PTAL!
|
| + for (std::set<std::string>::iterator ai = actions.begin(); |
| + ai != actions.end(); ++ai) { |
| + std::string title; |
| + DCHECK(TitleForExtensionAction(extension, *ai, &title)); |
| + |
| + DictionaryValue* task = new DictionaryValue; |
| + std::string task_id = |
| + file_handler_util::MakeTaskID(extension->id(), *ai); |
| + task->SetString("taskId", task_id); |
| + task->SetString("title", title); |
| + task->Set("patterns", new ListValue); |
| + |
| + GURL best_icon = extension->GetIconURL(kPreferredIconSize, |
| + ExtensionIconSet::MATCH_BIGGER); |
| + task->SetString("iconUrl", best_icon.spec()); |
| + |
| + task->SetBoolean("driveApp", false); |
| + result_list->Append(task); |
| + } |
| + } |
| + |
| + return true; |
| +} |
| + |
| bool GetFileTasksFileBrowserFunction::RunImpl() { |
| // First argument is the list of files to get tasks for. |
| ListValue* files_list = NULL; |
| @@ -700,6 +833,12 @@ bool GetFileTasksFileBrowserFunction::RunImpl() { |
| if (!FindDriveAppTasks(info_list, result_list)) |
| return false; |
| + // Take the union of Web Intents (that platform apps may accept) and all |
| + // previous Drive and extension tasks. As above, we know there aren't |
| + // duplicates because they're entirely different kinds of tasks. |
| + if (!FindWebIntentTasks(file_urls, result_list)) |
| + return false; |
| + |
| if (VLOG_IS_ON(1)) { |
| std::string result_json; |
| base::JSONWriter::WriteWithOptions( |
| @@ -710,8 +849,6 @@ bool GetFileTasksFileBrowserFunction::RunImpl() { |
| VLOG(1) << "GetFileTasks result:\n" << result_json; |
| } |
| - // TODO(zelidrag, serya): Add intent content tasks to result_list once we |
| - // implement that API. |
| SendResponse(true); |
| return true; |
| } |