summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/generated_resources.grd9
-rw-r--r--chrome/browser/download/download_util.cc2
-rw-r--r--chrome/browser/extensions/crx_installer.cc122
-rw-r--r--chrome/browser/extensions/crx_installer.h17
4 files changed, 91 insertions, 59 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 09d4b38..5293296 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3582,8 +3582,8 @@ each locale. -->
<message name="IDS_EXTENSION_DIRECTORY_NO_EXISTS" desc="Warning displayed in pack dialog when the extension directory does not exist.">
Input directory must exist.
</message>
- <message name="IDS_EXTENSION_DISALLOW_NON_DOWNLOADED_GALLERY_INSTALLS" desc="Error displayed when an extension that has an update URL used by the gallery is installed when not directly downloaded from the gallery.">
- This package can only be installed from the <ph name="CHROME_WEB_STORE">$1<ex>Chrome Web Store</ex></ph>.
+ <message name="IDS_EXTENSION_DISALLOW_NON_DOWNLOADED_GALLERY_INSTALLS" desc="Error displayed when an app or extension that has an update URL used by the gallery is installed when not directly downloaded from the gallery.">
+ This can only be installed from the <ph name="CHROME_WEB_STORE">$1<ex>Web Store</ex></ph>.
</message>
<message name="IDS_EXTENSION_PRIVATE_KEY_INVALID_PATH" desc="Warning displayed in pack dialog when the private key must be a valid path.">
Input value for private key must be a valid path.
@@ -3845,8 +3845,11 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_EXTENSION_PROMPT_ENABLE_INCOGNITO_BUTTON" desc="Text for the allow button on the extension run-in-incognito prompt">
Allow
</message>
+ <message name="IDS_EXTENSION_GET_MORE_APPS" desc="Promo text for button to the Web Store">
+ Get More Apps
+ </message>
<message name="IDS_EXTENSION_WEB_STORE_TITLE" desc="Text for the Chrome Web Store">
- Get more apps
+ Web Store
</message>
<message name="IDS_APPS_PROMO_HEADER" desc="Header for the apps promo">
New! Discover a world of apps &amp; games
diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc
index 8ced2b4..0a54b01 100644
--- a/chrome/browser/download/download_util.cc
+++ b/chrome/browser/download/download_util.cc
@@ -258,7 +258,7 @@ void OpenChromeExtension(Profile* profile,
installer->set_apps_require_extension_mime_type(true);
installer->set_allow_privilege_increase(true);
installer->set_original_url(download_item.url());
- installer->set_limit_web_extent_to_download_host(!is_gallery_download);
+ installer->set_is_gallery_install(is_gallery_download);
installer->InstallCrx(download_item.full_path());
installer->set_allow_silent_install(is_gallery_download);
}
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 3fa5484..40d8cd2 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -78,7 +78,7 @@ CrxInstaller::CrxInstaller(const FilePath& install_directory,
install_source_(Extension::INTERNAL),
delete_source_(false),
allow_privilege_increase_(false),
- limit_web_extent_to_download_host_(false),
+ is_gallery_install_(false),
create_app_shortcut_(false),
frontend_(frontend),
client_(client),
@@ -151,6 +151,78 @@ void CrxInstaller::ConvertUserScriptOnFileThread() {
OnUnpackSuccess(extension->path(), extension->path(), extension);
}
+bool CrxInstaller::AllowInstall(Extension* extension, std::string* error) {
+ DCHECK(error);
+
+ // We always allow themes and external installs.
+ if (extension->is_theme() || Extension::IsExternalLocation(install_source_))
+ return true;
+
+ if (!extensions_enabled_) {
+ *error = "Extensions are not enabled.";
+ return false;
+ }
+
+ // Make sure the expected id matches.
+ // TODO(aa): Also support expected version?
+ if (!expected_id_.empty() && expected_id_ != extension->id()) {
+ *error = base::StringPrintf(
+ "ID in new extension manifest (%s) does not match expected id (%s)",
+ extension->id().c_str(),
+ expected_id_.c_str());
+ return false;
+ }
+
+ if (extension_->is_app()) {
+ // If the app was downloaded, apps_require_extension_mime_type_
+ // will be set. In this case, check that it was served with the
+ // right mime type. Make an exception for file URLs, which come
+ // from the users computer and have no headers.
+ if (!original_url_.SchemeIsFile() &&
+ apps_require_extension_mime_type_ &&
+ original_mime_type_ != Extension::kMimeType) {
+ *error = base::StringPrintf(
+ "Apps must be served with content type %s.",
+ Extension::kMimeType);
+ return false;
+ }
+
+ // 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.
+ if (!is_gallery_install_) {
+ URLPattern pattern(UserScript::kValidUserScriptSchemes);
+ pattern.set_host(original_url_.host());
+ pattern.set_match_subdomains(true);
+
+ ExtensionExtent::PatternList patterns =
+ extension_->web_extent().patterns();
+ for (size_t i = 0; i < patterns.size(); ++i) {
+ if (!pattern.MatchesHost(patterns[i].host())) {
+ *error = base::StringPrintf(
+ "Apps must be served from the host that they affect.");
+ return false;
+ }
+ }
+
+ // For apps with a gallery update URL, require that they be installed
+ // from the gallery.
+ // TODO(erikkay) Apply this rule for paid extensions and themes as well.
+ if ((extension->update_url() ==
+ GURL(extension_urls::kGalleryUpdateHttpsUrl)) ||
+ (extension->update_url() ==
+ GURL(extension_urls::kGalleryUpdateHttpUrl))) {
+ *error = l10n_util::GetStringFUTF8(
+ IDS_EXTENSION_DISALLOW_NON_DOWNLOADED_GALLERY_INSTALLS,
+ l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE));
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
void CrxInstaller::OnUnpackFailure(const std::string& error_message) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
ReportFailureFromFileThread(error_message);
@@ -165,58 +237,16 @@ void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir,
extension_.reset(extension);
temp_dir_ = temp_dir;
- // If the extension was downloaded, apps_require_extension_mime_type_
- // will be set. In this case, check that if the extension is an app,
- // it was served with the right mime type. Make an exception for file
- // URLs, which come from the users computer and have no headers.
- if (extension->is_app() &&
- !original_url_.SchemeIsFile() &&
- apps_require_extension_mime_type_ &&
- original_mime_type_ != Extension::kMimeType) {
- ReportFailureFromFileThread(base::StringPrintf(
- "Applications must be served with content type %s.",
- Extension::kMimeType));
- return;
- }
-
// We don't have to delete the unpack dir explicity since it is a child of
// the temp dir.
unpacked_extension_root_ = extension_dir;
- // Determine whether to allow installation. We always allow themes and
- // external installs.
- if (!extensions_enabled_ && !extension->is_theme() &&
- !Extension::IsExternalLocation(install_source_)) {
- ReportFailureFromFileThread("Extensions are not enabled.");
- return;
- }
-
- // Make sure the expected id matches.
- // TODO(aa): Also support expected version?
- if (!expected_id_.empty() && expected_id_ != extension->id()) {
- ReportFailureFromFileThread(base::StringPrintf(
- "ID in new extension manifest (%s) does not match expected id (%s)",
- extension->id().c_str(),
- expected_id_.c_str()));
+ std::string error;
+ if (!AllowInstall(extension, &error)) {
+ ReportFailureFromFileThread(error);
return;
}
- // Require that apps are served from the domain they claim in their extent,
- // or some ancestor domain.
- if (extension_->is_app() && limit_web_extent_to_download_host_) {
- URLPattern pattern(UserScript::kValidUserScriptSchemes);
- pattern.set_host(original_url_.host());
- pattern.set_match_subdomains(true);
-
- for (size_t i = 0; i < extension_->web_extent().patterns().size(); ++i) {
- if (!pattern.MatchesHost(extension_->web_extent().patterns()[i].host())) {
- ReportFailureFromFileThread(base::StringPrintf(
- "Apps must be served from the host that they affect."));
- return;
- }
- }
- }
-
if (client_ || extension_->GetFullLaunchURL().is_valid()) {
Extension::DecodeIcon(extension_.get(), Extension::EXTENSION_ICON_LARGE,
&install_icon_);
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h
index ca3e90f..b1212a2 100644
--- a/chrome/browser/extensions/crx_installer.h
+++ b/chrome/browser/extensions/crx_installer.h
@@ -98,12 +98,8 @@ class CrxInstaller
bool allow_silent_install() const { return allow_silent_install_; }
void set_allow_silent_install(bool val) { allow_silent_install_ = val; }
- bool limit_web_extent_to_download_host() const {
- return limit_web_extent_to_download_host_;
- }
- void set_limit_web_extent_to_download_host(bool val) {
- limit_web_extent_to_download_host_ = val;
- }
+ bool is_gallery_install() const { return is_gallery_install_; }
+ void set_is_gallery_install(bool val) { is_gallery_install_ = val; }
// If |apps_require_extension_mime_type_| is set to true, be sure to set
// |original_mime_type_| as well.
@@ -122,6 +118,10 @@ class CrxInstaller
// Converts the source user script to an extension.
void ConvertUserScriptOnFileThread();
+ // Called after OnUnpackSuccess as a last check to see whether the install
+ // should complete.
+ bool AllowInstall(Extension* extension, std::string* error);
+
// SandboxedExtensionUnpackerClient
virtual void OnUnpackFailure(const std::string& error_message);
virtual void OnUnpackSuccess(const FilePath& temp_dir,
@@ -177,9 +177,8 @@ class CrxInstaller
// either. Defaults to false.
bool allow_privilege_increase_;
- // Limits the web extent to the app being installed to the host of the
- // download URL. If the crx being installed is not an app, this is a no-op.
- bool limit_web_extent_to_download_host_;
+ // Whether the install originated from the gallery.
+ bool is_gallery_install_;
// Whether to create an app shortcut after successful installation. This is
// set based on the user's selection in the UI and can only ever be true for