| 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 0d018fea5c840107bc68fbeb2eb4c8dd687fda83..558686334987e05894583e37ab0ebd709b609394 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/logging.h"
|
| #include "base/memory/scoped_vector.h"
|
| #include "base/memory/singleton.h"
|
| @@ -15,6 +18,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"
|
| @@ -50,6 +54,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/fileapi/file_system_context.h"
|
| @@ -58,6 +63,7 @@
|
| #include "webkit/fileapi/file_system_operation_context.h"
|
| #include "webkit/fileapi/file_system_types.h"
|
| #include "webkit/fileapi/file_system_util.h"
|
| +#include "webkit/glue/web_intent_service_data.h"
|
|
|
| using chromeos::disks::DiskMountManager;
|
| using content::BrowserContext;
|
| @@ -345,6 +351,68 @@ void CreateDriveTasks(
|
| }
|
| }
|
|
|
| +typedef std::vector<webkit_glue::WebIntentServiceData> ServiceList;
|
| +
|
| +// Returns the set 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;
|
| +
|
| + // TODO(thorogood): Test this!
|
| +
|
| + 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 {
|
| @@ -635,7 +703,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
|
| @@ -654,6 +721,78 @@ 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())
|
| + continue;
|
| +
|
| + if (profile_->IsOffTheRecord() &&
|
| + !service->IsIncognitoEnabled(extension->id()))
|
| + continue;
|
| +
|
| + const std::set<std::string> actions =
|
| + ActionsForExtension(extension, mime_types);
|
| + 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);
|
| +
|
| + // TODO(thorogood): Expand mime-types. Is this even important? We're
|
| + // already only serving this task if it satisfies the pattern list.
|
| + ListValue* pattern_list = new ListValue;
|
| + pattern_list->Append(new StringValue("filesystem:*"));
|
| + task->Set("patterns", pattern_list);
|
| +
|
| + 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() {
|
| ListValue* files_list = NULL;
|
| @@ -710,8 +849,12 @@ bool GetFileTasksFileBrowserFunction::RunImpl() {
|
| if (!FindDriveAppTasks(file_urls, result_list))
|
| return false;
|
|
|
| - // TODO(zelidrag, serya): Add intent content tasks to result_list once we
|
| - // implement that API.
|
| + // 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;
|
| +
|
| SendResponse(true);
|
| return true;
|
| }
|
|
|