Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / chromeos / file_manager / file_tasks_unittest.cc
blobb1d684608a06361b03e7bc2fad9a09615a28b43f
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/file_manager/file_tasks.h"
7 #include <algorithm>
8 #include <utility>
10 #include "base/command_line.h"
11 #include "base/prefs/pref_registry_simple.h"
12 #include "base/prefs/testing_pref_service.h"
13 #include "base/values.h"
14 #include "chrome/browser/chromeos/drive/file_system_util.h"
15 #include "chrome/browser/chromeos/file_manager/app_id.h"
16 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
17 #include "chrome/browser/chromeos/settings/cros_settings.h"
18 #include "chrome/browser/chromeos/settings/device_settings_service.h"
19 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/extensions/test_extension_system.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "components/drive/drive_app_registry.h"
24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "extensions/browser/extension_prefs.h"
26 #include "extensions/browser/extension_system.h"
27 #include "extensions/common/extension_builder.h"
28 #include "google_apis/drive/drive_api_parser.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "url/gurl.h"
32 namespace file_manager {
33 namespace file_tasks {
34 namespace {
36 // Registers the default task preferences. Used for testing
37 // ChooseAndSetDefaultTask().
38 void RegisterDefaultTaskPreferences(TestingPrefServiceSimple* pref_service) {
39 DCHECK(pref_service);
41 pref_service->registry()->RegisterDictionaryPref(
42 prefs::kDefaultTasksByMimeType);
43 pref_service->registry()->RegisterDictionaryPref(
44 prefs::kDefaultTasksBySuffix);
47 // Updates the default task preferences per the given dictionary values. Used
48 // for testing ChooseAndSetDefaultTask.
49 void UpdateDefaultTaskPreferences(TestingPrefServiceSimple* pref_service,
50 const base::DictionaryValue& mime_types,
51 const base::DictionaryValue& suffixes) {
52 DCHECK(pref_service);
54 pref_service->Set(prefs::kDefaultTasksByMimeType, mime_types);
55 pref_service->Set(prefs::kDefaultTasksBySuffix, suffixes);
58 } // namespace
60 TEST(FileManagerFileTasksTest,
61 FullTaskDescriptor_NonDriveAppWithIconAndDefault) {
62 FullTaskDescriptor full_descriptor(
63 TaskDescriptor("app-id",
64 TASK_TYPE_FILE_BROWSER_HANDLER,
65 "action-id"),
66 "task title",
67 GURL("http://example.com/icon.png"),
68 true /* is_default */,
69 false /* is_generic_file_handler */);
71 const std::string task_id =
72 TaskDescriptorToId(full_descriptor.task_descriptor());
73 EXPECT_EQ("app-id|file|action-id", task_id);
74 EXPECT_EQ("http://example.com/icon.png", full_descriptor.icon_url().spec());
75 EXPECT_EQ("task title", full_descriptor.task_title());
76 EXPECT_TRUE(full_descriptor.is_default());
79 TEST(FileManagerFileTasksTest,
80 FullTaskDescriptor_DriveAppWithoutIconAndNotDefault) {
81 FullTaskDescriptor full_descriptor(
82 TaskDescriptor("app-id",
83 TASK_TYPE_DRIVE_APP,
84 "action-id"),
85 "task title",
86 GURL(), // No icon URL.
87 false /* is_default */,
88 false /* is_generic_file_handler */);
90 const std::string task_id =
91 TaskDescriptorToId(full_descriptor.task_descriptor());
92 EXPECT_EQ("app-id|drive|action-id", task_id);
93 EXPECT_TRUE(full_descriptor.icon_url().is_empty());
94 EXPECT_EQ("task title", full_descriptor.task_title());
95 EXPECT_FALSE(full_descriptor.is_default());
98 TEST(FileManagerFileTasksTest, MakeTaskID) {
99 EXPECT_EQ("app-id|file|action-id",
100 MakeTaskID("app-id", TASK_TYPE_FILE_BROWSER_HANDLER, "action-id"));
101 EXPECT_EQ("app-id|app|action-id",
102 MakeTaskID("app-id", TASK_TYPE_FILE_HANDLER, "action-id"));
103 EXPECT_EQ("app-id|drive|action-id",
104 MakeTaskID("app-id", TASK_TYPE_DRIVE_APP, "action-id"));
107 TEST(FileManagerFileTasksTest, TaskDescriptorToId) {
108 EXPECT_EQ("app-id|file|action-id",
109 TaskDescriptorToId(TaskDescriptor("app-id",
110 TASK_TYPE_FILE_BROWSER_HANDLER,
111 "action-id")));
114 TEST(FileManagerFileTasksTest, ParseTaskID_FileBrowserHandler) {
115 TaskDescriptor task;
116 EXPECT_TRUE(ParseTaskID("app-id|file|action-id", &task));
117 EXPECT_EQ("app-id", task.app_id);
118 EXPECT_EQ(TASK_TYPE_FILE_BROWSER_HANDLER, task.task_type);
119 EXPECT_EQ("action-id", task.action_id);
122 TEST(FileManagerFileTasksTest, ParseTaskID_FileHandler) {
123 TaskDescriptor task;
124 EXPECT_TRUE(ParseTaskID("app-id|app|action-id", &task));
125 EXPECT_EQ("app-id", task.app_id);
126 EXPECT_EQ(TASK_TYPE_FILE_HANDLER, task.task_type);
127 EXPECT_EQ("action-id", task.action_id);
130 TEST(FileManagerFileTasksTest, ParseTaskID_DriveApp) {
131 TaskDescriptor task;
132 EXPECT_TRUE(ParseTaskID("app-id|drive|action-id", &task));
133 EXPECT_EQ("app-id", task.app_id);
134 EXPECT_EQ(TASK_TYPE_DRIVE_APP, task.task_type);
135 EXPECT_EQ("action-id", task.action_id);
138 TEST(FileManagerFileTasksTest, ParseTaskID_Legacy) {
139 TaskDescriptor task;
140 // A legacy task ID only has two parts. The task type should be
141 // TASK_TYPE_FILE_BROWSER_HANDLER.
142 EXPECT_TRUE(ParseTaskID("app-id|action-id", &task));
143 EXPECT_EQ("app-id", task.app_id);
144 EXPECT_EQ(TASK_TYPE_FILE_BROWSER_HANDLER, task.task_type);
145 EXPECT_EQ("action-id", task.action_id);
148 TEST(FileManagerFileTasksTest, ParseTaskID_LegacyDrive) {
149 TaskDescriptor task;
150 // A legacy task ID only has two parts. For Drive app, the app ID is
151 // prefixed with "drive-app:".
152 EXPECT_TRUE(ParseTaskID("drive-app:app-id|action-id", &task));
153 EXPECT_EQ("app-id", task.app_id);
154 EXPECT_EQ(TASK_TYPE_DRIVE_APP, task.task_type);
155 EXPECT_EQ("action-id", task.action_id);
158 TEST(FileManagerFileTasksTest, ParseTaskID_Invalid) {
159 TaskDescriptor task;
160 EXPECT_FALSE(ParseTaskID("invalid", &task));
163 TEST(FileManagerFileTasksTest, ParseTaskID_UnknownTaskType) {
164 TaskDescriptor task;
165 EXPECT_FALSE(ParseTaskID("app-id|unknown|action-id", &task));
168 TEST(FileManagerFileTasksTest, FindDriveAppTasks) {
169 TestingProfile profile;
170 // For DriveAppRegistry, which checks CurrentlyOn(BrowserThread::UI).
171 content::TestBrowserThreadBundle thread_bundle;
173 // Foo.app can handle "text/plain" and "text/html"
174 scoped_ptr<google_apis::AppResource> foo_app(new google_apis::AppResource);
175 foo_app->set_product_id("foo_app_id");
176 foo_app->set_application_id("foo_app_id");
177 foo_app->set_name("Foo");
178 foo_app->set_object_type("foo_object_type");
179 ScopedVector<std::string> foo_mime_types;
180 foo_mime_types.push_back(new std::string("text/plain"));
181 foo_mime_types.push_back(new std::string("text/html"));
182 foo_app->set_primary_mimetypes(foo_mime_types.Pass());
184 // Bar.app can only handle "text/plain".
185 scoped_ptr<google_apis::AppResource> bar_app(new google_apis::AppResource);
186 bar_app->set_product_id("bar_app_id");
187 bar_app->set_application_id("bar_app_id");
188 bar_app->set_name("Bar");
189 bar_app->set_object_type("bar_object_type");
190 ScopedVector<std::string> bar_mime_types;
191 bar_mime_types.push_back(new std::string("text/plain"));
192 bar_app->set_primary_mimetypes(bar_mime_types.Pass());
194 // Prepare DriveAppRegistry from Foo.app and Bar.app.
195 ScopedVector<google_apis::AppResource> app_resources;
196 app_resources.push_back(foo_app.release());
197 app_resources.push_back(bar_app.release());
198 google_apis::AppList app_list;
199 app_list.set_items(app_resources.Pass());
200 drive::DriveAppRegistry drive_app_registry(NULL);
201 drive_app_registry.UpdateFromAppList(app_list);
203 // Find apps for a "text/plain" file. Foo.app and Bar.app should be found.
204 PathAndMimeTypeSet path_mime_set;
205 path_mime_set.insert(
206 std::make_pair(
207 drive::util::GetDriveMountPointPath(&profile).AppendASCII("foo.txt"),
208 "text/plain"));
209 std::vector<FullTaskDescriptor> tasks;
210 FindDriveAppTasks(drive_app_registry,
211 path_mime_set,
212 &tasks);
213 ASSERT_EQ(2U, tasks.size());
214 // Sort the app IDs, as the order is not guaranteed.
215 std::vector<std::string> app_ids;
216 app_ids.push_back(tasks[0].task_descriptor().app_id);
217 app_ids.push_back(tasks[1].task_descriptor().app_id);
218 std::sort(app_ids.begin(), app_ids.end());
219 // Confirm that both Foo.app and Bar.app are found.
220 EXPECT_EQ("bar_app_id", app_ids[0]);
221 EXPECT_EQ("foo_app_id", app_ids[1]);
223 // Find apps for "text/plain" and "text/html" files. Only Foo.app should be
224 // found.
225 path_mime_set.clear();
226 path_mime_set.insert(
227 std::make_pair(
228 drive::util::GetDriveMountPointPath(&profile).AppendASCII("foo.txt"),
229 "text/plain"));
230 path_mime_set.insert(
231 std::make_pair(
232 drive::util::GetDriveMountPointPath(&profile).AppendASCII("foo.html"),
233 "text/html"));
234 tasks.clear();
235 FindDriveAppTasks(drive_app_registry,
236 path_mime_set,
237 &tasks);
238 ASSERT_EQ(1U, tasks.size());
239 // Confirm that only Foo.app is found.
240 EXPECT_EQ("foo_app_id", tasks[0].task_descriptor().app_id);
242 // Add a "text/plain" file not on Drive. No tasks should be found.
243 path_mime_set.insert(
244 std::make_pair(base::FilePath::FromUTF8Unsafe("not_on_drive.txt"),
245 "text/plain"));
246 tasks.clear();
247 FindDriveAppTasks(drive_app_registry,
248 path_mime_set,
249 &tasks);
250 // Confirm no tasks are found.
251 ASSERT_TRUE(tasks.empty());
254 // Test that the right task is chosen from multiple choices per mime types
255 // and file extensions.
256 TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_MultipleTasks) {
257 TestingPrefServiceSimple pref_service;
258 RegisterDefaultTaskPreferences(&pref_service);
260 // Text.app and Nice.app were found for "foo.txt".
261 TaskDescriptor text_app_task("text-app-id",
262 TASK_TYPE_FILE_HANDLER,
263 "action-id");
264 TaskDescriptor nice_app_task("nice-app-id",
265 TASK_TYPE_FILE_HANDLER,
266 "action-id");
267 std::vector<FullTaskDescriptor> tasks;
268 tasks.push_back(FullTaskDescriptor(
269 text_app_task,
270 "Text.app",
271 GURL("http://example.com/text_app.png"),
272 false /* is_default */,
273 false /* is_generic_file_handler */));
274 tasks.push_back(FullTaskDescriptor(
275 nice_app_task,
276 "Nice.app",
277 GURL("http://example.com/nice_app.png"),
278 false /* is_default */,
279 false /* is_generic_file_handler */));
280 PathAndMimeTypeSet path_mime_set;
281 path_mime_set.insert(std::make_pair(
282 base::FilePath::FromUTF8Unsafe("foo.txt"),
283 "text/plain"));
285 // None of them should be chosen as default, as nothing is set in the
286 // preferences.
287 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
288 EXPECT_FALSE(tasks[0].is_default());
289 EXPECT_FALSE(tasks[1].is_default());
291 // Set Text.app as default for "text/plain" in the preferences.
292 base::DictionaryValue empty;
293 base::DictionaryValue mime_types;
294 mime_types.SetStringWithoutPathExpansion(
295 "text/plain",
296 TaskDescriptorToId(text_app_task));
297 UpdateDefaultTaskPreferences(&pref_service, mime_types, empty);
299 // Text.app should be chosen as default.
300 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
301 EXPECT_TRUE(tasks[0].is_default());
302 EXPECT_FALSE(tasks[1].is_default());
304 // Change it back to non-default for testing further.
305 tasks[0].set_is_default(false);
307 // Clear the preferences and make sure none of them are default.
308 UpdateDefaultTaskPreferences(&pref_service, empty, empty);
309 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
310 EXPECT_FALSE(tasks[0].is_default());
311 EXPECT_FALSE(tasks[1].is_default());
313 // Set Nice.app as default for ".txt" in the preferences.
314 base::DictionaryValue suffixes;
315 suffixes.SetStringWithoutPathExpansion(
316 ".txt",
317 TaskDescriptorToId(nice_app_task));
318 UpdateDefaultTaskPreferences(&pref_service, empty, suffixes);
320 // Now Nice.app should be chosen as default.
321 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
322 EXPECT_FALSE(tasks[0].is_default());
323 EXPECT_TRUE(tasks[1].is_default());
326 // Test that Files.app's internal file browser handler is chosen as default
327 // even if nothing is set in the preferences.
328 TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_FallbackFileBrowser) {
329 TestingPrefServiceSimple pref_service;
330 RegisterDefaultTaskPreferences(&pref_service);
332 // Files.app's internal file browser handler was found for "foo.txt".
333 TaskDescriptor files_app_task(kFileManagerAppId,
334 TASK_TYPE_FILE_BROWSER_HANDLER,
335 "view-in-browser");
336 std::vector<FullTaskDescriptor> tasks;
337 tasks.push_back(FullTaskDescriptor(
338 files_app_task,
339 "View in browser",
340 GURL("http://example.com/some_icon.png"),
341 false /* is_default */,
342 false /* is_generic_file_handler */));
343 PathAndMimeTypeSet path_mime_set;
344 path_mime_set.insert(std::make_pair(
345 base::FilePath::FromUTF8Unsafe("foo.txt"),
346 "text/plain"));
348 // The internal file browser handler should be chosen as default, as it's a
349 // fallback file browser handler.
350 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
351 EXPECT_TRUE(tasks[0].is_default());
354 // Test IsGoodMatchFileHandler which returns whether a file handle info matches
355 // with files as good match or not.
356 TEST(FileManagerFileTasksTest, IsGoodMatchFileHandler) {
357 using FileHandlerInfo = extensions::FileHandlerInfo;
358 typedef std::pair<base::FilePath, std::string> PathMime;
360 PathAndMimeTypeSet path_and_mime_set_1;
361 path_and_mime_set_1.insert(
362 PathMime(base::FilePath(FILE_PATH_LITERAL("foo.jpg")), "image/jpeg"));
363 path_and_mime_set_1.insert(
364 PathMime(base::FilePath(FILE_PATH_LITERAL("bar.txt")), "text/plain"));
366 PathAndMimeTypeSet path_and_mime_set_2;
367 path_and_mime_set_2.insert(
368 PathMime(base::FilePath(FILE_PATH_LITERAL("foo.ics")), "text/calendar"));
370 // extensions: ["*"]
371 FileHandlerInfo file_handler_info_1;
372 file_handler_info_1.extensions.insert("*");
373 EXPECT_FALSE(
374 IsGoodMatchFileHandler(file_handler_info_1, path_and_mime_set_1));
376 // extensions: ["*", "jpg"]
377 FileHandlerInfo file_handler_info_2;
378 file_handler_info_2.extensions.insert("*");
379 file_handler_info_2.extensions.insert("jpg");
380 EXPECT_FALSE(
381 IsGoodMatchFileHandler(file_handler_info_2, path_and_mime_set_1));
383 // extensions: ["jpg"]
384 FileHandlerInfo file_handler_info_3;
385 file_handler_info_3.extensions.insert("jpg");
386 EXPECT_TRUE(IsGoodMatchFileHandler(file_handler_info_3, path_and_mime_set_1));
388 // types: ["*"]
389 FileHandlerInfo file_handler_info_4;
390 file_handler_info_4.types.insert("*");
391 EXPECT_FALSE(
392 IsGoodMatchFileHandler(file_handler_info_4, path_and_mime_set_1));
394 // types: ["*/*"]
395 FileHandlerInfo file_handler_info_5;
396 file_handler_info_5.types.insert("*/*");
397 EXPECT_FALSE(
398 IsGoodMatchFileHandler(file_handler_info_5, path_and_mime_set_1));
400 // types: ["image/*"]
401 FileHandlerInfo file_handler_info_6;
402 file_handler_info_6.types.insert("image/*");
403 // Partial wild card is not generic.
404 EXPECT_TRUE(IsGoodMatchFileHandler(file_handler_info_6, path_and_mime_set_1));
406 // types: ["*", "image/*"]
407 FileHandlerInfo file_handler_info_7;
408 file_handler_info_7.types.insert("*");
409 file_handler_info_7.types.insert("image/*");
410 EXPECT_FALSE(
411 IsGoodMatchFileHandler(file_handler_info_7, path_and_mime_set_1));
413 // extensions: ["*"], types: ["image/*"]
414 FileHandlerInfo file_handler_info_8;
415 file_handler_info_8.extensions.insert("*");
416 file_handler_info_8.types.insert("image/*");
417 EXPECT_FALSE(
418 IsGoodMatchFileHandler(file_handler_info_8, path_and_mime_set_1));
420 // types: ["text/*"] and target files contain unsupported text mime type, e.g.
421 // text/calendar.
422 FileHandlerInfo file_handler_info_9;
423 file_handler_info_9.types.insert("text/*");
424 EXPECT_FALSE(
425 IsGoodMatchFileHandler(file_handler_info_9, path_and_mime_set_2));
427 // types: ["text/*"] and target files don't contain unsupported text mime
428 // type.
429 FileHandlerInfo file_handler_info_10;
430 file_handler_info_10.types.insert("text/*");
431 EXPECT_TRUE(
432 IsGoodMatchFileHandler(file_handler_info_10, path_and_mime_set_1));
435 // Test using the test extension system, which needs lots of setup.
436 class FileManagerFileTasksComplexTest : public testing::Test {
437 protected:
438 FileManagerFileTasksComplexTest()
439 : command_line_(base::CommandLine::NO_PROGRAM), extension_service_(NULL) {
440 extensions::TestExtensionSystem* test_extension_system =
441 static_cast<extensions::TestExtensionSystem*>(
442 extensions::ExtensionSystem::Get(&test_profile_));
443 extension_service_ = test_extension_system->CreateExtensionService(
444 &command_line_,
445 base::FilePath() /* install_directory */,
446 false /* autoupdate_enabled*/);
449 content::TestBrowserThreadBundle thread_bundle_;
450 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
451 chromeos::ScopedTestCrosSettings test_cros_settings_;
452 chromeos::ScopedTestUserManager test_user_manager_;
453 TestingProfile test_profile_;
454 base::CommandLine command_line_;
455 ExtensionService* extension_service_; // Owned by test_profile_;
458 // The basic logic is similar to a test case for FindDriveAppTasks above.
459 TEST_F(FileManagerFileTasksComplexTest, FindFileHandlerTasks) {
460 // Random IDs generated by
461 // % ruby -le 'print (0...32).to_a.map{(?a + rand(16)).chr}.join'
462 const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
463 const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
464 const char kEphemeralId[] = "opoomfdlbjcbjinalcjdjfoiikdeaoel";
466 // Foo.app can handle "text/plain" and "text/html".
467 extensions::ExtensionBuilder foo_app;
468 foo_app.SetManifest(extensions::DictionaryBuilder()
469 .Set("name", "Foo")
470 .Set("version", "1.0.0")
471 .Set("manifest_version", 2)
472 .Set("app",
473 extensions::DictionaryBuilder()
474 .Set("background",
475 extensions::DictionaryBuilder()
476 .Set("scripts",
477 extensions::ListBuilder()
478 .Append("background.js"))))
479 .Set("file_handlers",
480 extensions::DictionaryBuilder()
481 .Set("text",
482 extensions::DictionaryBuilder()
483 .Set("title", "Text")
484 .Set("types",
485 extensions::ListBuilder()
486 .Append("text/plain")
487 .Append("text/html")))));
488 foo_app.SetID(kFooId);
489 extension_service_->AddExtension(foo_app.Build().get());
491 // Bar.app can only handle "text/plain".
492 extensions::ExtensionBuilder bar_app;
493 bar_app.SetManifest(extensions::DictionaryBuilder()
494 .Set("name", "Bar")
495 .Set("version", "1.0.0")
496 .Set("manifest_version", 2)
497 .Set("app",
498 extensions::DictionaryBuilder()
499 .Set("background",
500 extensions::DictionaryBuilder()
501 .Set("scripts",
502 extensions::ListBuilder()
503 .Append("background.js"))))
504 .Set("file_handlers",
505 extensions::DictionaryBuilder()
506 .Set("text",
507 extensions::DictionaryBuilder()
508 .Set("title", "Text")
509 .Set("types",
510 extensions::ListBuilder()
511 .Append("text/plain")))));
512 bar_app.SetID(kBarId);
513 extension_service_->AddExtension(bar_app.Build().get());
515 // Ephemeral.app is an ephemeral app that can handle "text/plain".
516 // It should not ever be found as ephemeral apps cannot be file handlers.
517 extensions::ExtensionBuilder ephemeral_app;
518 ephemeral_app.SetManifest(
519 extensions::DictionaryBuilder()
520 .Set("name", "Ephemeral")
521 .Set("version", "1.0.0")
522 .Set("manifest_version", 2)
523 .Set("app",
524 extensions::DictionaryBuilder().Set(
525 "background",
526 extensions::DictionaryBuilder().Set(
527 "scripts",
528 extensions::ListBuilder().Append("background.js"))))
529 .Set("file_handlers",
530 extensions::DictionaryBuilder().Set(
531 "text",
532 extensions::DictionaryBuilder().Set("title", "Text").Set(
533 "types",
534 extensions::ListBuilder().Append("text/plain")))));
535 ephemeral_app.SetID(kEphemeralId);
536 scoped_refptr<extensions::Extension> built_ephemeral_app(
537 ephemeral_app.Build());
538 extension_service_->AddExtension(built_ephemeral_app.get());
539 extensions::ExtensionPrefs* extension_prefs =
540 extensions::ExtensionPrefs::Get(&test_profile_);
541 extension_prefs->OnExtensionInstalled(built_ephemeral_app.get(),
542 extensions::Extension::ENABLED,
543 syncer::StringOrdinal(),
544 extensions::kInstallFlagIsEphemeral,
545 std::string());
547 // Find apps for a "text/plain" file. Foo.app and Bar.app should be found.
548 PathAndMimeTypeSet path_mime_set;
549 path_mime_set.insert(
550 std::make_pair(
551 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII(
552 "foo.txt"),
553 "text/plain"));
555 std::vector<FullTaskDescriptor> tasks;
556 FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks);
557 ASSERT_EQ(2U, tasks.size());
558 // Sort the app IDs, as the order is not guaranteed.
559 std::vector<std::string> app_ids;
560 app_ids.push_back(tasks[0].task_descriptor().app_id);
561 app_ids.push_back(tasks[1].task_descriptor().app_id);
562 std::sort(app_ids.begin(), app_ids.end());
563 // Confirm that both Foo.app and Bar.app are found.
564 EXPECT_EQ(kFooId, app_ids[0]);
565 EXPECT_EQ(kBarId, app_ids[1]);
567 // Find apps for "text/plain" and "text/html" files. Only Foo.app should be
568 // found.
569 path_mime_set.clear();
570 path_mime_set.insert(
571 std::make_pair(
572 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII(
573 "foo.txt"),
574 "text/plain"));
575 path_mime_set.insert(
576 std::make_pair(
577 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII(
578 "foo.html"),
579 "text/html"));
580 tasks.clear();
581 FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks);
582 ASSERT_EQ(1U, tasks.size());
583 // Confirm that only Foo.app is found.
584 EXPECT_EQ(kFooId, tasks[0].task_descriptor().app_id);
586 // Add an "image/png" file. No tasks should be found.
587 path_mime_set.insert(
588 std::make_pair(base::FilePath::FromUTF8Unsafe("foo.png"),
589 "image/png"));
590 tasks.clear();
591 FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks);
592 // Confirm no tasks are found.
593 ASSERT_TRUE(tasks.empty());
596 // The basic logic is similar to a test case for FindDriveAppTasks above.
597 TEST_F(FileManagerFileTasksComplexTest, FindFileBrowserHandlerTasks) {
598 // Copied from FindFileHandlerTasks test above.
599 const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
600 const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
601 const char kEphemeralId[] = "opoomfdlbjcbjinalcjdjfoiikdeaoel";
603 // Foo.app can handle ".txt" and ".html".
604 // This one is an extension, and has "file_browser_handlers"
605 extensions::ExtensionBuilder foo_app;
606 foo_app.SetManifest(
607 extensions::DictionaryBuilder()
608 .Set("name", "Foo")
609 .Set("version", "1.0.0")
610 .Set("manifest_version", 2)
611 .Set("permissions",
612 extensions::ListBuilder().Append("fileBrowserHandler"))
613 .Set(
614 "file_browser_handlers",
615 extensions::ListBuilder().Append(
616 extensions::DictionaryBuilder()
617 .Set("id", "open")
618 .Set("default_title", "open")
619 .Set("file_filters", extensions::ListBuilder()
620 .Append("filesystem:*.txt")
621 .Append("filesystem:*.html")))));
622 foo_app.SetID(kFooId);
623 extension_service_->AddExtension(foo_app.Build().get());
625 // Bar.app can only handle ".txt".
626 extensions::ExtensionBuilder bar_app;
627 bar_app.SetManifest(
628 extensions::DictionaryBuilder()
629 .Set("name", "Bar")
630 .Set("version", "1.0.0")
631 .Set("manifest_version", 2)
632 .Set("permissions",
633 extensions::ListBuilder().Append("fileBrowserHandler"))
634 .Set("file_browser_handlers",
635 extensions::ListBuilder().Append(
636 extensions::DictionaryBuilder()
637 .Set("id", "open")
638 .Set("default_title", "open")
639 .Set("file_filters", extensions::ListBuilder().Append(
640 "filesystem:*.txt")))));
641 bar_app.SetID(kBarId);
642 extension_service_->AddExtension(bar_app.Build().get());
644 // Ephemeral.app is an ephemeral app that can handle ".txt".
645 // It should not ever be found as ephemeral apps cannot be file browser
646 // handlers.
647 extensions::ExtensionBuilder ephemeral_app;
648 ephemeral_app.SetManifest(
649 extensions::DictionaryBuilder()
650 .Set("name", "Ephemeral")
651 .Set("version", "1.0.0")
652 .Set("manifest_version", 2)
653 .Set("permissions",
654 extensions::ListBuilder().Append("fileBrowserHandler"))
655 .Set("file_browser_handlers",
656 extensions::ListBuilder().Append(
657 extensions::DictionaryBuilder()
658 .Set("id", "open")
659 .Set("default_title", "open")
660 .Set("file_filters", extensions::ListBuilder().Append(
661 "filesystem:*.txt")))));
662 ephemeral_app.SetID(kEphemeralId);
663 scoped_refptr<extensions::Extension> built_ephemeral_app(
664 ephemeral_app.Build());
665 extension_service_->AddExtension(built_ephemeral_app.get());
666 extensions::ExtensionPrefs* extension_prefs =
667 extensions::ExtensionPrefs::Get(&test_profile_);
668 extension_prefs->OnExtensionInstalled(built_ephemeral_app.get(),
669 extensions::Extension::ENABLED,
670 syncer::StringOrdinal(),
671 extensions::kInstallFlagIsEphemeral,
672 std::string());
674 // Find apps for a ".txt" file. Foo.app and Bar.app should be found.
675 std::vector<GURL> file_urls;
676 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt"));
678 std::vector<FullTaskDescriptor> tasks;
679 FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks);
680 ASSERT_EQ(2U, tasks.size());
681 // Sort the app IDs, as the order is not guaranteed.
682 std::vector<std::string> app_ids;
683 app_ids.push_back(tasks[0].task_descriptor().app_id);
684 app_ids.push_back(tasks[1].task_descriptor().app_id);
685 std::sort(app_ids.begin(), app_ids.end());
686 // Confirm that both Foo.app and Bar.app are found.
687 EXPECT_EQ(kFooId, app_ids[0]);
688 EXPECT_EQ(kBarId, app_ids[1]);
690 // Find apps for ".txt" and ".html" files. Only Foo.app should be found.
691 file_urls.clear();
692 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt"));
693 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.html"));
694 tasks.clear();
695 FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks);
696 ASSERT_EQ(1U, tasks.size());
697 // Confirm that only Foo.app is found.
698 EXPECT_EQ(kFooId, tasks[0].task_descriptor().app_id);
700 // Add an ".png" file. No tasks should be found.
701 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.png"));
702 tasks.clear();
703 FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks);
704 // Confirm no tasks are found.
705 ASSERT_TRUE(tasks.empty());
708 // Test that all kinds of apps (file handler, file browser handler, and Drive
709 // app) are returned.
710 TEST_F(FileManagerFileTasksComplexTest, FindAllTypesOfTasks) {
711 // kFooId and kBarId copied from FindFileHandlerTasks test above.
712 const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
713 const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
714 const char kBazId[] = "plifkpkakemokpflgbnnigcoldgcbdmc";
716 // Foo.app can handle "text/plain".
717 // This is a packaged app (file handler).
718 extensions::ExtensionBuilder foo_app;
719 foo_app.SetManifest(extensions::DictionaryBuilder()
720 .Set("name", "Foo")
721 .Set("version", "1.0.0")
722 .Set("manifest_version", 2)
723 .Set("app",
724 extensions::DictionaryBuilder()
725 .Set("background",
726 extensions::DictionaryBuilder()
727 .Set("scripts",
728 extensions::ListBuilder()
729 .Append("background.js"))))
730 .Set("file_handlers",
731 extensions::DictionaryBuilder()
732 .Set("text",
733 extensions::DictionaryBuilder()
734 .Set("title", "Text")
735 .Set("types",
736 extensions::ListBuilder()
737 .Append("text/plain")))));
738 foo_app.SetID(kFooId);
739 extension_service_->AddExtension(foo_app.Build().get());
741 // Bar.app can only handle ".txt".
742 // This is an extension (file browser handler).
743 extensions::ExtensionBuilder bar_app;
744 bar_app.SetManifest(
745 extensions::DictionaryBuilder()
746 .Set("name", "Bar")
747 .Set("version", "1.0.0")
748 .Set("manifest_version", 2)
749 .Set("permissions",
750 extensions::ListBuilder().Append("fileBrowserHandler"))
751 .Set("file_browser_handlers",
752 extensions::ListBuilder().Append(
753 extensions::DictionaryBuilder()
754 .Set("id", "open")
755 .Set("default_title", "open")
756 .Set("file_filters", extensions::ListBuilder().Append(
757 "filesystem:*.txt")))));
758 bar_app.SetID(kBarId);
759 extension_service_->AddExtension(bar_app.Build().get());
761 // Baz.app can handle "text/plain".
762 // This is a Drive app.
763 scoped_ptr<google_apis::AppResource> baz_app(new google_apis::AppResource);
764 baz_app->set_product_id("baz_app_id");
765 baz_app->set_application_id(kBazId);
766 baz_app->set_name("Baz");
767 baz_app->set_object_type("baz_object_type");
768 ScopedVector<std::string> baz_mime_types;
769 baz_mime_types.push_back(new std::string("text/plain"));
770 baz_app->set_primary_mimetypes(baz_mime_types.Pass());
771 // Set up DriveAppRegistry.
772 ScopedVector<google_apis::AppResource> app_resources;
773 app_resources.push_back(baz_app.release());
774 google_apis::AppList app_list;
775 app_list.set_items(app_resources.Pass());
776 drive::DriveAppRegistry drive_app_registry(NULL);
777 drive_app_registry.UpdateFromAppList(app_list);
779 // Find apps for "foo.txt". All apps should be found.
780 PathAndMimeTypeSet path_mime_set;
781 std::vector<GURL> file_urls;
782 path_mime_set.insert(
783 std::make_pair(
784 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII(
785 "foo.txt"),
786 "text/plain"));
787 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt"));
789 std::vector<FullTaskDescriptor> tasks;
790 FindAllTypesOfTasks(&test_profile_,
791 &drive_app_registry,
792 path_mime_set,
793 file_urls,
794 &tasks);
795 ASSERT_EQ(3U, tasks.size());
797 // Sort the app IDs, as the order is not guaranteed.
798 std::vector<std::string> app_ids;
799 app_ids.push_back(tasks[0].task_descriptor().app_id);
800 app_ids.push_back(tasks[1].task_descriptor().app_id);
801 app_ids.push_back(tasks[2].task_descriptor().app_id);
802 std::sort(app_ids.begin(), app_ids.end());
803 // Confirm that all apps are found.
804 EXPECT_EQ(kFooId, app_ids[0]);
805 EXPECT_EQ(kBarId, app_ids[1]);
806 EXPECT_EQ(kBazId, app_ids[2]);
809 TEST_F(FileManagerFileTasksComplexTest, FindAllTypesOfTasks_GoogleDocument) {
810 // kFooId and kBarId copied from FindFileHandlerTasks test above.
811 const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
812 const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
814 // Foo.app can handle ".gdoc" files.
815 scoped_ptr<google_apis::AppResource> foo_app(new google_apis::AppResource);
816 foo_app->set_product_id("foo_app");
817 foo_app->set_application_id(kFooId);
818 foo_app->set_name("Foo");
819 foo_app->set_object_type("foo_object_type");
820 ScopedVector<std::string> foo_extensions;
821 foo_extensions.push_back(new std::string("gdoc")); // Not ".gdoc"
822 foo_app->set_primary_file_extensions(foo_extensions.Pass());
824 // Prepare DriveAppRegistry from Foo.app.
825 ScopedVector<google_apis::AppResource> app_resources;
826 app_resources.push_back(foo_app.release());
827 google_apis::AppList app_list;
828 app_list.set_items(app_resources.Pass());
829 drive::DriveAppRegistry drive_app_registry(NULL);
830 drive_app_registry.UpdateFromAppList(app_list);
832 // Bar.app can handle ".gdoc" files.
833 // This is an extension (file browser handler).
834 extensions::ExtensionBuilder bar_app;
835 bar_app.SetManifest(
836 extensions::DictionaryBuilder()
837 .Set("name", "Bar")
838 .Set("version", "1.0.0")
839 .Set("manifest_version", 2)
840 .Set("permissions",
841 extensions::ListBuilder().Append("fileBrowserHandler"))
842 .Set("file_browser_handlers",
843 extensions::ListBuilder().Append(
844 extensions::DictionaryBuilder()
845 .Set("id", "open")
846 .Set("default_title", "open")
847 .Set("file_filters", extensions::ListBuilder().Append(
848 "filesystem:*.gdoc")))));
849 bar_app.SetID(kBarId);
850 extension_service_->AddExtension(bar_app.Build().get());
852 // Files.app can handle ".gdoc" files.
853 // The ID "kFileManagerAppId" used here is precisely the one that identifies
854 // the Chrome OS Files.app application.
855 extensions::ExtensionBuilder files_app;
856 files_app.SetManifest(
857 extensions::DictionaryBuilder()
858 .Set("name", "Files")
859 .Set("version", "1.0.0")
860 .Set("manifest_version", 2)
861 .Set("permissions",
862 extensions::ListBuilder().Append("fileBrowserHandler"))
863 .Set("file_browser_handlers",
864 extensions::ListBuilder().Append(
865 extensions::DictionaryBuilder()
866 .Set("id", "open")
867 .Set("default_title", "open")
868 .Set("file_filters", extensions::ListBuilder().Append(
869 "filesystem:*.gdoc")))));
870 files_app.SetID(kFileManagerAppId);
871 extension_service_->AddExtension(files_app.Build().get());
873 // Find apps for a ".gdoc file". Only the built-in handler of Files.apps
874 // should be found.
875 PathAndMimeTypeSet path_mime_set;
876 std::vector<GURL> file_urls;
877 path_mime_set.insert(
878 std::make_pair(
879 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII(
880 "foo.gdoc"),
881 "application/vnd.google-apps.document"));
882 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.gdoc"));
884 std::vector<FullTaskDescriptor> tasks;
885 FindAllTypesOfTasks(&test_profile_,
886 &drive_app_registry,
887 path_mime_set,
888 file_urls,
889 &tasks);
890 ASSERT_EQ(1U, tasks.size());
891 EXPECT_EQ(kFileManagerAppId, tasks[0].task_descriptor().app_id);
894 TEST_F(FileManagerFileTasksComplexTest, FindFileHandlerTask_Generic) {
895 // Since we want to keep the order of the result as foo,bar,baz,qux,
896 // keep the ids in alphabetical order.
897 const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
898 const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
899 const char kBazId[] = "plifkpkakemokpflgbnnigcoldgcbdmc";
900 const char kQuxId[] = "pmifkpkakgkadkkhcmhgnigmmifgpaph";
902 // Foo app provides file handler for text/plain and all file types.
903 extensions::ExtensionBuilder foo_app;
904 foo_app.SetManifest(extensions::DictionaryBuilder()
905 .Set("name", "Foo")
906 .Set("version", "1.0.0")
907 .Set("manifest_version", 2)
908 .Set("app", extensions::DictionaryBuilder()
909 .Set("background", extensions::DictionaryBuilder()
910 .Set("scripts", extensions::ListBuilder()
911 .Append("background.js"))))
912 .Set("file_handlers",
913 extensions::DictionaryBuilder()
914 .Set("any",
915 extensions::DictionaryBuilder()
916 .Set("types", extensions::ListBuilder()
917 .Append("*/*")))
918 .Set("text",
919 extensions::DictionaryBuilder()
920 .Set("types", extensions::ListBuilder()
921 .Append("text/plain")))));
922 foo_app.SetID(kFooId);
923 extension_service_->AddExtension(foo_app.Build().get());
925 // Bar app provides file handler for .txt and not provide generic file
926 // handler.
927 extensions::ExtensionBuilder bar_app;
928 bar_app.SetManifest(extensions::DictionaryBuilder()
929 .Set("name", "Bar")
930 .Set("version", "1.0.0")
931 .Set("manifest_version", 2)
932 .Set("app", extensions::DictionaryBuilder()
933 .Set("background", extensions::DictionaryBuilder()
934 .Set("scripts", extensions::ListBuilder()
935 .Append("background.js"))))
936 .Set("file_handlers",
937 extensions::DictionaryBuilder()
938 .Set("text",
939 extensions::DictionaryBuilder()
940 .Set("extensions", extensions::ListBuilder()
941 .Append("txt")))));
942 bar_app.SetID(kBarId);
943 extension_service_->AddExtension(bar_app.Build().get());
945 // Baz app provides file handler for all extensions and images.
946 extensions::ExtensionBuilder baz_app;
947 baz_app.SetManifest(extensions::DictionaryBuilder()
948 .Set("name", "Baz")
949 .Set("version", "1.0.0")
950 .Set("manifest_version", 2)
951 .Set("app", extensions::DictionaryBuilder()
952 .Set("background", extensions::DictionaryBuilder()
953 .Set("scripts", extensions::ListBuilder()
954 .Append("background.js"))))
955 .Set("file_handlers",
956 extensions::DictionaryBuilder()
957 .Set("any",
958 extensions::DictionaryBuilder()
959 .Set("extensions", extensions::ListBuilder()
960 .Append("*")
961 .Append("bar")))
962 .Set("image",
963 extensions::DictionaryBuilder()
964 .Set("types", extensions::ListBuilder()
965 .Append("image/*")))));
966 baz_app.SetID(kBazId);
967 extension_service_->AddExtension(baz_app.Build().get());
969 // Qux app provides file handler for all types.
970 extensions::ExtensionBuilder qux_app;
971 qux_app.SetManifest(extensions::DictionaryBuilder()
972 .Set("name", "Qux")
973 .Set("version", "1.0.0")
974 .Set("manifest_version", 2)
975 .Set("app", extensions::DictionaryBuilder()
976 .Set("background", extensions::DictionaryBuilder()
977 .Set("scripts", extensions::ListBuilder()
978 .Append("background.js"))))
979 .Set("file_handlers",
980 extensions::DictionaryBuilder()
981 .Set("any",
982 extensions::DictionaryBuilder()
983 .Set("types", extensions::ListBuilder()
984 .Append("*")))));
985 qux_app.SetID(kQuxId);
986 extension_service_->AddExtension(qux_app.Build().get());
988 // Test case with .txt file
989 PathAndMimeTypeSet txt_path_mime_set;
990 txt_path_mime_set.insert(
991 std::make_pair(
992 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII(
993 "foo.txt"),
994 "text/plain"));
995 std::vector<FullTaskDescriptor> txt_result;
996 FindFileHandlerTasks(&test_profile_, txt_path_mime_set, &txt_result);
997 EXPECT_EQ(4U, txt_result.size());
998 // Foo app provides a handler for text/plain.
999 EXPECT_EQ("Foo", txt_result[0].task_title());
1000 EXPECT_FALSE(txt_result[0].is_generic_file_handler());
1001 // Bar app provides a handler for .txt.
1002 EXPECT_EQ("Bar", txt_result[1].task_title());
1003 EXPECT_FALSE(txt_result[1].is_generic_file_handler());
1004 // Baz app provides a handler for all extensions.
1005 EXPECT_EQ("Baz", txt_result[2].task_title());
1006 EXPECT_TRUE(txt_result[2].is_generic_file_handler());
1007 // Qux app provides a handler for all types.
1008 EXPECT_EQ("Qux", txt_result[3].task_title());
1009 EXPECT_TRUE(txt_result[3].is_generic_file_handler());
1011 // Test case with .jpg file
1012 PathAndMimeTypeSet jpg_path_mime_set;
1013 jpg_path_mime_set.insert(
1014 std::make_pair(
1015 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII(
1016 "foo.jpg"),
1017 "image/jpeg"));
1018 std::vector<FullTaskDescriptor> jpg_result;
1019 FindFileHandlerTasks(&test_profile_, jpg_path_mime_set, &jpg_result);
1020 EXPECT_EQ(3U, jpg_result.size());
1021 // Foo app provides a handler for all types.
1022 EXPECT_EQ("Foo", jpg_result[0].task_title());
1023 EXPECT_TRUE(jpg_result[0].is_generic_file_handler());
1024 // Baz app provides a handler for image/*. A partial wildcarded handler is
1025 // treated as non-generic handler.
1026 EXPECT_EQ("Baz", jpg_result[1].task_title());
1027 EXPECT_FALSE(jpg_result[1].is_generic_file_handler());
1028 // Qux app provides a handler for all types.
1029 EXPECT_EQ("Qux", jpg_result[2].task_title());
1030 EXPECT_TRUE(jpg_result[2].is_generic_file_handler());
1033 } // namespace file_tasks
1034 } // namespace file_manager.