// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/performance_manager/tab_helper_frame_node_source.h" #include #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" namespace performance_manager { TabHelperFrameNodeSource::TabHelperFrameNodeSource() : performance_manager_tab_helper_observations_(this) {} TabHelperFrameNodeSource::~TabHelperFrameNodeSource() { DCHECK(observed_frame_nodes_.empty()); DCHECK(!performance_manager_tab_helper_observations_.IsObservingAnySource()); } FrameNodeImpl* TabHelperFrameNodeSource::GetFrameNode( content::GlobalRenderFrameHostId render_process_host_id) { // Retrieve the client's RenderFrameHost and its associated // PerformanceManagerTabHelper. auto* render_frame_host = content::RenderFrameHost::FromID(render_process_host_id); if (!render_frame_host) return nullptr; PerformanceManagerTabHelper* performance_manager_tab_helper = PerformanceManagerTabHelper::FromWebContents( content::WebContents::FromRenderFrameHost(render_frame_host)); if (!performance_manager_tab_helper) return nullptr; return performance_manager_tab_helper->GetFrameNode(render_frame_host); } void TabHelperFrameNodeSource::SubscribeToFrameNode( content::GlobalRenderFrameHostId render_process_host_id, OnbeforeFrameNodeRemovedCallback on_before_frame_node_removed_callback) { auto* render_frame_host = content::RenderFrameHost::FromID(render_process_host_id); DCHECK(render_frame_host); PerformanceManagerTabHelper* performance_manager_tab_helper = PerformanceManagerTabHelper::FromWebContents( content::WebContents::FromRenderFrameHost(render_frame_host)); DCHECK(performance_manager_tab_helper); FrameNodeImpl* frame_node = performance_manager_tab_helper->GetFrameNode(render_frame_host); // Add the frame to the set of observed frames that belongs to // |performance_manager_tab_helper|. if (AddObservedFrameNode(performance_manager_tab_helper, frame_node)) { // Start observing the tab helper only if this is the first observed frame // that is associated with it. performance_manager_tab_helper_observations_.AddObservation( performance_manager_tab_helper); } // Then remember the frame's callback. bool inserted = frame_node_callbacks_ .insert(std::make_pair( frame_node, std::move(on_before_frame_node_removed_callback))) .second; DCHECK(inserted); } void TabHelperFrameNodeSource::UnsubscribeFromFrameNode( content::GlobalRenderFrameHostId render_process_host_id) { auto* render_frame_host = content::RenderFrameHost::FromID(render_process_host_id); DCHECK(render_frame_host); PerformanceManagerTabHelper* performance_manager_tab_helper = PerformanceManagerTabHelper::FromWebContents( content::WebContents::FromRenderFrameHost(render_frame_host)); DCHECK(performance_manager_tab_helper); FrameNodeImpl* frame_node = performance_manager_tab_helper->GetFrameNode(render_frame_host); // Remove the frame's callback without invoking it. size_t removed = frame_node_callbacks_.erase(frame_node); DCHECK_EQ(removed, 1u); // And also remove the frame from the set of observed frames that belongs to // |performance_manager_tab_helper|. if (RemoveObservedFrameNode(performance_manager_tab_helper, frame_node)) { // Stop observing that tab helper if there no longer are any observed // frames that are associated with it. performance_manager_tab_helper_observations_.RemoveObservation( performance_manager_tab_helper); } } void TabHelperFrameNodeSource::OnBeforeFrameNodeRemoved( PerformanceManagerTabHelper* performance_manager_tab_helper, FrameNodeImpl* frame_node) { // The tab helper owns many other frames than the ones this instance cares // about. Ignore irrelevant notifications. auto it = frame_node_callbacks_.find(frame_node); if (it == frame_node_callbacks_.end()) return; // Invoke the frame's callback and remove it. std::move(it->second).Run(frame_node); frame_node_callbacks_.erase(it); // And also remove the frame from the set of observed frames that belong to // |performance_manager_tab_helper|. if (RemoveObservedFrameNode(performance_manager_tab_helper, frame_node)) { // Stop observing that tab helper if there no longer are any observed // frames that are associated with it. performance_manager_tab_helper_observations_.RemoveObservation( performance_manager_tab_helper); } } bool TabHelperFrameNodeSource::AddObservedFrameNode( PerformanceManagerTabHelper* performance_manager_tab_helper, FrameNodeImpl* frame_node) { auto insertion_result = observed_frame_nodes_.insert({performance_manager_tab_helper, {}}); base::flat_set& frame_nodes = insertion_result.first->second; bool inserted = frame_nodes.insert(frame_node).second; DCHECK(inserted); return insertion_result.second; } bool TabHelperFrameNodeSource::RemoveObservedFrameNode( PerformanceManagerTabHelper* performance_manager_tab_helper, FrameNodeImpl* frame_node) { auto it = observed_frame_nodes_.find(performance_manager_tab_helper); DCHECK(it != observed_frame_nodes_.end()); base::flat_set& frame_nodes = it->second; size_t removed = frame_nodes.erase(frame_node); DCHECK_EQ(removed, 1u); if (frame_nodes.empty()) { observed_frame_nodes_.erase(it); return true; } return false; } } // namespace performance_manager