[Extensions UI] Plumb a ShowPopupCallback through calls to show popups

Extensions can trigger their toolbar action popup via the
chrome.action.openPopup() API method. Currently, this API waits for the
popup to show by observing newly-created extension hosts, waiting for
one to be created with the popup URL. This has the following issues:
- Most importantly, it doesn't catch failures (e.g., if the popup host
  closes for some reason before the popup is shown). This results in a
  perennially-unresolved promise in the extension and in a never-
  released ExtensionFunction in the browser.
- Tracking the host in this way isn't foolproof - if a popup were
  created for another reason, it would resolve this function. There's
  no way to attribute the popup to the particular API call.

To fix these, add a new callback, ShowPopupCallback, to the
ShowToolbarActionPopupForAPICall() calls. This callback will be invoked
with either the popup's ExtensionHost (on success) or null (on failure),
allowing the ExtensionFunction to appropriately respond to the calling
extension in both cases.

Plumb the callback through the corresponding methods and add a test for
the popup asynchronously failing to fully open.

Bug: 1245093
Change-Id: I277db3495d02c3d3a2bbef91fe2234cd3d6f4311
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3442608
Reviewed-by: Peter Kasting <[email protected]>
Commit-Queue: Devlin Cronin <[email protected]>
Cr-Commit-Position: refs/heads/main@{#969109}
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.h b/chrome/browser/ui/extensions/extension_action_view_controller.h
index 15b3603..487d6599 100644
--- a/chrome/browser/ui/extensions/extension_action_view_controller.h
+++ b/chrome/browser/ui/extensions/extension_action_view_controller.h
@@ -81,7 +81,7 @@
   void OnContextMenuShown() override;
   void OnContextMenuClosed() override;
   void ExecuteUserAction(InvocationSource source) override;
-  void TriggerPopupForAPI() override;
+  void TriggerPopupForAPI(ShowPopupCallback callback) override;
   void UpdateState() override;
   void RegisterCommand() override;
   void UnregisterCommand() override;
@@ -144,12 +144,15 @@
   // user action.
   // The popup may not be shown synchronously if the extension is hidden and
   // first needs to slide itself out.
-  void TriggerPopup(PopupShowAction show_action, bool by_user);
+  void TriggerPopup(PopupShowAction show_action,
+                    bool by_user,
+                    ShowPopupCallback callback);
 
   // Shows the popup with the given |host|.
   void ShowPopup(std::unique_ptr<extensions::ExtensionViewHost> host,
                  bool grant_tab_permissions,
-                 PopupShowAction show_action);
+                 PopupShowAction show_action,
+                 ShowPopupCallback callback);
 
   // Handles cleanup after the popup closes.
   void OnPopupClosed();