| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/command_line.h" |
| #include "base/file_path.h" |
| #include "base/file_util.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/path_service.h" |
| #include "base/string_number_conversions.h" |
| #include "base/string_util.h" |
| #include "base/utf_string_conversions.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/extensions/extension_constants.h" |
| #include "chrome/common/extensions/extension_error_utils.h" |
| #include "chrome/common/extensions/extension_sidebar_defaults.h" |
| #include "chrome/common/extensions/file_browser_handler.h" |
| #include "chrome/common/extensions/url_pattern.h" |
| #include "content/common/json_value_serializer.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace errors = extension_manifest_errors; |
| namespace keys = extension_manifest_keys; |
| |
| class ExtensionManifestTest : public testing::Test { |
| public: |
| ExtensionManifestTest() : enable_apps_(true) {} |
| |
| protected: |
| DictionaryValue* LoadManifestFile(const std::string& filename, |
| std::string* error) { |
| FilePath path; |
| PathService::Get(chrome::DIR_TEST_DATA, &path); |
| path = path.AppendASCII("extensions") |
| .AppendASCII("manifest_tests") |
| .AppendASCII(filename.c_str()); |
| EXPECT_TRUE(file_util::PathExists(path)); |
| |
| JSONFileValueSerializer serializer(path); |
| return static_cast<DictionaryValue*>(serializer.Deserialize(NULL, error)); |
| } |
| |
| scoped_refptr<Extension> LoadExtensionWithLocation( |
| DictionaryValue* value, |
| Extension::Location location, |
| bool strict_error_checks, |
| std::string* error) { |
| FilePath path; |
| PathService::Get(chrome::DIR_TEST_DATA, &path); |
| path = path.AppendASCII("extensions").AppendASCII("manifest_tests"); |
| int flags = Extension::NO_FLAGS; |
| if (strict_error_checks) |
| flags |= Extension::STRICT_ERROR_CHECKS; |
| return Extension::Create(path.DirName(), location, *value, flags, error); |
| } |
| |
| scoped_refptr<Extension> LoadExtension(const std::string& name, |
| std::string* error) { |
| return LoadExtensionWithLocation(name, Extension::INTERNAL, false, error); |
| } |
| |
| scoped_refptr<Extension> LoadExtensionStrict(const std::string& name, |
| std::string* error) { |
| return LoadExtensionWithLocation(name, Extension::INTERNAL, true, error); |
| } |
| |
| scoped_refptr<Extension> LoadExtension(DictionaryValue* value, |
| std::string* error) { |
| // Loading as an installed extension disables strict error checks. |
| return LoadExtensionWithLocation(value, Extension::INTERNAL, false, error); |
| } |
| |
| scoped_refptr<Extension> LoadExtensionWithLocation( |
| const std::string& name, |
| Extension::Location location, |
| bool strict_error_checks, |
| std::string* error) { |
| scoped_ptr<DictionaryValue> value(LoadManifestFile(name, error)); |
| if (!value.get()) |
| return NULL; |
| return LoadExtensionWithLocation(value.get(), location, |
| strict_error_checks, error); |
| } |
| |
| scoped_refptr<Extension> LoadAndExpectSuccess(const std::string& name) { |
| std::string error; |
| scoped_refptr<Extension> extension = LoadExtension(name, &error); |
| EXPECT_TRUE(extension) << name; |
| EXPECT_EQ("", error) << name; |
| return extension; |
| } |
| |
| scoped_refptr<Extension> LoadStrictAndExpectSuccess(const std::string& name) { |
| std::string error; |
| scoped_refptr<Extension> extension = LoadExtensionStrict(name, &error); |
| EXPECT_TRUE(extension) << name; |
| EXPECT_EQ("", error) << name; |
| return extension; |
| } |
| |
| scoped_refptr<Extension> LoadAndExpectSuccess(DictionaryValue* manifest, |
| const std::string& name) { |
| std::string error; |
| scoped_refptr<Extension> extension = LoadExtension(manifest, &error); |
| EXPECT_TRUE(extension) << "Unexpected success for " << name; |
| EXPECT_EQ("", error) << "Unexpected no error for " << name; |
| return extension; |
| } |
| |
| void VerifyExpectedError(Extension* extension, |
| const std::string& name, |
| const std::string& error, |
| const std::string& expected_error) { |
| EXPECT_FALSE(extension) << |
| "Expected failure loading extension '" << name << |
| "', but didn't get one."; |
| EXPECT_TRUE(MatchPattern(error, expected_error)) << name << |
| " expected '" << expected_error << "' but got '" << error << "'"; |
| } |
| |
| void LoadAndExpectError(const std::string& name, |
| const std::string& expected_error) { |
| std::string error; |
| scoped_refptr<Extension> extension(LoadExtension(name, &error)); |
| VerifyExpectedError(extension.get(), name, error, expected_error); |
| } |
| |
| void LoadAndExpectErrorStrict(const std::string& name, |
| const std::string& expected_error) { |
| std::string error; |
| scoped_refptr<Extension> extension(LoadExtensionStrict(name, &error)); |
| VerifyExpectedError(extension.get(), name, error, expected_error); |
| } |
| |
| void LoadAndExpectError(DictionaryValue* manifest, |
| const std::string& name, |
| const std::string& expected_error) { |
| std::string error; |
| scoped_refptr<Extension> extension(LoadExtension(manifest, &error)); |
| VerifyExpectedError(extension.get(), name, error, expected_error); |
| } |
| |
| bool enable_apps_; |
| }; |
| |
| TEST_F(ExtensionManifestTest, ValidApp) { |
| scoped_refptr<Extension> extension(LoadAndExpectSuccess("valid_app.json")); |
| ASSERT_EQ(2u, extension->web_extent().patterns().size()); |
| EXPECT_EQ("http://www.google.com/mail/*", |
| extension->web_extent().patterns()[0].GetAsString()); |
| EXPECT_EQ("http://www.google.com/foobar/*", |
| extension->web_extent().patterns()[1].GetAsString()); |
| EXPECT_EQ(extension_misc::LAUNCH_TAB, extension->launch_container()); |
| EXPECT_EQ("http://www.google.com/mail/", extension->launch_web_url()); |
| } |
| |
| TEST_F(ExtensionManifestTest, AppWebUrls) { |
| LoadAndExpectError("web_urls_wrong_type.json", |
| errors::kInvalidWebURLs); |
| LoadAndExpectError( |
| "web_urls_invalid_1.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidWebURL, |
| base::IntToString(0), |
| errors::kExpectString)); |
| |
| LoadAndExpectError( |
| "web_urls_invalid_2.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidWebURL, |
| base::IntToString(0), |
| URLPattern::GetParseResultString( |
| URLPattern::PARSE_ERROR_MISSING_SCHEME_SEPARATOR))); |
| |
| LoadAndExpectError( |
| "web_urls_invalid_3.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidWebURL, |
| base::IntToString(0), |
| errors::kNoWildCardsInPaths)); |
| |
| LoadAndExpectError( |
| "web_urls_invalid_4.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidWebURL, |
| base::IntToString(0), |
| errors::kCannotClaimAllURLsInExtent)); |
| |
| LoadAndExpectError( |
| "web_urls_invalid_5.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidWebURL, |
| base::IntToString(1), |
| errors::kCannotClaimAllHostsInExtent)); |
| |
| // Ports in app.urls only raise an error when loading as a |
| // developer would. |
| LoadAndExpectSuccess("web_urls_invalid_has_port.json"); |
| LoadAndExpectErrorStrict( |
| "web_urls_invalid_has_port.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidWebURL, |
| base::IntToString(1), |
| URLPattern::GetParseResultString(URLPattern::PARSE_ERROR_HAS_COLON))); |
| |
| |
| scoped_refptr<Extension> extension( |
| LoadAndExpectSuccess("web_urls_default.json")); |
| ASSERT_EQ(1u, extension->web_extent().patterns().size()); |
| EXPECT_EQ("*://www.google.com/*", |
| extension->web_extent().patterns()[0].GetAsString()); |
| } |
| |
| TEST_F(ExtensionManifestTest, AppLaunchContainer) { |
| scoped_refptr<Extension> extension; |
| |
| extension = LoadAndExpectSuccess("launch_tab.json"); |
| EXPECT_EQ(extension_misc::LAUNCH_TAB, extension->launch_container()); |
| |
| extension = LoadAndExpectSuccess("launch_panel.json"); |
| EXPECT_EQ(extension_misc::LAUNCH_PANEL, extension->launch_container()); |
| |
| extension = LoadAndExpectSuccess("launch_default.json"); |
| EXPECT_EQ(extension_misc::LAUNCH_TAB, extension->launch_container()); |
| |
| extension = LoadAndExpectSuccess("launch_width.json"); |
| EXPECT_EQ(640, extension->launch_width()); |
| |
| extension = LoadAndExpectSuccess("launch_height.json"); |
| EXPECT_EQ(480, extension->launch_height()); |
| |
| LoadAndExpectError("launch_window.json", |
| errors::kInvalidLaunchContainer); |
| LoadAndExpectError("launch_container_invalid_type.json", |
| errors::kInvalidLaunchContainer); |
| LoadAndExpectError("launch_container_invalid_value.json", |
| errors::kInvalidLaunchContainer); |
| LoadAndExpectError("launch_container_without_launch_url.json", |
| errors::kLaunchURLRequired); |
| LoadAndExpectError("launch_width_invalid.json", |
| errors::kInvalidLaunchWidthContainer); |
| LoadAndExpectError("launch_width_negative.json", |
| errors::kInvalidLaunchWidth); |
| LoadAndExpectError("launch_height_invalid.json", |
| errors::kInvalidLaunchHeightContainer); |
| LoadAndExpectError("launch_height_negative.json", |
| errors::kInvalidLaunchHeight); |
| } |
| |
| TEST_F(ExtensionManifestTest, AppLaunchURL) { |
| LoadAndExpectError("launch_path_and_url.json", |
| errors::kLaunchPathAndURLAreExclusive); |
| LoadAndExpectError("launch_path_invalid_type.json", |
| errors::kInvalidLaunchLocalPath); |
| LoadAndExpectError("launch_path_invalid_value.json", |
| errors::kInvalidLaunchLocalPath); |
| LoadAndExpectError("launch_url_invalid_type_1.json", |
| errors::kInvalidLaunchWebURL); |
| LoadAndExpectError("launch_url_invalid_type_2.json", |
| errors::kInvalidLaunchWebURL); |
| LoadAndExpectError("launch_url_invalid_type_3.json", |
| errors::kInvalidLaunchWebURL); |
| |
| scoped_refptr<Extension> extension; |
| extension = LoadAndExpectSuccess("launch_local_path.json"); |
| EXPECT_EQ(extension->url().spec() + "launch.html", |
| extension->GetFullLaunchURL().spec()); |
| |
| LoadAndExpectError("launch_web_url_relative.json", |
| errors::kInvalidLaunchWebURL); |
| |
| extension = LoadAndExpectSuccess("launch_web_url_absolute.json"); |
| EXPECT_EQ(GURL("http://www.google.com/launch.html"), |
| extension->GetFullLaunchURL()); |
| } |
| |
| TEST_F(ExtensionManifestTest, Override) { |
| LoadAndExpectError("override_newtab_and_history.json", |
| errors::kMultipleOverrides); |
| LoadAndExpectError("override_invalid_page.json", |
| errors::kInvalidChromeURLOverrides); |
| |
| scoped_refptr<Extension> extension; |
| |
| extension = LoadAndExpectSuccess("override_new_tab.json"); |
| EXPECT_EQ(extension->url().spec() + "newtab.html", |
| extension->GetChromeURLOverrides().find("newtab")->second.spec()); |
| |
| extension = LoadAndExpectSuccess("override_history.json"); |
| EXPECT_EQ(extension->url().spec() + "history.html", |
| extension->GetChromeURLOverrides().find("history")->second.spec()); |
| } |
| |
| TEST_F(ExtensionManifestTest, ChromeURLPermissionInvalid) { |
| LoadAndExpectError("permission_chrome_url_invalid.json", |
| errors::kInvalidPermissionScheme); |
| } |
| |
| TEST_F(ExtensionManifestTest, ChromeResourcesPermissionValidOnlyForComponents) { |
| LoadAndExpectError("permission_chrome_resources_url.json", |
| errors::kInvalidPermissionScheme); |
| std::string error; |
| scoped_refptr<Extension> extension; |
| extension = LoadExtensionWithLocation( |
| "permission_chrome_resources_url.json", |
| Extension::COMPONENT, |
| true, // Strict error checking |
| &error); |
| EXPECT_EQ("", error); |
| } |
| |
| TEST_F(ExtensionManifestTest, InvalidContentScriptMatchPattern) { |
| |
| // chrome:// urls are not allowed. |
| LoadAndExpectError( |
| "content_script_chrome_url_invalid.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidMatch, |
| base::IntToString(0), |
| base::IntToString(0), |
| URLPattern::GetParseResultString( |
| URLPattern::PARSE_ERROR_INVALID_SCHEME))); |
| |
| // Match paterns must be strings. |
| LoadAndExpectError( |
| "content_script_match_pattern_not_string.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidMatch, |
| base::IntToString(0), |
| base::IntToString(0), |
| errors::kExpectString)); |
| |
| // Ports in match patterns cause an error, but only when loading |
| // in developer mode. |
| LoadAndExpectSuccess("forbid_ports_in_content_scripts.json"); |
| |
| // Loading as a developer would should give an error. |
| LoadAndExpectErrorStrict( |
| "forbid_ports_in_content_scripts.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidMatch, |
| base::IntToString(1), |
| base::IntToString(0), |
| URLPattern::GetParseResultString( |
| URLPattern::PARSE_ERROR_HAS_COLON))); |
| } |
| |
| TEST_F(ExtensionManifestTest, ExperimentalPermission) { |
| LoadAndExpectError("experimental.json", errors::kExperimentalFlagRequired); |
| CommandLine old_command_line = *CommandLine::ForCurrentProcess(); |
| CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kEnableExperimentalExtensionApis); |
| LoadAndExpectSuccess("experimental.json"); |
| *CommandLine::ForCurrentProcess() = old_command_line; |
| } |
| |
| TEST_F(ExtensionManifestTest, DevToolsExtensions) { |
| LoadAndExpectError("devtools_extension_no_permissions.json", |
| errors::kDevToolsExperimental); |
| LoadAndExpectError("devtools_extension_url_invalid_type.json", |
| errors::kInvalidDevToolsPage); |
| |
| CommandLine old_command_line = *CommandLine::ForCurrentProcess(); |
| CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kEnableExperimentalExtensionApis); |
| |
| scoped_refptr<Extension> extension; |
| extension = LoadAndExpectSuccess("devtools_extension.json"); |
| EXPECT_EQ(extension->url().spec() + "devtools.html", |
| extension->devtools_url().spec()); |
| EXPECT_TRUE(extension->HasEffectiveAccessToAllHosts()); |
| |
| *CommandLine::ForCurrentProcess() = old_command_line; |
| } |
| |
| TEST_F(ExtensionManifestTest, Sidebar) { |
| LoadAndExpectError("sidebar.json", |
| errors::kExperimentalFlagRequired); |
| |
| CommandLine old_command_line = *CommandLine::ForCurrentProcess(); |
| CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kEnableExperimentalExtensionApis); |
| |
| LoadAndExpectError("sidebar_no_permissions.json", |
| errors::kSidebarExperimental); |
| |
| LoadAndExpectError("sidebar_icon_empty.json", |
| errors::kInvalidSidebarDefaultIconPath); |
| LoadAndExpectError("sidebar_icon_invalid_type.json", |
| errors::kInvalidSidebarDefaultIconPath); |
| LoadAndExpectError("sidebar_page_empty.json", |
| errors::kInvalidSidebarDefaultPage); |
| LoadAndExpectError("sidebar_page_invalid_type.json", |
| errors::kInvalidSidebarDefaultPage); |
| LoadAndExpectError("sidebar_title_invalid_type.json", |
| errors::kInvalidSidebarDefaultTitle); |
| |
| scoped_refptr<Extension> extension(LoadAndExpectSuccess("sidebar.json")); |
| ASSERT_TRUE(extension->sidebar_defaults() != NULL); |
| EXPECT_EQ(extension->sidebar_defaults()->default_title(), |
| ASCIIToUTF16("Default title")); |
| EXPECT_EQ(extension->sidebar_defaults()->default_icon_path(), |
| "icon.png"); |
| EXPECT_EQ(extension->url().spec() + "sidebar.html", |
| extension->sidebar_defaults()->default_page().spec()); |
| |
| *CommandLine::ForCurrentProcess() = old_command_line; |
| } |
| |
| TEST_F(ExtensionManifestTest, DisallowHybridApps) { |
| LoadAndExpectError("disallow_hybrid_1.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kHostedAppsCannotIncludeExtensionFeatures, |
| keys::kBrowserAction)); |
| LoadAndExpectError("disallow_hybrid_2.json", |
| errors::kBackgroundPermissionNeeded); |
| } |
| |
| TEST_F(ExtensionManifestTest, OptionsPageInApps) { |
| scoped_refptr<Extension> extension; |
| |
| // Allow options page with absolute URL in hosed apps. |
| extension = LoadAndExpectSuccess("hosted_app_absolute_options.json"); |
| EXPECT_STREQ("http", |
| extension->options_url().scheme().c_str()); |
| EXPECT_STREQ("example.com", |
| extension->options_url().host().c_str()); |
| EXPECT_STREQ("options.html", |
| extension->options_url().ExtractFileName().c_str()); |
| |
| // Forbid options page with relative URL in hosted apps. |
| LoadAndExpectError("hosted_app_relative_options.json", |
| errors::kInvalidOptionsPageInHostedApp); |
| |
| // Forbid options page with non-(http|https) scheme in hosted app. |
| LoadAndExpectError("hosted_app_file_options.json", |
| errors::kInvalidOptionsPageInHostedApp); |
| |
| // Forbid absolute URL for options page in packaged apps. |
| LoadAndExpectError("packaged_app_absolute_options.json", |
| errors::kInvalidOptionsPageExpectUrlInPackage); |
| } |
| |
| TEST_F(ExtensionManifestTest, AllowUnrecognizedPermissions) { |
| std::string error; |
| scoped_ptr<DictionaryValue> manifest( |
| LoadManifestFile("valid_app.json", &error)); |
| ASSERT_TRUE(manifest.get()); |
| |
| ListValue *permissions = new ListValue(); |
| manifest->Set(keys::kPermissions, permissions); |
| for (size_t i = 0; i < Extension::kNumPermissions; i++) { |
| const char* name = Extension::kPermissions[i].name; |
| StringValue* p = new StringValue(name); |
| permissions->Clear(); |
| permissions->Append(p); |
| std::string message_name = base::StringPrintf("permission-%s", name); |
| |
| // Extensions are allowed to contain unrecognized API permissions, |
| // so there shouldn't be any errors. |
| scoped_refptr<Extension> extension; |
| extension = LoadAndExpectSuccess(manifest.get(), message_name); |
| } |
| } |
| |
| TEST_F(ExtensionManifestTest, NormalizeIconPaths) { |
| scoped_refptr<Extension> extension( |
| LoadAndExpectSuccess("normalize_icon_paths.json")); |
| EXPECT_EQ("16.png", |
| extension->icons().Get(16, ExtensionIconSet::MATCH_EXACTLY)); |
| EXPECT_EQ("48.png", |
| extension->icons().Get(48, ExtensionIconSet::MATCH_EXACTLY)); |
| } |
| |
| TEST_F(ExtensionManifestTest, DisallowMultipleUISurfaces) { |
| LoadAndExpectError("multiple_ui_surfaces_1.json", errors::kOneUISurfaceOnly); |
| LoadAndExpectError("multiple_ui_surfaces_2.json", errors::kOneUISurfaceOnly); |
| LoadAndExpectError("multiple_ui_surfaces_3.json", errors::kOneUISurfaceOnly); |
| } |
| |
| TEST_F(ExtensionManifestTest, ParseHomepageURLs) { |
| scoped_refptr<Extension> extension( |
| LoadAndExpectSuccess("homepage_valid.json")); |
| LoadAndExpectError("homepage_empty.json", |
| extension_manifest_errors::kInvalidHomepageURL); |
| LoadAndExpectError("homepage_invalid.json", |
| extension_manifest_errors::kInvalidHomepageURL); |
| } |
| |
| TEST_F(ExtensionManifestTest, GetHomepageURL) { |
| scoped_refptr<Extension> extension( |
| LoadAndExpectSuccess("homepage_valid.json")); |
| EXPECT_EQ(GURL("http://foo.com#bar"), extension->GetHomepageURL()); |
| |
| // The Google Gallery URL ends with the id, which depends on the path, which |
| // can be different in testing, so we just check the part before id. |
| extension = LoadAndExpectSuccess("homepage_google_hosted.json"); |
| EXPECT_TRUE(StartsWithASCII(extension->GetHomepageURL().spec(), |
| "https://chrome.google.com/webstore/detail/", |
| false)); |
| |
| extension = LoadAndExpectSuccess("homepage_externally_hosted.json"); |
| EXPECT_EQ(GURL(), extension->GetHomepageURL()); |
| } |
| |
| TEST_F(ExtensionManifestTest, DefaultPathForExtent) { |
| scoped_refptr<Extension> extension( |
| LoadAndExpectSuccess("default_path_for_extent.json")); |
| |
| ASSERT_EQ(1u, extension->web_extent().patterns().size()); |
| EXPECT_EQ("/*", extension->web_extent().patterns()[0].path()); |
| EXPECT_TRUE(extension->web_extent().ContainsURL( |
| GURL("http://www.google.com/monkey"))); |
| } |
| |
| TEST_F(ExtensionManifestTest, DefaultLocale) { |
| LoadAndExpectError("default_locale_invalid.json", |
| extension_manifest_errors::kInvalidDefaultLocale); |
| |
| scoped_refptr<Extension> extension( |
| LoadAndExpectSuccess("default_locale_valid.json")); |
| EXPECT_EQ("de-AT", extension->default_locale()); |
| } |
| |
| TEST_F(ExtensionManifestTest, TtsProvider) { |
| LoadAndExpectError("tts_provider_invalid_1.json", |
| extension_manifest_errors::kInvalidTts); |
| LoadAndExpectError("tts_provider_invalid_2.json", |
| extension_manifest_errors::kInvalidTtsVoices); |
| LoadAndExpectError("tts_provider_invalid_3.json", |
| extension_manifest_errors::kInvalidTtsVoices); |
| LoadAndExpectError("tts_provider_invalid_4.json", |
| extension_manifest_errors::kInvalidTtsVoicesVoiceName); |
| LoadAndExpectError("tts_provider_invalid_5.json", |
| extension_manifest_errors::kInvalidTtsVoicesLocale); |
| LoadAndExpectError("tts_provider_invalid_6.json", |
| extension_manifest_errors::kInvalidTtsVoicesLocale); |
| LoadAndExpectError("tts_provider_invalid_7.json", |
| extension_manifest_errors::kInvalidTtsVoicesGender); |
| |
| scoped_refptr<Extension> extension( |
| LoadAndExpectSuccess("tts_provider_valid.json")); |
| |
| ASSERT_EQ(1u, extension->tts_voices().size()); |
| EXPECT_EQ("name", extension->tts_voices()[0].voice_name); |
| EXPECT_EQ("en-US", extension->tts_voices()[0].locale); |
| EXPECT_EQ("female", extension->tts_voices()[0].gender); |
| } |
| |
| TEST_F(ExtensionManifestTest, ForbidPortsInPermissions) { |
| // Loading as a user would shoud not trigger an error. |
| LoadAndExpectSuccess("forbid_ports_in_permissions.json"); |
| |
| // Ideally, loading as a developer would give an error. |
| // To ensure that we do not error out on a valid permission |
| // in a future version of chrome, validation is to loose |
| // to flag this case. |
| LoadStrictAndExpectSuccess("forbid_ports_in_permissions.json"); |
| } |
| |
| TEST_F(ExtensionManifestTest, IsolatedApps) { |
| // Requires --enable-experimental-app-manifests |
| scoped_refptr<Extension> extension( |
| LoadAndExpectSuccess("isolated_app_valid.json")); |
| EXPECT_FALSE(extension->is_storage_isolated()); |
| |
| CommandLine old_command_line = *CommandLine::ForCurrentProcess(); |
| CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kEnableExperimentalAppManifests); |
| scoped_refptr<Extension> extension2( |
| LoadAndExpectSuccess("isolated_app_valid.json")); |
| EXPECT_TRUE(extension2->is_storage_isolated()); |
| *CommandLine::ForCurrentProcess() = old_command_line; |
| } |
| |
| |
| TEST_F(ExtensionManifestTest, FileBrowserHandlers) { |
| LoadAndExpectError("filebrowser_invalid_actions_1.json", |
| errors::kInvalidFileBrowserHandler); |
| LoadAndExpectError("filebrowser_invalid_actions_2.json", |
| errors::kInvalidFileBrowserHandler); |
| LoadAndExpectError("filebrowser_invalid_action_id.json", |
| errors::kInvalidPageActionId); |
| LoadAndExpectError("filebrowser_invalid_action_title.json", |
| errors::kInvalidPageActionDefaultTitle); |
| LoadAndExpectError("filebrowser_invalid_action_id.json", |
| errors::kInvalidPageActionId); |
| LoadAndExpectError("filebrowser_invalid_file_filters_1.json", |
| errors::kInvalidFileFiltersList); |
| LoadAndExpectError("filebrowser_invalid_file_filters_2.json", |
| ExtensionErrorUtils::FormatErrorMessage( |
| errors::kInvalidFileFilterValue, base::IntToString(0))); |
| LoadAndExpectError("filebrowser_invalid_file_filters_url.json", |
| ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidURLPatternError, |
| "http:*.html")); |
| |
| scoped_refptr<Extension> extension( |
| LoadAndExpectSuccess("filebrowser_valid.json")); |
| ASSERT_TRUE(extension->file_browser_handlers() != NULL); |
| ASSERT_EQ(extension->file_browser_handlers()->size(), 1U); |
| const FileBrowserHandler* action = |
| extension->file_browser_handlers()->at(0).get(); |
| EXPECT_EQ(action->title(), "Default title"); |
| EXPECT_EQ(action->icon_path(), "icon.png"); |
| const FileBrowserHandler::PatternList& patterns = action->file_url_patterns(); |
| ASSERT_EQ(patterns.size(), 1U); |
| ASSERT_TRUE(action->MatchesURL( |
| GURL("filesystem:chrome-extension://foo/local/test.txt"))); |
| } |