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