Commit 88541ce7 authored by Thomas Lukaszewicz's avatar Thomas Lukaszewicz Committed by Chromium LUCI CQ

Tab Search: Remove page handler when Tab Search is hidden

This patch introduces a EmbedderHidden() method that enables bubble
WebUIController subclasses to take appropriate action when their
embedder is no longer visible.

TabSearchUI overrides this to destroy the |page_handler_| when its
embedding bubble is no longer visible to prevent background updates.

Cleaned up use of member variables in WebUIBubbleManagerBase and
WebUIBubbleManager<T>.

Bug: 1099917, 1166967
Change-Id: I374dd74b5a1c3d37a53e7213e64c096adef35bda
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2626114Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Reviewed-by: default avatardpapad <dpapad@chromium.org>
Reviewed-by: default avatarYuheng Huang <yuhengh@chromium.org>
Commit-Queue: Thomas Lukaszewicz <tluk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844343}
parent 91eef299
...@@ -16,17 +16,8 @@ constexpr base::TimeDelta kWebViewRetentionTime = ...@@ -16,17 +16,8 @@ constexpr base::TimeDelta kWebViewRetentionTime =
} // namespace } // namespace
WebUIBubbleManagerBase::WebUIBubbleManagerBase( WebUIBubbleManagerBase::WebUIBubbleManagerBase(views::View* anchor_view)
int task_manager_string_id, : anchor_view_(anchor_view),
views::View* anchor_view,
content::BrowserContext* browser_context,
const GURL& webui_url,
bool enable_extension_apis)
: task_manager_string_id_(task_manager_string_id),
anchor_view_(anchor_view),
browser_context_(browser_context),
webui_url_(webui_url),
enable_extension_apis_(enable_extension_apis),
cache_timer_(std::make_unique<base::RetainingOneShotTimer>( cache_timer_(std::make_unique<base::RetainingOneShotTimer>(
FROM_HERE, FROM_HERE,
kWebViewRetentionTime, kWebViewRetentionTime,
...@@ -82,6 +73,7 @@ void WebUIBubbleManagerBase::OnWidgetDestroying(views::Widget* widget) { ...@@ -82,6 +73,7 @@ void WebUIBubbleManagerBase::OnWidgetDestroying(views::Widget* widget) {
bubble_widget_observation_.Reset(); bubble_widget_observation_.Reset();
DCHECK(close_bubble_helper_); DCHECK(close_bubble_helper_);
close_bubble_helper_.reset(); close_bubble_helper_.reset();
WebViewHidden();
cache_timer_->Reset(); cache_timer_->Reset();
bubble_using_cached_webview_ = false; bubble_using_cached_webview_ = false;
} }
......
...@@ -28,11 +28,7 @@ class WebUIBubbleDialogView; ...@@ -28,11 +28,7 @@ class WebUIBubbleDialogView;
// and caching of the WebView. // and caching of the WebView.
class WebUIBubbleManagerBase : public views::WidgetObserver { class WebUIBubbleManagerBase : public views::WidgetObserver {
public: public:
WebUIBubbleManagerBase(int task_manager_string_id, explicit WebUIBubbleManagerBase(views::View* anchor_view);
views::View* anchor_view,
content::BrowserContext* browser_context,
const GURL& webui_url,
bool enable_extension_apis = false);
WebUIBubbleManagerBase(const WebUIBubbleManagerBase&) = delete; WebUIBubbleManagerBase(const WebUIBubbleManagerBase&) = delete;
const WebUIBubbleManagerBase& operator=(const WebUIBubbleManagerBase&) = const WebUIBubbleManagerBase& operator=(const WebUIBubbleManagerBase&) =
delete; delete;
...@@ -45,10 +41,6 @@ class WebUIBubbleManagerBase : public views::WidgetObserver { ...@@ -45,10 +41,6 @@ class WebUIBubbleManagerBase : public views::WidgetObserver {
// views::WidgetObserver: // views::WidgetObserver:
void OnWidgetDestroying(views::Widget* widget) override; void OnWidgetDestroying(views::Widget* widget) override;
int task_manager_string_id() const { return task_manager_string_id_; }
content::BrowserContext* browser_context() { return browser_context_; }
const GURL& webui_url() const { return webui_url_; }
bool enable_extension_apis() const { return enable_extension_apis_; }
bool bubble_using_cached_webview() const { bool bubble_using_cached_webview() const {
return bubble_using_cached_webview_; return bubble_using_cached_webview_;
} }
...@@ -58,19 +50,16 @@ class WebUIBubbleManagerBase : public views::WidgetObserver { ...@@ -58,19 +50,16 @@ class WebUIBubbleManagerBase : public views::WidgetObserver {
return bubble_view_; return bubble_view_;
} }
protected:
WebUIBubbleView* cached_web_view() { return cached_web_view_.get(); }
private: private:
virtual std::unique_ptr<WebUIBubbleView> CreateWebView() = 0; virtual std::unique_ptr<WebUIBubbleView> CreateWebView() = 0;
virtual void WebViewHidden() = 0;
void ResetWebView(); void ResetWebView();
// Used for tagging the web contents so that a distinctive name shows up in
// the task manager.
const int task_manager_string_id_;
views::View* anchor_view_; views::View* anchor_view_;
content::BrowserContext* browser_context_;
GURL webui_url_;
base::WeakPtr<WebUIBubbleDialogView> bubble_view_; base::WeakPtr<WebUIBubbleDialogView> bubble_view_;
const bool enable_extension_apis_;
// Tracks whether the current bubble was created by reusing // Tracks whether the current bubble was created by reusing
// |cached_web_view_|. // |cached_web_view_|.
...@@ -95,13 +84,23 @@ class WebUIBubbleManagerBase : public views::WidgetObserver { ...@@ -95,13 +84,23 @@ class WebUIBubbleManagerBase : public views::WidgetObserver {
template <typename T> template <typename T>
class WebUIBubbleManager : public WebUIBubbleManagerBase { class WebUIBubbleManager : public WebUIBubbleManagerBase {
public: public:
using WebUIBubbleManagerBase::WebUIBubbleManagerBase; WebUIBubbleManager(int task_manager_string_id,
views::View* anchor_view,
content::BrowserContext* browser_context,
const GURL& webui_url,
bool enable_extension_apis = false)
: WebUIBubbleManagerBase(anchor_view),
task_manager_string_id_(task_manager_string_id),
browser_context_(browser_context),
webui_url_(webui_url),
enable_extension_apis_(enable_extension_apis) {}
~WebUIBubbleManager() override = default;
private: private:
std::unique_ptr<WebUIBubbleView> CreateWebView() override { std::unique_ptr<WebUIBubbleView> CreateWebView() override {
auto web_view = std::make_unique<WebUIBubbleView>(browser_context()); auto web_view = std::make_unique<WebUIBubbleView>(browser_context_);
content::WebContents* web_contents = web_view->GetWebContents(); content::WebContents* web_contents = web_view->GetWebContents();
if (enable_extension_apis()) { if (enable_extension_apis_) {
// In order for the WebUI in the renderer to use extensions APIs we must // In order for the WebUI in the renderer to use extensions APIs we must
// add a ChromeExtensionWebContentsObserver to the WebView's WebContents. // add a ChromeExtensionWebContentsObserver to the WebView's WebContents.
extensions::ChromeExtensionWebContentsObserver::CreateForWebContents( extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
...@@ -109,11 +108,24 @@ class WebUIBubbleManager : public WebUIBubbleManagerBase { ...@@ -109,11 +108,24 @@ class WebUIBubbleManager : public WebUIBubbleManagerBase {
} }
task_manager::WebContentsTags::CreateForToolContents( task_manager::WebContentsTags::CreateForToolContents(
web_contents, task_manager_string_id()); web_contents, task_manager_string_id_);
web_view->template LoadURL<T>(webui_url_);
web_view->template LoadURL<T>(webui_url());
return web_view; return web_view;
} }
void WebViewHidden() override {
DCHECK(cached_web_view());
return cached_web_view()
->template GetWebUIController<T>()
->EmbedderHidden();
}
// Used for tagging the web contents so that a distinctive name shows up in
// the task manager.
const int task_manager_string_id_;
content::BrowserContext* browser_context_;
const GURL webui_url_;
const bool enable_extension_apis_;
}; };
#endif // CHROME_BROWSER_UI_VIEWS_BUBBLE_WEBUI_BUBBLE_MANAGER_H_ #endif // CHROME_BROWSER_UI_VIEWS_BUBBLE_WEBUI_BUBBLE_MANAGER_H_
...@@ -16,19 +16,22 @@ namespace { ...@@ -16,19 +16,22 @@ namespace {
class TestWebUIBubbleManager : public WebUIBubbleManagerBase { class TestWebUIBubbleManager : public WebUIBubbleManagerBase {
public: public:
explicit TestWebUIBubbleManager(Browser* browser) explicit TestWebUIBubbleManager(Browser* browser)
: WebUIBubbleManagerBase(IDS_ACCNAME_TAB_SEARCH, : WebUIBubbleManagerBase(BrowserView::GetBrowserViewForBrowser(browser)),
BrowserView::GetBrowserViewForBrowser(browser), browser_context_(browser->profile()) {}
browser->profile(),
GURL("chrome://about")) {}
TestWebUIBubbleManager(const TestWebUIBubbleManager&) = delete; TestWebUIBubbleManager(const TestWebUIBubbleManager&) = delete;
const TestWebUIBubbleManager& operator=(const TestWebUIBubbleManager&) = const TestWebUIBubbleManager& operator=(const TestWebUIBubbleManager&) =
delete; delete;
~TestWebUIBubbleManager() override = default; ~TestWebUIBubbleManager() override = default;
// WebUIBubbleManagerBase:
void WebViewHidden() override {}
private: private:
std::unique_ptr<WebUIBubbleView> CreateWebView() override { std::unique_ptr<WebUIBubbleView> CreateWebView() override {
return std::make_unique<WebUIBubbleView>(browser_context()); return std::make_unique<WebUIBubbleView>(browser_context_);
} }
content::BrowserContext* browser_context_;
}; };
} // namespace } // namespace
......
...@@ -42,11 +42,14 @@ class WebUIBubbleView : public views::WebView, ...@@ -42,11 +42,14 @@ class WebUIBubbleView : public views::WebView,
GetWebContents()->WasShown(); GetWebContents()->WasShown();
SetVisible(true); SetVisible(true);
LoadInitialURL(url); LoadInitialURL(url);
T* async_webui_controller =
GetWebContents()->GetWebUI()->GetController()->template GetAs<T>();
// Depends on the WebUIController object being constructed synchronously // Depends on the WebUIController object being constructed synchronously
// when the navigation is started in LoadInitialURL(). // when the navigation is started in LoadInitialURL().
async_webui_controller->set_embedder(weak_ptr_factory_.GetWeakPtr()); GetWebUIController<T>()->set_embedder(weak_ptr_factory_.GetWeakPtr());
}
template <typename T>
T* GetWebUIController() {
return GetWebContents()->GetWebUI()->GetController()->template GetAs<T>();
} }
void set_host(Host* host) { host_ = host; } void set_host(Host* host) { host_ = host; }
......
...@@ -90,6 +90,10 @@ TabSearchUI::TabSearchUI(content::WebUI* web_ui) ...@@ -90,6 +90,10 @@ TabSearchUI::TabSearchUI(content::WebUI* web_ui)
TabSearchUI::~TabSearchUI() = default; TabSearchUI::~TabSearchUI() = default;
void TabSearchUI::EmbedderHidden() {
page_handler_.reset();
}
WEB_UI_CONTROLLER_TYPE_IMPL(TabSearchUI) WEB_UI_CONTROLLER_TYPE_IMPL(TabSearchUI)
void TabSearchUI::BindInterface( void TabSearchUI::BindInterface(
......
...@@ -25,11 +25,18 @@ class TabSearchUI : public ui::MojoBubbleWebUIController, ...@@ -25,11 +25,18 @@ class TabSearchUI : public ui::MojoBubbleWebUIController,
TabSearchUI& operator=(const TabSearchUI&) = delete; TabSearchUI& operator=(const TabSearchUI&) = delete;
~TabSearchUI() override; ~TabSearchUI() override;
// ui::MojoBubbleWebUIController:
void EmbedderHidden() override;
// Instantiates the implementor of the mojom::PageHandlerFactory mojo // Instantiates the implementor of the mojom::PageHandlerFactory mojo
// interface passing the pending receiver that will be internally bound. // interface passing the pending receiver that will be internally bound.
void BindInterface( void BindInterface(
mojo::PendingReceiver<tab_search::mojom::PageHandlerFactory> receiver); mojo::PendingReceiver<tab_search::mojom::PageHandlerFactory> receiver);
TabSearchPageHandler* page_handler_for_testing() {
return page_handler_.get();
}
private: private:
// tab_search::mojom::PageHandlerFactory // tab_search::mojom::PageHandlerFactory
void CreatePageHandler( void CreatePageHandler(
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/webui/tab_search/tab_search_ui.h"
#include "chrome/common/chrome_isolated_world_ids.h" #include "chrome/common/chrome_isolated_world_ids.h"
#include "chrome/common/webui_url_constants.h" #include "chrome/common/webui_url_constants.h"
#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/in_process_browser_test.h"
...@@ -48,6 +49,12 @@ class TabSearchUIBrowserTest : public InProcessBrowserTest { ...@@ -48,6 +49,12 @@ class TabSearchUIBrowserTest : public InProcessBrowserTest {
return browser()->tab_strip_model()->GetActiveWebContents(); return browser()->tab_strip_model()->GetActiveWebContents();
} }
TabSearchUI* GetWebUIController() {
return webui_contents_->GetWebUI()
->GetController()
->template GetAs<TabSearchUI>();
}
protected: protected:
std::unique_ptr<content::WebContents> webui_contents_; std::unique_ptr<content::WebContents> webui_contents_;
...@@ -55,6 +62,14 @@ class TabSearchUIBrowserTest : public InProcessBrowserTest { ...@@ -55,6 +62,14 @@ class TabSearchUIBrowserTest : public InProcessBrowserTest {
base::test::ScopedFeatureList feature_list_; base::test::ScopedFeatureList feature_list_;
}; };
IN_PROC_BROWSER_TEST_F(TabSearchUIBrowserTest,
EmbedderHiddenDestroysPageHandler) {
EXPECT_NE(nullptr, GetWebUIController());
EXPECT_NE(nullptr, GetWebUIController()->page_handler_for_testing());
GetWebUIController()->EmbedderHidden();
EXPECT_EQ(nullptr, GetWebUIController()->page_handler_for_testing());
}
// TODO(romanarora): Investigate a way to call WebUI custom methods and refactor // TODO(romanarora): Investigate a way to call WebUI custom methods and refactor
// JS code below. // JS code below.
......
...@@ -35,6 +35,9 @@ class MojoBubbleWebUIController : public MojoWebUIController { ...@@ -35,6 +35,9 @@ class MojoBubbleWebUIController : public MojoWebUIController {
void set_embedder(base::WeakPtr<Embedder> embedder) { embedder_ = embedder; } void set_embedder(base::WeakPtr<Embedder> embedder) { embedder_ = embedder; }
base::WeakPtr<Embedder> embedder() { return embedder_; } base::WeakPtr<Embedder> embedder() { return embedder_; }
// Called when the embedder is hidden and is no longer visible on screen.
virtual void EmbedderHidden() {}
private: private:
base::WeakPtr<Embedder> embedder_; base::WeakPtr<Embedder> embedder_;
}; };
......
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