blob: 81c14d9ebd6aabde24de445d7c9d4df60001185b [file] [log] [blame]
// Copyright 2018 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/vr/service/isolated_device_provider.h"
#include "base/bind.h"
#include "chrome/browser/vr/service/vr_ui_host.h"
#include "content/public/common/service_manager_connection.h"
#include "device/vr/buildflags/buildflags.h"
#include "device/vr/isolated_gamepad_data_fetcher.h"
#include "services/service_manager/public/cpp/connector.h"
namespace {
constexpr int kMaxRetries = 3;
}
namespace vr {
void IsolatedVRDeviceProvider::Initialize(
base::RepeatingCallback<void(device::mojom::XRDeviceId,
device::mojom::VRDisplayInfoPtr,
device::mojom::XRRuntimePtr)>
add_device_callback,
base::RepeatingCallback<void(device::mojom::XRDeviceId)>
remove_device_callback,
base::OnceClosure initialization_complete) {
add_device_callback_ = std::move(add_device_callback);
remove_device_callback_ = std::move(remove_device_callback);
initialization_complete_ = std::move(initialization_complete);
SetupDeviceProvider();
}
bool IsolatedVRDeviceProvider::Initialized() {
return initialized_;
}
void IsolatedVRDeviceProvider::OnDeviceAdded(
device::mojom::XRRuntimePtr device,
device::mojom::IsolatedXRGamepadProviderFactoryPtr gamepad_factory,
device::mojom::XRCompositorHostPtr compositor_host,
device::mojom::XRDeviceId device_id) {
add_device_callback_.Run(device_id, nullptr, std::move(device));
auto ui_host =
(*VRUiHost::GetFactory())(device_id, std::move(compositor_host));
ui_host_map_.insert(std::make_pair(device_id, std::move(ui_host)));
device::IsolatedGamepadDataFetcher::Factory::AddGamepad(
device_id, std::move(gamepad_factory));
}
void IsolatedVRDeviceProvider::OnDeviceRemoved(device::mojom::XRDeviceId id) {
remove_device_callback_.Run(id);
ui_host_map_.erase(id);
device::IsolatedGamepadDataFetcher::Factory::RemoveGamepad(id);
}
void IsolatedVRDeviceProvider::OnServerError() {
// An error occurred - any devices we have added are now disconnected and
// should be removed.
for (auto& entry : ui_host_map_) {
auto id = entry.first;
remove_device_callback_.Run(id);
device::IsolatedGamepadDataFetcher::Factory::RemoveGamepad(id);
}
ui_host_map_.clear();
// At this point, XRRuntimeManager may be blocked waiting for us to return
// that we've enumerated all runtimes/devices. If we lost the connection to
// the service, we'll try again. If we've already tried too many times,
// then just assume we won't ever get devices, so report we are done now.
// This will unblock WebXR/WebVR promises so they can reject indicating we
// never found devices.
if (!initialized_ && retry_count_ >= kMaxRetries) {
OnDevicesEnumerated();
} else {
device_provider_.reset();
binding_.Close();
retry_count_++;
SetupDeviceProvider();
}
}
void IsolatedVRDeviceProvider::OnDevicesEnumerated() {
if (!initialized_) {
initialized_ = true;
std::move(initialization_complete_).Run();
}
// Either we've hit the max retries and given up (in which case we don't have
// a device provider which could error out and cause us to retry) or we've
// successfully gotten the device provider again after a retry, and we should
// reset our count in case it gets disconnected.
retry_count_ = 0;
}
void IsolatedVRDeviceProvider::SetupDeviceProvider() {
content::ServiceManagerConnection* connection =
content::ServiceManagerConnection::GetForProcess();
connection->GetConnector()->BindInterface(
device::mojom::kVrIsolatedServiceName,
mojo::MakeRequest(&device_provider_));
device_provider_.set_connection_error_handler(base::BindOnce(
&IsolatedVRDeviceProvider::OnServerError, base::Unretained(this)));
device::mojom::IsolatedXRRuntimeProviderClientPtr client;
binding_.Bind(mojo::MakeRequest(&client));
device_provider_->RequestDevices(std::move(client));
}
IsolatedVRDeviceProvider::IsolatedVRDeviceProvider() : binding_(this) {}
IsolatedVRDeviceProvider::~IsolatedVRDeviceProvider() {
for (auto& entry : ui_host_map_) {
auto device_id = entry.first;
device::IsolatedGamepadDataFetcher::Factory::RemoveGamepad(device_id);
}
// Default destructor handles renderer_host_map_ cleanup.
}
} // namespace vr