Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Unified Diff: chrome/browser/chromeos/extensions/file_browser_private_api.cc

Issue 10834383: Chrome OS "open with" picker allowing Web Intents (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: sync to head, comment Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
}

Powered by Google App Engine
This is Rietveld 408576698