summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/extensions/file_browser_private_api.cc100
-rw-r--r--chrome/browser/chromeos/extensions/file_browser_private_api.h5
-rw-r--r--chrome/browser/chromeos/extensions/file_handler_util.cc79
-rw-r--r--chrome/browser/chromeos/extensions/file_handler_util.h1
-rw-r--r--chrome/browser/extensions/api/app_runtime/app_runtime_api.cc1
-rw-r--r--chrome/browser/extensions/api/app_runtime/app_runtime_api.h1
-rw-r--r--chrome/browser/extensions/app_file_handler_util.cc79
-rw-r--r--chrome/browser/extensions/app_file_handler_util.h36
-rw-r--r--chrome/browser/extensions/platform_app_launcher.cc67
-rw-r--r--chrome/browser/extensions/platform_app_launcher.h9
-rw-r--r--chrome/chrome_browser_extensions.gypi2
-rw-r--r--chrome/common/extensions/extension.cc21
-rw-r--r--chrome/common/extensions/extension.h20
13 files changed, 380 insertions, 41 deletions
diff --git a/chrome/browser/chromeos/extensions/file_browser_private_api.cc b/chrome/browser/chromeos/extensions/file_browser_private_api.cc
index da0cbeb..f5e4cad 100644
--- a/chrome/browser/chromeos/extensions/file_browser_private_api.cc
+++ b/chrome/browser/chromeos/extensions/file_browser_private_api.cc
@@ -34,6 +34,7 @@
#include "chrome/browser/chromeos/extensions/file_handler_util.h"
#include "chrome/browser/chromeos/extensions/file_manager_util.h"
#include "chrome/browser/chromeos/system/statistics_provider.h"
+#include "chrome/browser/extensions/app_file_handler_util.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -75,6 +76,7 @@
#include "webkit/fileapi/file_system_util.h"
#include "webkit/glue/web_intent_service_data.h"
+using app_file_handler_util::FindFileHandlersForMimeTypes;
using chromeos::disks::DiskMountManager;
using content::BrowserContext;
using content::BrowserThread;
@@ -793,17 +795,8 @@ bool GetFileTasksFileBrowserFunction::FindDriveAppTasks(
return true;
}
-// Find Web Intent platform apps that support the View task, and add them to
-// the |result_list|. These will be marked as kTaskWebIntent.
-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;
+static void GetMimeTypesForFileURLs(const std::vector<GURL>& file_urls,
+ 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());
@@ -819,12 +812,81 @@ bool GetFileTasksFileBrowserFunction::FindWebIntentTasks(
// If the file doesn't have an extension or its mime-type cannot be
// determined, then indicate that it has the empty mime-type. This will
// only be matched if the Web Intents accepts "*" or "*/*".
- mime_types.insert("");
+ mime_types->insert("");
} else {
- mime_types.insert(mime_type);
+ mime_types->insert(mime_type);
+ }
+ }
+}
+
+bool GetFileTasksFileBrowserFunction::FindAppTasks(
+ 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;
+ GetMimeTypesForFileURLs(file_urls, &mime_types);
+
+ for (ExtensionSet::const_iterator iter = service->extensions()->begin();
+ iter != service->extensions()->end();
+ ++iter) {
+ const Extension* extension = *iter;
+
+ // We don't support using hosted apps to open files.
+ if (!extension->is_platform_app())
+ continue;
+
+ if (profile_->IsOffTheRecord() &&
+ !service->IsIncognitoEnabled(extension->id()))
+ continue;
+
+ typedef std::vector<const Extension::FileHandlerInfo*> FileHandlerList;
+ FileHandlerList file_handlers =
+ FindFileHandlersForMimeTypes(*extension, mime_types);
+ // TODO(benwells): also support matching by file extension.
+ if (file_handlers.empty())
+ continue;
+
+ for (FileHandlerList::iterator i = file_handlers.begin();
+ i != file_handlers.end(); ++i) {
+ DictionaryValue* task = new DictionaryValue;
+ std::string task_id = file_handler_util::MakeTaskID(extension->id(),
+ file_handler_util::kTaskApp, (*i)->id);
+ task->SetString("taskId", task_id);
+ task->SetString("title", (*i)->title);
+ task->SetBoolean("isDefault", false);
+
+ GURL best_icon = extension->GetIconURL(kPreferredIconSize,
+ ExtensionIconSet::MATCH_BIGGER);
+ if (!best_icon.is_empty())
+ task->SetString("iconUrl", best_icon.spec());
+ else
+ task->SetString("iconUrl", kDefaultIcon);
+
+ task->SetBoolean("driveApp", false);
+ result_list->Append(task);
}
}
+ return true;
+}
+
+// Find Web Intent platform apps that support the View task, and add them to
+// the |result_list|. These will be marked as kTaskWebIntent.
+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;
+ GetMimeTypesForFileURLs(file_urls, &mime_types);
+
for (ExtensionSet::const_iterator iter = service->extensions()->begin();
iter != service->extensions()->end();
++iter) {
@@ -958,9 +1020,15 @@ bool GetFileTasksFileBrowserFunction::RunImpl() {
result_list->Append(task);
}
- // 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.
+ // Take the union of platform app file handlers, 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 (!FindAppTasks(file_urls, result_list))
+ return false;
+
+ // TODO(benwells): remove the web intents tasks once we no longer support
+ // them.
if (!FindWebIntentTasks(file_urls, result_list))
return false;
diff --git a/chrome/browser/chromeos/extensions/file_browser_private_api.h b/chrome/browser/chromeos/extensions/file_browser_private_api.h
index e70c8ba..7fc0b31 100644
--- a/chrome/browser/chromeos/extensions/file_browser_private_api.h
+++ b/chrome/browser/chromeos/extensions/file_browser_private_api.h
@@ -172,6 +172,11 @@ class GetFileTasksFileBrowserFunction : public AsyncExtensionFunction {
// types, appending them to the |result_list|.
bool FindWebIntentTasks(const std::vector<GURL>& file_urls,
ListValue* result_list);
+
+ // Find the list of app file handlers that can be used with the given file
+ // types, appending them to the |result_list|.
+ bool FindAppTasks(const std::vector<GURL>& file_urls,
+ ListValue* result_list);
};
// Implements the chrome.fileBrowserPrivate.executeTask method.
diff --git a/chrome/browser/chromeos/extensions/file_handler_util.cc b/chrome/browser/chromeos/extensions/file_handler_util.cc
index ed6473f..26ee7cb 100644
--- a/chrome/browser/chromeos/extensions/file_handler_util.cc
+++ b/chrome/browser/chromeos/extensions/file_handler_util.cc
@@ -55,6 +55,7 @@ namespace file_handler_util {
const char kTaskFile[] = "file";
const char kTaskDrive[] = "drive";
const char kTaskWebIntent[] = "web-intent";
+const char kTaskApp[] = "app";
namespace {
@@ -263,7 +264,8 @@ std::string MakeTaskID(const std::string& extension_id,
const std::string& action_id) {
DCHECK(task_type == kTaskFile ||
task_type == kTaskDrive ||
- task_type == kTaskWebIntent);
+ task_type == kTaskWebIntent ||
+ task_type == kTaskApp);
return base::StringPrintf("%s|%s|%s",
extension_id.c_str(),
task_type.c_str(),
@@ -313,7 +315,8 @@ bool CrackTaskID(const std::string& task_id,
*task_type = result[1];
DCHECK(*task_type == kTaskFile ||
*task_type == kTaskDrive ||
- *task_type == kTaskWebIntent);
+ *task_type == kTaskWebIntent ||
+ *task_type == kTaskApp);
}
if (action_id)
@@ -562,6 +565,27 @@ class WebIntentTaskExecutor : public FileTaskExecutor {
const std::string action_id_;
};
+class AppTaskExecutor : public FileTaskExecutor {
+ public:
+ // FileTaskExecutor overrides.
+ virtual bool ExecuteAndNotify(const std::vector<GURL>& file_urls,
+ const FileTaskFinishedCallback& done) OVERRIDE;
+
+ private:
+ // FileTaskExecutor is the only class allowed to create one.
+ friend class FileTaskExecutor;
+
+ AppTaskExecutor(Profile* profile,
+ const std::string& extension_id,
+ const std::string& action_id);
+ virtual ~AppTaskExecutor();
+
+ bool ExecuteForURL(const GURL& file_url);
+
+ const std::string extension_id_;
+ const std::string action_id_;
+};
+
// static
FileTaskExecutor* FileTaskExecutor::Create(Profile* profile,
const GURL source_url,
@@ -587,6 +611,11 @@ FileTaskExecutor* FileTaskExecutor::Create(Profile* profile,
extension_id,
action_id);
+ if (task_type == kTaskApp)
+ return new AppTaskExecutor(profile,
+ extension_id,
+ action_id);
+
NOTREACHED();
return NULL;
}
@@ -1066,4 +1095,50 @@ bool WebIntentTaskExecutor::ExecuteForURL(const GURL& file_url) {
return true;
}
+AppTaskExecutor::AppTaskExecutor(
+ Profile* profile,
+ const std::string& extension_id,
+ const std::string& action_id)
+ : FileTaskExecutor(profile, extension_id),
+ action_id_(action_id) {
+}
+
+AppTaskExecutor::~AppTaskExecutor() {}
+
+bool AppTaskExecutor::ExecuteAndNotify(
+ const std::vector<GURL>& file_urls,
+ const FileTaskFinishedCallback& done) {
+ bool success = true;
+
+ for (std::vector<GURL>::const_iterator i = file_urls.begin();
+ i != file_urls.end(); ++i) {
+ if (!ExecuteForURL(*i))
+ success = false;
+ }
+
+ if (!done.is_null())
+ done.Run(success);
+
+ return true;
+}
+
+bool AppTaskExecutor::ExecuteForURL(const GURL& file_url) {
+ fileapi::FileSystemURL url(file_url);
+ if (!chromeos::CrosMountPointProvider::CanHandleURL(url))
+ return false;
+
+ scoped_refptr<fileapi::FileSystemContext> file_system_context =
+ BrowserContext::GetDefaultStoragePartition(profile())->
+ GetFileSystemContext();
+ fileapi::ExternalFileSystemMountPointProvider* external_provider =
+ file_system_context->external_provider();
+ if (!external_provider || !external_provider->IsAccessAllowed(url))
+ return false;
+
+ FilePath local_path = url.path();
+ extensions::LaunchPlatformAppWithFileHandler(profile(), GetExtension(),
+ action_id_, local_path);
+ return true;
+}
+
} // namespace file_handler_util
diff --git a/chrome/browser/chromeos/extensions/file_handler_util.h b/chrome/browser/chromeos/extensions/file_handler_util.h
index d06b196..69fd2e7 100644
--- a/chrome/browser/chromeos/extensions/file_handler_util.h
+++ b/chrome/browser/chromeos/extensions/file_handler_util.h
@@ -29,6 +29,7 @@ namespace file_handler_util {
extern const char kTaskFile[];
extern const char kTaskDrive[];
extern const char kTaskWebIntent[];
+extern const char kTaskApp[];
void UpdateFileHandlerUsageStats(Profile* profile, const std::string& task_id);
diff --git a/chrome/browser/extensions/api/app_runtime/app_runtime_api.cc b/chrome/browser/extensions/api/app_runtime/app_runtime_api.cc
index cca8487..09fb6c9 100644
--- a/chrome/browser/extensions/api/app_runtime/app_runtime_api.cc
+++ b/chrome/browser/extensions/api/app_runtime/app_runtime_api.cc
@@ -55,6 +55,7 @@ void AppEventRouter::DispatchOnRestartedEvent(
// static.
void AppEventRouter::DispatchOnLaunchedEventWithFileEntry(
Profile* profile, const Extension* extension, const string16& action,
+ const std::string& handler_id,
const std::string& file_system_id, const std::string& base_name) {
scoped_ptr<ListValue> args(new ListValue());
DictionaryValue* launch_data = new DictionaryValue();
diff --git a/chrome/browser/extensions/api/app_runtime/app_runtime_api.h b/chrome/browser/extensions/api/app_runtime/app_runtime_api.h
index b58a35a..583f827 100644
--- a/chrome/browser/extensions/api/app_runtime/app_runtime_api.h
+++ b/chrome/browser/extensions/api/app_runtime/app_runtime_api.h
@@ -47,6 +47,7 @@ class AppEventRouter {
Profile* profile,
const Extension* extension,
const string16& action,
+ const std::string& handler_id,
const std::string& file_system_id,
const std::string& base_name);
diff --git a/chrome/browser/extensions/app_file_handler_util.cc b/chrome/browser/extensions/app_file_handler_util.cc
new file mode 100644
index 0000000..df31c28
--- /dev/null
+++ b/chrome/browser/extensions/app_file_handler_util.cc
@@ -0,0 +1,79 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/app_file_handler_util.h"
+
+#include "net/base/mime_util.h"
+
+using extensions::Extension;
+
+namespace app_file_handler_util {
+
+typedef std::vector<Extension::FileHandlerInfo> FileHandlerList;
+
+const Extension::FileHandlerInfo* FileHandlerForId(
+ const Extension& app,
+ const std::string& handler_id) {
+ const FileHandlerList& file_handlers = app.file_handlers();
+ for (FileHandlerList::const_iterator i = file_handlers.begin();
+ i != file_handlers.end(); i++) {
+ if (i->id == handler_id)
+ return &*i;
+ }
+ return NULL;
+}
+
+const Extension::FileHandlerInfo* FirstFileHandlerForMimeType(
+ const Extension& app,
+ const std::string& mime_type) {
+ const FileHandlerList& file_handlers = app.file_handlers();
+ for (FileHandlerList::const_iterator i = file_handlers.begin();
+ i != file_handlers.end(); i++) {
+ for (std::set<std::string>::const_iterator t = i->types.begin();
+ t != i->types.end(); t++) {
+ if (net::MatchesMimeType(*t, mime_type))
+ return &*i;
+ }
+ }
+ return NULL;
+}
+
+std::vector<const Extension::FileHandlerInfo*> FindFileHandlersForMimeTypes(
+ const Extension& app,
+ const std::set<std::string>& mime_types) {
+ std::vector<const Extension::FileHandlerInfo*> handlers;
+ if (mime_types.empty())
+ return handlers;
+
+ // Look for file handlers which can handle all the MIME types specified.
+ const FileHandlerList& file_handlers = app.file_handlers();
+ for (FileHandlerList::const_iterator data = file_handlers.begin();
+ data != file_handlers.end(); ++data) {
+ bool handles_all_types = true;
+ for (std::set<std::string>::const_iterator type_iter = mime_types.begin();
+ type_iter != mime_types.end(); ++type_iter) {
+ if (!FileHandlerCanHandleFileWithMimeType(*data, *type_iter)) {
+ handles_all_types = false;
+ break;
+ }
+ }
+ if (handles_all_types)
+ handlers.push_back(&*data);
+ }
+ return handlers;
+}
+
+bool FileHandlerCanHandleFileWithMimeType(
+ const extensions::Extension::FileHandlerInfo& handler,
+ const std::string& mime_type) {
+ // TODO(benwells): this should check the file's extension as well.
+ for (std::set<std::string>::const_iterator type = handler.types.begin();
+ type != handler.types.end(); ++type) {
+ if (net::MatchesMimeType(*type, mime_type))
+ return true;
+ }
+ return false;
+}
+
+} // namespace
diff --git a/chrome/browser/extensions/app_file_handler_util.h b/chrome/browser/extensions/app_file_handler_util.h
new file mode 100644
index 0000000..6cc5710
--- /dev/null
+++ b/chrome/browser/extensions/app_file_handler_util.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_APP_FILE_HANDLER_UTIL_H_
+#define CHROME_BROWSER_EXTENSIONS_APP_FILE_HANDLER_UTIL_H_
+
+#include "chrome/common/extensions/extension.h"
+
+// TODO(benwells): move this to platform_apps namespace.
+namespace app_file_handler_util {
+
+// Returns the file handler with the specified |handler_id|, or NULL if there
+// is no such handler.
+const extensions::Extension::FileHandlerInfo* FileHandlerForId(
+ const extensions::Extension& app,
+ const std::string& handler_id);
+
+// Returns the first file handler that can handle the given MIME type, or NULL
+// if is no such handler.
+const extensions::Extension::FileHandlerInfo* FirstFileHandlerForMimeType(
+ const extensions::Extension& app,
+ const std::string& mime_type);
+
+std::vector<const extensions::Extension::FileHandlerInfo*>
+FindFileHandlersForMimeTypes(
+ const extensions::Extension& extension,
+ const std::set<std::string>& mime_types);
+
+bool FileHandlerCanHandleFileWithMimeType(
+ const extensions::Extension::FileHandlerInfo& handler,
+ const std::string& mime_type);
+
+}
+
+#endif // CHROME_BROWSER_EXTENSIONS_APP_FILE_HANDLER_UTIL_H_
diff --git a/chrome/browser/extensions/platform_app_launcher.cc b/chrome/browser/extensions/platform_app_launcher.cc
index b127641..e0aaf52 100644
--- a/chrome/browser/extensions/platform_app_launcher.cc
+++ b/chrome/browser/extensions/platform_app_launcher.cc
@@ -12,6 +12,7 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/api/app_runtime/app_runtime_api.h"
+#include "chrome/browser/extensions/app_file_handler_util.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_system.h"
@@ -33,6 +34,9 @@
#include "webkit/glue/web_intent_service_data.h"
using content::BrowserThread;
+using app_file_handler_util::FileHandlerForId;
+using app_file_handler_util::FileHandlerCanHandleFileWithMimeType;
+using app_file_handler_util::FirstFileHandlerForMimeType;
namespace extensions {
@@ -91,7 +95,8 @@ class PlatformAppPathLauncher
const FilePath& file_path)
: profile_(profile),
extension_(extension),
- file_path_(file_path) {}
+ file_path_(file_path),
+ handler_id_("") {}
void Launch() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -105,6 +110,11 @@ class PlatformAppPathLauncher
&PlatformAppPathLauncher::GetMimeTypeAndLaunch, this));
}
+ void LaunchWithHandler(const std::string& handler_id) {
+ handler_id_ = handler_id;
+ Launch();
+ }
+
private:
friend class base::RefCountedThreadSafe<PlatformAppPathLauncher>;
@@ -142,26 +152,43 @@ class PlatformAppPathLauncher
}
void LaunchWithMimeType(const std::string& mime_type) {
- // Find the intent service from the platform app for the file being opened.
- webkit_glue::WebIntentServiceData service;
+ // Find the intent service or file handler from the platform app for the
+ // file being opened.
bool found_service = false;
- std::vector<webkit_glue::WebIntentServiceData> services =
- extension_->intents_services();
- for (size_t i = 0; i < services.size(); i++) {
- std::string service_type_ascii = UTF16ToASCII(services[i].type);
- if (services[i].action == ASCIIToUTF16(web_intents::kActionView) &&
- net::MatchesMimeType(service_type_ascii, mime_type)) {
- service = services[i];
- found_service = true;
- break;
+ const Extension::FileHandlerInfo* handler = NULL;
+ if (!handler_id_.empty())
+ handler = FileHandlerForId(*extension_, handler_id_);
+ else
+ handler = FirstFileHandlerForMimeType(*extension_, mime_type);
+ if (handler &&
+ !FileHandlerCanHandleFileWithMimeType(*handler, mime_type)) {
+ LOG(WARNING) << "Extension does not provide a valid file handler for "
+ << file_path_.value();
+ LaunchWithNoLaunchData();
+ return;
+ }
+ found_service = !!handler;
+
+ // TODO(benwells): remove this once we no longer support the "intents"
+ // syntax in platform app manifests.
+ if (!found_service) {
+ std::vector<webkit_glue::WebIntentServiceData> services =
+ extension_->intents_services();
+ for (size_t i = 0; i < services.size(); i++) {
+ std::string service_type_ascii = UTF16ToASCII(services[i].type);
+ if (services[i].action == ASCIIToUTF16(web_intents::kActionView) &&
+ net::MatchesMimeType(service_type_ascii, mime_type)) {
+ found_service = true;
+ break;
+ }
}
}
// If this app doesn't have an intent that supports the file, launch with
// no launch data.
if (!found_service) {
- LOG(WARNING) << "Extension does not provide a valid intent for "
+ LOG(WARNING) << "Extension does not provide a valid file handler for "
<< file_path_.value();
LaunchWithNoLaunchData();
return;
@@ -220,7 +247,7 @@ class PlatformAppPathLauncher
extensions::AppEventRouter::DispatchOnLaunchedEventWithFileEntry(
profile_, extension_, ASCIIToUTF16(web_intents::kActionView),
- filesystem_id, registered_name);
+ handler_id_, filesystem_id, registered_name);
}
// The profile the app should be run in.
@@ -229,6 +256,8 @@ class PlatformAppPathLauncher
const Extension* extension_;
// The path to be passed through to the app.
const FilePath file_path_;
+ // The ID of the file handler used to launch the app.
+ std::string handler_id_;
DISALLOW_COPY_AND_ASSIGN(PlatformAppPathLauncher);
};
@@ -352,6 +381,7 @@ void LaunchPlatformApp(Profile* profile,
return;
}
+ // TODO(benwells): add a command-line argument to provide a handler ID.
LaunchPlatformAppWithPath(profile, extension, path);
}
@@ -366,6 +396,15 @@ void LaunchPlatformAppWithPath(Profile* profile,
launcher->Launch();
}
+void LaunchPlatformAppWithFileHandler(Profile* profile,
+ const Extension* extension,
+ const std::string& handler_id,
+ const FilePath& file_path) {
+ scoped_refptr<PlatformAppPathLauncher> launcher =
+ new PlatformAppPathLauncher(profile, extension, file_path);
+ launcher->LaunchWithHandler(handler_id);
+}
+
void LaunchPlatformAppWithWebIntent(
Profile* profile,
const Extension* extension,
diff --git a/chrome/browser/extensions/platform_app_launcher.h b/chrome/browser/extensions/platform_app_launcher.h
index 6721c00..7a5f6d3 100644
--- a/chrome/browser/extensions/platform_app_launcher.h
+++ b/chrome/browser/extensions/platform_app_launcher.h
@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_EXTENSIONS_PLATFORM_APP_LAUNCHER_H_
#define CHROME_BROWSER_EXTENSIONS_PLATFORM_APP_LAUNCHER_H_
+#include <string>
+
class CommandLine;
class FilePath;
class Profile;
@@ -33,6 +35,13 @@ void LaunchPlatformAppWithPath(Profile* profile,
const Extension* extension,
const FilePath& file_path);
+// Launches the platform app |extension| with the contents of |file_path|
+// available through the launch data.
+void LaunchPlatformAppWithFileHandler(Profile* profile,
+ const Extension* extension,
+ const std::string& handler_id,
+ const FilePath& file_path);
+
// Launches the platform app |extension| with the supplied web intent. Creates
// appropriate launch data for the |web_intent_data| field present. |extension|
// and |profile| must not be NULL.
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index 7e74a98..a89867a 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -361,6 +361,8 @@
'browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.h',
'browser/extensions/api/webstore_private/webstore_private_api.cc',
'browser/extensions/api/webstore_private/webstore_private_api.h',
+ 'browser/extensions/app_file_handler_util.cc',
+ 'browser/extensions/app_file_handler_util.h',
'browser/extensions/app_host_installer_win.cc',
'browser/extensions/app_host_installer_win.h',
'browser/extensions/app_notification.cc',
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index bba77563..7adcf41 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -335,6 +335,9 @@ Extension::OAuth2Info::~OAuth2Info() {}
Extension::ActionInfo::ActionInfo() {}
Extension::ActionInfo::~ActionInfo() {}
+Extension::FileHandlerInfo::FileHandlerInfo() {}
+Extension::FileHandlerInfo::~FileHandlerInfo() {}
+
//
// Extension
//
@@ -2123,13 +2126,12 @@ bool Extension::LoadFileHandler(const std::string& handler_id,
string16* error) {
DCHECK(error);
DCHECK(is_platform_app());
- webkit_glue::WebIntentServiceData service;
+ FileHandlerInfo handler;
- // TODO(jeremya): use a file-handler-specific data structure instead of web
- // intents.
- service.action = ASCIIToUTF16("http://webintents.org/view");
+ handler.id = handler_id;
const ListValue* mime_types = NULL;
+ // TODO(benwells): handle file extensions.
if (!handler_info.HasKey(keys::kFileHandlerTypes) ||
!handler_info.GetList(keys::kFileHandlerTypes, &mime_types) ||
mime_types->GetSize() == 0) {
@@ -2138,23 +2140,24 @@ bool Extension::LoadFileHandler(const std::string& handler_id,
return false;
}
- service.service_url = GetBackgroundURL();
-
if (handler_info.HasKey(keys::kFileHandlerTitle) &&
- !handler_info.GetString(keys::kFileHandlerTitle, &service.title)) {
+ !handler_info.GetString(keys::kFileHandlerTitle, &handler.title)) {
*error = ASCIIToUTF16(errors::kInvalidFileHandlerTitle);
return false;
}
+ std::string type;
for (size_t i = 0; i < mime_types->GetSize(); ++i) {
- if (!mime_types->GetString(i, &service.type)) {
+ if (!mime_types->GetString(i, &type)) {
*error = ErrorUtils::FormatErrorMessageUTF16(
errors::kInvalidFileHandlerTypeElement, handler_id,
std::string(base::IntToString(i)));
return false;
}
- intents_services_.push_back(service);
+ handler.types.insert(type);
}
+
+ file_handlers_.push_back(handler);
return true;
}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 685990c..3a5a42c 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -234,6 +234,19 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
std::string id;
};
+ struct FileHandlerInfo {
+ explicit FileHandlerInfo();
+ ~FileHandlerInfo();
+ std::string id;
+ std::string title;
+
+ // File extensions associated with this handler.
+ std::set<std::string> extensions;
+
+ // MIME types associated with this handler.
+ std::set<std::string> types;
+ };
+
struct InstallWarning {
enum Format {
// IMPORTANT: Do not build HTML strings from user or developer-supplied
@@ -780,6 +793,10 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
int launch_width() const { return launch_width_; }
int launch_height() const { return launch_height_; }
+ const std::vector<FileHandlerInfo>& file_handlers() const {
+ return file_handlers_;
+ }
+
// Theme-related.
bool is_theme() const;
base::DictionaryValue* GetThemeImages() const { return theme_images_.get(); }
@@ -1212,6 +1229,9 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// List of intent services that this extension provides, if any.
std::vector<webkit_glue::WebIntentServiceData> intents_services_;
+ // List of file handlers associated with this extension, if any.
+ std::vector<FileHandlerInfo> file_handlers_;
+
// Whether the extension has host permissions or user script patterns that
// imply access to file:/// scheme URLs (the user may not have actually
// granted it that access).