diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/generated_resources.grd | 9 | ||||
-rw-r--r-- | chrome/browser/download/download_util.cc | 2 | ||||
-rw-r--r-- | chrome/browser/extensions/crx_installer.cc | 122 | ||||
-rw-r--r-- | chrome/browser/extensions/crx_installer.h | 17 |
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 & 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 |