diff --git a/chrome/browser/performance_manager/policies/page_discarding_helper.cc b/chrome/browser/performance_manager/policies/page_discarding_helper.cc index 1becb533519a4d..6e17c4ec1f381a 100644 --- a/chrome/browser/performance_manager/policies/page_discarding_helper.cc +++ b/chrome/browser/performance_manager/policies/page_discarding_helper.cc @@ -235,10 +235,13 @@ PageDiscardingHelper::DiscardMultiplePagesImpl( PageNodeImpl::FromNode(node)); // PageNode may be replaced after discard. TabHandle is not replaced after - // discard. - TabPageDecorator::TabHandle* tab_handle; + // discard, but it *can* be destroyed if the discard observer fan-out + // synchronously closes the replacement tab; hold a WeakPtr. + base::WeakPtr tab_handle; if (!result.first_discard_time.has_value()) { - tab_handle = TabPageDecorator::FromPageNode(node); + if (auto* handle = TabPageDecorator::FromPageNode(node)) { + tab_handle = handle->GetWeakPtr(); + } } // Do the discard. diff --git a/components/performance_manager/decorators/tab_page_decorator.cc b/components/performance_manager/decorators/tab_page_decorator.cc index 1fcbfe52833557..7de9e676589241 100644 --- a/components/performance_manager/decorators/tab_page_decorator.cc +++ b/components/performance_manager/decorators/tab_page_decorator.cc @@ -34,6 +34,10 @@ class TabPageDecorator::Data TabPageDecorator::TabPageDecorator() = default; TabPageDecorator::~TabPageDecorator() = default; +TabPageDecorator::TabHandle::TabHandle(const PageNode* page_node) + : page_node_(page_node) {} +TabPageDecorator::TabHandle::~TabHandle() = default; + void TabPageDecorator::AddObserver(TabPageObserver* observer) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); observers_.AddObserver(observer); diff --git a/components/performance_manager/public/decorators/tab_page_decorator.h b/components/performance_manager/public/decorators/tab_page_decorator.h index eef7554edd028c..7df1e22f231b7c 100644 --- a/components/performance_manager/public/decorators/tab_page_decorator.h +++ b/components/performance_manager/public/decorators/tab_page_decorator.h @@ -6,6 +6,7 @@ #define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_TAB_PAGE_DECORATOR_H_ #include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/observer_list_types.h" #include "base/sequence_checker.h" @@ -69,17 +70,25 @@ class TabPageDecorator : public PageNodeObserver, // associated with the tab. class TabPageDecorator::TabHandle { public: + ~TabHandle(); + const PageNode* page_node() const { return page_node_; } + // Callers that hold a TabHandle* across operations that may run the discard + // observer fan-out (which can synchronously close the tab and free this + // object) must hold a WeakPtr instead of a raw pointer. + base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } + private: friend class TabPageDecorator::Data; friend class TabPageDecorator; - explicit TabHandle(const PageNode* page_node) : page_node_(page_node) {} + explicit TabHandle(const PageNode* page_node); void SetPageNode(const PageNode* page_node) { page_node_ = page_node; } raw_ptr page_node_; + base::WeakPtrFactory weak_factory_{this}; }; class TabPageObserver : public base::CheckedObserver {