blob: 33ff00d4b816c90d0488fff48c40b1a33235428a [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/compute_pressure/pressure_service_impl.h"
#include <utility>
#include "base/memory/ptr_util.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/bindings/message.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/compute_pressure/pressure_service.mojom.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
namespace content {
// static
void PressureServiceImpl::Create(
RenderFrameHost* render_frame_host,
mojo::PendingReceiver<blink::mojom::PressureService> receiver) {
if (!network::IsOriginPotentiallyTrustworthy(
render_frame_host->GetLastCommittedOrigin())) {
mojo::ReportBadMessage("Compute Pressure access from an insecure origin");
return;
}
GetOrCreateForCurrentDocument(render_frame_host)
->BindReceiver(std::move(receiver));
}
PressureServiceImpl::PressureServiceImpl(RenderFrameHost* render_frame_host)
: DocumentUserData<PressureServiceImpl>(render_frame_host) {
DCHECK(render_frame_host);
}
PressureServiceImpl::~PressureServiceImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void PressureServiceImpl::BindReceiver(
mojo::PendingReceiver<blink::mojom::PressureService> receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (receiver_.is_bound()) {
mojo::ReportBadMessage("PressureService is already connected");
return;
}
receiver_.Bind(std::move(receiver));
// base::Unretained is safe because Mojo guarantees the callback will not
// be called after `observers_` is deallocated, and `observers_` is owned by
// this class.
receiver_.set_disconnect_handler(
base::BindRepeating(&PressureServiceImpl::OnServiceReceiverDisconnected,
base::Unretained(this)));
}
void PressureServiceImpl::BindObserver(
mojo::PendingRemote<blink::mojom::PressureObserver> observer,
BindObserverCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!render_frame_host().IsActive() ||
render_frame_host().IsNestedWithinFencedFrame()) {
std::move(callback).Run(blink::mojom::PressureStatus::kNotSupported);
return;
}
if (!remote_.is_bound()) {
auto receiver = remote_.BindNewPipeAndPassReceiver();
// base::Unretained is safe because Mojo guarantees the callback will not
// be called after `remote_` is deallocated, and `remote_` is owned by
// this class.
remote_.set_disconnect_handler(
base::BindRepeating(&PressureServiceImpl::OnManagerRemoteDisconnected,
base::Unretained(this)));
GetDeviceService().BindPressureManager(std::move(receiver));
}
ResetObserverState();
observer_.Bind(std::move(observer));
// base::Unretained is safe because Mojo guarantees the callback will not
// be called after `observers_` is deallocated, and `observers_` is owned by
// this class.
observer_.set_disconnect_handler(
base::BindRepeating(&PressureServiceImpl::OnObserverRemoteDisconnected,
base::Unretained(this)));
client_.reset();
remote_->AddClient(
client_.BindNewPipeAndPassRemote(),
base::BindOnce(&PressureServiceImpl::DidBindObserver,
base::Unretained(this), std::move(callback)));
// base::Unretained is safe because Mojo guarantees the callback will not
// be called after `client_` is deallocated, and `client_` is owned by
// this class.
client_.set_disconnect_handler(base::BindOnce(
&PressureServiceImpl::ResetObserverState, base::Unretained(this)));
}
// TODO(crbug.com/1391848): PressureUpdate can be sent from PressureManagerImpl
// to PressureObserverManager directly, because PressureUpdate is not filtered
// in PressureServiceImpl any more.
void PressureServiceImpl::PressureStateChanged(
device::mojom::PressureUpdatePtr update) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observer_->OnUpdate(update.Clone());
}
void PressureServiceImpl::OnObserverRemoteDisconnected() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
client_.reset();
ResetObserverState();
}
void PressureServiceImpl::OnManagerRemoteDisconnected() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observer_.reset();
client_.reset();
remote_.reset();
}
void PressureServiceImpl::OnServiceReceiverDisconnected() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
receiver_.reset();
observer_.reset();
client_.reset();
remote_.reset();
}
void PressureServiceImpl::DidBindObserver(BindObserverCallback callback,
bool success) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!success) {
std::move(callback).Run(blink::mojom::PressureStatus::kNotSupported);
ResetObserverState();
return;
}
std::move(callback).Run(blink::mojom::PressureStatus::kOk);
}
void PressureServiceImpl::ResetObserverState() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observer_.reset();
}
DOCUMENT_USER_DATA_KEY_IMPL(PressureServiceImpl);
} // namespace content