summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_protocols.cc71
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc5
-rw-r--r--chrome/browser/net/chrome_url_request_context.h4
-rw-r--r--chrome/common/extensions/extension.cc68
-rw-r--r--chrome/common/extensions/extension.h1
-rw-r--r--chrome/common/extensions/extension_constants.cc2
-rw-r--r--chrome/common/extensions/extension_constants.h1
-rw-r--r--chrome/common/extensions/extension_manifests_unittest.cc7
-rw-r--r--chrome/test/data/extensions/manifest_tests/disallow_hybrid_1.json18
-rw-r--r--chrome/test/data/extensions/manifest_tests/disallow_hybrid_2.json18
10 files changed, 141 insertions, 54 deletions
diff --git a/chrome/browser/extensions/extension_protocols.cc b/chrome/browser/extensions/extension_protocols.cc
index d88e045..f1b09eb 100644
--- a/chrome/browser/extensions/extension_protocols.cc
+++ b/chrome/browser/extensions/extension_protocols.cc
@@ -65,44 +65,61 @@ class URLRequestResourceBundleJob : public URLRequestSimpleJob {
int resource_id_;
};
-} // namespace
-
-// Factory registered with URLRequest to create URLRequestJobs for extension://
-// URLs.
-static URLRequestJob* CreateExtensionURLRequestJob(URLRequest* request,
- const std::string& scheme) {
- ChromeURLRequestContext* context =
- static_cast<ChromeURLRequestContext*>(request->context());
-
+// Returns true if an chrome-extension:// resource should be allowed to load.
+bool AllowExtensionResourceLoad(URLRequest* request,
+ ChromeURLRequestContext* context,
+ const std::string& scheme) {
const ResourceDispatcherHostRequestInfo* info =
ResourceDispatcherHost::InfoForRequest(request);
+ GURL origin_url(info->frame_origin());
+
+ // chrome:// URLs are always allowed to load chrome-extension:// resources.
+ // The app launcher in the NTP uses this feature, as does dev tools.
+ if (origin_url.SchemeIs(chrome::kChromeUIScheme))
+ return true;
+
+ // Disallow loading of packaged resources for hosted apps. We don't allow
+ // hybrid hosted/packaged apps.
+ if (context->ExtensionHasWebExtent(request->url().host()))
+ return false;
+
+ // chrome-extension:// pages can load resources from extensions and packaged
+ // apps. This is allowed for legacy reasons.
+ if (origin_url.SchemeIs(chrome::kExtensionScheme))
+ return true;
+
// Extension resources should only be loadable from web pages which the
// extension has host permissions to (and therefore could be running script
// in, which might need access to the extension resources).
- //
- // chrome:// pages are exempt. We allow them to load any extension resource.
- // This is used for, eg, the app launcher in the NTP.
- //
- // chrome-extension:// pages are also exempt, mostly for legacy reasons. Some
- // extensions did this to integrate with each other before we added this code.
- GURL origin_url(info->frame_origin());
- if (!origin_url.is_empty() &&
- !origin_url.SchemeIs(chrome::kChromeUIScheme) &&
- !origin_url.SchemeIs(chrome::kExtensionScheme)) {
- ExtensionExtent host_permissions =
- context->GetEffectiveHostPermissionsForExtension(
- request->url().host());
- if (!host_permissions.ContainsURL(GURL(info->frame_origin())))
- return new URLRequestErrorJob(request, net::ERR_ADDRESS_UNREACHABLE);
- }
+ ExtensionExtent host_permissions =
+ context->GetEffectiveHostPermissionsForExtension(request->url().host());
+ if (!origin_url.is_empty() && !host_permissions.ContainsURL(origin_url))
+ return false;
// Don't allow toplevel navigations to extension resources in incognito mode.
// This is because an extension must run in a single process, and an
// incognito tab prevents that.
- // TODO(mpcomplete): better error code.
if (context->is_off_the_record() &&
- info && info->resource_type() == ResourceType::MAIN_FRAME)
+ info->resource_type() == ResourceType::MAIN_FRAME) {
+ return false;
+ }
+
+ // Otherwise, the resource load is allowed.
+ return true;
+}
+
+} // namespace
+
+// Factory registered with URLRequest to create URLRequestJobs for extension://
+// URLs.
+static URLRequestJob* CreateExtensionURLRequestJob(URLRequest* request,
+ const std::string& scheme) {
+ ChromeURLRequestContext* context =
+ static_cast<ChromeURLRequestContext*>(request->context());
+
+ // TODO(mpcomplete): better error code.
+ if (!AllowExtensionResourceLoad(request, context, scheme))
return new URLRequestErrorJob(request, net::ERR_ADDRESS_UNREACHABLE);
// chrome-extension://extension-id/resource/path.js
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index a67e506..6441dc9 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -790,6 +790,11 @@ FilePath ChromeURLRequestContext::GetPathForExtension(const std::string& id) {
return FilePath();
}
+bool ChromeURLRequestContext::ExtensionHasWebExtent(const std::string& id) {
+ ExtensionInfoMap::iterator iter = extension_info_.find(id);
+ return iter != extension_info_.end() && !iter->second->extent.is_empty();
+}
+
std::string ChromeURLRequestContext::GetDefaultLocaleForExtension(
const std::string& id) {
ExtensionInfoMap::iterator iter = extension_info_.find(id);
diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h
index 1e7065e..0bd0770e 100644
--- a/chrome/browser/net/chrome_url_request_context.h
+++ b/chrome/browser/net/chrome_url_request_context.h
@@ -79,6 +79,10 @@ class ChromeURLRequestContext : public URLRequestContext {
// Gets the path to the directory for the specified extension.
FilePath GetPathForExtension(const std::string& id);
+ // Returns true if the specified extension exists and has a non-empty web
+ // extent.
+ bool ExtensionHasWebExtent(const std::string& id);
+
// Returns an empty string if the extension with |id| doesn't have a default
// locale.
std::string GetDefaultLocaleForExtension(const std::string& id);
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 902eab4..f0e9683 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -71,28 +71,37 @@ static void ConvertHexadecimalToIDAlphabet(std::string* id) {
const int kValidWebExtentSchemes =
URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS;
-} // namespace
-
-const FilePath::CharType Extension::kManifestFilename[] =
- FILE_PATH_LITERAL("manifest.json");
-const FilePath::CharType Extension::kLocaleFolder[] =
- FILE_PATH_LITERAL("_locales");
-const FilePath::CharType Extension::kMessagesFilename[] =
- FILE_PATH_LITERAL("messages.json");
-
-// A list of all the keys allowed by themes.
-static const wchar_t* kValidThemeKeys[] = {
+// These keys are allowed by all crx files (apps, extensions, themes, etc).
+static const wchar_t* kBaseCrxKeys[] = {
keys::kCurrentLocale,
keys::kDefaultLocale,
keys::kDescription,
+ keys::kIcons,
keys::kName,
keys::kPublicKey,
keys::kSignature,
- keys::kTheme,
keys::kVersion,
keys::kUpdateURL
};
+bool IsBaseCrxKey(const std::wstring& key) {
+ for (size_t i = 0; i < arraysize(kBaseCrxKeys); ++i) {
+ if (key == kBaseCrxKeys[i])
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
+const FilePath::CharType Extension::kManifestFilename[] =
+ FILE_PATH_LITERAL("manifest.json");
+const FilePath::CharType Extension::kLocaleFolder[] =
+ FILE_PATH_LITERAL("_locales");
+const FilePath::CharType Extension::kMessagesFilename[] =
+ FILE_PATH_LITERAL("messages.json");
+
#if defined(OS_WIN)
const char* Extension::kExtensionRegistryPath =
"Software\\Google\\Chrome\\Extensions";
@@ -514,23 +523,10 @@ ExtensionAction* Extension::LoadExtensionActionHelper(
}
bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) {
- // Generate a map of allowable keys
- static std::map<std::string, bool> theme_keys;
- static bool theme_key_mapped = false;
- if (!theme_key_mapped) {
- for (size_t i = 0; i < arraysize(kValidThemeKeys); ++i) {
- // TODO(viettrungluu): Make the constants |char*|s and avoid converting.
- theme_keys[WideToUTF8(kValidThemeKeys[i])] = true;
- }
- theme_key_mapped = true;
- }
-
- // Go through all the root level keys and verify that they're in the map
- // of keys allowable by themes. If they're not, then make a not of it for
- // later.
for (DictionaryValue::key_iterator iter = source.begin_keys();
iter != source.end_keys(); ++iter) {
- if (theme_keys.find(*iter) == theme_keys.end())
+ std::wstring key = ASCIIToWide(*iter);
+ if (!IsBaseCrxKey(key) && key != keys::kTheme)
return true;
}
return false;
@@ -725,6 +721,23 @@ bool Extension::LoadLaunchFullscreen(const DictionaryValue* manifest,
return true;
}
+bool Extension::EnsureNotHybridApp(const DictionaryValue* manifest,
+ std::string* error) {
+ if (web_extent().is_empty())
+ return true;
+
+ for (DictionaryValue::key_iterator iter = manifest->begin_keys();
+ iter != manifest->end_keys(); ++iter) {
+ std::wstring key = ASCIIToWide(*iter);
+ if (!IsBaseCrxKey(key) && key != keys::kApp && key != keys::kPermissions) {
+ *error = errors::kHostedAppsCannotIncludeExtensionFeatures;
+ return false;
+ }
+ }
+
+ return true;
+}
+
Extension::Extension(const FilePath& path)
: converted_from_user_script_(false),
is_theme_(false),
@@ -1506,6 +1519,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
!LoadExtent(manifest_value_.get(), keys::kBrowseURLs, &browse_extent_,
errors::kInvalidBrowseURLs, errors::kInvalidBrowseURL,
error) ||
+ !EnsureNotHybridApp(manifest_value_.get(), error) ||
!LoadLaunchURL(manifest_value_.get(), error) ||
!LoadLaunchContainer(manifest_value_.get(), error) ||
!LoadLaunchFullscreen(manifest_value_.get(), error)) {
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 9f3ca6c..432e82c 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -424,6 +424,7 @@ class Extension {
bool LoadLaunchFullscreen(const DictionaryValue* manifest,
std::string* error);
bool LoadLaunchURL(const DictionaryValue* manifest, std::string* error);
+ bool EnsureNotHybridApp(const DictionaryValue* manifest, std::string* error);
// Helper method to load an ExtensionAction from the page_action or
// browser_action entries in the manifest.
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index ce4d74f..8fdeb2e 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -97,6 +97,8 @@ const char* kDisabledByPolicy =
const char* kDevToolsExperimental =
"You must request the 'experimental' permission in order to use the"
" DevTools API.";
+const char* kHostedAppsCannotIncludeExtensionFeatures =
+ "Hosted apps cannot use extension features.";
const char* kInvalidAllFrames =
"Invalid value for 'content_scripts[*].all_frames'.";
const char* kInvalidBackground =
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index bc85b3c..4027737 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -89,6 +89,7 @@ namespace extension_manifest_errors {
extern const char* kCannotScriptGallery;
extern const char* kChromeVersionTooLow;
extern const char* kDevToolsExperimental;
+ extern const char* kHostedAppsCannotIncludeExtensionFeatures;
extern const char* kInvalidAllFrames;
extern const char* kInvalidBackground;
extern const char* kInvalidBrowserAction;
diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc
index 36c4b89..df2dad0 100644
--- a/chrome/common/extensions/extension_manifests_unittest.cc
+++ b/chrome/common/extensions/extension_manifests_unittest.cc
@@ -263,3 +263,10 @@ TEST_F(ManifestTest, DevToolsExtensions) {
extension->devtools_url().spec());
*CommandLine::ForCurrentProcess() = old_command_line;
}
+
+TEST_F(ManifestTest, DisallowHybridApps) {
+ LoadAndExpectError("disallow_hybrid_1.json",
+ errors::kHostedAppsCannotIncludeExtensionFeatures);
+ LoadAndExpectError("disallow_hybrid_2.json",
+ errors::kHostedAppsCannotIncludeExtensionFeatures);
+}
diff --git a/chrome/test/data/extensions/manifest_tests/disallow_hybrid_1.json b/chrome/test/data/extensions/manifest_tests/disallow_hybrid_1.json
new file mode 100644
index 0000000..8cca112
--- /dev/null
+++ b/chrome/test/data/extensions/manifest_tests/disallow_hybrid_1.json
@@ -0,0 +1,18 @@
+{
+ "name": "test",
+ "version": "1",
+ "app": {
+ "urls": [
+ "http://www.google.com/mail/",
+ "http://www.google.com/foobar/"
+ ],
+ "launch": {
+ "container": "window",
+ "web_url": "http://www.google.com/mail/"
+ }
+ },
+ "permissions": [
+ "notifications"
+ ],
+ "browser_action": {}
+}
diff --git a/chrome/test/data/extensions/manifest_tests/disallow_hybrid_2.json b/chrome/test/data/extensions/manifest_tests/disallow_hybrid_2.json
new file mode 100644
index 0000000..bad2e6c
--- /dev/null
+++ b/chrome/test/data/extensions/manifest_tests/disallow_hybrid_2.json
@@ -0,0 +1,18 @@
+{
+ "name": "test",
+ "version": "1",
+ "app": {
+ "urls": [
+ "http://www.google.com/mail/",
+ "http://www.google.com/foobar/"
+ ],
+ "launch": {
+ "container": "window",
+ "web_url": "http://www.google.com/mail/"
+ }
+ },
+ "permissions": [
+ "notifications"
+ ],
+ "background_page": "foo.html"
+}