- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_manager / file_tasks_unittest.cc
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.
4
5 #include "chrome/browser/chromeos/file_manager/file_tasks.h"
6
7 #include <algorithm>
8 #include <utility>
9
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/drive_app_registry.h"
15 #include "chrome/browser/chromeos/drive/file_system_util.h"
16 #include "chrome/browser/chromeos/file_manager/app_id.h"
17 #include "chrome/browser/chromeos/login/user_manager.h"
18 #include "chrome/browser/chromeos/settings/cros_settings.h"
19 #include "chrome/browser/chromeos/settings/device_settings_service.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/extension_system.h"
22 #include "chrome/browser/extensions/test_extension_system.h"
23 #include "chrome/browser/google_apis/drive_api_parser.h"
24 #include "chrome/common/extensions/extension_builder.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/test/base/testing_profile.h"
27 #include "content/public/test/test_browser_thread_bundle.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "url/gurl.h"
30
31 namespace file_manager {
32 namespace file_tasks {
33 namespace {
34
35 // Registers the default task preferences. Used for testing
36 // ChooseAndSetDefaultTask().
37 void RegisterDefaultTaskPreferences(TestingPrefServiceSimple* pref_service) {
38   DCHECK(pref_service);
39
40   pref_service->registry()->RegisterDictionaryPref(
41       prefs::kDefaultTasksByMimeType);
42   pref_service->registry()->RegisterDictionaryPref(
43       prefs::kDefaultTasksBySuffix);
44 }
45
46 // Updates the default task preferences per the given dictionary values. Used
47 // for testing ChooseAndSetDefaultTask.
48 void UpdateDefaultTaskPreferences(TestingPrefServiceSimple* pref_service,
49                                   const DictionaryValue& mime_types,
50                                   const DictionaryValue& suffixes) {
51   DCHECK(pref_service);
52
53   pref_service->Set(prefs::kDefaultTasksByMimeType, mime_types);
54   pref_service->Set(prefs::kDefaultTasksBySuffix, suffixes);
55 }
56
57 }  // namespace
58
59 TEST(FileManagerFileTasksTest,
60      FullTaskDescriptor_NonDriveAppWithIconAndDefault) {
61   FullTaskDescriptor full_descriptor(
62       TaskDescriptor("app-id",
63                      TASK_TYPE_FILE_BROWSER_HANDLER,
64                      "action-id"),
65       "task title",
66       GURL("http://example.com/icon.png"),
67       true /* is_default */);
68
69   const std::string task_id =
70       TaskDescriptorToId(full_descriptor.task_descriptor());
71   EXPECT_EQ("app-id|file|action-id", task_id);
72   EXPECT_EQ("http://example.com/icon.png", full_descriptor.icon_url().spec());
73   EXPECT_EQ("task title", full_descriptor.task_title());
74   EXPECT_TRUE(full_descriptor.is_default());
75 }
76
77 TEST(FileManagerFileTasksTest,
78      FullTaskDescriptor_DriveAppWithoutIconAndNotDefault) {
79   FullTaskDescriptor full_descriptor(
80       TaskDescriptor("app-id",
81                      TASK_TYPE_DRIVE_APP,
82                      "action-id"),
83       "task title",
84       GURL(),  // No icon URL.
85       false /* is_default */);
86
87   const std::string task_id =
88       TaskDescriptorToId(full_descriptor.task_descriptor());
89   EXPECT_EQ("app-id|drive|action-id", task_id);
90   EXPECT_TRUE(full_descriptor.icon_url().is_empty());
91   EXPECT_EQ("task title", full_descriptor.task_title());
92   EXPECT_FALSE(full_descriptor.is_default());
93 }
94
95 TEST(FileManagerFileTasksTest, MakeTaskID) {
96   EXPECT_EQ("app-id|file|action-id",
97             MakeTaskID("app-id", TASK_TYPE_FILE_BROWSER_HANDLER, "action-id"));
98   EXPECT_EQ("app-id|app|action-id",
99             MakeTaskID("app-id", TASK_TYPE_FILE_HANDLER, "action-id"));
100   EXPECT_EQ("app-id|drive|action-id",
101             MakeTaskID("app-id", TASK_TYPE_DRIVE_APP, "action-id"));
102 }
103
104 TEST(FileManagerFileTasksTest, MakeDriveAppTaskId) {
105   EXPECT_EQ("app-id|drive|open-with", MakeDriveAppTaskId("app-id"));
106 }
107
108 TEST(FileManagerFileTasksTest, TaskDescriptorToId) {
109   EXPECT_EQ("app-id|file|action-id",
110             TaskDescriptorToId(TaskDescriptor("app-id",
111                                               TASK_TYPE_FILE_BROWSER_HANDLER,
112                                               "action-id")));
113 }
114
115 TEST(FileManagerFileTasksTest, ParseTaskID_FileBrowserHandler) {
116   TaskDescriptor task;
117   EXPECT_TRUE(ParseTaskID("app-id|file|action-id", &task));
118   EXPECT_EQ("app-id", task.app_id);
119   EXPECT_EQ(TASK_TYPE_FILE_BROWSER_HANDLER, task.task_type);
120   EXPECT_EQ("action-id", task.action_id);
121 }
122
123 TEST(FileManagerFileTasksTest, ParseTaskID_FileHandler) {
124   TaskDescriptor task;
125   EXPECT_TRUE(ParseTaskID("app-id|app|action-id", &task));
126   EXPECT_EQ("app-id", task.app_id);
127   EXPECT_EQ(TASK_TYPE_FILE_HANDLER, task.task_type);
128   EXPECT_EQ("action-id", task.action_id);
129 }
130
131 TEST(FileManagerFileTasksTest, ParseTaskID_DriveApp) {
132   TaskDescriptor task;
133   EXPECT_TRUE(ParseTaskID("app-id|drive|action-id", &task));
134   EXPECT_EQ("app-id", task.app_id);
135   EXPECT_EQ(TASK_TYPE_DRIVE_APP, task.task_type);
136   EXPECT_EQ("action-id", task.action_id);
137 }
138
139 TEST(FileManagerFileTasksTest, ParseTaskID_Legacy) {
140   TaskDescriptor task;
141   // A legacy task ID only has two parts. The task type should be
142   // TASK_TYPE_FILE_BROWSER_HANDLER.
143   EXPECT_TRUE(ParseTaskID("app-id|action-id", &task));
144   EXPECT_EQ("app-id", task.app_id);
145   EXPECT_EQ(TASK_TYPE_FILE_BROWSER_HANDLER, task.task_type);
146   EXPECT_EQ("action-id", task.action_id);
147 }
148
149 TEST(FileManagerFileTasksTest, ParseTaskID_LegacyDrive) {
150   TaskDescriptor task;
151   // A legacy task ID only has two parts. For Drive app, the app ID is
152   // prefixed with "drive-app:".
153   EXPECT_TRUE(ParseTaskID("drive-app:app-id|action-id", &task));
154   EXPECT_EQ("app-id", task.app_id);
155   EXPECT_EQ(TASK_TYPE_DRIVE_APP, task.task_type);
156   EXPECT_EQ("action-id", task.action_id);
157 }
158
159 TEST(FileManagerFileTasksTest, ParseTaskID_Invalid) {
160   TaskDescriptor task;
161   EXPECT_FALSE(ParseTaskID("invalid", &task));
162 }
163
164 TEST(FileManagerFileTasksTest, ParseTaskID_UnknownTaskType) {
165   TaskDescriptor task;
166   EXPECT_FALSE(ParseTaskID("app-id|unknown|action-id", &task));
167 }
168
169 TEST(FileManagerFileTasksTest, FindDriveAppTasks) {
170   // For DriveAppRegistry, which checks CurrentlyOn(BrowserThread::UI).
171   content::TestBrowserThreadBundle thread_bundle;
172
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_url(
176       GURL("https://chrome.google.com/webstore/detail/foo_app_id"));
177   foo_app->set_application_id("foo_app_id");
178   foo_app->set_name("Foo");
179   foo_app->set_object_type("foo_object_type");
180   ScopedVector<std::string> foo_mime_types;
181   foo_mime_types.push_back(new std::string("text/plain"));
182   foo_mime_types.push_back(new std::string("text/html"));
183   foo_app->set_primary_mimetypes(foo_mime_types.Pass());
184
185   // Bar.app can only handle "text/plain".
186   scoped_ptr<google_apis::AppResource> bar_app(new google_apis::AppResource);
187   bar_app->set_product_url(
188       GURL("https://chrome.google.com/webstore/detail/bar_app_id"));
189   bar_app->set_application_id("bar_app_id");
190   bar_app->set_name("Bar");
191   bar_app->set_object_type("bar_object_type");
192   ScopedVector<std::string> bar_mime_types;
193   bar_mime_types.push_back(new std::string("text/plain"));
194   bar_app->set_primary_mimetypes(bar_mime_types.Pass());
195
196   // Prepare DriveAppRegistry from Foo.app and Bar.app.
197   ScopedVector<google_apis::AppResource> app_resources;
198   app_resources.push_back(foo_app.release());
199   app_resources.push_back(bar_app.release());
200   google_apis::AppList app_list;
201   app_list.set_items(app_resources.Pass());
202   drive::DriveAppRegistry drive_app_registry(NULL);
203   drive_app_registry.UpdateFromAppList(app_list);
204
205   // Find apps for a "text/plain" file. Foo.app and Bar.app should be found.
206   PathAndMimeTypeSet path_mime_set;
207   path_mime_set.insert(
208       std::make_pair(
209           drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
210           "text/plain"));
211   std::vector<FullTaskDescriptor> tasks;
212   FindDriveAppTasks(drive_app_registry,
213                     path_mime_set,
214                     &tasks);
215   ASSERT_EQ(2U, tasks.size());
216   // Sort the app IDs, as the order is not guaranteed.
217   std::vector<std::string> app_ids;
218   app_ids.push_back(tasks[0].task_descriptor().app_id);
219   app_ids.push_back(tasks[1].task_descriptor().app_id);
220   std::sort(app_ids.begin(), app_ids.end());
221   // Confirm that both Foo.app and Bar.app are found.
222   EXPECT_EQ("bar_app_id", app_ids[0]);
223   EXPECT_EQ("foo_app_id", app_ids[1]);
224
225   // Find apps for "text/plain" and "text/html" files. Only Foo.app should be
226   // found.
227   path_mime_set.clear();
228   path_mime_set.insert(
229       std::make_pair(
230           drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
231           "text/plain"));
232   path_mime_set.insert(
233       std::make_pair(
234           drive::util::GetDriveMountPointPath().AppendASCII("foo.html"),
235           "text/html"));
236   tasks.clear();
237   FindDriveAppTasks(drive_app_registry,
238                     path_mime_set,
239                     &tasks);
240   ASSERT_EQ(1U, tasks.size());
241   // Confirm that only Foo.app is found.
242   EXPECT_EQ("foo_app_id", tasks[0].task_descriptor().app_id);
243
244   // Add a "text/plain" file not on Drive. No tasks should be found.
245   path_mime_set.insert(
246       std::make_pair(base::FilePath::FromUTF8Unsafe("not_on_drive.txt"),
247                      "text/plain"));
248   tasks.clear();
249   FindDriveAppTasks(drive_app_registry,
250                     path_mime_set,
251                     &tasks);
252   // Confirm no tasks are found.
253   ASSERT_TRUE(tasks.empty());
254 }
255
256 // Test that the right task is chosen from multiple choices per mime types
257 // and file extensions.
258 TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_MultipleTasks) {
259   TestingPrefServiceSimple pref_service;
260   RegisterDefaultTaskPreferences(&pref_service);
261
262   // Text.app and Nice.app were found for "foo.txt".
263   TaskDescriptor text_app_task("text-app-id",
264                                TASK_TYPE_FILE_HANDLER,
265                                "action-id");
266   TaskDescriptor nice_app_task("nice-app-id",
267                                TASK_TYPE_FILE_HANDLER,
268                                "action-id");
269   std::vector<FullTaskDescriptor> tasks;
270   tasks.push_back(FullTaskDescriptor(
271       text_app_task,
272       "Text.app",
273       GURL("http://example.com/text_app.png"),
274       false /* is_default */));
275   tasks.push_back(FullTaskDescriptor(
276       nice_app_task,
277       "Nice.app",
278       GURL("http://example.com/nice_app.png"),
279       false /* is_default */));
280   PathAndMimeTypeSet path_mime_set;
281   path_mime_set.insert(std::make_pair(
282       base::FilePath::FromUTF8Unsafe("foo.txt"),
283       "text/plain"));
284
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());
290
291   // Set Text.app as default for "text/plain" in the preferences.
292   DictionaryValue empty;
293   DictionaryValue mime_types;
294   mime_types.SetStringWithoutPathExpansion(
295       "text/plain",
296       TaskDescriptorToId(text_app_task));
297   UpdateDefaultTaskPreferences(&pref_service, mime_types, empty);
298
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());
303
304   // Change it back to non-default for testing further.
305   tasks[0].set_is_default(false);
306
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());
312
313   // Set Nice.app as default for ".txt" in the preferences.
314   DictionaryValue suffixes;
315   suffixes.SetStringWithoutPathExpansion(
316       ".txt",
317       TaskDescriptorToId(nice_app_task));
318   UpdateDefaultTaskPreferences(&pref_service, empty, suffixes);
319
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());
324 }
325
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);
331
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   PathAndMimeTypeSet path_mime_set;
343   path_mime_set.insert(std::make_pair(
344       base::FilePath::FromUTF8Unsafe("foo.txt"),
345       "text/plain"));
346
347   // The internal file browser handler should be chosen as default, as it's a
348   // fallback file browser handler.
349   ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks);
350   EXPECT_TRUE(tasks[0].is_default());
351 }
352
353 // Test using the test extension system, which needs lots of setup.
354 class FileManagerFileTasksComplexTest : public testing::Test {
355  protected:
356   FileManagerFileTasksComplexTest()
357       : command_line_(CommandLine::NO_PROGRAM),
358         extension_service_(NULL) {
359     extensions::TestExtensionSystem* test_extension_system =
360         static_cast<extensions::TestExtensionSystem*>(
361             extensions::ExtensionSystem::Get(&test_profile_));
362     extension_service_ = test_extension_system->CreateExtensionService(
363         &command_line_,
364         base::FilePath()  /* install_directory */,
365         false  /* autoupdate_enabled*/);
366   }
367
368   content::TestBrowserThreadBundle thread_bundle_;
369   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
370   chromeos::ScopedTestCrosSettings test_cros_settings_;
371   chromeos::ScopedTestUserManager test_user_manager_;
372   TestingProfile test_profile_;
373   CommandLine command_line_;
374   ExtensionService* extension_service_;  // Owned by test_profile_;
375 };
376
377 // The basic logic is similar to a test case for FindDriveAppTasks above.
378 TEST_F(FileManagerFileTasksComplexTest, FindFileHandlerTasks) {
379   // Random IDs generated by
380   // % ruby -le 'print (0...32).to_a.map{(?a + rand(16)).chr}.join'
381   const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
382   const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
383
384   // Foo.app can handle "text/plain" and "text/html".
385   extensions::ExtensionBuilder foo_app;
386   foo_app.SetManifest(extensions::DictionaryBuilder()
387                       .Set("name", "Foo")
388                       .Set("version", "1.0.0")
389                       .Set("manifest_version", 2)
390                       .Set("app",
391                            extensions::DictionaryBuilder()
392                            .Set("background",
393                                 extensions::DictionaryBuilder()
394                                 .Set("scripts",
395                                      extensions::ListBuilder()
396                                      .Append("background.js"))))
397                       .Set("file_handlers",
398                            extensions::DictionaryBuilder()
399                            .Set("text",
400                                 extensions::DictionaryBuilder()
401                                 .Set("title", "Text")
402                                 .Set("types",
403                                      extensions::ListBuilder()
404                                      .Append("text/plain")
405                                      .Append("text/html")))));
406   foo_app.SetID(kFooId);
407   extension_service_->AddExtension(foo_app.Build().get());
408
409   // Bar.app can only handle "text/plain".
410   extensions::ExtensionBuilder bar_app;
411   bar_app.SetManifest(extensions::DictionaryBuilder()
412                       .Set("name", "Bar")
413                       .Set("version", "1.0.0")
414                       .Set("manifest_version", 2)
415                       .Set("app",
416                            extensions::DictionaryBuilder()
417                            .Set("background",
418                                 extensions::DictionaryBuilder()
419                                 .Set("scripts",
420                                      extensions::ListBuilder()
421                                      .Append("background.js"))))
422                       .Set("file_handlers",
423                            extensions::DictionaryBuilder()
424                            .Set("text",
425                                 extensions::DictionaryBuilder()
426                                 .Set("title", "Text")
427                                 .Set("types",
428                                      extensions::ListBuilder()
429                                      .Append("text/plain")))));
430   bar_app.SetID(kBarId);
431   extension_service_->AddExtension(bar_app.Build().get());
432
433   // Find apps for a "text/plain" file. Foo.app and Bar.app should be found.
434   PathAndMimeTypeSet path_mime_set;
435   path_mime_set.insert(
436       std::make_pair(
437           drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
438           "text/plain"));
439
440   std::vector<FullTaskDescriptor> tasks;
441   FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks);
442   ASSERT_EQ(2U, tasks.size());
443   // Sort the app IDs, as the order is not guaranteed.
444   std::vector<std::string> app_ids;
445   app_ids.push_back(tasks[0].task_descriptor().app_id);
446   app_ids.push_back(tasks[1].task_descriptor().app_id);
447   std::sort(app_ids.begin(), app_ids.end());
448   // Confirm that both Foo.app and Bar.app are found.
449   EXPECT_EQ(kFooId, app_ids[0]);
450   EXPECT_EQ(kBarId, app_ids[1]);
451
452   // Find apps for "text/plain" and "text/html" files. Only Foo.app should be
453   // found.
454   path_mime_set.clear();
455   path_mime_set.insert(
456       std::make_pair(
457           drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
458           "text/plain"));
459   path_mime_set.insert(
460       std::make_pair(
461           drive::util::GetDriveMountPointPath().AppendASCII("foo.html"),
462           "text/html"));
463   tasks.clear();
464   FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks);
465   ASSERT_EQ(1U, tasks.size());
466   // Confirm that only Foo.app is found.
467   EXPECT_EQ(kFooId, tasks[0].task_descriptor().app_id);
468
469   // Add an "image/png" file. No tasks should be found.
470   path_mime_set.insert(
471       std::make_pair(base::FilePath::FromUTF8Unsafe("foo.png"),
472                      "image/png"));
473   tasks.clear();
474   FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks);
475   // Confirm no tasks are found.
476   ASSERT_TRUE(tasks.empty());
477 }
478
479 // The basic logic is similar to a test case for FindDriveAppTasks above.
480 TEST_F(FileManagerFileTasksComplexTest, FindFileBrowserHandlerTasks) {
481   // Copied from FindFileHandlerTasks test above.
482   const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
483   const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
484
485   // Foo.app can handle ".txt" and ".html".
486   // This one is an extension, and has "file_browser_handlers"
487   extensions::ExtensionBuilder foo_app;
488   foo_app.SetManifest(extensions::DictionaryBuilder()
489                       .Set("name", "Foo")
490                       .Set("version", "1.0.0")
491                       .Set("manifest_version", 2)
492                       .Set("file_browser_handlers",
493                            extensions::ListBuilder()
494                            .Append(extensions::DictionaryBuilder()
495                                    .Set("id", "open")
496                                    .Set("default_title", "open")
497                                    .Set("file_filters",
498                                         extensions::ListBuilder()
499                                         .Append("filesystem:*.txt")
500                                         .Append("filesystem:*.html")))));
501   foo_app.SetID(kFooId);
502   extension_service_->AddExtension(foo_app.Build().get());
503
504   // Bar.app can only handle ".txt".
505   extensions::ExtensionBuilder bar_app;
506   bar_app.SetManifest(extensions::DictionaryBuilder()
507                       .Set("name", "Bar")
508                       .Set("version", "1.0.0")
509                       .Set("manifest_version", 2)
510                       .Set("file_browser_handlers",
511                            extensions::ListBuilder()
512                            .Append(extensions::DictionaryBuilder()
513                                    .Set("id", "open")
514                                    .Set("default_title", "open")
515                                    .Set("file_filters",
516                                         extensions::ListBuilder()
517                                         .Append("filesystem:*.txt")))));
518   bar_app.SetID(kBarId);
519   extension_service_->AddExtension(bar_app.Build().get());
520
521   // Find apps for a ".txt" file. Foo.app and Bar.app should be found.
522   std::vector<GURL> file_urls;
523   file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt"));
524
525   std::vector<FullTaskDescriptor> tasks;
526   FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks);
527   ASSERT_EQ(2U, tasks.size());
528   // Sort the app IDs, as the order is not guaranteed.
529   std::vector<std::string> app_ids;
530   app_ids.push_back(tasks[0].task_descriptor().app_id);
531   app_ids.push_back(tasks[1].task_descriptor().app_id);
532   std::sort(app_ids.begin(), app_ids.end());
533   // Confirm that both Foo.app and Bar.app are found.
534   EXPECT_EQ(kFooId, app_ids[0]);
535   EXPECT_EQ(kBarId, app_ids[1]);
536
537   // Find apps for ".txt" and ".html" files. Only Foo.app should be found.
538   file_urls.clear();
539   file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt"));
540   file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.html"));
541   tasks.clear();
542   FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks);
543   ASSERT_EQ(1U, tasks.size());
544   // Confirm that only Foo.app is found.
545   EXPECT_EQ(kFooId, tasks[0].task_descriptor().app_id);
546
547   // Add an ".png" file. No tasks should be found.
548   file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.png"));
549   tasks.clear();
550   FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks);
551   // Confirm no tasks are found.
552   ASSERT_TRUE(tasks.empty());
553 }
554
555 // Test that all kinds of apps (file handler, file browser handler, and Drive
556 // app) are returned.
557 TEST_F(FileManagerFileTasksComplexTest, FindAllTypesOfTasks) {
558   // kFooId and kBarId copied from FindFileHandlerTasks test above.
559   const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
560   const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
561   const char kBazId[] = "plifkpkakemokpflgbnnigcoldgcbdmc";
562
563   // Foo.app can handle "text/plain".
564   // This is a packaged app (file handler).
565   extensions::ExtensionBuilder foo_app;
566   foo_app.SetManifest(extensions::DictionaryBuilder()
567                       .Set("name", "Foo")
568                       .Set("version", "1.0.0")
569                       .Set("manifest_version", 2)
570                       .Set("app",
571                            extensions::DictionaryBuilder()
572                            .Set("background",
573                                 extensions::DictionaryBuilder()
574                                 .Set("scripts",
575                                      extensions::ListBuilder()
576                                      .Append("background.js"))))
577                       .Set("file_handlers",
578                            extensions::DictionaryBuilder()
579                            .Set("text",
580                                 extensions::DictionaryBuilder()
581                                 .Set("title", "Text")
582                                 .Set("types",
583                                      extensions::ListBuilder()
584                                      .Append("text/plain")))));
585   foo_app.SetID(kFooId);
586   extension_service_->AddExtension(foo_app.Build().get());
587
588   // Bar.app can only handle ".txt".
589   // This is an extension (file browser handler).
590   extensions::ExtensionBuilder bar_app;
591   bar_app.SetManifest(extensions::DictionaryBuilder()
592                       .Set("name", "Bar")
593                       .Set("version", "1.0.0")
594                       .Set("manifest_version", 2)
595                       .Set("file_browser_handlers",
596                            extensions::ListBuilder()
597                            .Append(extensions::DictionaryBuilder()
598                                    .Set("id", "open")
599                                    .Set("default_title", "open")
600                                    .Set("file_filters",
601                                         extensions::ListBuilder()
602                                         .Append("filesystem:*.txt")))));
603   bar_app.SetID(kBarId);
604   extension_service_->AddExtension(bar_app.Build().get());
605
606   // Baz.app can handle "text/plain".
607   // This is a Drive app.
608   scoped_ptr<google_apis::AppResource> baz_app(new google_apis::AppResource);
609   baz_app->set_product_url(
610       GURL("https://chrome.google.com/webstore/detail/baz_app_id"));
611   baz_app->set_application_id(kBazId);
612   baz_app->set_name("Baz");
613   baz_app->set_object_type("baz_object_type");
614   ScopedVector<std::string> baz_mime_types;
615   baz_mime_types.push_back(new std::string("text/plain"));
616   baz_app->set_primary_mimetypes(baz_mime_types.Pass());
617   // Set up DriveAppRegistry.
618   ScopedVector<google_apis::AppResource> app_resources;
619   app_resources.push_back(baz_app.release());
620   google_apis::AppList app_list;
621   app_list.set_items(app_resources.Pass());
622   drive::DriveAppRegistry drive_app_registry(NULL);
623   drive_app_registry.UpdateFromAppList(app_list);
624
625   // Find apps for "foo.txt". All apps should be found.
626   PathAndMimeTypeSet path_mime_set;
627   std::vector<GURL> file_urls;
628   path_mime_set.insert(
629       std::make_pair(
630           drive::util::GetDriveMountPointPath().AppendASCII("foo.txt"),
631           "text/plain"));
632   file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt"));
633
634   std::vector<FullTaskDescriptor> tasks;
635   FindAllTypesOfTasks(&test_profile_,
636                       &drive_app_registry,
637                       path_mime_set,
638                       file_urls,
639                       &tasks);
640   ASSERT_EQ(3U, tasks.size());
641
642   // Sort the app IDs, as the order is not guaranteed.
643   std::vector<std::string> app_ids;
644   app_ids.push_back(tasks[0].task_descriptor().app_id);
645   app_ids.push_back(tasks[1].task_descriptor().app_id);
646   app_ids.push_back(tasks[2].task_descriptor().app_id);
647   std::sort(app_ids.begin(), app_ids.end());
648   // Confirm that all apps are found.
649   EXPECT_EQ(kFooId, app_ids[0]);
650   EXPECT_EQ(kBarId, app_ids[1]);
651   EXPECT_EQ(kBazId, app_ids[2]);
652 }
653
654 TEST_F(FileManagerFileTasksComplexTest, FindAllTypesOfTasks_GoogleDocument) {
655   // kFooId and kBarId copied from FindFileHandlerTasks test above.
656   const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
657   const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
658
659   // Foo.app can handle ".gdoc" files.
660   scoped_ptr<google_apis::AppResource> foo_app(new google_apis::AppResource);
661   foo_app->set_product_url(
662       GURL("https://chrome.google.com/webstore/detail/foo_app"));
663   foo_app->set_application_id(kFooId);
664   foo_app->set_name("Foo");
665   foo_app->set_object_type("foo_object_type");
666   ScopedVector<std::string> foo_extensions;
667   foo_extensions.push_back(new std::string("gdoc"));  // Not ".gdoc"
668   foo_app->set_primary_file_extensions(foo_extensions.Pass());
669
670   // Prepare DriveAppRegistry from Foo.app.
671   ScopedVector<google_apis::AppResource> app_resources;
672   app_resources.push_back(foo_app.release());
673   google_apis::AppList app_list;
674   app_list.set_items(app_resources.Pass());
675   drive::DriveAppRegistry drive_app_registry(NULL);
676   drive_app_registry.UpdateFromAppList(app_list);
677
678   // Bar.app can handle ".gdoc" files.
679   // This is an extension (file browser handler).
680   extensions::ExtensionBuilder bar_app;
681   bar_app.SetManifest(extensions::DictionaryBuilder()
682                       .Set("name", "Bar")
683                       .Set("version", "1.0.0")
684                       .Set("manifest_version", 2)
685                       .Set("file_browser_handlers",
686                            extensions::ListBuilder()
687                            .Append(extensions::DictionaryBuilder()
688                                    .Set("id", "open")
689                                    .Set("default_title", "open")
690                                    .Set("file_filters",
691                                         extensions::ListBuilder()
692                                         .Append("filesystem:*.gdoc")))));
693   bar_app.SetID(kBarId);
694   extension_service_->AddExtension(bar_app.Build().get());
695
696   // Files.app can handle ".gdoc" files.
697   // The ID "kFileManagerAppId" used here is precisely the one that identifies
698   // the Chrome OS Files.app application.
699   extensions::ExtensionBuilder files_app;
700   files_app.SetManifest(extensions::DictionaryBuilder()
701                        .Set("name", "Files")
702                        .Set("version", "1.0.0")
703                        .Set("manifest_version", 2)
704                        .Set("file_browser_handlers",
705                             extensions::ListBuilder()
706                             .Append(extensions::DictionaryBuilder()
707                                     .Set("id", "open")
708                                     .Set("default_title", "open")
709                                     .Set("file_filters",
710                                          extensions::ListBuilder()
711                                          .Append("filesystem:*.gdoc")))));
712   files_app.SetID(kFileManagerAppId);
713   extension_service_->AddExtension(files_app.Build().get());
714
715   // Find apps for a ".gdoc file". Only the built-in handler of Files.apps
716   // should be found.
717   PathAndMimeTypeSet path_mime_set;
718   std::vector<GURL> file_urls;
719   path_mime_set.insert(
720       std::make_pair(
721           drive::util::GetDriveMountPointPath().AppendASCII("foo.gdoc"),
722           "application/vnd.google-apps.document"));
723   file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.gdoc"));
724
725   std::vector<FullTaskDescriptor> tasks;
726   FindAllTypesOfTasks(&test_profile_,
727                       &drive_app_registry,
728                       path_mime_set,
729                       file_urls,
730                       &tasks);
731   ASSERT_EQ(1U, tasks.size());
732   EXPECT_EQ(kFileManagerAppId, tasks[0].task_descriptor().app_id);
733 }
734
735 }  // namespace file_tasks
736 }  // namespace file_manager.