Improve the auto-update process by also delaying updates to old-style packaged apps while the app is still in use.
BUG=301827
Review URL: https://codereview.chromium.org/45863008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@232632 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index a37be367..d9e4b1ce 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/memory/ref_counted.h"
#include "chrome/browser/download/download_crx_util.h"
+#include "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
@@ -19,6 +20,7 @@
#include "chrome/common/extensions/feature_switch.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/download_manager.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/test/download_test_observer.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/switches.h"
@@ -208,29 +210,6 @@
mock_prompt->extension_id());
ASSERT_TRUE(permissions.get());
}
-
- // Creates and returns a popup ExtensionHost for an extension and waits
- // for a url to load in the host's web contents.
- // The caller is responsible for cleaning up the returned ExtensionHost.
- ExtensionHost* OpenUrlInExtensionPopupHost(const Extension* extension,
- const GURL& url) {
- ExtensionSystem* extension_system = extensions::ExtensionSystem::Get(
- browser()->profile());
- ExtensionProcessManager* epm = extension_system->process_manager();
- ExtensionHost* extension_host =
- epm->CreatePopupHost(extension, url, browser());
-
- extension_host->CreateRenderViewSoon();
- if (!extension_host->IsRenderViewLive()) {
- content::WindowedNotificationObserver observer(
- content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
- content::Source<content::WebContents>(
- extension_host->host_contents()));
- observer.Wait();
- }
-
- return extension_host;
- }
};
#if defined(OS_CHROMEOS)
@@ -419,10 +398,16 @@
// Make test extension non-idle by opening the extension's browser action
// popup. This should cause the installation to be delayed.
- std::string popup_url = std::string("chrome-extension://")
- + extension_id + std::string("/popup.html");
- scoped_ptr<ExtensionHost> extension_host = scoped_ptr<ExtensionHost>(
- OpenUrlInExtensionPopupHost(extension, GURL(popup_url)));
+ content::WindowedNotificationObserver loading_observer(
+ chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
+ content::Source<Profile>(profile()));
+ BrowserActionTestUtil util(browser());
+ // There is only one extension, so just click the first browser action.
+ ASSERT_EQ(1, util.NumberOfBrowserActions());
+ util.Press(0);
+ loading_observer.Wait();
+ ExtensionHost* extension_host =
+ content::Details<ExtensionHost>(loading_observer.details()).ptr();
// Install version 2 of the extension and check that it is indeed delayed.
ASSERT_TRUE(UpdateExtensionWaitForIdle(
@@ -432,10 +417,14 @@
extension = service->GetExtensionById(extension_id, false);
ASSERT_EQ("1.0", extension->version()->GetString());
- // Make the extension idle again by navigating away from the extension's
- // browser action page. This should not trigger the delayed install.
- extension_system->process_manager()->UnregisterRenderViewHost(
- extension_host->render_view_host());
+ // Make the extension idle again by closing the popup. This should not trigger
+ //the delayed install.
+ content::WindowedNotificationObserver terminated_observer(
+ content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
+ content::Source<content::RenderProcessHost>(
+ extension_host->render_process_host()));
+ extension_host->render_view_host()->ClosePage();
+ terminated_observer.Wait();
ASSERT_EQ(1u, service->delayed_installs()->size());
// Install version 3 of the extension. Because the extension is idle,
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 2db9801a..8261a3ba 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -355,8 +355,6 @@
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
content::NotificationService::AllBrowserContextsAndSources());
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
- content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED,
content::NotificationService::AllBrowserContextsAndSources());
pref_change_registrar_.Init(profile->GetPrefs());
@@ -2497,6 +2495,23 @@
if (!profile_->IsSameProfile(host_profile->GetOriginalProfile()))
break;
+ if (process_map_.Contains(process->GetID())) {
+ // An extension process was terminated, this might have resulted in an
+ // app or extension becoming idle.
+ std::set<std::string> extension_ids =
+ process_map_.GetExtensionsInProcess(process->GetID());
+ for (std::set<std::string>::const_iterator it = extension_ids.begin();
+ it != extension_ids.end(); ++it) {
+ if (delayed_installs_.Contains(*it)) {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ExtensionService::MaybeFinishDelayedInstallation,
+ AsWeakPtr(), *it),
+ base::TimeDelta::FromSeconds(kUpdateIdleDelay));
+ }
+ }
+ }
+
process_map_.RemoveAllFromProcess(process->GetID());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -2505,21 +2520,6 @@
process->GetID()));
break;
}
- case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
- extensions::ExtensionHost* host =
- content::Details<extensions::ExtensionHost>(details).ptr();
- std::string extension_id = host->extension_id();
- if (delayed_installs_.Contains(extension_id)) {
- // We were waiting for this extension to become idle, it now might have,
- // so maybe finish installation.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&ExtensionService::MaybeFinishDelayedInstallation,
- AsWeakPtr(), extension_id),
- base::TimeDelta::FromSeconds(kUpdateIdleDelay));
- }
- break;
- }
case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: {
// Notify extensions that chrome update is available.
extensions::RuntimeEventRouter::DispatchOnBrowserUpdateAvailableEvent(
@@ -2641,6 +2641,13 @@
process_manager->GetBackgroundHostForExtension(extension_id);
if (host)
return false;
+
+ content::SiteInstance* site_instance = process_manager->GetSiteInstanceForURL(
+ Extension::GetBaseURLFromExtensionId(extension_id));
+ if (site_instance && site_instance->HasProcess()) {
+ return false;
+ }
+
return process_manager->GetRenderViewHostsForExtension(extension_id).empty();
}