diff options
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). |