blob: 598ff0a103459f400b30228e09e9b436efbc426d [file] [log] [blame]
// Copyright 2013 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/chromeos/file_manager/file_tasks.h"
#include <algorithm>
#include <utility>
#include "base/command_line.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/testing_pref_service.h"
#include "base/values.h"
#include "chrome/browser/chromeos/drive/drive_app_registry.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/file_manager/app_id.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/google_apis/drive_api_parser.h"
#include "chrome/common/extensions/extension_builder.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace file_manager {
namespace file_tasks {
namespace {
// Registers the default task preferences. Used for testing
// ChooseAndSetDefaultTask().
void RegisterDefaultTaskPreferences(TestingPrefServiceSimple* pref_service) {
DCHECK(pref_service);
pref_service->registry()->RegisterDictionaryPref(
prefs::kDefaultTasksByMimeType);
pref_service->registry()->RegisterDictionaryPref(
prefs::kDefaultTasksBySuffix);
}
// Updates the default task preferences per the given dictionary values. Used
// for testing ChooseAndSetDefaultTask.
void UpdateDefaultTaskPreferences(TestingPrefServiceSimple* pref_service,
const DictionaryValue& mime_types,
const DictionaryValue& suffixes) {
DCHECK(pref_service);
pref_service->Set(prefs::kDefaultTasksByMimeType, mime_types);
pref_service->Set(prefs::kDefaultTasksBySuffix, suffixes);
}
} // namespace
TEST(FileManagerFileTasksTest,
FullTaskDescriptor_NonDriveAppWithIconAndDefault) {
FullTaskDescriptor full_descriptor(
TaskDescriptor("app-id",
TASK_TYPE_FILE_BROWSER_HANDLER,
"action-id"),
"task title",
GURL("http://example.com/icon.png"),
true /* is_default */);
const std::string task_id =
TaskDescriptorToId(full_descriptor.task_descriptor());
EXPECT_EQ("app-id|file|action-id", task_id);
EXPECT_EQ("http://example.com/icon.png", full_descriptor.icon_url().spec());
EXPECT_EQ("task title", full_descriptor.task_title());
EXPECT_TRUE(full_descriptor.is_default());
}
TEST(FileManagerFileTasksTest,
FullTaskDescriptor_DriveAppWithoutIconAndNotDefault) {
FullTaskDescriptor full_descriptor(
TaskDescriptor("app-id",
TASK_TYPE_DRIVE_APP,
"action-id"),
"task title",
GURL(), // No icon URL.
false /* is_default */);
const std::string task_id =
TaskDescriptorToId(full_descriptor.task_descriptor());
EXPECT_EQ("app-id|drive|action-id", task_id);
EXPECT_TRUE(full_descriptor.icon_url().is_empty());
EXPECT_EQ("task title", full_descriptor.task_title());
EXPECT_FALSE(full_descriptor.is_default());
}
TEST(FileManagerFileTasksTest, MakeTaskID) {
EXPECT_EQ("app-id|file|action-id",
MakeTaskID("app-id", TASK_TYPE_FILE_BROWSER_HANDLER, "action-id"));
EXPECT_EQ("app-id|app|action-id",
MakeTaskID("app-id", TASK_TYPE_FILE_HANDLER, "action-id"));
EXPECT_EQ("app-id|drive|action-id",
MakeTaskID("app-id", TASK_TYPE_DRIVE_APP, "action-id"));
}
TEST(FileManagerFileTasksTest, MakeDriveAppTaskId) {
EXPECT_EQ("app-id|drive|open-with", MakeDriveAppTaskId("app-id"));
}
TEST(FileManagerFileTasksTest, TaskDescriptorToId) {
EXPECT_EQ("app-id|file|action-id",
TaskDescriptorToId(TaskDescriptor("app-id",
TASK_TYPE_FILE_BROWSER_HANDLER,
"action-id")));
}
TEST(FileManagerFileTasksTest, ParseTaskID_FileBrowserHandler) {
TaskDescriptor task;
EXPECT_TRUE(ParseTaskID("app-id|file|action-id", &task));
EXPECT_EQ("app-id", task.app_id);
EXPECT_EQ(TASK_TYPE_FILE_BROWSER_HANDLER, task.task_type);
EXPECT_EQ("action-id", task.action_id);
}
TEST(FileManagerFileTasksTest, ParseTaskID_FileHandler) {
TaskDescriptor task;
EXPECT_TRUE(ParseTaskID("app-id|app|action-id", &task));
EXPECT_EQ("app-id", task.app_id);
EXPECT_EQ(TASK_TYPE_FILE_HANDLER, task.task_type);
EXPECT_EQ("action-id", task.action_id);
}
TEST(FileManagerFileTasksTest, ParseTaskID_DriveApp) {
TaskDescriptor task;
EXPECT_TRUE(ParseTaskID("app-id|drive|action-id", &task));
EXPECT_EQ("app-id", task.app_id);
EXPECT_EQ(TASK_TYPE_DRIVE_APP, task.task_type);
EXPECT_EQ("action-id", task.action_id);
}
TEST(FileManagerFileTasksTest, ParseTaskID_Legacy) {
TaskDescriptor task;
// A legacy task ID only has two parts. The task type should be
// TASK_TYPE_FILE_BROWSER_HANDLER.
EXPECT_TRUE(ParseTaskID("app-id|action-id", &task));
EXPECT_EQ("app-id", task.app_id);
EXPECT_EQ(TASK_TYPE_FILE_BROWSER_HANDLER, task.task_type);
EXPECT_EQ("action-id", task.action_id);
}
TEST(FileManagerFileTasksTest, ParseTaskID_LegacyDrive) {
TaskDescriptor task;
// A legacy task ID only has two parts. For Drive app, the app ID is
// prefixed with "drive-app:".
EXPECT_TRUE(ParseTaskID("drive-app:app-id|action-id", &task));
EXPECT_EQ("app-id", task.app_id);
EXPECT_EQ(TASK_TYPE_DRIVE_APP, task.task_type);
EXPECT_EQ("action-id", task.action_id);
}
TEST(FileManagerFileTasksTest, ParseTaskID_Invalid) {
TaskDescriptor task;
EXPECT_FALSE(ParseTaskID("invalid", &task));
}
TEST(FileManagerFileTasksTest, ParseTaskID_UnknownTaskType) {
TaskDescriptor task;
EXPECT_FALSE(ParseTaskID("app-id|unknown|action-id", &task));
}
TEST(FileManagerFileTasksTest, FindDriveAppTasks) {
// For DriveAppRegistry, which checks CurrentlyOn(BrowserThread::UI).
content::TestBrowserThreadBundle thread_bundle;
// Foo.app can handle "text/plain" and "text/html"
scoped_ptr<google_apis::AppResource> foo_app(new google_apis::AppResource);
foo_app->set_product_url(
GURL("https://chrome.google.com/webstore/detail/foo_app_id"));
foo_app->set_application_id("foo_app_id");
foo_app->set_name("Foo");
foo_app->set_object_type("foo_object_type");
ScopedVector<std::string> foo_mime_types;
foo_mime_types.push_back(new std::string("text/plain"));
foo_mime_types.push_back(new std::string("text/html"));
foo_app->set_primary_mimetypes(foo_mime_types.Pass());
// Bar.app can only handle "text/plain".
scoped_ptr<google_apis::AppResource> bar_app(new google_apis::AppResource);
bar_app->set_product_url(
GURL("https://chrome.google.com/webstore/detail/bar_app_id"));
bar_app->set_application_id("bar_app_id");
bar_app->set_name("Bar");
bar_app->set_object_type("bar_object_type");
ScopedVector<std::string> bar_mime_types;
bar_mime_types.push_back(new std::string("text/plain"));
bar_app->set_primary_mimetypes(bar_mime_types.Pass());
// Prepare DriveAppRegistry from Foo.app and Bar.app.
ScopedVector<google_apis::AppResource> app_resources;
app_resources.push_back(foo_app.release());
app_resources.push_back(bar_app.release());
google_apis::AppList app_list;
app_list.set_items(app_resources.Pass());
drive::DriveAppRegistry drive_app_registry(NULL);
drive_app_registry.UpdateFromAppList(app_list);
// Find apps for a "text/plain" file. Foo.app and Bar.app should be found.
PathAndMimeTypeSet path_mime_set;
path_mime_set.insert(
std::make_pair(
drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
"text/plain"));
std::vector<FullTaskDescriptor> tasks;
FindDriveAppTasks(drive_app_registry,
path_mime_set,
&tasks);
ASSERT_EQ(2U, tasks.size());
// Sort the app IDs, as the order is not guaranteed.
std::vector<std::string> app_ids;
app_ids.push_back(tasks[0].task_descriptor().app_id);
app_ids.push_back(tasks[1].task_descriptor().app_id);
std::sort(app_ids.begin(), app_ids.end());
// Confirm that both Foo.app and Bar.app are found.
EXPECT_EQ("bar_app_id", app_ids[0]);
EXPECT_EQ("foo_app_id", app_ids[1]);
// Find apps for "text/plain" and "text/html" files. Only Foo.app should be
// found.
path_mime_set.clear();
path_mime_set.insert(
std::make_pair(
drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
"text/plain"));
path_mime_set.insert(
std::make_pair(
drive::util::GetDriveMountPointPath().AppendASCII("foo.html"),
"text/html"));
tasks.clear();
FindDriveAppTasks(drive_app_registry,
path_mime_set,
&tasks);
ASSERT_EQ(1U, tasks.size());
// Confirm that only Foo.app is found.
EXPECT_EQ("foo_app_id", tasks[0].task_descriptor().app_id);
// Add a "text/plain" file not on Drive. No tasks should be found.
path_mime_set.insert(
std::make_pair(base::FilePath::FromUTF8Unsafe("not_on_drive.txt"),
"text/plain"));
tasks.clear();
FindDriveAppTasks(drive_app_registry,
path_mime_set,
&tasks);
// Confirm no tasks are found.
ASSERT_TRUE(tasks.empty());
}
TEST(FileManagerFileTasksTest, FindDriveAppTasks_GoogleDocument) {
// For DriveAppRegistry, which checks CurrentlyOn(BrowserThread::UI).
content::TestBrowserThreadBundle thread_bundle;
// Foo.app can handle ".gdoc" files.
scoped_ptr<google_apis::AppResource> foo_app(new google_apis::AppResource);
foo_app->set_product_url(
GURL("https://chrome.google.com/webstore/detail/foo_app_id"));
foo_app->set_application_id("foo_app_id");
foo_app->set_name("Foo");
foo_app->set_object_type("foo_object_type");
ScopedVector<std::string> foo_extensions;
foo_extensions.push_back(new std::string("gdoc")); // Not ".gdoc"
foo_app->set_primary_file_extensions(foo_extensions.Pass());
// Prepare DriveAppRegistry from Foo.app.
ScopedVector<google_apis::AppResource> app_resources;
app_resources.push_back(foo_app.release());
google_apis::AppList app_list;
app_list.set_items(app_resources.Pass());
drive::DriveAppRegistry drive_app_registry(NULL);
drive_app_registry.UpdateFromAppList(app_list);
// Find apps for a ".gdoc file". Foo.app can handle it but should not be
// found, as it should be rejected.
PathAndMimeTypeSet path_mime_set;
path_mime_set.insert(
std::make_pair(
drive::util::GetDriveMountPointPath().AppendASCII("foo.gdoc"),
"application/vnd.google-apps.document"));
std::vector<FullTaskDescriptor> tasks;
FindDriveAppTasks(drive_app_registry, path_mime_set, &tasks);
EXPECT_TRUE(tasks.empty());
}
// Test that the right task is chosen from multiple choices per mime types
// and file extensions.
TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_MultipleTasks) {
TestingPrefServiceSimple pref_service;
RegisterDefaultTaskPreferences(&pref_service);
// Text.app and Nice.app were found for "foo.txt".
TaskDescriptor text_app_task("text-app-id",
TASK_TYPE_FILE_HANDLER,
"action-id");
TaskDescriptor nice_app_task("nice-app-id",
TASK_TYPE_FILE_HANDLER,
"action-id");
std::vector<FullTaskDescriptor> tasks;
tasks.push_back(FullTaskDescriptor(
text_app_task,
"Text.app",
GURL("http://example.com/text_app.png"),
false /* is_default */));
tasks.push_back(FullTaskDescriptor(
nice_app_task,
"Nice.app",
GURL("http://example.com/nice_app.png"),
false /* is_default */));
PathAndMimeTypeSet path_mime_set;
path_mime_set.insert(std::make_pair(
base::FilePath::FromUTF8Unsafe("foo.txt"),
"text/plain"));
// None of them should be chosen as default, as nothing is set in the
// preferences.
ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
EXPECT_FALSE(tasks[0].is_default());
EXPECT_FALSE(tasks[1].is_default());
// Set Text.app as default for "text/plain" in the preferences.
DictionaryValue empty;
DictionaryValue mime_types;
mime_types.SetStringWithoutPathExpansion(
"text/plain",
TaskDescriptorToId(text_app_task));
UpdateDefaultTaskPreferences(&pref_service, mime_types, empty);
// Text.app should be chosen as default.
ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
EXPECT_TRUE(tasks[0].is_default());
EXPECT_FALSE(tasks[1].is_default());
// Change it back to non-default for testing further.
tasks[0].set_is_default(false);
// Clear the preferences and make sure none of them are default.
UpdateDefaultTaskPreferences(&pref_service, empty, empty);
ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
EXPECT_FALSE(tasks[0].is_default());
EXPECT_FALSE(tasks[1].is_default());
// Set Nice.app as default for ".txt" in the preferences.
DictionaryValue suffixes;
suffixes.SetStringWithoutPathExpansion(
".txt",
TaskDescriptorToId(nice_app_task));
UpdateDefaultTaskPreferences(&pref_service, empty, suffixes);
// Now Nice.app should be chosen as default.
ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
EXPECT_FALSE(tasks[0].is_default());
EXPECT_TRUE(tasks[1].is_default());
}
// Test that Files.app's internal file browser handler is chosen as default
// even if nothing is set in the preferences.
TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_FallbackFileBrowser) {
TestingPrefServiceSimple pref_service;
RegisterDefaultTaskPreferences(&pref_service);
// Files.app's internal file browser handler was found for "foo.txt".
TaskDescriptor files_app_task(kFileManagerAppId,
TASK_TYPE_FILE_BROWSER_HANDLER,
"view-in-browser");
std::vector<FullTaskDescriptor> tasks;
tasks.push_back(FullTaskDescriptor(
files_app_task,
"View in browser",
GURL("http://example.com/some_icon.png"),
false /* is_default */));
PathAndMimeTypeSet path_mime_set;
path_mime_set.insert(std::make_pair(
base::FilePath::FromUTF8Unsafe("foo.txt"),
"text/plain"));
// The internal file browser handler should be chosen as default, as it's a
// fallback file browser handler.
ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
EXPECT_TRUE(tasks[0].is_default());
}
// Test using the test extension system, which needs lots of setup.
class FileManagerFileTasksComplexTest : public testing::Test {
protected:
FileManagerFileTasksComplexTest()
: command_line_(CommandLine::NO_PROGRAM),
extension_service_(NULL) {
extensions::TestExtensionSystem* test_extension_system =
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(&test_profile_));
extension_service_ = test_extension_system->CreateExtensionService(
&command_line_,
base::FilePath() /* install_directory */,
false /* autoupdate_enabled*/);
}
content::TestBrowserThreadBundle thread_bundle_;
chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
chromeos::ScopedTestCrosSettings test_cros_settings_;
chromeos::ScopedTestUserManager test_user_manager_;
TestingProfile test_profile_;
CommandLine command_line_;
ExtensionService* extension_service_; // Owned by test_profile_;
};
// The basic logic is similar to a test case for FindDriveAppTasks above.
TEST_F(FileManagerFileTasksComplexTest, FindFileHandlerTasks) {
// Random IDs generated by
// % ruby -le 'print (0...32).to_a.map{(?a + rand(16)).chr}.join'
const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
// Foo.app can handle "text/plain" and "text/html".
extensions::ExtensionBuilder foo_app;
foo_app.SetManifest(extensions::DictionaryBuilder()
.Set("name", "Foo")
.Set("version", "1.0.0")
.Set("manifest_version", 2)
.Set("app",
extensions::DictionaryBuilder()
.Set("background",
extensions::DictionaryBuilder()
.Set("scripts",
extensions::ListBuilder()
.Append("background.js"))))
.Set("file_handlers",
extensions::DictionaryBuilder()
.Set("text",
extensions::DictionaryBuilder()
.Set("title", "Text")
.Set("types",
extensions::ListBuilder()
.Append("text/plain")
.Append("text/html")))));
foo_app.SetID(kFooId);
extension_service_->AddExtension(foo_app.Build().get());
// Bar.app can only handle "text/plain".
extensions::ExtensionBuilder bar_app;
bar_app.SetManifest(extensions::DictionaryBuilder()
.Set("name", "Bar")
.Set("version", "1.0.0")
.Set("manifest_version", 2)
.Set("app",
extensions::DictionaryBuilder()
.Set("background",
extensions::DictionaryBuilder()
.Set("scripts",
extensions::ListBuilder()
.Append("background.js"))))
.Set("file_handlers",
extensions::DictionaryBuilder()
.Set("text",
extensions::DictionaryBuilder()
.Set("title", "Text")
.Set("types",
extensions::ListBuilder()
.Append("text/plain")))));
bar_app.SetID(kBarId);
extension_service_->AddExtension(bar_app.Build().get());
// Find apps for a "text/plain" file. Foo.app and Bar.app should be found.
PathAndMimeTypeSet path_mime_set;
path_mime_set.insert(
std::make_pair(
drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
"text/plain"));
std::vector<FullTaskDescriptor> tasks;
FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks);
ASSERT_EQ(2U, tasks.size());
// Sort the app IDs, as the order is not guaranteed.
std::vector<std::string> app_ids;
app_ids.push_back(tasks[0].task_descriptor().app_id);
app_ids.push_back(tasks[1].task_descriptor().app_id);
std::sort(app_ids.begin(), app_ids.end());
// Confirm that both Foo.app and Bar.app are found.
EXPECT_EQ(kFooId, app_ids[0]);
EXPECT_EQ(kBarId, app_ids[1]);
// Find apps for "text/plain" and "text/html" files. Only Foo.app should be
// found.
path_mime_set.clear();
path_mime_set.insert(
std::make_pair(
drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
"text/plain"));
path_mime_set.insert(
std::make_pair(
drive::util::GetDriveMountPointPath().AppendASCII("foo.html"),
"text/html"));
tasks.clear();
FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks);
ASSERT_EQ(1U, tasks.size());
// Confirm that only Foo.app is found.
EXPECT_EQ(kFooId, tasks[0].task_descriptor().app_id);
// Add an "image/png" file. No tasks should be found.
path_mime_set.insert(
std::make_pair(base::FilePath::FromUTF8Unsafe("foo.png"),
"image/png"));
tasks.clear();
FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks);
// Confirm no tasks are found.
ASSERT_TRUE(tasks.empty());
}
// The basic logic is similar to a test case for FindDriveAppTasks above.
TEST_F(FileManagerFileTasksComplexTest, FindFileBrowserHandlerTasks) {
// Copied from FindFileHandlerTasks test above.
const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
// Foo.app can handle ".txt" and ".html".
// This one is an extension, and has "file_browser_handlers"
extensions::ExtensionBuilder foo_app;
foo_app.SetManifest(extensions::DictionaryBuilder()
.Set("name", "Foo")
.Set("version", "1.0.0")
.Set("manifest_version", 2)
.Set("file_browser_handlers",
extensions::ListBuilder()
.Append(extensions::DictionaryBuilder()
.Set("id", "open")
.Set("default_title", "open")
.Set("file_filters",
extensions::ListBuilder()
.Append("filesystem:*.txt")
.Append("filesystem:*.html")))));
foo_app.SetID(kFooId);
extension_service_->AddExtension(foo_app.Build().get());
// Bar.app can only handle ".txt".
extensions::ExtensionBuilder bar_app;
bar_app.SetManifest(extensions::DictionaryBuilder()
.Set("name", "Bar")
.Set("version", "1.0.0")
.Set("manifest_version", 2)
.Set("file_browser_handlers",
extensions::ListBuilder()
.Append(extensions::DictionaryBuilder()
.Set("id", "open")
.Set("default_title", "open")
.Set("file_filters",
extensions::ListBuilder()
.Append("filesystem:*.txt")))));
bar_app.SetID(kBarId);
extension_service_->AddExtension(bar_app.Build().get());
// Find apps for a ".txt" file. Foo.app and Bar.app should be found.
std::vector<GURL> file_urls;
file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt"));
std::vector<FullTaskDescriptor> tasks;
FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks);
ASSERT_EQ(2U, tasks.size());
// Sort the app IDs, as the order is not guaranteed.
std::vector<std::string> app_ids;
app_ids.push_back(tasks[0].task_descriptor().app_id);
app_ids.push_back(tasks[1].task_descriptor().app_id);
std::sort(app_ids.begin(), app_ids.end());
// Confirm that both Foo.app and Bar.app are found.
EXPECT_EQ(kFooId, app_ids[0]);
EXPECT_EQ(kBarId, app_ids[1]);
// Find apps for ".txt" and ".html" files. Only Foo.app should be found.
file_urls.clear();
file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt"));
file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.html"));
tasks.clear();
FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks);
ASSERT_EQ(1U, tasks.size());
// Confirm that only Foo.app is found.
EXPECT_EQ(kFooId, tasks[0].task_descriptor().app_id);
// Add an ".png" file. No tasks should be found.
file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.png"));
tasks.clear();
FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks);
// Confirm no tasks are found.
ASSERT_TRUE(tasks.empty());
}
// Test that all kinds of apps (file handler, file browser handler, and Drive
// app) are returned.
TEST_F(FileManagerFileTasksComplexTest, FindAllTypesOfTasks) {
// kFooId and kBarId copied from FindFileHandlerTasks test above.
const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
const char kBazId[] = "plifkpkakemokpflgbnnigcoldgcbdmc";
// Foo.app can handle "text/plain".
// This is a packaged app (file handler).
extensions::ExtensionBuilder foo_app;
foo_app.SetManifest(extensions::DictionaryBuilder()
.Set("name", "Foo")
.Set("version", "1.0.0")
.Set("manifest_version", 2)
.Set("app",
extensions::DictionaryBuilder()
.Set("background",
extensions::DictionaryBuilder()
.Set("scripts",
extensions::ListBuilder()
.Append("background.js"))))
.Set("file_handlers",
extensions::DictionaryBuilder()
.Set("text",
extensions::DictionaryBuilder()
.Set("title", "Text")
.Set("types",
extensions::ListBuilder()
.Append("text/plain")))));
foo_app.SetID(kFooId);
extension_service_->AddExtension(foo_app.Build().get());
// Bar.app can only handle ".txt".
// This is an extension (file browser handler).
extensions::ExtensionBuilder bar_app;
bar_app.SetManifest(extensions::DictionaryBuilder()
.Set("name", "Bar")
.Set("version", "1.0.0")
.Set("manifest_version", 2)
.Set("file_browser_handlers",
extensions::ListBuilder()
.Append(extensions::DictionaryBuilder()
.Set("id", "open")
.Set("default_title", "open")
.Set("file_filters",
extensions::ListBuilder()
.Append("filesystem:*.txt")))));
bar_app.SetID(kBarId);
extension_service_->AddExtension(bar_app.Build().get());
// Baz.app can handle "text/plain".
// This is a Drive app.
scoped_ptr<google_apis::AppResource> baz_app(new google_apis::AppResource);
baz_app->set_product_url(
GURL("https://chrome.google.com/webstore/detail/baz_app_id"));
baz_app->set_application_id(kBazId);
baz_app->set_name("Baz");
baz_app->set_object_type("baz_object_type");
ScopedVector<std::string> baz_mime_types;
baz_mime_types.push_back(new std::string("text/plain"));
baz_app->set_primary_mimetypes(baz_mime_types.Pass());
// Set up DriveAppRegistry.
ScopedVector<google_apis::AppResource> app_resources;
app_resources.push_back(baz_app.release());
google_apis::AppList app_list;
app_list.set_items(app_resources.Pass());
drive::DriveAppRegistry drive_app_registry(NULL);
drive_app_registry.UpdateFromAppList(app_list);
// Find apps for "foo.txt". All apps should be found.
PathAndMimeTypeSet path_mime_set;
std::vector<GURL> file_urls;
path_mime_set.insert(
std::make_pair(
drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
"text/plain"));
file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt"));
std::vector<FullTaskDescriptor> tasks;
FindAllTypesOfTasks(&test_profile_,
&drive_app_registry,
path_mime_set,
file_urls,
&tasks);
ASSERT_EQ(3U, tasks.size());
// Sort the app IDs, as the order is not guaranteed.
std::vector<std::string> app_ids;
app_ids.push_back(tasks[0].task_descriptor().app_id);
app_ids.push_back(tasks[1].task_descriptor().app_id);
app_ids.push_back(tasks[2].task_descriptor().app_id);
std::sort(app_ids.begin(), app_ids.end());
// Confirm that all apps are found.
EXPECT_EQ(kFooId, app_ids[0]);
EXPECT_EQ(kBarId, app_ids[1]);
EXPECT_EQ(kBazId, app_ids[2]);
}
} // namespace file_tasks
} // namespace file_manager.