Chromium Code Reviews| 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 f5714bf1b713be741bd4a137857093853a7005d8..0b511124698664f8bcbc0a0fb0aa73dbef2cb5a8 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" |
| @@ -17,6 +20,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/extensions/file_handler_util.h" |
| @@ -34,6 +38,7 @@ |
| #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/intents/web_intents_util.h" |
| #include "chrome/browser/google_apis/operation_registry.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/browser.h" |
| @@ -54,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" |
| @@ -63,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; |
| @@ -78,7 +85,7 @@ using gdata::OperationRegistry; |
| 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. |
| @@ -235,6 +242,44 @@ GURL FindPreferredIcon(const InstalledApp::IconList& icons, |
| return result; |
| } |
| +// Given an extension, a Web Intents |action|, and a set of |mime_types|, |
| +// determines whether this extension supports this action for all specified |
| +// mime-types. |
| +// If this method returns true, also returns the |title| of this action. |
| +bool ExtensionSupportsAction(const Extension* extension, |
|
tbarzic
2012/09/13 18:44:45
nit:
const Extension* extension should got to the
thorogood
2012/09/16 03:41:19
Done.
|
| + 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), *pending_iter)) |
| + pending.erase(current); |
| + } |
| + if (found_title.empty()) |
| + found_title = UTF16ToUTF8(data->title); |
| + } |
| + |
| + if (!pending.empty()) |
| + return false; // we haven't found all mime-types |
| + |
| + *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, |
| @@ -601,8 +646,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::TASK_DRIVE, "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). |
| @@ -655,9 +700,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); |
| + file_handler_util::TaskType 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) |
| + DCHECK_EQ(task_type, file_handler_util::TASK_DRIVE); |
| + if (!result || task_type != file_handler_util::TASK_DRIVE) |
| continue; |
| WebAppInfoMap::const_iterator info_iter = app_info.find(app_id); |
| DCHECK(info_iter != app_info.end()); |
| @@ -706,7 +754,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 |
| @@ -728,6 +775,73 @@ 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 TASK_WEBINTENT. |
| +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; |
| + std::string title; |
| + |
| + // We don't support using hosted apps to open files. |
| + if (!extension->is_platform_app()) |
| + continue; |
| + |
| + if (profile_->IsOffTheRecord() && |
| + !service->IsIncognitoEnabled(extension->id())) |
| + continue; |
| + |
| + if (!ExtensionSupportsAction( |
| + 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::TASK_WEBINTENT, 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; |
| @@ -797,8 +911,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::TASK_FILE, 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. |
| @@ -822,6 +936,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( |
| @@ -832,8 +952,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; |
| } |
| @@ -862,8 +980,10 @@ bool ExecuteTasksFileBrowserFunction::RunImpl() { |
| return false; |
| std::string extension_id; |
| + file_handler_util::TaskType 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; |
| } |
| @@ -885,6 +1005,7 @@ bool ExecuteTasksFileBrowserFunction::RunImpl() { |
| FileTaskExecutor::Create(profile(), |
| source_url(), |
| extension_id, |
| + task_type, |
| action_id)); |
| if (!executor->ExecuteAndNotify( |
| @@ -2017,7 +2138,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); |