#include "chrome/browser/extensions/extension_install_ui.h"
#include "chrome/browser/extensions/extension_special_storage_policy.h"
#include "chrome/browser/extensions/extension_sync_service.h"
-#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/external_install_ui.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "extensions/browser/app_sorting.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/external_provider_interface.h"
#include "extensions/browser/management_policy.h"
DISALLOW_COPY_AND_ASSIGN(SharedModuleProvider);
};
+enum VerifyAllSuccess {
+ VERIFY_ALL_BOOTSTRAP_SUCCESS = 0,
+ VERIFY_ALL_BOOTSTRAP_FAILURE,
+ VERIFY_ALL_NON_BOOTSTRAP_SUCCESS,
+ VERIFY_ALL_NON_BOOTSTRAP_FAILURE,
+
+ // Used in histograms. Do not remove/reorder any entries above, and the below
+ // MAX entry should always come last.
+
+ VERIFY_ALL_SUCCESS_MAX
+};
+
+void LogVerifyAllSuccessHistogram(bool bootstrap, bool success) {
+ VerifyAllSuccess result;
+ if (bootstrap && success)
+ result = VERIFY_ALL_BOOTSTRAP_SUCCESS;
+ else if (bootstrap && !success)
+ result = VERIFY_ALL_BOOTSTRAP_FAILURE;
+ else if (!bootstrap && success)
+ result = VERIFY_ALL_NON_BOOTSTRAP_SUCCESS;
+ else
+ result = VERIFY_ALL_NON_BOOTSTRAP_FAILURE;
+
+ UMA_HISTOGRAM_ENUMERATION("ExtensionService.VerifyAllSuccess",
+ result, VERIFY_ALL_SUCCESS_MAX);
+}
+
+void LogAddVerifiedSuccess(bool success) {
+ UMA_HISTOGRAM_BOOLEAN("ExtensionService.AddVerified", success);
+}
} // namespace
return ®istry_->enabled_extensions();
}
-const ExtensionSet* ExtensionService::disabled_extensions() const {
- return ®istry_->disabled_extensions();
-}
-
const ExtensionSet* ExtensionService::delayed_installs() const {
return &delayed_installs_;
}
// rather than running immediately at startup.
CheckForExternalUpdates();
- InstallVerifier* verifier =
- extensions::ExtensionSystem::Get(profile_)->install_verifier();
- if (verifier->NeedsBootstrap())
- VerifyAllExtensions();
+ MaybeBootstrapVerifier();
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()),
}
}
-void ExtensionService::VerifyAllExtensions() {
+void ExtensionService::MaybeBootstrapVerifier() {
+ InstallVerifier* verifier =
+ extensions::ExtensionSystem::Get(profile_)->install_verifier();
+ bool do_bootstrap = false;
+
+ if (verifier->NeedsBootstrap()) {
+ do_bootstrap = true;
+ } else {
+ // If any of the installed extensions have an install time newer than the
+ // signature's timestamp, we need to bootstrap because our signature may
+ // be missing valid extensions.
+ base::Time timestamp = verifier->SignatureTimestamp();
+ scoped_ptr<extensions::ExtensionSet> extensions =
+ GenerateInstalledExtensionsSet();
+ for (extensions::ExtensionSet::const_iterator i = extensions->begin();
+ i != extensions->end();
+ ++i) {
+ const Extension& extension = **i;
+ base::Time install_time =
+ extension_prefs_->GetInstallTime(extension.id());
+ if (verifier->NeedsVerification(extension) &&
+ install_time < base::Time::Now() && install_time >= timestamp) {
+ do_bootstrap = true;
+ break;
+ }
+ }
+ }
+ if (do_bootstrap)
+ VerifyAllExtensions(true); // bootstrap=true.
+}
+
+void ExtensionService::VerifyAllExtensions(bool bootstrap) {
ExtensionIdSet to_add;
scoped_ptr<ExtensionSet> all_extensions = GenerateInstalledExtensionsSet();
}
extensions::ExtensionSystem::Get(profile_)->install_verifier()->AddMany(
to_add, base::Bind(&ExtensionService::FinishVerifyAllExtensions,
- AsWeakPtr()));
+ AsWeakPtr(), bootstrap));
}
-void ExtensionService::FinishVerifyAllExtensions(bool success) {
+void ExtensionService::FinishVerifyAllExtensions(bool bootstrap, bool success) {
+ LogVerifyAllSuccessHistogram(bootstrap, success);
if (success) {
// Check to see if any currently unverified extensions became verified.
InstallVerifier* verifier =
// Certain extension locations are specific enough that we can
// auto-acknowledge any extension that came from one of them.
- if (Manifest::IsPolicyLocation(extension->location()))
+ if (Manifest::IsPolicyLocation(extension->location()) ||
+ extension->location() == Manifest::EXTERNAL_COMPONENT)
AcknowledgeExternalExtension(extension->id());
const Extension::State initial_state =
initial_enable ? Extension::ENABLED : Extension::DISABLED;
delayed_installs_.Remove(extension->id());
if (InstallVerifier::NeedsVerification(*extension)) {
extensions::ExtensionSystem::Get(profile_)->install_verifier()->Add(
- extension->id(), InstallVerifier::AddResultCallback());
+ extension->id(), base::Bind(LogAddVerifiedSuccess));
}
FinishInstallation(extension);
}
void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
// No need to check for duplicates; inserting a duplicate is a no-op.
registry_->AddTerminated(make_scoped_refptr(extension));
+ extensions_being_terminated_.erase(extension->id());
UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_TERMINATE);
}
extensions::ExtensionHost* host =
content::Details<extensions::ExtensionHost>(details).ptr();
+ // If the extension is already being terminated, there is nothing left to
+ // do.
+ if (!extensions_being_terminated_.insert(host->extension_id()).second)
+ break;
+
// Mark the extension as terminated and Unload it. We want it to
// be in a consistent state: either fully working or not loaded
// at all, but never half-crashed. We do it in a PostTask so