blob: 286dae9a51cd37386d2dcc4f3ad64b1955d20b50 [file] [log] [blame]
// 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 <utility>
#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::GlobalFrameRoutingId 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::GlobalFrameRoutingId 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::GlobalFrameRoutingId 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<FrameNodeImpl*>& 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<FrameNodeImpl*>& 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