blob: aae3a38ad50eae4f55db1fca1b46f8d053b91e6a [file] [log] [blame]
// Copyright 2017 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 "chrome/browser/resource_coordinator/page_signal_receiver.h"
#include "base/lazy_instance.h"
#include "base/time/time.h"
#include "content/public/common/service_manager_connection.h"
#include "services/resource_coordinator/public/cpp/coordination_unit_id.h"
#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
#include "services/resource_coordinator/public/interfaces/service_constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace resource_coordinator {
namespace {
base::LazyInstance<PageSignalReceiver>::Leaky g_page_signal_receiver;
}
// static
bool PageSignalReceiver::IsEnabled() {
// Check that service_manager is active and Resource Coordinator is enabled.
return content::ServiceManagerConnection::GetForProcess() != nullptr &&
resource_coordinator::IsResourceCoordinatorEnabled();
}
// static
PageSignalReceiver* PageSignalReceiver::GetInstance() {
if (!IsEnabled())
return nullptr;
return g_page_signal_receiver.Pointer();
}
PageSignalReceiver::PageSignalReceiver() : binding_(this) {}
PageSignalReceiver::~PageSignalReceiver() = default;
void PageSignalReceiver::NotifyPageAlmostIdle(const CoordinationUnitID& cu_id) {
DCHECK(IsPageAlmostIdleSignalEnabled());
auto web_contents_iter = cu_id_web_contents_map_.find(cu_id);
if (web_contents_iter == cu_id_web_contents_map_.end())
return;
for (auto& observer : observers_)
observer.OnPageAlmostIdle(web_contents_iter->second);
}
void PageSignalReceiver::SetExpectedTaskQueueingDuration(
const CoordinationUnitID& cu_id,
base::TimeDelta duration) {
auto web_contents_iter = cu_id_web_contents_map_.find(cu_id);
if (web_contents_iter == cu_id_web_contents_map_.end())
return;
for (auto& observer : observers_)
observer.OnExpectedTaskQueueingDurationSet(web_contents_iter->second,
duration);
}
void PageSignalReceiver::AddObserver(PageSignalObserver* observer) {
// When PageSignalReceiver starts to have observer, construct the mojo
// channel.
if (!observers_.might_have_observers()) {
content::ServiceManagerConnection* service_manager_connection =
content::ServiceManagerConnection::GetForProcess();
// Ensure service_manager is active before trying to connect to it.
if (service_manager_connection) {
service_manager::Connector* connector =
service_manager_connection->GetConnector();
mojom::PageSignalGeneratorPtr page_signal_generator_ptr;
connector->BindInterface(mojom::kServiceName,
mojo::MakeRequest(&page_signal_generator_ptr));
mojom::PageSignalReceiverPtr page_signal_receiver_ptr;
binding_.Bind(mojo::MakeRequest(&page_signal_receiver_ptr));
page_signal_generator_ptr->AddReceiver(
std::move(page_signal_receiver_ptr));
}
}
observers_.AddObserver(observer);
}
void PageSignalReceiver::RemoveObserver(PageSignalObserver* observer) {
observers_.RemoveObserver(observer);
}
void PageSignalReceiver::AssociateCoordinationUnitIDWithWebContents(
const CoordinationUnitID& cu_id,
content::WebContents* web_contents) {
cu_id_web_contents_map_[cu_id] = web_contents;
}
void PageSignalReceiver::RemoveCoordinationUnitID(
const CoordinationUnitID& cu_id) {
cu_id_web_contents_map_.erase(cu_id);
}
} // namespace resource_coordinator