extension_manifests_unittest.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
1// Copyright (c) 2011 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 "base/command_line.h" 6#include "base/file_path.h" 7#include "base/file_util.h" 8#include "base/memory/scoped_ptr.h" 9#include "base/path_service.h" 10#include "base/string_number_conversions.h" 11#include "base/string_util.h" 12#include "base/utf_string_conversions.h" 13#include "chrome/common/chrome_paths.h" 14#include "chrome/common/chrome_switches.h" 15#include "chrome/common/extensions/extension.h" 16#include "chrome/common/extensions/extension_constants.h" 17#include "chrome/common/extensions/extension_error_utils.h" 18#include "chrome/common/extensions/extension_sidebar_defaults.h" 19#include "chrome/common/extensions/file_browser_handler.h" 20#include "chrome/common/extensions/url_pattern.h" 21#include "content/common/json_value_serializer.h" 22#include "testing/gtest/include/gtest/gtest.h" 23 24namespace errors = extension_manifest_errors; 25namespace keys = extension_manifest_keys; 26 27class ExtensionManifestTest : public testing::Test { 28 public: 29 ExtensionManifestTest() : enable_apps_(true) {} 30 31 protected: 32 DictionaryValue* LoadManifestFile(const std::string& filename, 33 std::string* error) { 34 FilePath path; 35 PathService::Get(chrome::DIR_TEST_DATA, &path); 36 path = path.AppendASCII("extensions") 37 .AppendASCII("manifest_tests") 38 .AppendASCII(filename.c_str()); 39 EXPECT_TRUE(file_util::PathExists(path)); 40 41 JSONFileValueSerializer serializer(path); 42 return static_cast<DictionaryValue*>(serializer.Deserialize(NULL, error)); 43 } 44 45 scoped_refptr<Extension> LoadExtensionWithLocation( 46 DictionaryValue* value, 47 Extension::Location location, 48 bool strict_error_checks, 49 std::string* error) { 50 FilePath path; 51 PathService::Get(chrome::DIR_TEST_DATA, &path); 52 path = path.AppendASCII("extensions").AppendASCII("manifest_tests"); 53 int flags = Extension::NO_FLAGS; 54 if (strict_error_checks) 55 flags |= Extension::STRICT_ERROR_CHECKS; 56 return Extension::Create(path.DirName(), location, *value, flags, error); 57 } 58 59 scoped_refptr<Extension> LoadExtension(const std::string& name, 60 std::string* error) { 61 return LoadExtensionWithLocation(name, Extension::INTERNAL, false, error); 62 } 63 64 scoped_refptr<Extension> LoadExtensionStrict(const std::string& name, 65 std::string* error) { 66 return LoadExtensionWithLocation(name, Extension::INTERNAL, true, error); 67 } 68 69 scoped_refptr<Extension> LoadExtension(DictionaryValue* value, 70 std::string* error) { 71 // Loading as an installed extension disables strict error checks. 72 return LoadExtensionWithLocation(value, Extension::INTERNAL, false, error); 73 } 74 75 scoped_refptr<Extension> LoadExtensionWithLocation( 76 const std::string& name, 77 Extension::Location location, 78 bool strict_error_checks, 79 std::string* error) { 80 scoped_ptr<DictionaryValue> value(LoadManifestFile(name, error)); 81 if (!value.get()) 82 return NULL; 83 return LoadExtensionWithLocation(value.get(), location, 84 strict_error_checks, error); 85 } 86 87 scoped_refptr<Extension> LoadAndExpectSuccess(const std::string& name) { 88 std::string error; 89 scoped_refptr<Extension> extension = LoadExtension(name, &error); 90 EXPECT_TRUE(extension) << name; 91 EXPECT_EQ("", error) << name; 92 return extension; 93 } 94 95 scoped_refptr<Extension> LoadStrictAndExpectSuccess(const std::string& name) { 96 std::string error; 97 scoped_refptr<Extension> extension = LoadExtensionStrict(name, &error); 98 EXPECT_TRUE(extension) << name; 99 EXPECT_EQ("", error) << name; 100 return extension; 101 } 102 103 scoped_refptr<Extension> LoadAndExpectSuccess(DictionaryValue* manifest, 104 const std::string& name) { 105 std::string error; 106 scoped_refptr<Extension> extension = LoadExtension(manifest, &error); 107 EXPECT_TRUE(extension) << "Unexpected success for " << name; 108 EXPECT_EQ("", error) << "Unexpected no error for " << name; 109 return extension; 110 } 111 112 void VerifyExpectedError(Extension* extension, 113 const std::string& name, 114 const std::string& error, 115 const std::string& expected_error) { 116 EXPECT_FALSE(extension) << 117 "Expected failure loading extension '" << name << 118 "', but didn't get one."; 119 EXPECT_TRUE(MatchPattern(error, expected_error)) << name << 120 " expected '" << expected_error << "' but got '" << error << "'"; 121 } 122 123 void LoadAndExpectError(const std::string& name, 124 const std::string& expected_error) { 125 std::string error; 126 scoped_refptr<Extension> extension(LoadExtension(name, &error)); 127 VerifyExpectedError(extension.get(), name, error, expected_error); 128 } 129 130 void LoadAndExpectErrorStrict(const std::string& name, 131 const std::string& expected_error) { 132 std::string error; 133 scoped_refptr<Extension> extension(LoadExtensionStrict(name, &error)); 134 VerifyExpectedError(extension.get(), name, error, expected_error); 135 } 136 137 void LoadAndExpectError(DictionaryValue* manifest, 138 const std::string& name, 139 const std::string& expected_error) { 140 std::string error; 141 scoped_refptr<Extension> extension(LoadExtension(manifest, &error)); 142 VerifyExpectedError(extension.get(), name, error, expected_error); 143 } 144 145 bool enable_apps_; 146}; 147 148TEST_F(ExtensionManifestTest, ValidApp) { 149 scoped_refptr<Extension> extension(LoadAndExpectSuccess("valid_app.json")); 150 ASSERT_EQ(2u, extension->web_extent().patterns().size()); 151 EXPECT_EQ("http://www.google.com/mail/*", 152 extension->web_extent().patterns()[0].GetAsString()); 153 EXPECT_EQ("http://www.google.com/foobar/*", 154 extension->web_extent().patterns()[1].GetAsString()); 155 EXPECT_EQ(extension_misc::LAUNCH_TAB, extension->launch_container()); 156 EXPECT_EQ("http://www.google.com/mail/", extension->launch_web_url()); 157} 158 159TEST_F(ExtensionManifestTest, AppWebUrls) { 160 LoadAndExpectError("web_urls_wrong_type.json", 161 errors::kInvalidWebURLs); 162 LoadAndExpectError( 163 "web_urls_invalid_1.json", 164 ExtensionErrorUtils::FormatErrorMessage( 165 errors::kInvalidWebURL, 166 base::IntToString(0), 167 errors::kExpectString)); 168 169 LoadAndExpectError( 170 "web_urls_invalid_2.json", 171 ExtensionErrorUtils::FormatErrorMessage( 172 errors::kInvalidWebURL, 173 base::IntToString(0), 174 URLPattern::GetParseResultString( 175 URLPattern::PARSE_ERROR_MISSING_SCHEME_SEPARATOR))); 176 177 LoadAndExpectError( 178 "web_urls_invalid_3.json", 179 ExtensionErrorUtils::FormatErrorMessage( 180 errors::kInvalidWebURL, 181 base::IntToString(0), 182 errors::kNoWildCardsInPaths)); 183 184 LoadAndExpectError( 185 "web_urls_invalid_4.json", 186 ExtensionErrorUtils::FormatErrorMessage( 187 errors::kInvalidWebURL, 188 base::IntToString(0), 189 errors::kCannotClaimAllURLsInExtent)); 190 191 LoadAndExpectError( 192 "web_urls_invalid_5.json", 193 ExtensionErrorUtils::FormatErrorMessage( 194 errors::kInvalidWebURL, 195 base::IntToString(1), 196 errors::kCannotClaimAllHostsInExtent)); 197 198 // Ports in app.urls only raise an error when loading as a 199 // developer would. 200 LoadAndExpectSuccess("web_urls_invalid_has_port.json"); 201 LoadAndExpectErrorStrict( 202 "web_urls_invalid_has_port.json", 203 ExtensionErrorUtils::FormatErrorMessage( 204 errors::kInvalidWebURL, 205 base::IntToString(1), 206 URLPattern::GetParseResultString(URLPattern::PARSE_ERROR_HAS_COLON))); 207 208 209 scoped_refptr<Extension> extension( 210 LoadAndExpectSuccess("web_urls_default.json")); 211 ASSERT_EQ(1u, extension->web_extent().patterns().size()); 212 EXPECT_EQ("*://www.google.com/*", 213 extension->web_extent().patterns()[0].GetAsString()); 214} 215 216TEST_F(ExtensionManifestTest, AppLaunchContainer) { 217 scoped_refptr<Extension> extension; 218 219 extension = LoadAndExpectSuccess("launch_tab.json"); 220 EXPECT_EQ(extension_misc::LAUNCH_TAB, extension->launch_container()); 221 222 extension = LoadAndExpectSuccess("launch_panel.json"); 223 EXPECT_EQ(extension_misc::LAUNCH_PANEL, extension->launch_container()); 224 225 extension = LoadAndExpectSuccess("launch_default.json"); 226 EXPECT_EQ(extension_misc::LAUNCH_TAB, extension->launch_container()); 227 228 extension = LoadAndExpectSuccess("launch_width.json"); 229 EXPECT_EQ(640, extension->launch_width()); 230 231 extension = LoadAndExpectSuccess("launch_height.json"); 232 EXPECT_EQ(480, extension->launch_height()); 233 234 LoadAndExpectError("launch_window.json", 235 errors::kInvalidLaunchContainer); 236 LoadAndExpectError("launch_container_invalid_type.json", 237 errors::kInvalidLaunchContainer); 238 LoadAndExpectError("launch_container_invalid_value.json", 239 errors::kInvalidLaunchContainer); 240 LoadAndExpectError("launch_container_without_launch_url.json", 241 errors::kLaunchURLRequired); 242 LoadAndExpectError("launch_width_invalid.json", 243 errors::kInvalidLaunchWidthContainer); 244 LoadAndExpectError("launch_width_negative.json", 245 errors::kInvalidLaunchWidth); 246 LoadAndExpectError("launch_height_invalid.json", 247 errors::kInvalidLaunchHeightContainer); 248 LoadAndExpectError("launch_height_negative.json", 249 errors::kInvalidLaunchHeight); 250} 251 252TEST_F(ExtensionManifestTest, AppLaunchURL) { 253 LoadAndExpectError("launch_path_and_url.json", 254 errors::kLaunchPathAndURLAreExclusive); 255 LoadAndExpectError("launch_path_invalid_type.json", 256 errors::kInvalidLaunchLocalPath); 257 LoadAndExpectError("launch_path_invalid_value.json", 258 errors::kInvalidLaunchLocalPath); 259 LoadAndExpectError("launch_url_invalid_type_1.json", 260 errors::kInvalidLaunchWebURL); 261 LoadAndExpectError("launch_url_invalid_type_2.json", 262 errors::kInvalidLaunchWebURL); 263 LoadAndExpectError("launch_url_invalid_type_3.json", 264 errors::kInvalidLaunchWebURL); 265 266 scoped_refptr<Extension> extension; 267 extension = LoadAndExpectSuccess("launch_local_path.json"); 268 EXPECT_EQ(extension->url().spec() + "launch.html", 269 extension->GetFullLaunchURL().spec()); 270 271 LoadAndExpectError("launch_web_url_relative.json", 272 errors::kInvalidLaunchWebURL); 273 274 extension = LoadAndExpectSuccess("launch_web_url_absolute.json"); 275 EXPECT_EQ(GURL("http://www.google.com/launch.html"), 276 extension->GetFullLaunchURL()); 277} 278 279TEST_F(ExtensionManifestTest, Override) { 280 LoadAndExpectError("override_newtab_and_history.json", 281 errors::kMultipleOverrides); 282 LoadAndExpectError("override_invalid_page.json", 283 errors::kInvalidChromeURLOverrides); 284 285 scoped_refptr<Extension> extension; 286 287 extension = LoadAndExpectSuccess("override_new_tab.json"); 288 EXPECT_EQ(extension->url().spec() + "newtab.html", 289 extension->GetChromeURLOverrides().find("newtab")->second.spec()); 290 291 extension = LoadAndExpectSuccess("override_history.json"); 292 EXPECT_EQ(extension->url().spec() + "history.html", 293 extension->GetChromeURLOverrides().find("history")->second.spec()); 294} 295 296TEST_F(ExtensionManifestTest, ChromeURLPermissionInvalid) { 297 LoadAndExpectError("permission_chrome_url_invalid.json", 298 errors::kInvalidPermissionScheme); 299} 300 301TEST_F(ExtensionManifestTest, ChromeResourcesPermissionValidOnlyForComponents) { 302 LoadAndExpectError("permission_chrome_resources_url.json", 303 errors::kInvalidPermissionScheme); 304 std::string error; 305 scoped_refptr<Extension> extension; 306 extension = LoadExtensionWithLocation( 307 "permission_chrome_resources_url.json", 308 Extension::COMPONENT, 309 true, // Strict error checking 310 &error); 311 EXPECT_EQ("", error); 312} 313 314TEST_F(ExtensionManifestTest, InvalidContentScriptMatchPattern) { 315 316 // chrome:// urls are not allowed. 317 LoadAndExpectError( 318 "content_script_chrome_url_invalid.json", 319 ExtensionErrorUtils::FormatErrorMessage( 320 errors::kInvalidMatch, 321 base::IntToString(0), 322 base::IntToString(0), 323 URLPattern::GetParseResultString( 324 URLPattern::PARSE_ERROR_INVALID_SCHEME))); 325 326 // Match paterns must be strings. 327 LoadAndExpectError( 328 "content_script_match_pattern_not_string.json", 329 ExtensionErrorUtils::FormatErrorMessage( 330 errors::kInvalidMatch, 331 base::IntToString(0), 332 base::IntToString(0), 333 errors::kExpectString)); 334 335 // Ports in match patterns cause an error, but only when loading 336 // in developer mode. 337 LoadAndExpectSuccess("forbid_ports_in_content_scripts.json"); 338 339 // Loading as a developer would should give an error. 340 LoadAndExpectErrorStrict( 341 "forbid_ports_in_content_scripts.json", 342 ExtensionErrorUtils::FormatErrorMessage( 343 errors::kInvalidMatch, 344 base::IntToString(1), 345 base::IntToString(0), 346 URLPattern::GetParseResultString( 347 URLPattern::PARSE_ERROR_HAS_COLON))); 348} 349 350TEST_F(ExtensionManifestTest, ExperimentalPermission) { 351 LoadAndExpectError("experimental.json", errors::kExperimentalFlagRequired); 352 CommandLine old_command_line = *CommandLine::ForCurrentProcess(); 353 CommandLine::ForCurrentProcess()->AppendSwitch( 354 switches::kEnableExperimentalExtensionApis); 355 LoadAndExpectSuccess("experimental.json"); 356 *CommandLine::ForCurrentProcess() = old_command_line; 357} 358 359TEST_F(ExtensionManifestTest, DevToolsExtensions) { 360 LoadAndExpectError("devtools_extension_no_permissions.json", 361 errors::kDevToolsExperimental); 362 LoadAndExpectError("devtools_extension_url_invalid_type.json", 363 errors::kInvalidDevToolsPage); 364 365 CommandLine old_command_line = *CommandLine::ForCurrentProcess(); 366 CommandLine::ForCurrentProcess()->AppendSwitch( 367 switches::kEnableExperimentalExtensionApis); 368 369 scoped_refptr<Extension> extension; 370 extension = LoadAndExpectSuccess("devtools_extension.json"); 371 EXPECT_EQ(extension->url().spec() + "devtools.html", 372 extension->devtools_url().spec()); 373 EXPECT_TRUE(extension->HasEffectiveAccessToAllHosts()); 374 375 *CommandLine::ForCurrentProcess() = old_command_line; 376} 377 378TEST_F(ExtensionManifestTest, Sidebar) { 379 LoadAndExpectError("sidebar.json", 380 errors::kExperimentalFlagRequired); 381 382 CommandLine old_command_line = *CommandLine::ForCurrentProcess(); 383 CommandLine::ForCurrentProcess()->AppendSwitch( 384 switches::kEnableExperimentalExtensionApis); 385 386 LoadAndExpectError("sidebar_no_permissions.json", 387 errors::kSidebarExperimental); 388 389 LoadAndExpectError("sidebar_icon_empty.json", 390 errors::kInvalidSidebarDefaultIconPath); 391 LoadAndExpectError("sidebar_icon_invalid_type.json", 392 errors::kInvalidSidebarDefaultIconPath); 393 LoadAndExpectError("sidebar_page_empty.json", 394 errors::kInvalidSidebarDefaultPage); 395 LoadAndExpectError("sidebar_page_invalid_type.json", 396 errors::kInvalidSidebarDefaultPage); 397 LoadAndExpectError("sidebar_title_invalid_type.json", 398 errors::kInvalidSidebarDefaultTitle); 399 400 scoped_refptr<Extension> extension(LoadAndExpectSuccess("sidebar.json")); 401 ASSERT_TRUE(extension->sidebar_defaults() != NULL); 402 EXPECT_EQ(extension->sidebar_defaults()->default_title(), 403 ASCIIToUTF16("Default title")); 404 EXPECT_EQ(extension->sidebar_defaults()->default_icon_path(), 405 "icon.png"); 406 EXPECT_EQ(extension->url().spec() + "sidebar.html", 407 extension->sidebar_defaults()->default_page().spec()); 408 409 *CommandLine::ForCurrentProcess() = old_command_line; 410} 411 412TEST_F(ExtensionManifestTest, DisallowHybridApps) { 413 LoadAndExpectError("disallow_hybrid_1.json", 414 ExtensionErrorUtils::FormatErrorMessage( 415 errors::kHostedAppsCannotIncludeExtensionFeatures, 416 keys::kBrowserAction)); 417 LoadAndExpectError("disallow_hybrid_2.json", 418 errors::kBackgroundPermissionNeeded); 419} 420 421TEST_F(ExtensionManifestTest, OptionsPageInApps) { 422 scoped_refptr<Extension> extension; 423 424 // Allow options page with absolute URL in hosed apps. 425 extension = LoadAndExpectSuccess("hosted_app_absolute_options.json"); 426 EXPECT_STREQ("http", 427 extension->options_url().scheme().c_str()); 428 EXPECT_STREQ("example.com", 429 extension->options_url().host().c_str()); 430 EXPECT_STREQ("options.html", 431 extension->options_url().ExtractFileName().c_str()); 432 433 // Forbid options page with relative URL in hosted apps. 434 LoadAndExpectError("hosted_app_relative_options.json", 435 errors::kInvalidOptionsPageInHostedApp); 436 437 // Forbid options page with non-(http|https) scheme in hosted app. 438 LoadAndExpectError("hosted_app_file_options.json", 439 errors::kInvalidOptionsPageInHostedApp); 440 441 // Forbid absolute URL for options page in packaged apps. 442 LoadAndExpectError("packaged_app_absolute_options.json", 443 errors::kInvalidOptionsPageExpectUrlInPackage); 444} 445 446TEST_F(ExtensionManifestTest, AllowUnrecognizedPermissions) { 447 std::string error; 448 scoped_ptr<DictionaryValue> manifest( 449 LoadManifestFile("valid_app.json", &error)); 450 ASSERT_TRUE(manifest.get()); 451 452 ListValue *permissions = new ListValue(); 453 manifest->Set(keys::kPermissions, permissions); 454 for (size_t i = 0; i < Extension::kNumPermissions; i++) { 455 const char* name = Extension::kPermissions[i].name; 456 StringValue* p = new StringValue(name); 457 permissions->Clear(); 458 permissions->Append(p); 459 std::string message_name = base::StringPrintf("permission-%s", name); 460 461 // Extensions are allowed to contain unrecognized API permissions, 462 // so there shouldn't be any errors. 463 scoped_refptr<Extension> extension; 464 extension = LoadAndExpectSuccess(manifest.get(), message_name); 465 } 466} 467 468TEST_F(ExtensionManifestTest, NormalizeIconPaths) { 469 scoped_refptr<Extension> extension( 470 LoadAndExpectSuccess("normalize_icon_paths.json")); 471 EXPECT_EQ("16.png", 472 extension->icons().Get(16, ExtensionIconSet::MATCH_EXACTLY)); 473 EXPECT_EQ("48.png", 474 extension->icons().Get(48, ExtensionIconSet::MATCH_EXACTLY)); 475} 476 477TEST_F(ExtensionManifestTest, DisallowMultipleUISurfaces) { 478 LoadAndExpectError("multiple_ui_surfaces_1.json", errors::kOneUISurfaceOnly); 479 LoadAndExpectError("multiple_ui_surfaces_2.json", errors::kOneUISurfaceOnly); 480 LoadAndExpectError("multiple_ui_surfaces_3.json", errors::kOneUISurfaceOnly); 481} 482 483TEST_F(ExtensionManifestTest, ParseHomepageURLs) { 484 scoped_refptr<Extension> extension( 485 LoadAndExpectSuccess("homepage_valid.json")); 486 LoadAndExpectError("homepage_empty.json", 487 extension_manifest_errors::kInvalidHomepageURL); 488 LoadAndExpectError("homepage_invalid.json", 489 extension_manifest_errors::kInvalidHomepageURL); 490} 491 492TEST_F(ExtensionManifestTest, GetHomepageURL) { 493 scoped_refptr<Extension> extension( 494 LoadAndExpectSuccess("homepage_valid.json")); 495 EXPECT_EQ(GURL("http://foo.com#bar"), extension->GetHomepageURL()); 496 497 // The Google Gallery URL ends with the id, which depends on the path, which 498 // can be different in testing, so we just check the part before id. 499 extension = LoadAndExpectSuccess("homepage_google_hosted.json"); 500 EXPECT_TRUE(StartsWithASCII(extension->GetHomepageURL().spec(), 501 "https://chrome.google.com/webstore/detail/", 502 false)); 503 504 extension = LoadAndExpectSuccess("homepage_externally_hosted.json"); 505 EXPECT_EQ(GURL(), extension->GetHomepageURL()); 506} 507 508TEST_F(ExtensionManifestTest, DefaultPathForExtent) { 509 scoped_refptr<Extension> extension( 510 LoadAndExpectSuccess("default_path_for_extent.json")); 511 512 ASSERT_EQ(1u, extension->web_extent().patterns().size()); 513 EXPECT_EQ("/*", extension->web_extent().patterns()[0].path()); 514 EXPECT_TRUE(extension->web_extent().ContainsURL( 515 GURL("http://www.google.com/monkey"))); 516} 517 518TEST_F(ExtensionManifestTest, DefaultLocale) { 519 LoadAndExpectError("default_locale_invalid.json", 520 extension_manifest_errors::kInvalidDefaultLocale); 521 522 scoped_refptr<Extension> extension( 523 LoadAndExpectSuccess("default_locale_valid.json")); 524 EXPECT_EQ("de-AT", extension->default_locale()); 525} 526 527TEST_F(ExtensionManifestTest, TtsProvider) { 528 LoadAndExpectError("tts_provider_invalid_1.json", 529 extension_manifest_errors::kInvalidTts); 530 LoadAndExpectError("tts_provider_invalid_2.json", 531 extension_manifest_errors::kInvalidTtsVoices); 532 LoadAndExpectError("tts_provider_invalid_3.json", 533 extension_manifest_errors::kInvalidTtsVoices); 534 LoadAndExpectError("tts_provider_invalid_4.json", 535 extension_manifest_errors::kInvalidTtsVoicesVoiceName); 536 LoadAndExpectError("tts_provider_invalid_5.json", 537 extension_manifest_errors::kInvalidTtsVoicesLocale); 538 LoadAndExpectError("tts_provider_invalid_6.json", 539 extension_manifest_errors::kInvalidTtsVoicesLocale); 540 LoadAndExpectError("tts_provider_invalid_7.json", 541 extension_manifest_errors::kInvalidTtsVoicesGender); 542 543 scoped_refptr<Extension> extension( 544 LoadAndExpectSuccess("tts_provider_valid.json")); 545 546 ASSERT_EQ(1u, extension->tts_voices().size()); 547 EXPECT_EQ("name", extension->tts_voices()[0].voice_name); 548 EXPECT_EQ("en-US", extension->tts_voices()[0].locale); 549 EXPECT_EQ("female", extension->tts_voices()[0].gender); 550} 551 552TEST_F(ExtensionManifestTest, ForbidPortsInPermissions) { 553 // Loading as a user would shoud not trigger an error. 554 LoadAndExpectSuccess("forbid_ports_in_permissions.json"); 555 556 // Ideally, loading as a developer would give an error. 557 // To ensure that we do not error out on a valid permission 558 // in a future version of chrome, validation is to loose 559 // to flag this case. 560 LoadStrictAndExpectSuccess("forbid_ports_in_permissions.json"); 561} 562 563TEST_F(ExtensionManifestTest, IsolatedApps) { 564 // Requires --enable-experimental-app-manifests 565 scoped_refptr<Extension> extension( 566 LoadAndExpectSuccess("isolated_app_valid.json")); 567 EXPECT_FALSE(extension->is_storage_isolated()); 568 569 CommandLine old_command_line = *CommandLine::ForCurrentProcess(); 570 CommandLine::ForCurrentProcess()->AppendSwitch( 571 switches::kEnableExperimentalAppManifests); 572 scoped_refptr<Extension> extension2( 573 LoadAndExpectSuccess("isolated_app_valid.json")); 574 EXPECT_TRUE(extension2->is_storage_isolated()); 575 *CommandLine::ForCurrentProcess() = old_command_line; 576} 577 578 579TEST_F(ExtensionManifestTest, FileBrowserHandlers) { 580 LoadAndExpectError("filebrowser_invalid_actions_1.json", 581 errors::kInvalidFileBrowserHandler); 582 LoadAndExpectError("filebrowser_invalid_actions_2.json", 583 errors::kInvalidFileBrowserHandler); 584 LoadAndExpectError("filebrowser_invalid_action_id.json", 585 errors::kInvalidPageActionId); 586 LoadAndExpectError("filebrowser_invalid_action_title.json", 587 errors::kInvalidPageActionDefaultTitle); 588 LoadAndExpectError("filebrowser_invalid_action_id.json", 589 errors::kInvalidPageActionId); 590 LoadAndExpectError("filebrowser_invalid_file_filters_1.json", 591 errors::kInvalidFileFiltersList); 592 LoadAndExpectError("filebrowser_invalid_file_filters_2.json", 593 ExtensionErrorUtils::FormatErrorMessage( 594 errors::kInvalidFileFilterValue, base::IntToString(0))); 595 LoadAndExpectError("filebrowser_invalid_file_filters_url.json", 596 ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidURLPatternError, 597 "http:*.html")); 598 599 scoped_refptr<Extension> extension( 600 LoadAndExpectSuccess("filebrowser_valid.json")); 601 ASSERT_TRUE(extension->file_browser_handlers() != NULL); 602 ASSERT_EQ(extension->file_browser_handlers()->size(), 1U); 603 const FileBrowserHandler* action = 604 extension->file_browser_handlers()->at(0).get(); 605 EXPECT_EQ(action->title(), "Default title"); 606 EXPECT_EQ(action->icon_path(), "icon.png"); 607 const FileBrowserHandler::PatternList& patterns = action->file_url_patterns(); 608 ASSERT_EQ(patterns.size(), 1U); 609 ASSERT_TRUE(action->MatchesURL( 610 GURL("filesystem:chrome-extension://foo/local/test.txt"))); 611} 612