Allow extensions on chrome:// URLs, when flag is set and permission is explicitly requested in the manifest.
BUG=174183 Review URL: https://chromiumcodereview.appspot.com/12792005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@189586 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
chrome
app
browser
common
test
data
extensions
manifest_tests
extensions/common
@ -6319,6 +6319,12 @@ Keep your key file in a safe place. You will need it to create new versions of y
|
||||
<message name="IDS_FLAGS_EXPERIMENTAL_EXTENSION_APIS_DESCRIPTION" desc="Description of the 'Experimental Extension APIs' lab.">
|
||||
Enables experimental extension APIs. Note that the extension gallery doesn't allow you to upload extensions that use experimental APIs.
|
||||
</message>
|
||||
<message name="IDS_FLAGS_EXTENSIONS_ON_CHROME_URLS_NAME" desc="Name of the 'Extensions on chrome:// URLs' lab">
|
||||
Extensions on chrome:// URLs
|
||||
</message>
|
||||
<message name="IDS_FLAGS_EXTENSIONS_ON_CHROME_URLS_DESCRIPTION" desc="Description of the 'Extensions on chrome:// URLs' lab">
|
||||
Enables running extensions on chrome:// URLs, where extensions explicitly request this permission.
|
||||
</message>
|
||||
<message name="IDS_FLAGS_ACTION_BOX_NAME" desc="Name of the 'Action Box' lab.">
|
||||
Action box
|
||||
</message>
|
||||
|
@ -466,6 +466,13 @@ const Experiment kExperiments[] = {
|
||||
kOsDesktop,
|
||||
SINGLE_VALUE_TYPE(switches::kEnableExperimentalExtensionApis)
|
||||
},
|
||||
{
|
||||
"extensions-on-chrome-urls",
|
||||
IDS_FLAGS_EXTENSIONS_ON_CHROME_URLS_NAME,
|
||||
IDS_FLAGS_EXTENSIONS_ON_CHROME_URLS_DESCRIPTION,
|
||||
kOsAll,
|
||||
SINGLE_VALUE_TYPE(switches::kExtensionsOnChromeURLs)
|
||||
},
|
||||
{
|
||||
"action-box",
|
||||
IDS_FLAGS_ACTION_BOX_NAME,
|
||||
|
@ -1170,6 +1170,7 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
|
||||
switches::kEnablePasswordGeneration,
|
||||
switches::kEnablePnacl,
|
||||
switches::kEnableWatchdog,
|
||||
switches::kExtensionsOnChromeURLs,
|
||||
switches::kMemoryProfiling,
|
||||
switches::kMessageLoopHistogrammer,
|
||||
switches::kNoJsRandomness,
|
||||
|
@ -41,7 +41,7 @@ void ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) {
|
||||
if (IsGranted(extension))
|
||||
return;
|
||||
|
||||
URLPattern pattern(UserScript::kValidUserScriptSchemes);
|
||||
URLPattern pattern(UserScript::ValidUserScriptSchemes());
|
||||
if (pattern.Parse(web_contents()->GetURL().spec()) !=
|
||||
URLPattern::PARSE_SUCCESS) {
|
||||
// Pattern parsing could fail if this is an unsupported URL e.g. chrome://.
|
||||
|
@ -325,7 +325,7 @@ CrxInstallerError CrxInstaller::AllowInstall(const Extension* extension) {
|
||||
// For self-hosted apps, verify that the entire extent is on the same
|
||||
// host (or a subdomain of the host) the download happened from. There's
|
||||
// no way for us to verify that the app controls any other hosts.
|
||||
URLPattern pattern(UserScript::kValidUserScriptSchemes);
|
||||
URLPattern pattern(UserScript::ValidUserScriptSchemes());
|
||||
pattern.SetHost(download_url_.host());
|
||||
pattern.SetMatchSubdomains(true);
|
||||
|
||||
|
@ -544,7 +544,7 @@ PermissionSet* ExtensionPrefs::ReadExtensionPrefPermissionSet(
|
||||
URLPatternSet scriptable_hosts;
|
||||
ReadExtensionPrefURLPatternSet(
|
||||
extension_id, JoinPrefs(pref_key, kPrefScriptableHosts),
|
||||
&scriptable_hosts, UserScript::kValidUserScriptSchemes);
|
||||
&scriptable_hosts, UserScript::ValidUserScriptSchemes());
|
||||
|
||||
return new PermissionSet(apis, explicit_hosts, scriptable_hosts);
|
||||
}
|
||||
|
@ -117,12 +117,12 @@ bool UserScriptMaster::ScriptReloader::ParseMetadataHeader(
|
||||
} else if (GetDeclarationValue(line, kDescriptionDeclaration, &value)) {
|
||||
script->set_description(value);
|
||||
} else if (GetDeclarationValue(line, kMatchDeclaration, &value)) {
|
||||
URLPattern pattern(UserScript::kValidUserScriptSchemes);
|
||||
URLPattern pattern(UserScript::ValidUserScriptSchemes());
|
||||
if (URLPattern::PARSE_SUCCESS != pattern.Parse(value))
|
||||
return false;
|
||||
script->add_url_pattern(pattern);
|
||||
} else if (GetDeclarationValue(line, kExcludeMatchDeclaration, &value)) {
|
||||
URLPattern exclude(UserScript::kValidUserScriptSchemes);
|
||||
URLPattern exclude(UserScript::ValidUserScriptSchemes());
|
||||
if (URLPattern::PARSE_SUCCESS != exclude.Parse(value))
|
||||
return false;
|
||||
script->add_exclude_url_pattern(exclude);
|
||||
|
@ -27,6 +27,7 @@ void ShowBadFlagsPrompt(Browser* browser) {
|
||||
// Browser plugin is dangerous on regular pages because it breaks the Same
|
||||
// Origin Policy.
|
||||
switches::kEnableBrowserPluginForAllViewTypes,
|
||||
switches::kExtensionsOnChromeURLs,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -500,6 +500,11 @@ const char kEnableExtensionActivityUI[] = "enable-extension-activity-ui";
|
||||
// Enables or disables showing extensions in the action box.
|
||||
const char kExtensionsInActionBox[] = "extensions-in-action-box";
|
||||
|
||||
// Enables or disables running extensions on chrome:// URLs.
|
||||
// Extensions still need to explicitly request access to chrome:// URLs in the
|
||||
// manifest.
|
||||
const char kExtensionsOnChromeURLs[] = "extensions-on-chrome-urls";
|
||||
|
||||
// By default, cookies are not allowed on file://. They are needed for testing,
|
||||
// for example page cycler and layout tests. See bug 1157243.
|
||||
const char kEnableFileCookies[] = "enable-file-cookies";
|
||||
|
@ -182,6 +182,7 @@ extern const char kEnableUserAlternateProtocolPorts[];
|
||||
extern const char kEnableWatchdog[];
|
||||
extern const char kEnableWebSocketOverSpdy[];
|
||||
extern const char kExtensionsInActionBox[];
|
||||
extern const char kExtensionsOnChromeURLs[];
|
||||
extern const char kEventPageIdleTime[];
|
||||
extern const char kEventPageSuspendingTime[];
|
||||
extern const char kExplicitlyAllowedPorts[];
|
||||
|
@ -271,7 +271,7 @@ void ExtensionAPI::LoadSchema(const std::string& name,
|
||||
std::string pattern;
|
||||
CHECK(matches->GetString(i, &pattern));
|
||||
pattern_set.AddPattern(
|
||||
URLPattern(UserScript::kValidUserScriptSchemes, pattern));
|
||||
URLPattern(UserScript::ValidUserScriptSchemes(), pattern));
|
||||
}
|
||||
url_matching_apis_[schema_namespace] = pattern_set;
|
||||
}
|
||||
|
@ -219,8 +219,11 @@ const char Extension::kMimeType[] = "application/x-chrome-extension";
|
||||
const int Extension::kValidWebExtentSchemes =
|
||||
URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS;
|
||||
|
||||
const int Extension::kValidHostPermissionSchemes =
|
||||
UserScript::kValidUserScriptSchemes | URLPattern::SCHEME_CHROMEUI;
|
||||
const int Extension::kValidHostPermissionSchemes = URLPattern::SCHEME_CHROMEUI |
|
||||
URLPattern::SCHEME_HTTP |
|
||||
URLPattern::SCHEME_HTTPS |
|
||||
URLPattern::SCHEME_FILE |
|
||||
URLPattern::SCHEME_FTP;
|
||||
|
||||
Extension::Requirements::Requirements()
|
||||
: webgl(false),
|
||||
@ -592,26 +595,50 @@ bool Extension::ParsePermissions(const char* key,
|
||||
URLPattern pattern = URLPattern(kAllowedSchemes);
|
||||
URLPattern::ParseResult parse_result = pattern.Parse(permission_str);
|
||||
if (parse_result == URLPattern::PARSE_SUCCESS) {
|
||||
// The path component is not used for host permissions, so we force it
|
||||
// to match all paths.
|
||||
pattern.SetPath("/*");
|
||||
int valid_schemes = pattern.valid_schemes();
|
||||
if (pattern.MatchesScheme(chrome::kFileScheme) &&
|
||||
!CanExecuteScriptEverywhere()) {
|
||||
wants_file_access_ = true;
|
||||
if (!(creation_flags_ & ALLOW_FILE_ACCESS))
|
||||
valid_schemes &= ~URLPattern::SCHEME_FILE;
|
||||
}
|
||||
|
||||
if (pattern.scheme() != chrome::kChromeUIScheme &&
|
||||
!CanExecuteScriptEverywhere()) {
|
||||
// Keep chrome:// in allowed schemes only if it's explicitly requested
|
||||
// or CanExecuteScriptEverywhere is true. If the
|
||||
// extensions_on_chrome_urls flag is not set, CanSpecifyHostPermission
|
||||
// will fail, so don't check the flag here.
|
||||
valid_schemes &= ~URLPattern::SCHEME_CHROMEUI;
|
||||
}
|
||||
pattern.SetValidSchemes(valid_schemes);
|
||||
|
||||
if (!CanSpecifyHostPermission(pattern, *api_permissions)) {
|
||||
// TODO(aboxhall): make a warning (see line 633)
|
||||
*error = ErrorUtils::FormatErrorMessageUTF16(
|
||||
errors::kInvalidPermissionScheme, permission_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The path component is not used for host permissions, so we force it
|
||||
// to match all paths.
|
||||
pattern.SetPath("/*");
|
||||
host_permissions->AddPattern(pattern);
|
||||
|
||||
if (pattern.MatchesScheme(chrome::kFileScheme) &&
|
||||
!CanExecuteScriptEverywhere()) {
|
||||
wants_file_access_ = true;
|
||||
if (!(creation_flags_ & ALLOW_FILE_ACCESS)) {
|
||||
pattern.SetValidSchemes(
|
||||
pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
|
||||
// We need to make sure all_urls matches chrome://favicon and
|
||||
// (maybe) chrome://thumbnail, so add them back in to host_permissions
|
||||
// separately.
|
||||
if (pattern.match_all_urls()) {
|
||||
host_permissions->AddPattern(
|
||||
URLPattern(URLPattern::SCHEME_CHROMEUI,
|
||||
chrome::kChromeUIFaviconURL));
|
||||
if (api_permissions->find(APIPermission::kExperimental) !=
|
||||
api_permissions->end()) {
|
||||
host_permissions->AddPattern(
|
||||
URLPattern(URLPattern::SCHEME_CHROMEUI,
|
||||
chrome::kChromeUIThumbnailURL));
|
||||
}
|
||||
}
|
||||
|
||||
host_permissions->AddPattern(pattern);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -666,13 +693,6 @@ bool Extension::CanSilentlyIncreasePermissions() const {
|
||||
}
|
||||
|
||||
bool Extension::HasHostPermission(const GURL& url) const {
|
||||
if (url.SchemeIs(chrome::kChromeUIScheme) &&
|
||||
url.host() != chrome::kChromeUIFaviconHost &&
|
||||
url.host() != chrome::kChromeUIThumbnailHost &&
|
||||
location() != Manifest::COMPONENT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
base::AutoLock auto_lock(runtime_data_lock_);
|
||||
return runtime_data_.GetActivePermissions()->
|
||||
HasExplicitAccessToOrigin(url);
|
||||
@ -805,9 +825,12 @@ bool Extension::CanExecuteScriptOnPage(const GURL& document_url,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (document_url.SchemeIs(chrome::kChromeUIScheme) &&
|
||||
!CanExecuteScriptEverywhere()) {
|
||||
return false;
|
||||
if (!CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kExtensionsOnChromeURLs)) {
|
||||
if (document_url.SchemeIs(chrome::kChromeUIScheme) &&
|
||||
!CanExecuteScriptEverywhere()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (top_frame_url.SchemeIs(extensions::kExtensionScheme) &&
|
||||
@ -1964,6 +1987,7 @@ bool Extension::LoadExtensionFeatures(string16* error) {
|
||||
bool Extension::LoadContentScripts(string16* error) {
|
||||
if (!manifest_->HasKey(keys::kContentScripts))
|
||||
return true;
|
||||
|
||||
const ListValue* list_value;
|
||||
if (!manifest_->GetList(keys::kContentScripts, &list_value)) {
|
||||
*error = ASCIIToUTF16(errors::kInvalidContentScriptsList);
|
||||
@ -1981,6 +2005,7 @@ bool Extension::LoadContentScripts(string16* error) {
|
||||
UserScript script;
|
||||
if (!LoadUserScriptHelper(content_script, i, error, &script))
|
||||
return false; // Failed to parse script context definition.
|
||||
|
||||
script.set_extension_id(id());
|
||||
if (converted_from_user_script_) {
|
||||
script.set_emulate_greasemonkey(true);
|
||||
@ -2106,9 +2131,8 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
|
||||
return false;
|
||||
}
|
||||
|
||||
URLPattern pattern(UserScript::kValidUserScriptSchemes);
|
||||
if (CanExecuteScriptEverywhere())
|
||||
pattern.SetValidSchemes(URLPattern::SCHEME_ALL);
|
||||
URLPattern pattern(
|
||||
UserScript::ValidUserScriptSchemes(CanExecuteScriptEverywhere()));
|
||||
|
||||
URLPattern::ParseResult parse_result = pattern.Parse(match_str);
|
||||
if (parse_result != URLPattern::PARSE_SUCCESS) {
|
||||
@ -2120,6 +2144,17 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(aboxhall): check for webstore
|
||||
if (!CanExecuteScriptEverywhere() &&
|
||||
pattern.scheme() != chrome::kChromeUIScheme) {
|
||||
// Exclude SCHEME_CHROMEUI unless it's been explicitly requested.
|
||||
// If the --extensions-on-chrome-urls flag has not been passed, requesting
|
||||
// a chrome:// url will cause a parse failure above, so there's no need to
|
||||
// check the flag here.
|
||||
pattern.SetValidSchemes(
|
||||
pattern.valid_schemes() & ~URLPattern::SCHEME_CHROMEUI);
|
||||
}
|
||||
|
||||
if (pattern.MatchesScheme(chrome::kFileScheme) &&
|
||||
!CanExecuteScriptEverywhere()) {
|
||||
wants_file_access_ = true;
|
||||
@ -2153,9 +2188,9 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
|
||||
return false;
|
||||
}
|
||||
|
||||
URLPattern pattern(UserScript::kValidUserScriptSchemes);
|
||||
if (CanExecuteScriptEverywhere())
|
||||
pattern.SetValidSchemes(URLPattern::SCHEME_ALL);
|
||||
int valid_schemes =
|
||||
UserScript::ValidUserScriptSchemes(CanExecuteScriptEverywhere());
|
||||
URLPattern pattern(valid_schemes);
|
||||
URLPattern::ParseResult parse_result = pattern.Parse(match_str);
|
||||
if (parse_result != URLPattern::PARSE_SUCCESS) {
|
||||
*error = ErrorUtils::FormatErrorMessageUTF16(
|
||||
@ -2359,6 +2394,12 @@ bool Extension::CanSpecifyHostPermission(const URLPattern& pattern,
|
||||
if (CanExecuteScriptEverywhere())
|
||||
return true;
|
||||
|
||||
if (CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kExtensionsOnChromeURLs))
|
||||
return true;
|
||||
|
||||
// TODO(aboxhall): return from_webstore() when webstore handles blocking
|
||||
// extensions which request chrome:// urls
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "chrome/common/extensions/extension.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/file_util.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/format_macros.h"
|
||||
@ -13,6 +14,7 @@
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/utf_string_conversions.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
#include "chrome/common/extensions/api/commands/commands_handler.h"
|
||||
#include "chrome/common/extensions/api/plugins/plugins_handler.h"
|
||||
#include "chrome/common/extensions/background_info.h"
|
||||
@ -657,11 +659,10 @@ class ExtensionScriptAndCaptureVisibleTest : public testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(ExtensionScriptAndCaptureVisibleTest, Permissions) {
|
||||
scoped_refptr<Extension> extension;
|
||||
|
||||
// Test <all_urls> for regular extensions.
|
||||
extension = LoadManifestStrict("script_and_capture",
|
||||
scoped_refptr<Extension> extension = LoadManifestStrict("script_and_capture",
|
||||
"extension_regular_all.json");
|
||||
|
||||
EXPECT_TRUE(Allowed(extension, http_url));
|
||||
EXPECT_TRUE(Allowed(extension, https_url));
|
||||
EXPECT_TRUE(Blocked(extension, file_url));
|
||||
@ -745,6 +746,103 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, Permissions) {
|
||||
EXPECT_FALSE(extension->HasHostPermission(settings_url));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ExtensionScriptAndCaptureVisibleTest, PermissionsWithChromeURLsEnabled) {
|
||||
CommandLine::ForCurrentProcess()->AppendSwitch(
|
||||
switches::kExtensionsOnChromeURLs);
|
||||
|
||||
scoped_refptr<Extension> extension;
|
||||
|
||||
// Test <all_urls> for regular extensions.
|
||||
extension = LoadManifestStrict("script_and_capture",
|
||||
"extension_regular_all.json");
|
||||
EXPECT_TRUE(Allowed(extension, http_url));
|
||||
EXPECT_TRUE(Allowed(extension, https_url));
|
||||
EXPECT_TRUE(Blocked(extension, file_url));
|
||||
EXPECT_TRUE(Blocked(extension, settings_url));
|
||||
EXPECT_TRUE(Allowed(extension, favicon_url)); // chrome:// requested
|
||||
EXPECT_TRUE(Blocked(extension, about_url));
|
||||
EXPECT_TRUE(Blocked(extension, extension_url));
|
||||
|
||||
// Test access to iframed content.
|
||||
GURL within_extension_url = extension->GetResourceURL("page.html");
|
||||
EXPECT_TRUE(AllowedScript(extension, http_url, http_url_with_path));
|
||||
EXPECT_TRUE(AllowedScript(extension, https_url, http_url_with_path));
|
||||
EXPECT_TRUE(AllowedScript(extension, http_url, within_extension_url));
|
||||
EXPECT_TRUE(AllowedScript(extension, https_url, within_extension_url));
|
||||
EXPECT_TRUE(BlockedScript(extension, http_url, extension_url));
|
||||
EXPECT_TRUE(BlockedScript(extension, https_url, extension_url));
|
||||
|
||||
EXPECT_FALSE(extension->HasHostPermission(settings_url));
|
||||
EXPECT_FALSE(extension->HasHostPermission(about_url));
|
||||
EXPECT_TRUE(extension->HasHostPermission(favicon_url));
|
||||
|
||||
// Test * for scheme, which implies just the http/https schemes.
|
||||
extension = LoadManifestStrict("script_and_capture",
|
||||
"extension_wildcard.json");
|
||||
EXPECT_TRUE(Allowed(extension, http_url));
|
||||
EXPECT_TRUE(Allowed(extension, https_url));
|
||||
EXPECT_TRUE(Blocked(extension, settings_url));
|
||||
EXPECT_TRUE(Blocked(extension, about_url));
|
||||
EXPECT_TRUE(Blocked(extension, file_url));
|
||||
EXPECT_TRUE(Blocked(extension, favicon_url));
|
||||
extension = LoadManifest("script_and_capture",
|
||||
"extension_wildcard_settings.json");
|
||||
EXPECT_TRUE(Blocked(extension, settings_url));
|
||||
|
||||
// Having chrome://*/ should work for regular extensions with the flag
|
||||
// enabled.
|
||||
std::string error;
|
||||
extension = LoadManifestUnchecked("script_and_capture",
|
||||
"extension_wildcard_chrome.json",
|
||||
Manifest::INTERNAL, Extension::NO_FLAGS,
|
||||
&error);
|
||||
EXPECT_FALSE(extension == NULL);
|
||||
EXPECT_TRUE(Blocked(extension, http_url));
|
||||
EXPECT_TRUE(Blocked(extension, https_url));
|
||||
EXPECT_TRUE(Allowed(extension, settings_url));
|
||||
EXPECT_TRUE(Blocked(extension, about_url));
|
||||
EXPECT_TRUE(Blocked(extension, file_url));
|
||||
EXPECT_TRUE(Allowed(extension, favicon_url)); // chrome:// requested
|
||||
|
||||
// Having chrome://favicon/* should not give you chrome://*
|
||||
extension = LoadManifestStrict("script_and_capture",
|
||||
"extension_chrome_favicon_wildcard.json");
|
||||
EXPECT_TRUE(Blocked(extension, settings_url));
|
||||
EXPECT_TRUE(Allowed(extension, favicon_url)); // chrome:// requested
|
||||
EXPECT_TRUE(Blocked(extension, about_url));
|
||||
EXPECT_TRUE(extension->HasHostPermission(favicon_url));
|
||||
|
||||
// Having http://favicon should not give you chrome://favicon
|
||||
extension = LoadManifestStrict("script_and_capture",
|
||||
"extension_http_favicon.json");
|
||||
EXPECT_TRUE(Blocked(extension, settings_url));
|
||||
EXPECT_TRUE(Blocked(extension, favicon_url));
|
||||
|
||||
// Component extensions with <all_urls> should get everything.
|
||||
extension = LoadManifest("script_and_capture", "extension_component_all.json",
|
||||
Manifest::COMPONENT, Extension::NO_FLAGS);
|
||||
EXPECT_TRUE(Allowed(extension, http_url));
|
||||
EXPECT_TRUE(Allowed(extension, https_url));
|
||||
EXPECT_TRUE(Allowed(extension, settings_url));
|
||||
EXPECT_TRUE(Allowed(extension, about_url));
|
||||
EXPECT_TRUE(Allowed(extension, favicon_url));
|
||||
EXPECT_TRUE(extension->HasHostPermission(favicon_url));
|
||||
|
||||
// Component extensions should only get access to what they ask for.
|
||||
extension = LoadManifest("script_and_capture",
|
||||
"extension_component_google.json", Manifest::COMPONENT,
|
||||
Extension::NO_FLAGS);
|
||||
EXPECT_TRUE(Allowed(extension, http_url));
|
||||
EXPECT_TRUE(Blocked(extension, https_url));
|
||||
EXPECT_TRUE(Blocked(extension, file_url));
|
||||
EXPECT_TRUE(Blocked(extension, settings_url));
|
||||
EXPECT_TRUE(Blocked(extension, favicon_url));
|
||||
EXPECT_TRUE(Blocked(extension, about_url));
|
||||
EXPECT_TRUE(Blocked(extension, extension_url));
|
||||
EXPECT_FALSE(extension->HasHostPermission(settings_url));
|
||||
}
|
||||
|
||||
TEST_F(ExtensionScriptAndCaptureVisibleTest, TabSpecific) {
|
||||
scoped_refptr<Extension> extension =
|
||||
LoadManifestStrict("script_and_capture", "tab_specific.json");
|
||||
|
@ -2,11 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
#include "chrome/common/extensions/extension.h"
|
||||
#include "chrome/common/extensions/extension_manifest_constants.h"
|
||||
#include "chrome/common/extensions/manifest.h"
|
||||
#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace errors = extension_manifest_errors;
|
||||
@ -16,6 +17,21 @@ TEST_F(ExtensionManifestTest, ChromeURLPermissionInvalid) {
|
||||
errors::kInvalidPermissionScheme);
|
||||
}
|
||||
|
||||
TEST_F(ExtensionManifestTest, ChromeURLPermissionAllowedWithFlag) {
|
||||
CommandLine::ForCurrentProcess()->AppendSwitch(
|
||||
switches::kExtensionsOnChromeURLs);
|
||||
std::string error;
|
||||
scoped_refptr<extensions::Extension> extension =
|
||||
LoadAndExpectSuccess("permission_chrome_url_invalid.json");
|
||||
EXPECT_EQ("", error);
|
||||
const GURL newtab_url("chrome://newtab/");
|
||||
EXPECT_TRUE(extension->CanExecuteScriptOnPage(newtab_url,
|
||||
newtab_url,
|
||||
0,
|
||||
NULL,
|
||||
&error)) << error;
|
||||
}
|
||||
|
||||
TEST_F(ExtensionManifestTest, ChromeResourcesPermissionValidOnlyForComponents) {
|
||||
LoadAndExpectError("permission_chrome_resources_url.json",
|
||||
errors::kInvalidPermissionScheme);
|
||||
|
@ -2,11 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
#include "chrome/common/extensions/extension.h"
|
||||
#include "chrome/common/extensions/extension_manifest_constants.h"
|
||||
#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
|
||||
#include "extensions/common/error_utils.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@ -35,3 +36,14 @@ TEST_F(ExtensionManifestTest, ContentScriptMatchPattern) {
|
||||
|
||||
LoadAndExpectSuccess("ports_in_content_scripts.json");
|
||||
}
|
||||
|
||||
TEST_F(ExtensionManifestTest, ContentScriptsOnChromeUrlsWithFlag) {
|
||||
CommandLine::ForCurrentProcess()->AppendSwitch(
|
||||
switches::kExtensionsOnChromeURLs);
|
||||
std::string error;
|
||||
scoped_refptr<extensions::Extension> extension =
|
||||
LoadAndExpectSuccess("content_script_chrome_url_invalid.json");
|
||||
EXPECT_EQ("", error);
|
||||
const GURL newtab_url("chrome://newtab/");
|
||||
EXPECT_TRUE(extension->HasContentScriptAtURL(newtab_url));
|
||||
}
|
||||
|
@ -4,8 +4,10 @@
|
||||
|
||||
#include "chrome/common/extensions/user_script.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/pickle.h"
|
||||
#include "base/string_util.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -24,6 +26,15 @@ bool UrlMatchesGlobs(const std::vector<std::string>* globs,
|
||||
|
||||
namespace extensions {
|
||||
|
||||
// The bitmask for valid user script injectable schemes used by URLPattern.
|
||||
enum {
|
||||
kValidUserScriptSchemes = URLPattern::SCHEME_CHROMEUI |
|
||||
URLPattern::SCHEME_HTTP |
|
||||
URLPattern::SCHEME_HTTPS |
|
||||
URLPattern::SCHEME_FILE |
|
||||
URLPattern::SCHEME_FTP
|
||||
};
|
||||
|
||||
// static
|
||||
const char UserScript::kFileExtension[] = ".user.js";
|
||||
|
||||
@ -33,6 +44,18 @@ bool UserScript::IsURLUserScript(const GURL& url,
|
||||
mime_type != "text/html";
|
||||
}
|
||||
|
||||
// static
|
||||
int UserScript::ValidUserScriptSchemes(bool canExecuteScriptEverywhere) {
|
||||
if (canExecuteScriptEverywhere)
|
||||
return URLPattern::SCHEME_ALL;
|
||||
int valid_schemes = kValidUserScriptSchemes;
|
||||
if (!CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kExtensionsOnChromeURLs)) {
|
||||
valid_schemes &= ~URLPattern::SCHEME_CHROMEUI;
|
||||
}
|
||||
return valid_schemes;
|
||||
}
|
||||
|
||||
UserScript::File::File(const base::FilePath& extension_root,
|
||||
const base::FilePath& relative_path,
|
||||
const GURL& url)
|
||||
@ -184,20 +207,16 @@ void UserScript::UnpickleURLPatternSet(const ::Pickle& pickle,
|
||||
for (uint64 i = 0; i < num_patterns; ++i) {
|
||||
int valid_schemes;
|
||||
CHECK(pickle.ReadInt(iter, &valid_schemes));
|
||||
|
||||
std::string pattern_str;
|
||||
URLPattern pattern(valid_schemes);
|
||||
CHECK(pickle.ReadString(iter, &pattern_str));
|
||||
|
||||
// We remove the file scheme if it's not actually allowed (see Extension::
|
||||
// LoadUserScriptHelper), but we need it temporarily while loading the
|
||||
// pattern so that it's valid.
|
||||
bool had_file_scheme = (valid_schemes & URLPattern::SCHEME_FILE) != 0;
|
||||
if (!had_file_scheme)
|
||||
pattern.SetValidSchemes(valid_schemes | URLPattern::SCHEME_FILE);
|
||||
CHECK(URLPattern::PARSE_SUCCESS == pattern.Parse(pattern_str));
|
||||
if (!had_file_scheme)
|
||||
pattern.SetValidSchemes(valid_schemes);
|
||||
URLPattern pattern(kValidUserScriptSchemes);
|
||||
URLPattern::ParseResult result = pattern.Parse(pattern_str);
|
||||
CHECK(URLPattern::PARSE_SUCCESS == result) <<
|
||||
URLPattern::GetParseResultString(result) << " " << pattern_str.c_str();
|
||||
|
||||
pattern.SetValidSchemes(valid_schemes);
|
||||
pattern_list->AddPattern(pattern);
|
||||
}
|
||||
}
|
||||
|
@ -26,18 +26,14 @@ class UserScript {
|
||||
// The file extension for standalone user scripts.
|
||||
static const char kFileExtension[];
|
||||
|
||||
// The bitmask for valid user script injectable schemes used by URLPattern.
|
||||
enum {
|
||||
kValidUserScriptSchemes = URLPattern::SCHEME_HTTP |
|
||||
URLPattern::SCHEME_HTTPS |
|
||||
URLPattern::SCHEME_FILE |
|
||||
URLPattern::SCHEME_FTP
|
||||
};
|
||||
|
||||
// Check if a URL should be treated as a user script and converted to an
|
||||
// extension.
|
||||
static bool IsURLUserScript(const GURL& url, const std::string& mime_type);
|
||||
|
||||
// Get the valid user script schemes for the current process. If
|
||||
// canExecuteScriptEverywhere is true, this will return ALL_SCHEMES.
|
||||
static int ValidUserScriptSchemes(bool canExecuteScriptEverywhere = false);
|
||||
|
||||
// Locations that user scripts can be run inside the document.
|
||||
enum RunLocation {
|
||||
UNDEFINED,
|
||||
|
@ -3,7 +3,8 @@
|
||||
"version": "1",
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["chrome://newtab/"]
|
||||
"matches": ["chrome://newtab/"],
|
||||
"js": ["javascript.js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -188,6 +188,9 @@ class URLPattern {
|
||||
// Get an error string for a ParseResult.
|
||||
static const char* GetParseResultString(URLPattern::ParseResult parse_result);
|
||||
|
||||
// Checks whether the bit is set for the given scheme in the given scheme mask
|
||||
static bool IsSchemeBitSet(const std::string& scheme, const int mask);
|
||||
|
||||
private:
|
||||
// Returns true if any of the |schemes| items matches our scheme.
|
||||
bool MatchesAnyScheme(const std::vector<std::string>& schemes) const;
|
||||
@ -206,8 +209,7 @@ class URLPattern {
|
||||
|
||||
// A bitmask containing the schemes which are considered valid for this
|
||||
// pattern. Parse() uses this to decide whether a pattern contains a valid
|
||||
// scheme. MatchesScheme uses this to decide whether a wildcard scheme_
|
||||
// matches a given test scheme.
|
||||
// scheme.
|
||||
int valid_schemes_;
|
||||
|
||||
// True if this is a special-case "<all_urls>" pattern.
|
||||
|
Reference in New Issue
Block a user