blob: 140cbed7c26b0431d1065ee7766b7ca4bb5af996 [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 "chromecast/browser/service_connector.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/task/post_task.h"
#include "chromecast/browser/system_connector.h"
#include "chromecast/common/mojom/constants.mojom.h"
#include "chromecast/common/mojom/multiroom.mojom.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace chromecast {
namespace {
ServiceConnector* g_instance = nullptr;
} // namespace
const ServiceConnectorClientId kBrowserProcessClientId =
ServiceConnectorClientId::FromUnsafeValue(1);
const ServiceConnectorClientId kMediaServiceClientId =
ServiceConnectorClientId::FromUnsafeValue(2);
ServiceConnector::ServiceConnector() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(!g_instance);
g_instance = this;
}
ServiceConnector::~ServiceConnector() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK_EQ(this, g_instance);
g_instance = nullptr;
}
// static
mojo::PendingRemote<mojom::ServiceConnector> ServiceConnector::MakeRemote(
ServiceConnectorClientId client_id) {
DCHECK(g_instance);
mojo::PendingRemote<mojom::ServiceConnector> remote;
BindReceiver(client_id, remote.InitWithNewPipeAndPassReceiver());
return remote;
}
// static
void ServiceConnector::BindReceiver(
ServiceConnectorClientId client_id,
mojo::PendingReceiver<mojom::ServiceConnector> receiver) {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&ServiceConnector::BindReceiver, client_id,
std::move(receiver)));
return;
}
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(g_instance);
g_instance->receivers_.Add(g_instance, std::move(receiver), client_id);
}
void ServiceConnector::Connect(const std::string& service_name,
mojo::GenericPendingReceiver receiver) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
const ServiceConnectorClientId client_id = receivers_.current_context();
// If the client is browser code, forward indscriminately through the Service
// Manager. The browser generally has access unfettered to everything.
if (client_id == kBrowserProcessClientId) {
auto interface_name = *receiver.interface_name();
GetSystemConnector()->BindInterface(
service_manager::ServiceFilter::ByName(service_name), interface_name,
receiver.PassPipe());
return;
}
// In the public implementation of this class, the only other client we
// support is the Media Service, binding to the MultiroomManager interface in
// the Chromecast service.
if (client_id != kMediaServiceClientId ||
service_name != mojom::kChromecastServiceName) {
LOG(ERROR) << "Client " << client_id.GetUnsafeValue()
<< " attempted to bind " << *receiver.interface_name()
<< " in inaccessible service " << service_name;
return;
}
if (auto r = receiver.As<mojom::MultiroomManager>()) {
GetSystemConnector()->BindInterface(service_name, std::move(r));
return;
}
LOG(ERROR) << "Media Service attempted to bind inaccessible interface "
<< *receiver.interface_name() << " in \"chromecast\" service.";
}
} // namespace chromecast