summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extensions_service.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/extensions_service.cc')
-rw-r--r--chrome/browser/extensions/extensions_service.cc137
1 files changed, 108 insertions, 29 deletions
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 61de28b..e9d635c 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -97,20 +97,24 @@ void GetExplicitOriginsInExtent(Extension* extension,
} // namespace
-PendingExtensionInfo::PendingExtensionInfo(const GURL& update_url,
- bool is_theme,
- bool install_silently,
- bool enable_on_install,
- bool enable_incognito_on_install)
+PendingExtensionInfo::PendingExtensionInfo(
+ const GURL& update_url,
+ PendingExtensionInfo::ExpectedCrxType expected_crx_type,
+ bool is_from_sync,
+ bool install_silently,
+ bool enable_on_install,
+ bool enable_incognito_on_install)
: update_url(update_url),
- is_theme(is_theme),
+ expected_crx_type(expected_crx_type),
+ is_from_sync(is_from_sync),
install_silently(install_silently),
enable_on_install(enable_on_install),
enable_incognito_on_install(enable_incognito_on_install) {}
PendingExtensionInfo::PendingExtensionInfo()
: update_url(),
- is_theme(false),
+ expected_crx_type(PendingExtensionInfo::UNKNOWN),
+ is_from_sync(true),
install_silently(false),
enable_on_install(false),
enable_incognito_on_install(false) {}
@@ -274,7 +278,9 @@ void ExtensionsService::UpdateExtension(const std::string& id,
const FilePath& extension_path,
const GURL& download_url) {
PendingExtensionMap::const_iterator it = pending_extensions_.find(id);
- if ((it == pending_extensions_.end()) &&
+ bool is_pending_extension = (it != pending_extensions_.end());
+
+ if (!is_pending_extension &&
!GetExtensionByIdInternal(id, true, true)) {
LOG(WARNING) << "Will not update extension " << id
<< " because it is not installed or pending";
@@ -289,7 +295,7 @@ void ExtensionsService::UpdateExtension(const std::string& id,
// We want a silent install only for non-pending extensions and
// pending extensions that have install_silently set.
ExtensionInstallUI* client =
- ((it == pending_extensions_.end()) || it->second.install_silently) ?
+ (!is_pending_extension || it->second.install_silently) ?
NULL : new ExtensionInstallUI(profile_);
scoped_refptr<CrxInstaller> installer(
@@ -297,32 +303,59 @@ void ExtensionsService::UpdateExtension(const std::string& id,
this, // frontend
client));
installer->set_expected_id(id);
+ if (is_pending_extension && !it->second.is_from_sync)
+ installer->set_install_source(Extension::EXTERNAL_PREF_DOWNLOAD);
installer->set_delete_source(true);
installer->set_original_url(download_url);
installer->InstallCrx(extension_path);
}
-void ExtensionsService::AddPendingExtension(
+void ExtensionsService::AddPendingExtensionFromSync(
const std::string& id, const GURL& update_url,
- bool is_theme, bool install_silently,
- bool enable_on_install, bool enable_incognito_on_install) {
+ PendingExtensionInfo::ExpectedCrxType expected_crx_type,
+ bool install_silently, bool enable_on_install,
+ bool enable_incognito_on_install) {
if (GetExtensionByIdInternal(id, true, true)) {
LOG(DFATAL) << "Trying to add pending extension " << id
<< " which already exists";
return;
}
AddPendingExtensionInternal(
- id, update_url, is_theme, install_silently,
+ id, update_url, expected_crx_type, true, install_silently,
enable_on_install, enable_incognito_on_install);
}
+void ExtensionsService::AddPendingExtensionFromExternalUpdateUrl(
+ const std::string& id, const GURL& update_url) {
+ // Add the extension to this list of extensions to update.
+ // We do not know if the id refers to a theme, so make is_theme unknown.
+ const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType =
+ PendingExtensionInfo::UNKNOWN;
+ const bool kIsFromSync = false;
+ const bool kInstallSilently = true;
+ const bool kEnableOnInstall = true;
+ const bool kEnableIncognitoOnInstall = false;
+
+ if (GetExtensionByIdInternal(id, true, true)) {
+ LOG(DFATAL) << "Trying to add extension " << id
+ << " by external update, but it is already installed.";
+ return;
+ }
+
+ AddPendingExtensionInternal(id, update_url, kExpectedCrxType, kIsFromSync,
+ kInstallSilently, kEnableOnInstall,
+ kEnableIncognitoOnInstall);
+}
+
void ExtensionsService::AddPendingExtensionInternal(
const std::string& id, const GURL& update_url,
- bool is_theme, bool install_silently,
+ PendingExtensionInfo::ExpectedCrxType expected_crx_type,
+ bool is_from_sync, bool install_silently,
bool enable_on_install, bool enable_incognito_on_install) {
pending_extensions_[id] =
- PendingExtensionInfo(update_url, is_theme, install_silently,
- enable_on_install, enable_incognito_on_install);
+ PendingExtensionInfo(update_url, expected_crx_type, is_from_sync,
+ install_silently, enable_on_install,
+ enable_incognito_on_install);
}
void ExtensionsService::ReloadExtension(const std::string& extension_id) {
@@ -1024,14 +1057,22 @@ void ExtensionsService::OnExtensionInstalled(Extension* extension,
pending_extensions_.find(extension->id());
if (it != pending_extensions_.end()) {
PendingExtensionInfo pending_extension_info = it->second;
+ PendingExtensionInfo::ExpectedCrxType expected_crx_type =
+ pending_extension_info.expected_crx_type;
+ bool is_from_sync = pending_extension_info.is_from_sync;
pending_extensions_.erase(it);
it = pending_extensions_.end();
+
// Set initial state from pending extension data.
- if (pending_extension_info.is_theme != extension->is_theme()) {
+ PendingExtensionInfo::ExpectedCrxType actual_crx_type =
+ (extension->is_theme() ? PendingExtensionInfo::THEME
+ : PendingExtensionInfo::EXTENSION);
+
+ if (expected_crx_type != PendingExtensionInfo::UNKNOWN &&
+ expected_crx_type != actual_crx_type) {
LOG(WARNING)
<< "Not installing pending extension " << extension->id()
- << " with is_theme = " << extension->is_theme()
- << "; expected is_theme = " << pending_extension_info.is_theme;
+ << " with is_theme = " << extension->is_theme();
// Delete the extension directory since we're not going to
// load it.
ChromeThread::PostTask(
@@ -1039,13 +1080,29 @@ void ExtensionsService::OnExtensionInstalled(Extension* extension,
NewRunnableFunction(&DeleteFileHelper, extension->path(), true));
return;
}
+
+ // If |extension| is not syncable, and was installed via sync, disallow
+ // the instanation.
+ //
+ // Themes are always allowed. Because they contain no active code, they
+ // are less of a risk than extensions.
+ //
+ // If |is_from_sync| is false, then the install was not initiated by sync,
+ // and this check should pass. Extensions that were installed from an
+ // update URL in external_extensions.json are an example. They are not
+ // syncable, because the user did not make an explicit choice to install
+ // them. However, they were installed through the update mechanism, so
+ // control must pass into this function.
+ //
+ // TODO(akalin): When we do apps sync, we have to work with its
+ // traits, too.
const browser_sync::ExtensionSyncTraits extension_sync_traits =
browser_sync::GetExtensionSyncTraits();
const browser_sync::ExtensionSyncTraits app_sync_traits =
browser_sync::GetAppSyncTraits();
// If an extension is a theme, we bypass the valid/syncable check
// as themes are harmless.
- if (!extension->is_theme() &&
+ if (!extension->is_theme() && is_from_sync &&
!browser_sync::IsExtensionValidAndSyncable(
*extension, extension_sync_traits.allowed_extension_types) &&
!browser_sync::IsExtensionValidAndSyncable(
@@ -1073,7 +1130,7 @@ void ExtensionsService::OnExtensionInstalled(Extension* extension,
NewRunnableFunction(&DeleteFileHelper, extension->path(), true));
return;
}
- if (pending_extension_info.is_theme) {
+ if (extension->is_theme()) {
DCHECK(pending_extension_info.enable_on_install);
initial_state = Extension::ENABLED;
DCHECK(!pending_extension_info.enable_incognito_on_install);
@@ -1187,10 +1244,11 @@ void ExtensionsService::SetProviderForTesting(
location, test_provider));
}
-void ExtensionsService::OnExternalExtensionFound(const std::string& id,
- const std::string& version,
- const FilePath& path,
- Extension::Location location) {
+void ExtensionsService::OnExternalExtensionFileFound(
+ const std::string& id,
+ const std::string& version,
+ const FilePath& path,
+ Extension::Location location) {
// Before even bothering to unpack, check and see if we already have this
// version. This is important because these extensions are going to get
// installed on every startup.
@@ -1303,7 +1361,8 @@ ExtensionsServiceBackend::ExtensionsServiceBackend(
const FilePath& install_directory)
: frontend_(NULL),
install_directory_(install_directory),
- alert_on_error_(false) {
+ alert_on_error_(false),
+ external_extension_added_(false) {
// TODO(aa): This ends up doing blocking IO on the UI thread because it reads
// pref data in the ctor and that is called on the UI thread. Would be better
// to re-read data each time we list external extensions, anyway.
@@ -1396,14 +1455,23 @@ void ExtensionsServiceBackend::CheckForExternalUpdates(
// they could install an extension manually themselves anyway.
alert_on_error_ = false;
frontend_ = frontend;
+ external_extension_added_ = false;
// Ask each external extension provider to give us a call back for each
- // extension they know about. See OnExternalExtensionFound.
+ // extension they know about. See OnExternalExtension(File|UpdateUrl)Found.
+
for (ProviderMap::const_iterator i = external_extension_providers_.begin();
i != external_extension_providers_.end(); ++i) {
ExternalExtensionProvider* provider = i->second.get();
provider->VisitRegisteredExtension(this, ids_to_ignore);
}
+
+ if (external_extension_added_ && frontend->updater()) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ frontend->updater(), &ExtensionUpdater::CheckNow));
+ }
}
void ExtensionsServiceBackend::CheckExternalUninstall(
@@ -1441,16 +1509,27 @@ void ExtensionsServiceBackend::SetProviderForTesting(
linked_ptr<ExternalExtensionProvider>(test_provider);
}
-void ExtensionsServiceBackend::OnExternalExtensionFound(
+void ExtensionsServiceBackend::OnExternalExtensionFileFound(
const std::string& id, const Version* version, const FilePath& path,
Extension::Location location) {
ChromeThread::PostTask(
ChromeThread::UI, FROM_HERE,
NewRunnableMethod(
- frontend_, &ExtensionsService::OnExternalExtensionFound, id,
+ frontend_, &ExtensionsService::OnExternalExtensionFileFound, id,
version->GetString(), path, location));
}
+void ExtensionsServiceBackend::OnExternalExtensionUpdateUrlFound(
+ const std::string& id, const GURL& update_url) {
+ if (frontend_->GetExtensionById(id, true)) {
+ // Already installed. Do not change the update URL that the extension set.
+ return;
+ }
+
+ frontend_->AddPendingExtensionFromExternalUpdateUrl(id, update_url);
+ external_extension_added_ |= true;
+}
+
void ExtensionsServiceBackend::ReloadExtensionManifests(
ExtensionPrefs::ExtensionsInfo* extensions_to_reload,
base::TimeTicks start_time,