blob: 203cfde84be448880f66dd6b7f920433353fa6d8 [file] [log] [blame]
// Copyright 2015 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 "modules/vr/NavigatorVR.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/dom/DOMException.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/frame/FrameOwner.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Navigator.h"
#include "core/page/Page.h"
#include "modules/vr/VRController.h"
#include "modules/vr/VRDisplay.h"
#include "modules/vr/VRGetDevicesCallback.h"
#include "modules/vr/VRPose.h"
#include "wtf/PtrUtil.h"
namespace blink {
namespace {
// https://html.spec.whatwg.org/multipage/embedded-content.html#allowed-to-use
bool allowedToUseVR(const Frame* frame)
{
// To determine whether a Document object |document| is allowed to use the
// feature indicated by attribute name |allowattribute|, run these steps:
// 1. If |document| has no browsing context, then return false.
if (!frame)
return false;
// 2. If |document|'s browsing context has no browsing context container, then
// return true.
if (frame->isMainFrame())
return true;
// 3. If |document|'s browsing context has a browsing context container that
// is an iframe element with an |allowattribute| attribute specified, and
// whose node document is allowed to use the feature indicated by
// |allowattribute|, then return true.
if (frame->owner() && frame->owner()->allowVR())
return allowedToUseVR(frame->tree().parent());
// 4. Return false.
return false;
}
} // namespace
NavigatorVR* NavigatorVR::from(Document& document)
{
if (!document.frame() || !document.frame()->domWindow())
return 0;
Navigator& navigator = *document.frame()->domWindow()->navigator();
return &from(navigator);
}
NavigatorVR& NavigatorVR::from(Navigator& navigator)
{
NavigatorVR* supplement = static_cast<NavigatorVR*>(Supplement<Navigator>::from(navigator, supplementName()));
if (!supplement) {
supplement = new NavigatorVR(navigator.frame());
provideTo(navigator, supplementName(), supplement);
}
return *supplement;
}
ScriptPromise NavigatorVR::getVRDisplays(ScriptState* scriptState, Navigator& navigator)
{
return NavigatorVR::from(navigator).getVRDisplays(scriptState);
}
ScriptPromise NavigatorVR::getVRDisplays(ScriptState* scriptState)
{
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
ScriptPromise promise = resolver->promise();
if (!allowedToUseVR(m_frame)) {
DOMException* exception = DOMException::create(NotAllowedError, "Access to VR devices is not allowed in this context.");
resolver->reject(exception);
return promise;
}
Document* document = m_frame ? m_frame->document() : 0;
if (!document || !controller()) {
DOMException* exception = DOMException::create(InvalidStateError, "The object is no longer associated to a document.");
resolver->reject(exception);
return promise;
}
controller()->getDisplays(resolver);
return promise;
}
VRController* NavigatorVR::controller()
{
if (!frame())
return 0;
if (!m_controller) {
m_controller = new VRController(this);
}
return m_controller;
}
Document* NavigatorVR::document()
{
return m_frame ? m_frame->document() : 0;
}
DEFINE_TRACE(NavigatorVR)
{
visitor->trace(m_controller);
Supplement<Navigator>::trace(visitor);
DOMWindowProperty::trace(visitor);
}
NavigatorVR::NavigatorVR(LocalFrame* frame)
: DOMWindowProperty(frame)
{
}
NavigatorVR::~NavigatorVR()
{
}
const char* NavigatorVR::supplementName()
{
return "NavigatorVR";
}
void NavigatorVR::fireVRDisplayPresentChange(VRDisplay* display)
{
enqueueEvent(VRDisplayEvent::create(EventTypeNames::vrdisplaypresentchange, true, false, display, ""));
}
void NavigatorVR::enqueueEvent(VRDisplayEvent* event) {
if (m_frame && m_frame->localDOMWindow()) {
m_frame->localDOMWindow()->enqueueWindowEvent(event);
}
}
} // namespace blink