Commit 7a42da02 authored by Glen Robertson's avatar Glen Robertson Committed by Chromium LUCI CQ

Try to avoid observing ABM that may be destroyed.

Sometimes WebAppMetrics is still holding a foreground_web_contents on
shutdown, and thus fails to deregister itself as an observer of the
associated AppBannerManager, which is already gone.
This change adds extra checks to try to prevent getting into this state,
and dumps crash reports if in an unexpected state.

Bug: 1162123
Change-Id: I142e6cc30395decf7a09ca2c6773de8c65865535
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2620919
Commit-Queue: Glen Robertson <glenrob@chromium.org>
Reviewed-by: default avatarMatthew Denton <mpdenton@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843424}
parent fabc0b0b
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chrome/browser/ui/web_applications/web_app_metrics.h" #include "chrome/browser/ui/web_applications/web_app_metrics.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/debug/dump_without_crashing.h"
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/power_monitor/power_monitor.h" #include "base/power_monitor/power_monitor.h"
...@@ -94,6 +95,10 @@ WebAppMetrics::WebAppMetrics(Profile* profile) ...@@ -94,6 +95,10 @@ WebAppMetrics::WebAppMetrics(Profile* profile)
} }
WebAppMetrics::~WebAppMetrics() { WebAppMetrics::~WebAppMetrics() {
// Foreground web contents should already be nullptr by this point, or we have
// somehow missed being notified of its destruction.
if (foreground_web_contents_ != nullptr)
base::debug::DumpWithoutCrashing();
UpdateForegroundWebContents(nullptr); UpdateForegroundWebContents(nullptr);
BrowserList::RemoveObserver(this); BrowserList::RemoveObserver(this);
base::PowerMonitor::RemoveObserver(this); base::PowerMonitor::RemoveObserver(this);
...@@ -188,6 +193,13 @@ void WebAppMetrics::OnTabStripModelChanged( ...@@ -188,6 +193,13 @@ void WebAppMetrics::OnTabStripModelChanged(
UpdateForegroundWebContents(selection.new_contents); UpdateForegroundWebContents(selection.new_contents);
// Contents being replaced should never be the new selection.
if (change.type() == TabStripModelChange::kReplaced &&
change.GetReplace()->old_contents == foreground_web_contents_) {
base::debug::DumpWithoutCrashing();
UpdateForegroundWebContents(nullptr);
}
if (change.type() == TabStripModelChange::kRemoved) { if (change.type() == TabStripModelChange::kRemoved) {
for (const TabStripModelChange::ContentsWithIndexAndWillBeDeleted& for (const TabStripModelChange::ContentsWithIndexAndWillBeDeleted&
contents : change.GetRemove()->contents) { contents : change.GetRemove()->contents) {
...@@ -196,13 +208,16 @@ void WebAppMetrics::OnTabStripModelChanged( ...@@ -196,13 +208,16 @@ void WebAppMetrics::OnTabStripModelChanged(
WebAppTabHelperBase::FromWebContents(contents.contents); WebAppTabHelperBase::FromWebContents(contents.contents);
if (tab_helper && !tab_helper->GetAppId().empty()) if (tab_helper && !tab_helper->GetAppId().empty())
app_last_interacted_time_.erase(tab_helper->GetAppId()); app_last_interacted_time_.erase(tab_helper->GetAppId());
// Foreground contents should not be going away. // Newly-selected foreground contents should not be going away.
DCHECK_NE(contents.contents, foreground_web_contents_); if (contents.contents == foreground_web_contents_) {
base::debug::DumpWithoutCrashing();
UpdateForegroundWebContents(nullptr);
}
} }
} }
} }
UpdateUkmData(selection.new_contents, TabSwitching::kTo); UpdateUkmData(foreground_web_contents_, TabSwitching::kTo);
} }
void WebAppMetrics::OnSuspend() { void WebAppMetrics::OnSuspend() {
...@@ -263,6 +278,13 @@ void WebAppMetrics::OnInstallableWebAppStatusUpdated() { ...@@ -263,6 +278,13 @@ void WebAppMetrics::OnInstallableWebAppStatusUpdated() {
UpdateUkmData(foreground_web_contents_, TabSwitching::kTo); UpdateUkmData(foreground_web_contents_, TabSwitching::kTo);
} }
void WebAppMetrics::WebContentsDestroyed() {
// TODO (crbug.com/1162123): Remove this method in M91 or later.
// Should have stopped observing this WebContents before this point.
base::debug::DumpWithoutCrashing();
UpdateForegroundWebContents(nullptr);
}
void WebAppMetrics::RemoveBrowserListObserverForTesting() { void WebAppMetrics::RemoveBrowserListObserverForTesting() {
BrowserList::RemoveObserver(this); BrowserList::RemoveObserver(this);
} }
...@@ -359,6 +381,7 @@ void WebAppMetrics::UpdateForegroundWebContents(WebContents* web_contents) { ...@@ -359,6 +381,7 @@ void WebAppMetrics::UpdateForegroundWebContents(WebContents* web_contents) {
return; return;
app_banner_manager_observer_.RemoveAll(); app_banner_manager_observer_.RemoveAll();
foreground_web_contents_ = web_contents; foreground_web_contents_ = web_contents;
WebContentsObserver::Observe(web_contents);
if (web_contents) { if (web_contents) {
auto* app_banner_manager = auto* app_banner_manager =
webapps::AppBannerManager::FromWebContents(web_contents); webapps::AppBannerManager::FromWebContents(web_contents);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "chrome/browser/web_applications/components/web_app_id.h" #include "chrome/browser/web_applications/components/web_app_id.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
#include "components/site_engagement/content/site_engagement_observer.h" #include "components/site_engagement/content/site_engagement_observer.h"
#include "content/public/browser/web_contents_observer.h"
class Profile; class Profile;
class Browser; class Browser;
...@@ -32,6 +33,7 @@ class WebAppMetrics : public KeyedService, ...@@ -32,6 +33,7 @@ class WebAppMetrics : public KeyedService,
public BrowserListObserver, public BrowserListObserver,
public TabStripModelObserver, public TabStripModelObserver,
public webapps::AppBannerManager::Observer, public webapps::AppBannerManager::Observer,
public content::WebContentsObserver,
public base::PowerObserver { public base::PowerObserver {
public: public:
static WebAppMetrics* Get(Profile* profile); static WebAppMetrics* Get(Profile* profile);
...@@ -69,6 +71,9 @@ class WebAppMetrics : public KeyedService, ...@@ -69,6 +71,9 @@ class WebAppMetrics : public KeyedService,
// webapps::AppBannerManager::Observer: // webapps::AppBannerManager::Observer:
void OnInstallableWebAppStatusUpdated() override; void OnInstallableWebAppStatusUpdated() override;
// content::WebContentsObserver:
void WebContentsDestroyed() override;
// Browser activation causes flaky tests. Call observer methods directly. // Browser activation causes flaky tests. Call observer methods directly.
void RemoveBrowserListObserverForTesting(); void RemoveBrowserListObserverForTesting();
void CountUserInstalledAppsForTesting(); void CountUserInstalledAppsForTesting();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment