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/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_system.h" 26#include "extensions/common/extension_builder.h" 27#include "google_apis/drive/drive_api_parser.h" 28#include "testing/gtest/include/gtest/gtest.h" 29#include "url/gurl.h" 30 31namespace file_manager { 32namespace file_tasks { 33namespace { 34 35// Registers the default task preferences. Used for testing 36// ChooseAndSetDefaultTask(). 37void 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. 48void UpdateDefaultTaskPreferences(TestingPrefServiceSimple* pref_service, 49 const base::DictionaryValue& mime_types, 50 const base::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 59TEST(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 77TEST(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 95TEST(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 104TEST(FileManagerFileTasksTest, MakeDriveAppTaskId) { 105 EXPECT_EQ("app-id|drive|open-with", MakeDriveAppTaskId("app-id")); 106} 107 108TEST(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 115TEST(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 123TEST(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 131TEST(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 139TEST(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 149TEST(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 159TEST(FileManagerFileTasksTest, ParseTaskID_Invalid) { 160 TaskDescriptor task; 161 EXPECT_FALSE(ParseTaskID("invalid", &task)); 162} 163 164TEST(FileManagerFileTasksTest, ParseTaskID_UnknownTaskType) { 165 TaskDescriptor task; 166 EXPECT_FALSE(ParseTaskID("app-id|unknown|action-id", &task)); 167} 168 169TEST(FileManagerFileTasksTest, FindDriveAppTasks) { 170 TestingProfile profile; 171 // For DriveAppRegistry, which checks CurrentlyOn(BrowserThread::UI). 172 content::TestBrowserThreadBundle thread_bundle; 173 174 // Foo.app can handle "text/plain" and "text/html" 175 scoped_ptr<google_apis::AppResource> foo_app(new google_apis::AppResource); 176 foo_app->set_product_id("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_id("bar_app_id"); 188 bar_app->set_application_id("bar_app_id"); 189 bar_app->set_name("Bar"); 190 bar_app->set_object_type("bar_object_type"); 191 ScopedVector<std::string> bar_mime_types; 192 bar_mime_types.push_back(new std::string("text/plain")); 193 bar_app->set_primary_mimetypes(bar_mime_types.Pass()); 194 195 // Prepare DriveAppRegistry from Foo.app and Bar.app. 196 ScopedVector<google_apis::AppResource> app_resources; 197 app_resources.push_back(foo_app.release()); 198 app_resources.push_back(bar_app.release()); 199 google_apis::AppList app_list; 200 app_list.set_items(app_resources.Pass()); 201 drive::DriveAppRegistry drive_app_registry(NULL); 202 drive_app_registry.UpdateFromAppList(app_list); 203 204 // Find apps for a "text/plain" file. Foo.app and Bar.app should be found. 205 PathAndMimeTypeSet path_mime_set; 206 path_mime_set.insert( 207 std::make_pair( 208 drive::util::GetDriveMountPointPath(&profile).AppendASCII("foo.txt"), 209 "text/plain")); 210 std::vector<FullTaskDescriptor> tasks; 211 FindDriveAppTasks(drive_app_registry, 212 path_mime_set, 213 &tasks); 214 ASSERT_EQ(2U, tasks.size()); 215 // Sort the app IDs, as the order is not guaranteed. 216 std::vector<std::string> app_ids; 217 app_ids.push_back(tasks[0].task_descriptor().app_id); 218 app_ids.push_back(tasks[1].task_descriptor().app_id); 219 std::sort(app_ids.begin(), app_ids.end()); 220 // Confirm that both Foo.app and Bar.app are found. 221 EXPECT_EQ("bar_app_id", app_ids[0]); 222 EXPECT_EQ("foo_app_id", app_ids[1]); 223 224 // Find apps for "text/plain" and "text/html" files. Only Foo.app should be 225 // found. 226 path_mime_set.clear(); 227 path_mime_set.insert( 228 std::make_pair( 229 drive::util::GetDriveMountPointPath(&profile).AppendASCII("foo.txt"), 230 "text/plain")); 231 path_mime_set.insert( 232 std::make_pair( 233 drive::util::GetDriveMountPointPath(&profile).AppendASCII("foo.html"), 234 "text/html")); 235 tasks.clear(); 236 FindDriveAppTasks(drive_app_registry, 237 path_mime_set, 238 &tasks); 239 ASSERT_EQ(1U, tasks.size()); 240 // Confirm that only Foo.app is found. 241 EXPECT_EQ("foo_app_id", tasks[0].task_descriptor().app_id); 242 243 // Add a "text/plain" file not on Drive. No tasks should be found. 244 path_mime_set.insert( 245 std::make_pair(base::FilePath::FromUTF8Unsafe("not_on_drive.txt"), 246 "text/plain")); 247 tasks.clear(); 248 FindDriveAppTasks(drive_app_registry, 249 path_mime_set, 250 &tasks); 251 // Confirm no tasks are found. 252 ASSERT_TRUE(tasks.empty()); 253} 254 255// Test that the right task is chosen from multiple choices per mime types 256// and file extensions. 257TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_MultipleTasks) { 258 TestingPrefServiceSimple pref_service; 259 RegisterDefaultTaskPreferences(&pref_service); 260 261 // Text.app and Nice.app were found for "foo.txt". 262 TaskDescriptor text_app_task("text-app-id", 263 TASK_TYPE_FILE_HANDLER, 264 "action-id"); 265 TaskDescriptor nice_app_task("nice-app-id", 266 TASK_TYPE_FILE_HANDLER, 267 "action-id"); 268 std::vector<FullTaskDescriptor> tasks; 269 tasks.push_back(FullTaskDescriptor( 270 text_app_task, 271 "Text.app", 272 GURL("http://example.com/text_app.png"), 273 false /* is_default */)); 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 PathAndMimeTypeSet path_mime_set; 280 path_mime_set.insert(std::make_pair( 281 base::FilePath::FromUTF8Unsafe("foo.txt"), 282 "text/plain")); 283 284 // None of them should be chosen as default, as nothing is set in the 285 // preferences. 286 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks); 287 EXPECT_FALSE(tasks[0].is_default()); 288 EXPECT_FALSE(tasks[1].is_default()); 289 290 // Set Text.app as default for "text/plain" in the preferences. 291 base::DictionaryValue empty; 292 base::DictionaryValue mime_types; 293 mime_types.SetStringWithoutPathExpansion( 294 "text/plain", 295 TaskDescriptorToId(text_app_task)); 296 UpdateDefaultTaskPreferences(&pref_service, mime_types, empty); 297 298 // Text.app should be chosen as default. 299 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks); 300 EXPECT_TRUE(tasks[0].is_default()); 301 EXPECT_FALSE(tasks[1].is_default()); 302 303 // Change it back to non-default for testing further. 304 tasks[0].set_is_default(false); 305 306 // Clear the preferences and make sure none of them are default. 307 UpdateDefaultTaskPreferences(&pref_service, empty, empty); 308 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks); 309 EXPECT_FALSE(tasks[0].is_default()); 310 EXPECT_FALSE(tasks[1].is_default()); 311 312 // Set Nice.app as default for ".txt" in the preferences. 313 base::DictionaryValue suffixes; 314 suffixes.SetStringWithoutPathExpansion( 315 ".txt", 316 TaskDescriptorToId(nice_app_task)); 317 UpdateDefaultTaskPreferences(&pref_service, empty, suffixes); 318 319 // Now Nice.app should be chosen as default. 320 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks); 321 EXPECT_FALSE(tasks[0].is_default()); 322 EXPECT_TRUE(tasks[1].is_default()); 323} 324 325// Test that Files.app's internal file browser handler is chosen as default 326// even if nothing is set in the preferences. 327TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_FallbackFileBrowser) { 328 TestingPrefServiceSimple pref_service; 329 RegisterDefaultTaskPreferences(&pref_service); 330 331 // Files.app's internal file browser handler was found for "foo.txt". 332 TaskDescriptor files_app_task(kFileManagerAppId, 333 TASK_TYPE_FILE_BROWSER_HANDLER, 334 "view-in-browser"); 335 std::vector<FullTaskDescriptor> tasks; 336 tasks.push_back(FullTaskDescriptor( 337 files_app_task, 338 "View in browser", 339 GURL("http://example.com/some_icon.png"), 340 false /* is_default */)); 341 PathAndMimeTypeSet path_mime_set; 342 path_mime_set.insert(std::make_pair( 343 base::FilePath::FromUTF8Unsafe("foo.txt"), 344 "text/plain")); 345 346 // The internal file browser handler should be chosen as default, as it's a 347 // fallback file browser handler. 348 ChooseAndSetDefaultTask(pref_service, path_mime_set, &tasks); 349 EXPECT_TRUE(tasks[0].is_default()); 350} 351 352// Test using the test extension system, which needs lots of setup. 353class FileManagerFileTasksComplexTest : public testing::Test { 354 protected: 355 FileManagerFileTasksComplexTest() 356 : command_line_(CommandLine::NO_PROGRAM), 357 extension_service_(NULL) { 358 extensions::TestExtensionSystem* test_extension_system = 359 static_cast<extensions::TestExtensionSystem*>( 360 extensions::ExtensionSystem::Get(&test_profile_)); 361 extension_service_ = test_extension_system->CreateExtensionService( 362 &command_line_, 363 base::FilePath() /* install_directory */, 364 false /* autoupdate_enabled*/); 365 } 366 367 content::TestBrowserThreadBundle thread_bundle_; 368 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 369 chromeos::ScopedTestCrosSettings test_cros_settings_; 370 chromeos::ScopedTestUserManager test_user_manager_; 371 TestingProfile test_profile_; 372 CommandLine command_line_; 373 ExtensionService* extension_service_; // Owned by test_profile_; 374}; 375 376// The basic logic is similar to a test case for FindDriveAppTasks above. 377TEST_F(FileManagerFileTasksComplexTest, FindFileHandlerTasks) { 378 // Random IDs generated by 379 // % ruby -le 'print (0...32).to_a.map{(?a + rand(16)).chr}.join' 380 const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph"; 381 const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca"; 382 383 // Foo.app can handle "text/plain" and "text/html". 384 extensions::ExtensionBuilder foo_app; 385 foo_app.SetManifest(extensions::DictionaryBuilder() 386 .Set("name", "Foo") 387 .Set("version", "1.0.0") 388 .Set("manifest_version", 2) 389 .Set("app", 390 extensions::DictionaryBuilder() 391 .Set("background", 392 extensions::DictionaryBuilder() 393 .Set("scripts", 394 extensions::ListBuilder() 395 .Append("background.js")))) 396 .Set("file_handlers", 397 extensions::DictionaryBuilder() 398 .Set("text", 399 extensions::DictionaryBuilder() 400 .Set("title", "Text") 401 .Set("types", 402 extensions::ListBuilder() 403 .Append("text/plain") 404 .Append("text/html"))))); 405 foo_app.SetID(kFooId); 406 extension_service_->AddExtension(foo_app.Build().get()); 407 408 // Bar.app can only handle "text/plain". 409 extensions::ExtensionBuilder bar_app; 410 bar_app.SetManifest(extensions::DictionaryBuilder() 411 .Set("name", "Bar") 412 .Set("version", "1.0.0") 413 .Set("manifest_version", 2) 414 .Set("app", 415 extensions::DictionaryBuilder() 416 .Set("background", 417 extensions::DictionaryBuilder() 418 .Set("scripts", 419 extensions::ListBuilder() 420 .Append("background.js")))) 421 .Set("file_handlers", 422 extensions::DictionaryBuilder() 423 .Set("text", 424 extensions::DictionaryBuilder() 425 .Set("title", "Text") 426 .Set("types", 427 extensions::ListBuilder() 428 .Append("text/plain"))))); 429 bar_app.SetID(kBarId); 430 extension_service_->AddExtension(bar_app.Build().get()); 431 432 // Find apps for a "text/plain" file. Foo.app and Bar.app should be found. 433 PathAndMimeTypeSet path_mime_set; 434 path_mime_set.insert( 435 std::make_pair( 436 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII( 437 "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(&test_profile_).AppendASCII( 458 "foo.txt"), 459 "text/plain")); 460 path_mime_set.insert( 461 std::make_pair( 462 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII( 463 "foo.html"), 464 "text/html")); 465 tasks.clear(); 466 FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks); 467 ASSERT_EQ(1U, tasks.size()); 468 // Confirm that only Foo.app is found. 469 EXPECT_EQ(kFooId, tasks[0].task_descriptor().app_id); 470 471 // Add an "image/png" file. No tasks should be found. 472 path_mime_set.insert( 473 std::make_pair(base::FilePath::FromUTF8Unsafe("foo.png"), 474 "image/png")); 475 tasks.clear(); 476 FindFileHandlerTasks(&test_profile_, path_mime_set, &tasks); 477 // Confirm no tasks are found. 478 ASSERT_TRUE(tasks.empty()); 479} 480 481// The basic logic is similar to a test case for FindDriveAppTasks above. 482TEST_F(FileManagerFileTasksComplexTest, FindFileBrowserHandlerTasks) { 483 // Copied from FindFileHandlerTasks test above. 484 const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph"; 485 const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca"; 486 487 // Foo.app can handle ".txt" and ".html". 488 // This one is an extension, and has "file_browser_handlers" 489 extensions::ExtensionBuilder foo_app; 490 foo_app.SetManifest(extensions::DictionaryBuilder() 491 .Set("name", "Foo") 492 .Set("version", "1.0.0") 493 .Set("manifest_version", 2) 494 .Set("file_browser_handlers", 495 extensions::ListBuilder() 496 .Append(extensions::DictionaryBuilder() 497 .Set("id", "open") 498 .Set("default_title", "open") 499 .Set("file_filters", 500 extensions::ListBuilder() 501 .Append("filesystem:*.txt") 502 .Append("filesystem:*.html"))))); 503 foo_app.SetID(kFooId); 504 extension_service_->AddExtension(foo_app.Build().get()); 505 506 // Bar.app can only handle ".txt". 507 extensions::ExtensionBuilder bar_app; 508 bar_app.SetManifest(extensions::DictionaryBuilder() 509 .Set("name", "Bar") 510 .Set("version", "1.0.0") 511 .Set("manifest_version", 2) 512 .Set("file_browser_handlers", 513 extensions::ListBuilder() 514 .Append(extensions::DictionaryBuilder() 515 .Set("id", "open") 516 .Set("default_title", "open") 517 .Set("file_filters", 518 extensions::ListBuilder() 519 .Append("filesystem:*.txt"))))); 520 bar_app.SetID(kBarId); 521 extension_service_->AddExtension(bar_app.Build().get()); 522 523 // Find apps for a ".txt" file. Foo.app and Bar.app should be found. 524 std::vector<GURL> file_urls; 525 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt")); 526 527 std::vector<FullTaskDescriptor> tasks; 528 FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks); 529 ASSERT_EQ(2U, tasks.size()); 530 // Sort the app IDs, as the order is not guaranteed. 531 std::vector<std::string> app_ids; 532 app_ids.push_back(tasks[0].task_descriptor().app_id); 533 app_ids.push_back(tasks[1].task_descriptor().app_id); 534 std::sort(app_ids.begin(), app_ids.end()); 535 // Confirm that both Foo.app and Bar.app are found. 536 EXPECT_EQ(kFooId, app_ids[0]); 537 EXPECT_EQ(kBarId, app_ids[1]); 538 539 // Find apps for ".txt" and ".html" files. Only Foo.app should be found. 540 file_urls.clear(); 541 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt")); 542 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.html")); 543 tasks.clear(); 544 FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks); 545 ASSERT_EQ(1U, tasks.size()); 546 // Confirm that only Foo.app is found. 547 EXPECT_EQ(kFooId, tasks[0].task_descriptor().app_id); 548 549 // Add an ".png" file. No tasks should be found. 550 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.png")); 551 tasks.clear(); 552 FindFileBrowserHandlerTasks(&test_profile_, file_urls, &tasks); 553 // Confirm no tasks are found. 554 ASSERT_TRUE(tasks.empty()); 555} 556 557// Test that all kinds of apps (file handler, file browser handler, and Drive 558// app) are returned. 559TEST_F(FileManagerFileTasksComplexTest, FindAllTypesOfTasks) { 560 // kFooId and kBarId copied from FindFileHandlerTasks test above. 561 const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph"; 562 const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca"; 563 const char kBazId[] = "plifkpkakemokpflgbnnigcoldgcbdmc"; 564 565 // Foo.app can handle "text/plain". 566 // This is a packaged app (file handler). 567 extensions::ExtensionBuilder foo_app; 568 foo_app.SetManifest(extensions::DictionaryBuilder() 569 .Set("name", "Foo") 570 .Set("version", "1.0.0") 571 .Set("manifest_version", 2) 572 .Set("app", 573 extensions::DictionaryBuilder() 574 .Set("background", 575 extensions::DictionaryBuilder() 576 .Set("scripts", 577 extensions::ListBuilder() 578 .Append("background.js")))) 579 .Set("file_handlers", 580 extensions::DictionaryBuilder() 581 .Set("text", 582 extensions::DictionaryBuilder() 583 .Set("title", "Text") 584 .Set("types", 585 extensions::ListBuilder() 586 .Append("text/plain"))))); 587 foo_app.SetID(kFooId); 588 extension_service_->AddExtension(foo_app.Build().get()); 589 590 // Bar.app can only handle ".txt". 591 // This is an extension (file browser handler). 592 extensions::ExtensionBuilder bar_app; 593 bar_app.SetManifest(extensions::DictionaryBuilder() 594 .Set("name", "Bar") 595 .Set("version", "1.0.0") 596 .Set("manifest_version", 2) 597 .Set("file_browser_handlers", 598 extensions::ListBuilder() 599 .Append(extensions::DictionaryBuilder() 600 .Set("id", "open") 601 .Set("default_title", "open") 602 .Set("file_filters", 603 extensions::ListBuilder() 604 .Append("filesystem:*.txt"))))); 605 bar_app.SetID(kBarId); 606 extension_service_->AddExtension(bar_app.Build().get()); 607 608 // Baz.app can handle "text/plain". 609 // This is a Drive app. 610 scoped_ptr<google_apis::AppResource> baz_app(new google_apis::AppResource); 611 baz_app->set_product_id("baz_app_id"); 612 baz_app->set_application_id(kBazId); 613 baz_app->set_name("Baz"); 614 baz_app->set_object_type("baz_object_type"); 615 ScopedVector<std::string> baz_mime_types; 616 baz_mime_types.push_back(new std::string("text/plain")); 617 baz_app->set_primary_mimetypes(baz_mime_types.Pass()); 618 // Set up DriveAppRegistry. 619 ScopedVector<google_apis::AppResource> app_resources; 620 app_resources.push_back(baz_app.release()); 621 google_apis::AppList app_list; 622 app_list.set_items(app_resources.Pass()); 623 drive::DriveAppRegistry drive_app_registry(NULL); 624 drive_app_registry.UpdateFromAppList(app_list); 625 626 // Find apps for "foo.txt". All apps should be found. 627 PathAndMimeTypeSet path_mime_set; 628 std::vector<GURL> file_urls; 629 path_mime_set.insert( 630 std::make_pair( 631 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII( 632 "foo.txt"), 633 "text/plain")); 634 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.txt")); 635 636 std::vector<FullTaskDescriptor> tasks; 637 FindAllTypesOfTasks(&test_profile_, 638 &drive_app_registry, 639 path_mime_set, 640 file_urls, 641 &tasks); 642 ASSERT_EQ(3U, tasks.size()); 643 644 // Sort the app IDs, as the order is not guaranteed. 645 std::vector<std::string> app_ids; 646 app_ids.push_back(tasks[0].task_descriptor().app_id); 647 app_ids.push_back(tasks[1].task_descriptor().app_id); 648 app_ids.push_back(tasks[2].task_descriptor().app_id); 649 std::sort(app_ids.begin(), app_ids.end()); 650 // Confirm that all apps are found. 651 EXPECT_EQ(kFooId, app_ids[0]); 652 EXPECT_EQ(kBarId, app_ids[1]); 653 EXPECT_EQ(kBazId, app_ids[2]); 654} 655 656TEST_F(FileManagerFileTasksComplexTest, FindAllTypesOfTasks_GoogleDocument) { 657 // kFooId and kBarId copied from FindFileHandlerTasks test above. 658 const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph"; 659 const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca"; 660 661 // Foo.app can handle ".gdoc" files. 662 scoped_ptr<google_apis::AppResource> foo_app(new google_apis::AppResource); 663 foo_app->set_product_id("foo_app"); 664 foo_app->set_application_id(kFooId); 665 foo_app->set_name("Foo"); 666 foo_app->set_object_type("foo_object_type"); 667 ScopedVector<std::string> foo_extensions; 668 foo_extensions.push_back(new std::string("gdoc")); // Not ".gdoc" 669 foo_app->set_primary_file_extensions(foo_extensions.Pass()); 670 671 // Prepare DriveAppRegistry from Foo.app. 672 ScopedVector<google_apis::AppResource> app_resources; 673 app_resources.push_back(foo_app.release()); 674 google_apis::AppList app_list; 675 app_list.set_items(app_resources.Pass()); 676 drive::DriveAppRegistry drive_app_registry(NULL); 677 drive_app_registry.UpdateFromAppList(app_list); 678 679 // Bar.app can handle ".gdoc" files. 680 // This is an extension (file browser handler). 681 extensions::ExtensionBuilder bar_app; 682 bar_app.SetManifest(extensions::DictionaryBuilder() 683 .Set("name", "Bar") 684 .Set("version", "1.0.0") 685 .Set("manifest_version", 2) 686 .Set("file_browser_handlers", 687 extensions::ListBuilder() 688 .Append(extensions::DictionaryBuilder() 689 .Set("id", "open") 690 .Set("default_title", "open") 691 .Set("file_filters", 692 extensions::ListBuilder() 693 .Append("filesystem:*.gdoc"))))); 694 bar_app.SetID(kBarId); 695 extension_service_->AddExtension(bar_app.Build().get()); 696 697 // Files.app can handle ".gdoc" files. 698 // The ID "kFileManagerAppId" used here is precisely the one that identifies 699 // the Chrome OS Files.app application. 700 extensions::ExtensionBuilder files_app; 701 files_app.SetManifest(extensions::DictionaryBuilder() 702 .Set("name", "Files") 703 .Set("version", "1.0.0") 704 .Set("manifest_version", 2) 705 .Set("file_browser_handlers", 706 extensions::ListBuilder() 707 .Append(extensions::DictionaryBuilder() 708 .Set("id", "open") 709 .Set("default_title", "open") 710 .Set("file_filters", 711 extensions::ListBuilder() 712 .Append("filesystem:*.gdoc"))))); 713 files_app.SetID(kFileManagerAppId); 714 extension_service_->AddExtension(files_app.Build().get()); 715 716 // Find apps for a ".gdoc file". Only the built-in handler of Files.apps 717 // should be found. 718 PathAndMimeTypeSet path_mime_set; 719 std::vector<GURL> file_urls; 720 path_mime_set.insert( 721 std::make_pair( 722 drive::util::GetDriveMountPointPath(&test_profile_).AppendASCII( 723 "foo.gdoc"), 724 "application/vnd.google-apps.document")); 725 file_urls.push_back(GURL("filesystem:chrome-extension://id/dir/foo.gdoc")); 726 727 std::vector<FullTaskDescriptor> tasks; 728 FindAllTypesOfTasks(&test_profile_, 729 &drive_app_registry, 730 path_mime_set, 731 file_urls, 732 &tasks); 733 ASSERT_EQ(1U, tasks.size()); 734 EXPECT_EQ(kFileManagerAppId, tasks[0].task_descriptor().app_id); 735} 736 737} // namespace file_tasks 738} // namespace file_manager. 739