blob: a5282610223f0497561156e2870ef0fb1ad0680b [file] [log] [blame]
// Copyright 2016 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/vr_service_impl.h"
#include <utility>
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/vr/service/vr_device_manager.h"
#include "chrome/browser/vr/service/vr_display_host.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "device/vr/vr_device.h"
#include "device/vr/vr_display_impl.h"
namespace vr {
VRServiceImpl::VRServiceImpl(content::RenderFrameHost* render_frame_host)
: WebContentsObserver(
content::WebContents::FromRenderFrameHost(render_frame_host)),
render_frame_host_(render_frame_host) {
DCHECK(render_frame_host_);
// TODO(crbug/701027): make sure that client_ is never null by initializing it
// in the constructor.
}
// Constructor for testing.
VRServiceImpl::VRServiceImpl() : render_frame_host_(nullptr) {}
void VRServiceImpl::SetBinding(mojo::StrongBindingPtr<VRService> binding) {
binding_ = std::move(binding);
}
VRServiceImpl::~VRServiceImpl() {
// Destroy VRDisplay before calling RemoveService below. RemoveService might
// implicitly trigger destory VRDevice which VRDisplay needs to access in its
// dtor.
displays_.clear();
VRDeviceManager::GetInstance()->RemoveService(this);
}
void VRServiceImpl::Create(content::RenderFrameHost* render_frame_host,
device::mojom::VRServiceRequest request) {
std::unique_ptr<VRServiceImpl> vr_service_impl =
std::make_unique<VRServiceImpl>(render_frame_host);
VRServiceImpl* impl = vr_service_impl.get();
impl->SetBinding(
mojo::MakeStrongBinding(std::move(vr_service_impl), std::move(request)));
}
void VRServiceImpl::SetClient(device::mojom::VRServiceClientPtr service_client,
SetClientCallback callback) {
DCHECK(!client_.get());
client_ = std::move(service_client);
set_client_callback_ = std::move(callback);
// Once a client has been connected AddService will force any VRDisplays to
// send ConnectDevice to it so that it's populated with the currently active
// displays. Thereafter it will stay up to date by virtue of listening for new
// connected events.
VRDeviceManager::GetInstance()->AddService(this);
}
void VRServiceImpl::InitializationComplete() {
DCHECK(!set_client_callback_.is_null());
base::ResetAndReturn(&set_client_callback_).Run();
}
// Creates a VRDisplayImpl unique to this service so that the associated page
// can communicate with the VRDevice.
void VRServiceImpl::ConnectDevice(device::VRDevice* device) {
// Client should always be set as this is called through SetClient.
DCHECK(client_);
DCHECK(displays_.find(device) == displays_.end());
device::mojom::VRDisplayInfoPtr display_info = device->GetVRDisplayInfo();
DCHECK(display_info);
if (!display_info)
return;
displays_[device] = std::make_unique<VRDisplayHost>(
device, render_frame_host_, client_.get(), std::move(display_info));
}
void VRServiceImpl::RemoveDevice(device::VRDevice* device) {
DCHECK(client_);
auto it = displays_.find(device);
DCHECK(it != displays_.end());
displays_.erase(it);
}
void VRServiceImpl::SetListeningForActivate(bool listening) {
for (const auto& display : displays_)
display.second->SetListeningForActivate(listening);
}
void VRServiceImpl::OnWebContentsFocused(content::RenderWidgetHost* host) {
OnWebContentsFocusChanged(host, true);
}
void VRServiceImpl::OnWebContentsLostFocus(content::RenderWidgetHost* host) {
OnWebContentsFocusChanged(host, false);
}
void VRServiceImpl::RenderFrameDeleted(content::RenderFrameHost* host) {
if (host != render_frame_host_)
return;
// Binding should always be live here, as this is a StrongBinding.
// Close the binding (and delete this VrServiceImpl) when the RenderFrameHost
// is deleted.
DCHECK(binding_.get());
binding_->Close();
}
void VRServiceImpl::OnWebContentsFocusChanged(content::RenderWidgetHost* host,
bool focused) {
if (!render_frame_host_->GetView() ||
render_frame_host_->GetView()->GetRenderWidgetHost() != host) {
return;
}
for (const auto& display : displays_)
display.second->SetInFocusedFrame(focused);
}
} // namespace vr