Use `InfoBarObserver` to reconcile invalid pointers in `EmulationHandler`

Fixed: 1302189
Change-Id: I91cbaa5a0a30930a442fa17d7739f76be6c37ff4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3499005
Auto-Submit: Randolf Jung <[email protected]>
Reviewed-by: Andrey Kosyakov <[email protected]>
Commit-Queue: Randolf Jung <[email protected]>
Cr-Commit-Position: refs/heads/main@{#977615}
diff --git a/chrome/browser/devtools/protocol/emulation_handler.cc b/chrome/browser/devtools/protocol/emulation_handler.cc
index ab466b05..afdef64 100644
--- a/chrome/browser/devtools/protocol/emulation_handler.cc
+++ b/chrome/browser/devtools/protocol/emulation_handler.cc
@@ -13,6 +13,9 @@
     : agent_host_(agent_host) {
   protocol::Emulation::Dispatcher::wire(dispatcher, this);
 }
+EmulationHandler::~EmulationHandler() {
+  SetAutomationOverride(false);
+}
 
 protocol::Response EmulationHandler::Disable() {
   SetAutomationOverride(false);
@@ -20,30 +23,44 @@
 }
 
 protocol::Response EmulationHandler::SetAutomationOverride(bool enabled) {
-  // Fallthrough requests when the override is already enabled.
-  if (enabled && automation_info_bar_)
+  if (!enabled) {
+    if (automation_info_bar_) {
+      automation_info_bar_->RemoveSelf();
+    }
     return protocol::Response::FallThrough();
-
-  infobars::ContentInfoBarManager* info_bar_manager = nullptr;
-  content::WebContents* web_contents = agent_host_->GetWebContents();
-  if (web_contents) {
-    info_bar_manager = infobars::ContentInfoBarManager::FromWebContents(
-        web_contents->GetOutermostWebContents());
   }
+  if (automation_info_bar_) {
+    return protocol::Response::FallThrough();
+  }
+
+  infobars::ContentInfoBarManager* info_bar_manager =
+      GetContentInfoBarManager();
   if (!info_bar_manager) {
     // Implies the web content cannot have an info bar attached. A priori, the
     // automation override doesn't matter on the chrome layer.
     return protocol::Response::FallThrough();
   }
 
-  if (!enabled) {
-    if (automation_info_bar_) {
-      info_bar_manager->RemoveInfoBar(automation_info_bar_);
-      automation_info_bar_ = nullptr;
-    }
-    return protocol::Response::FallThrough();
-  }
-
+  // Note since the observer removes itself when the info bar is removed, the
+  // observer is added at most once because of the info bar nullity check above.
+  info_bar_manager->AddObserver(this);
   automation_info_bar_ = AutomationInfoBarDelegate::Create(info_bar_manager);
   return protocol::Response::FallThrough();
 }
+
+infobars::ContentInfoBarManager* EmulationHandler::GetContentInfoBarManager() {
+  content::WebContents* web_contents = agent_host_->GetWebContents();
+  if (!web_contents) {
+    return nullptr;
+  }
+  return infobars::ContentInfoBarManager::FromWebContents(
+      web_contents->GetOutermostWebContents());
+}
+
+void EmulationHandler::OnInfoBarRemoved(infobars::InfoBar* infobar,
+                                        bool animate) {
+  if (automation_info_bar_ == infobar) {
+    infobar->owner()->RemoveObserver(this);
+    automation_info_bar_ = nullptr;
+  }
+}