| Index: chrome/browser/extensions/extension_gcm_app_handler.cc
|
| diff --git a/chrome/browser/extensions/extension_gcm_app_handler.cc b/chrome/browser/extensions/extension_gcm_app_handler.cc
|
| index c55111e8a28d8bad3d11748d9c7f51462f15b48c..8791df0326f5bec186ed7215ae3da9d7e3e63ae3 100644
|
| --- a/chrome/browser/extensions/extension_gcm_app_handler.cc
|
| +++ b/chrome/browser/extensions/extension_gcm_app_handler.cc
|
| @@ -25,6 +25,8 @@ namespace extensions {
|
|
|
| namespace {
|
|
|
| +const char kDummyAppId[] = "extension.guard.dummy.id";
|
| +
|
| base::LazyInstance<BrowserContextKeyedAPIFactory<ExtensionGCMAppHandler> >
|
| g_factory = LAZY_INSTANCE_INITIALIZER;
|
|
|
| @@ -94,15 +96,37 @@ void ExtensionGCMAppHandler::OnExtensionLoaded(
|
| content::BrowserContext* browser_context,
|
| const Extension* extension) {
|
| if (IsGCMPermissionEnabled(extension))
|
| - GetGCMDriver()->AddAppHandler(extension->id(), this);
|
| + AddAppHandler(extension->id());
|
| }
|
|
|
| void ExtensionGCMAppHandler::OnExtensionUnloaded(
|
| content::BrowserContext* browser_context,
|
| const Extension* extension,
|
| UnloadedExtensionInfo::Reason reason) {
|
| - if (IsGCMPermissionEnabled(extension))
|
| - GetGCMDriver()->RemoveAppHandler(extension->id());
|
| + if (!IsGCMPermissionEnabled(extension))
|
| + return;
|
| +
|
| + if (reason == UnloadedExtensionInfo::REASON_UPDATE &&
|
| + GetGCMDriver()->app_handlers().size() == 1) {
|
| + // When the extension is being updated, it will be first unloaded and then
|
| + // loaded again by ExtensionService::AddExtension. If the app handler for
|
| + // this extension is the only handler, removing it and adding it again will
|
| + // cause the GCM service being stopped and restarted unnecessarily. To work
|
| + // around this, we add a dummy app handler to guard against it. This dummy
|
| + // app handler will be removed once the extension loading logic is done.
|
| + //
|
| + // Also note that the GCM message routing will not be interruptted during
|
| + // the update process since unloading and reloading extension are done in
|
| + // the single function ExtensionService::AddExtension.
|
| + AddDummyAppHandler();
|
| +
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&ExtensionGCMAppHandler::RemoveDummyAppHandler,
|
| + weak_factory_.GetWeakPtr()));
|
| + }
|
| +
|
| + RemoveAppHandler(extension->id());
|
| }
|
|
|
| void ExtensionGCMAppHandler::OnExtensionUninstalled(
|
| @@ -114,10 +138,18 @@ void ExtensionGCMAppHandler::OnExtensionUninstalled(
|
| base::Bind(&ExtensionGCMAppHandler::OnUnregisterCompleted,
|
| weak_factory_.GetWeakPtr(),
|
| extension->id()));
|
| - GetGCMDriver()->RemoveAppHandler(extension->id());
|
| + RemoveAppHandler(extension->id());
|
| }
|
| }
|
|
|
| +void ExtensionGCMAppHandler::AddDummyAppHandler() {
|
| + AddAppHandler(kDummyAppId);
|
| +}
|
| +
|
| +void ExtensionGCMAppHandler::RemoveDummyAppHandler() {
|
| + RemoveAppHandler(kDummyAppId);
|
| +}
|
| +
|
| gcm::GCMDriver* ExtensionGCMAppHandler::GetGCMDriver() const {
|
| return gcm::GCMProfileServiceFactory::GetForProfile(profile_)->driver();
|
| }
|
| @@ -127,4 +159,12 @@ void ExtensionGCMAppHandler::OnUnregisterCompleted(
|
| // Nothing to do.
|
| }
|
|
|
| +void ExtensionGCMAppHandler::AddAppHandler(const std::string& app_id) {
|
| + GetGCMDriver()->AddAppHandler(app_id, this);
|
| +}
|
| +
|
| +void ExtensionGCMAppHandler::RemoveAppHandler(const std::string& app_id) {
|
| + GetGCMDriver()->RemoveAppHandler(app_id);
|
| +}
|
| +
|
| } // namespace extensions
|
|
|