0

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:
aboxhall@chromium.org
2013-03-21 12:57:29 +00:00
parent fc7a1dbbc6
commit ac2e2acd50
19 changed files with 269 additions and 63 deletions

@ -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.