diff options
Diffstat (limited to 'chrome/browser/chromeos/extensions/file_browser_private_api.cc')
-rw-r--r-- | chrome/browser/chromeos/extensions/file_browser_private_api.cc | 153 |
1 files changed, 140 insertions, 13 deletions
diff --git a/chrome/browser/chromeos/extensions/file_browser_private_api.cc b/chrome/browser/chromeos/extensions/file_browser_private_api.cc index 22e88ee..c7dd48c 100644 --- a/chrome/browser/chromeos/extensions/file_browser_private_api.cc +++ b/chrome/browser/chromeos/extensions/file_browser_private_api.cc @@ -9,6 +9,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/string_split.h" #include "base/stringprintf.h" #include "base/time.h" +#include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/network_library.h" @@ -32,8 +36,10 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/extensions/process_map.h" +#include "chrome/browser/google_apis/operation_registry.h" #include "chrome/browser/google_apis/gdata_util.h" #include "chrome/browser/google_apis/gdata_wapi_parser.h" +#include "chrome/browser/intents/web_intents_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" @@ -53,6 +59,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" @@ -62,6 +69,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; @@ -76,7 +84,7 @@ using gdata::InstalledApp; namespace { // Default icon path for drive docs. -const char kDefaultDriveIcon[] = "images/filetype_generic.png"; +const char kDefaultIcon[] = "images/filetype_generic.png"; const int kPreferredIconSize = 16; // Error messages. @@ -234,6 +242,45 @@ GURL FindPreferredIcon(const InstalledApp::IconList& icons, return result; } +// Finds the title of the given Web Intents |action|, if the passed extension +// supports this action for all specified |mime_types|. Returns true and +// provides the |title| as output on success. +bool FindTitleForActionWithTypes( + const Extension* extension, + const std::string& action, + const std::set<std::string>& mime_types, + std::string* title) { + DCHECK(!mime_types.empty()); + std::set<std::string> pending(mime_types.begin(), mime_types.end()); + std::string found_title; + + for (std::vector<webkit_glue::WebIntentServiceData>::const_iterator data = + extension->intents_services().begin(); + data != extension->intents_services().end(); ++data) { + if (pending.empty()) + break; + + if (UTF16ToUTF8(data->action) != action) + continue; + + std::set<std::string>::iterator pending_iter = pending.begin(); + while (pending_iter != pending.end()) { + std::set<std::string>::iterator current = pending_iter++; + if (net::MatchesMimeType(UTF16ToUTF8(data->type), *current)) + pending.erase(current); + } + if (found_title.empty()) + found_title = UTF16ToUTF8(data->title); + } + + // Not all mime-types have been found. + if (!pending.empty()) + return false; + + *title = found_title; + return true; +} + // Retrieves total and remaining available size on |mount_path|. void GetSizeStatsOnFileThread(const std::string& mount_path, size_t* total_size_kb, @@ -602,8 +649,8 @@ void GetFileTasksFileBrowserFunction::IntersectAvailableDriveTasks( app_info->insert(std::make_pair((*apps)->app_id, *apps)); // TODO(gspencer): For now, the action id is always "open-with", but we // could add any actions that the drive app supports. - std::string task_id = - file_handler_util::MakeDriveTaskID((*apps)->app_id, "open-with"); + std::string task_id = file_handler_util::MakeTaskID( + (*apps)->app_id, file_handler_util::kTaskDrive, "open-with"); tasks_for_this_file.insert(task_id); // If we failed to insert a task_id because there was a duplicate, then we // must delete it (since we own it). @@ -656,10 +703,12 @@ void GetFileTasksFileBrowserFunction::CreateDriveTasks( for (std::set<std::string>::const_iterator app_iter = available_tasks.begin(); app_iter != available_tasks.end(); ++app_iter) { std::string app_id; - bool result = file_handler_util::CrackDriveTaskID(*app_iter, &app_id, NULL); + std::string task_type; + bool result = file_handler_util::CrackTaskID( + *app_iter, &app_id, &task_type, NULL); DCHECK(result) << "Unable to parse Drive task id: " << *app_iter; - if (!result) - continue; + DCHECK_EQ(task_type, file_handler_util::kTaskDrive); + WebAppInfoMap::const_iterator info_iter = app_info.find(app_id); DCHECK(info_iter != app_info.end()); gdata::DriveWebAppInfo* info = info_iter->second; @@ -707,7 +756,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 @@ -729,6 +777,77 @@ 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; + 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)) { + // 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(""); + } else { + mime_types.insert(mime_type); + } + } + + 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; + + std::string title; + if (!FindTitleForActionWithTypes( + extension, web_intents::kActionView, mime_types, &title)) + continue; + + DictionaryValue* task = new DictionaryValue; + std::string task_id = file_handler_util::MakeTaskID(extension->id(), + file_handler_util::kTaskWebIntent, web_intents::kActionView); + task->SetString("taskId", task_id); + task->SetString("title", 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; +} + bool GetFileTasksFileBrowserFunction::RunImpl() { // First argument is the list of files to get tasks for. ListValue* files_list = NULL; @@ -798,8 +917,8 @@ bool GetFileTasksFileBrowserFunction::RunImpl() { const Extension* extension = service->GetExtensionById(extension_id, false); CHECK(extension); DictionaryValue* task = new DictionaryValue; - task->SetString("taskId", - file_handler_util::MakeTaskID(extension_id, handler->id())); + task->SetString("taskId", file_handler_util::MakeTaskID( + extension_id, file_handler_util::kTaskFile, handler->id())); task->SetString("title", handler->title()); // TODO(zelidrag): Figure out how to expose icon URL that task defined in // manifest instead of the default extension icon. @@ -823,6 +942,12 @@ 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. + if (!FindWebIntentTasks(file_urls, result_list)) + return false; + if (VLOG_IS_ON(1)) { std::string result_json; base::JSONWriter::WriteWithOptions( @@ -833,8 +958,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; } @@ -863,8 +986,10 @@ bool ExecuteTasksFileBrowserFunction::RunImpl() { return false; std::string extension_id; + std::string task_type; std::string action_id; - if (!file_handler_util::CrackTaskID(task_id, &extension_id, &action_id)) { + if (!file_handler_util::CrackTaskID( + task_id, &extension_id, &task_type, &action_id)) { LOG(WARNING) << "Invalid task " << task_id; return false; } @@ -886,6 +1011,7 @@ bool ExecuteTasksFileBrowserFunction::RunImpl() { FileTaskExecutor::Create(profile(), source_url(), extension_id, + task_type, action_id)); if (!executor->ExecuteAndNotify( @@ -2035,7 +2161,8 @@ void GetDriveFilePropertiesFunction::OnOperationComplete( file_specific_info.content_mime_type(), file_path.Extension()); std::string default_app_id; - file_handler_util::CrackDriveTaskID(default_task_id, &default_app_id, NULL); + file_handler_util::CrackTaskID( + default_task_id, &default_app_id, NULL, NULL); ListValue* apps = new ListValue(); property_dict->Set("driveApps", apps); |