summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbajones <bajones@chromium.org>2015-06-18 09:39:07 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-18 16:39:47 +0000
commit4ab52def6d1861a55fd9864b47f56c16e4b423a0 (patch)
tree264d5754c3cae805c8f19959f30e04dd88d5ed63
parent5d1fef66183dbe232abef3144bef2db8bf5dd7b8 (diff)
downloadchromium_src-4ab52def6d1861a55fd9864b47f56c16e4b423a0.zip
chromium_src-4ab52def6d1861a55fd9864b47f56c16e4b423a0.tar.gz
chromium_src-4ab52def6d1861a55fd9864b47f56c16e4b423a0.tar.bz2
Adding Chrome-side WebVR interface and Cardboard implementation
WebVR Spec: http://mozvr.github.io/webvr-spec/webvr.html For the Blink half of this CL, see https://codereview.chromium.org/848053002 Provides an Android-only, Cardboard-SDK-based implementation of the initial WebVR interface, as well as the basic plumbing required to get data from Javascript to the right place in the browser process and back. BUG=389343 Review URL: https://codereview.chromium.org/829803003 Cr-Commit-Position: refs/heads/master@{#335062}
-rw-r--r--build/common.gypi12
-rw-r--r--build/config/BUILD.gn3
-rw-r--r--build/config/features.gni4
-rw-r--r--chrome/app/generated_resources.grd6
-rw-r--r--chrome/browser/about_flags.cc7
-rw-r--r--chrome/browser/chromeos/login/chrome_restart_request.cc1
-rw-r--r--content/browser/BUILD.gn19
-rw-r--r--content/browser/DEPS1
-rw-r--r--content/browser/android/browser_jni_registrar.cc5
-rw-r--r--content/browser/frame_host/render_frame_host_impl.cc14
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc1
-rw-r--r--content/browser/vr/OWNERS2
-rw-r--r--content/browser/vr/android/cardboard/cardboard_vr_device.cc188
-rw-r--r--content/browser/vr/android/cardboard/cardboard_vr_device.h37
-rw-r--r--content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc29
-rw-r--r--content/browser/vr/android/cardboard/cardboard_vr_device_provider.h33
-rw-r--r--content/browser/vr/test/fake_vr_device.cc33
-rw-r--r--content/browser/vr/test/fake_vr_device.h34
-rw-r--r--content/browser/vr/test/fake_vr_device_provider.cc43
-rw-r--r--content/browser/vr/test/fake_vr_device_provider.h35
-rw-r--r--content/browser/vr/vr_device.cc22
-rw-r--r--content/browser/vr/vr_device.h48
-rw-r--r--content/browser/vr/vr_device_manager.cc148
-rw-r--r--content/browser/vr/vr_device_manager.h78
-rw-r--r--content/browser/vr/vr_device_manager_unittest.cc96
-rw-r--r--content/browser/vr/vr_device_provider.h27
-rw-r--r--content/child/runtime_features.cc5
-rw-r--r--content/common/BUILD.gn1
-rw-r--r--content/common/vr_service.mojom73
-rw-r--r--content/content.gyp10
-rw-r--r--content/content_browser.gypi17
-rw-r--r--content/content_common_mojo_bindings.gyp1
-rw-r--r--content/content_renderer.gypi8
-rw-r--r--content/public/android/BUILD.gn11
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java88
-rw-r--r--content/public/common/content_switches.cc3
-rw-r--r--content/public/common/content_switches.h1
-rw-r--r--content/renderer/BUILD.gn9
-rw-r--r--content/renderer/render_frame_impl.cc13
-rw-r--r--content/renderer/render_frame_impl.h10
-rw-r--r--content/renderer/vr/vr_dispatcher.cc69
-rw-r--r--content/renderer/vr/vr_dispatcher.h55
-rw-r--r--content/renderer/vr/vr_type_converters.cc147
-rw-r--r--content/renderer/vr/vr_type_converters.h62
-rw-r--r--mojo/common/weak_binding_set.h2
-rw-r--r--third_party/cardboard-java/BUILD.gn4
-rw-r--r--tools/metrics/histograms/histograms.xml1
47 files changed, 1514 insertions, 2 deletions
diff --git a/build/common.gypi b/build/common.gypi
index 04368e7..6d77eaa 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -1016,6 +1016,14 @@
}, {
'pkg-config': 'pkg-config'
}],
+
+ # Enable WebVR support by default on Android
+ # Still requires command line flag to access API
+ ['OS=="android"', {
+ 'enable_webvr%': 1,
+ }, {
+ 'enable_webvr%': 0,
+ }],
],
# Setting this to '0' will cause V8's startup snapshot to be
@@ -1232,6 +1240,7 @@
'mac_views_browser%': '<(mac_views_browser)',
'android_app_version_name%': '<(android_app_version_name)',
'android_app_version_code%': '<(android_app_version_code)',
+ 'enable_webvr%': '<(enable_webvr)',
# Use system protobuf instead of bundled one.
'use_system_protobuf%': 0,
@@ -3030,6 +3039,9 @@
['v8_use_external_startup_data==1', {
'defines': ['V8_USE_EXTERNAL_STARTUP_DATA'],
}],
+ ['enable_webvr==1', {
+ 'defines': ['ENABLE_WEBVR'],
+ }],
# SAFE_BROWSING_SERVICE - browser manages a safe-browsing service.
# SAFE_BROWSING_DB_LOCAL - service manages a local database.
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index d1e6ee7..9fc86fd 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -269,6 +269,9 @@ config("feature_flags") {
if (enable_media_router) {
defines += [ "ENABLE_MEDIA_ROUTER=1" ]
}
+ if (enable_webvr) {
+ defines += [ "ENABLE_WEBVR" ]
+ }
}
# Debug/release ----------------------------------------------------------------
diff --git a/build/config/features.gni b/build/config/features.gni
index daf5177..8ef35f8 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -195,3 +195,7 @@ enable_hangout_services_extension = false
# Whether to back up data before sync.
enable_pre_sync_backup = is_win || is_mac || (is_linux && !is_chromeos)
+
+# Enable WebVR support by default on Android
+# Still requires command line flag to access API
+enable_webvr = is_android
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index fe443dd..5710807 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5950,6 +5950,12 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_FLAGS_ENABLE_WEBRTC_STUN_ORIGIN_DESCRIPTION" desc="Description of chrome:flags option to turn on Origin header for WebRTC STUN messages">
When enabled, Stun messages generated by WebRTC will contain the Origin header.
</message>
+ <message name="IDS_FLAGS_ENABLE_WEBVR_NAME" desc="Name of the 'Enable WebVR' flag.">
+ Enable WebVR
+ </message>
+ <message name="IDS_FLAGS_ENABLE_WEBVR_DESCRIPTION" desc="Description for the flag to enable WebVR APIs.">
+ Enabling this option allows web applications to access experimental Virtual Reality APIs.
+ </message>
<if expr="is_android">
<message name="IDS_FLAGS_DISABLE_WEBAUDIO_NAME" desc="Name of the 'Disable WebAudio' lab.">
Disable WebAudio
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 6b26f7f..2da2f56 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1992,6 +1992,13 @@ const Experiment kExperiments[] = {
ENABLE_DISABLE_VALUE_TYPE(switches::kEnableMacViewsNativeAppWindows,
switches::kDisableMacViewsNativeAppWindows)},
#endif
+#if defined(ENABLE_WEBVR)
+ {"enable-webvr",
+ IDS_FLAGS_ENABLE_WEBVR_NAME,
+ IDS_FLAGS_ENABLE_WEBVR_DESCRIPTION,
+ kOsAll,
+ SINGLE_VALUE_TYPE(switches::kEnableWebVR)},
+#endif
// NOTE: Adding new command-line switches requires adding corresponding
// entries to enum "LoginCustomFlags" in histograms.xml. See note in
// histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 16b433d..9e77998 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -158,6 +158,7 @@ std::string DeriveCommandLine(const GURL& start_url,
::switches::kVModule,
::switches::kEnableWebGLDraftExtensions,
::switches::kEnableWebGLImageChromium,
+ ::switches::kEnableWebVR,
#if defined(ENABLE_WEBRTC)
::switches::kDisableWebRtcHWDecoding,
::switches::kDisableWebRtcHWEncoding,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 3cdfc88..d71883c 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -479,4 +479,23 @@ source_set("browser") {
if (enable_media_mojo_renderer) {
deps += [ "//media/mojo/services:renderer_service" ]
}
+
+ if (enable_webvr) {
+ sources += [
+ "vr/vr_device.cc",
+ "vr/vr_device.h",
+ "vr/vr_device_manager.cc",
+ "vr/vr_device_manager.h",
+ "vr/vr_device_provider.h",
+ ]
+ }
+
+ if (enable_webvr && is_android) {
+ sources += [
+ "vr/android/cardboard/cardboard_vr_device.cc",
+ "vr/android/cardboard/cardboard_vr_device.h",
+ "vr/android/cardboard/cardboard_vr_device_provider.cc",
+ "vr/android/cardboard/cardboard_vr_device_provider.h",
+ ]
+ }
}
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 2ed7e5c..092903f 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -63,6 +63,7 @@ include_rules = [
"+third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h",
"+third_party/WebKit/public/platform/modules/notifications/WebNotificationPermission.h",
"+third_party/WebKit/public/platform/modules/push_messaging/WebPushPermissionStatus.h",
+ "+third_party/WebKit/public/platform/modules/vr/WebVR.h",
"+third_party/WebKit/public/web/mac/WebScrollbarTheme.h",
"+third_party/WebKit/public/web/WebAXEnums.h",
"+third_party/WebKit/public/web/WebCompositionUnderline.h",
diff --git a/content/browser/android/browser_jni_registrar.cc b/content/browser/android/browser_jni_registrar.cc
index 808e3f3..43adba8 100644
--- a/content/browser/android/browser_jni_registrar.cc
+++ b/content/browser/android/browser_jni_registrar.cc
@@ -40,6 +40,7 @@
#include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
#include "content/browser/speech/speech_recognizer_impl_android.h"
#include "content/browser/time_zone_monitor_android.h"
+#include "content/browser/vr/android/cardboard/cardboard_vr_device.h"
#include "content/browser/web_contents/web_contents_android.h"
#include "mojo/android/system/core_impl.h"
@@ -52,6 +53,10 @@ base::android::RegistrationMethod kContentRegisteredMethods[] = {
{"BrowserAccessibilityManager",
content::RegisterBrowserAccessibilityManager},
{"BrowserStartupController", content::RegisterBrowserStartupController},
+#if defined(ENABLE_WEBVR)
+ {"CardboardVRDevice",
+ content::CardboardVRDevice::RegisterCardboardVRDevice},
+#endif
{"ChildProcessLauncher", content::RegisterChildProcessLauncher},
{"ContentReadbackHandler",
content::ContentReadbackHandler::RegisterContentReadbackHandler},
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 74ac164..11ae65a 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -81,6 +81,10 @@
#include "media/mojo/services/mojo_renderer_service.h"
#endif
+#if defined(ENABLE_WEBVR)
+#include "content/browser/vr/vr_device_manager.h"
+#endif
+
using base::TimeDelta;
namespace content {
@@ -1579,6 +1583,16 @@ void RenderFrameHostImpl::RegisterMojoServices() {
GetServiceRegistry()->AddService<mojo::Shell>(base::Bind(
&FrameMojoShell::BindRequest, base::Unretained(frame_mojo_shell_.get())));
+#if defined(ENABLE_WEBVR)
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
+
+ if (browser_command_line.HasSwitch(switches::kEnableWebVR)) {
+ GetServiceRegistry()->AddService<VRService>(
+ base::Bind(&VRDeviceManager::BindRequest));
+ }
+#endif
+
GetContentClient()->browser()->OverrideRenderFrameMojoServices(
GetServiceRegistry(), this);
}
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index aa2cee4..4754ddb 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1306,6 +1306,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableWebBluetooth,
switches::kEnableWebGLDraftExtensions,
switches::kEnableWebGLImageChromium,
+ switches::kEnableWebVR,
switches::kExplicitlyAllowedPorts,
switches::kForceDeviceScaleFactor,
switches::kForceDisplayList2dCanvas,
diff --git a/content/browser/vr/OWNERS b/content/browser/vr/OWNERS
new file mode 100644
index 0000000..1c724a6
--- /dev/null
+++ b/content/browser/vr/OWNERS
@@ -0,0 +1,2 @@
+bajones@chromium.org
+kbr@chromium.org
diff --git a/content/browser/vr/android/cardboard/cardboard_vr_device.cc b/content/browser/vr/android/cardboard/cardboard_vr_device.cc
new file mode 100644
index 0000000..11f8505
--- /dev/null
+++ b/content/browser/vr/android/cardboard/cardboard_vr_device.cc
@@ -0,0 +1,188 @@
+// 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 "content/browser/vr/android/cardboard/cardboard_vr_device.h"
+
+#include <math.h>
+#include <algorithm>
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "jni/CardboardVRDevice_jni.h"
+
+using base::android::AttachCurrentThread;
+
+namespace content {
+
+namespace {
+
+// Source:
+// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
+VRVector4Ptr MatrixToOrientationQuat(const float m[16]) {
+ VRVector4Ptr out = VRVector4::New();
+ float trace = m[0] + m[5] + m[10];
+ float root;
+ if (trace > 0.0f) {
+ root = sqrtf(1.0f + trace) * 2.0f;
+ out->x = (m[9] - m[6]) / root;
+ out->y = (m[2] - m[8]) / root;
+ out->z = (m[4] - m[1]) / root;
+ out->w = 0.25f * root;
+ } else if ((m[0] > m[5]) && (m[0] > m[10])) {
+ root = sqrtf(1.0f + m[0] - m[5] - m[10]) * 2.0f;
+ out->x = 0.25f * root;
+ out->y = (m[1] + m[4]) / root;
+ out->z = (m[2] + m[8]) / root;
+ out->w = (m[9] - m[6]) / root;
+ } else if (m[5] > m[10]) {
+ root = sqrtf(1.0f + m[5] - m[0] - m[10]) * 2.0f;
+ out->x = (m[1] + m[4]) / root;
+ out->y = 0.25f * root;
+ out->z = (m[6] + m[9]) / root;
+ out->w = (m[2] - m[8]) / root;
+ } else {
+ root = sqrtf(1.0f + m[10] - m[0] - m[5]) * 2.0f;
+ out->x = (m[2] + m[8]) / root;
+ out->y = (m[6] + m[9]) / root;
+ out->z = 0.25f * root;
+ out->w = (m[4] - m[1]) / root;
+ }
+
+ return out.Pass();
+}
+
+} // namespace
+
+bool CardboardVRDevice::RegisterCardboardVRDevice(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+CardboardVRDevice::CardboardVRDevice(VRDeviceProvider* provider)
+ : VRDevice(provider), frame_index_(0) {
+ j_cardboard_device_.Reset(Java_CardboardVRDevice_create(
+ AttachCurrentThread(), base::android::GetApplicationContext()));
+}
+
+CardboardVRDevice::~CardboardVRDevice() {
+ Java_CardboardVRDevice_stopTracking(AttachCurrentThread(),
+ j_cardboard_device_.obj());
+}
+
+VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() {
+ VRDeviceInfoPtr device = VRDeviceInfo::New();
+
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jstring> j_device_name =
+ Java_CardboardVRDevice_getDeviceName(env, j_cardboard_device_.obj());
+ device->deviceName =
+ base::android::ConvertJavaStringToUTF8(env, j_device_name.obj());
+
+ ScopedJavaLocalRef<jfloatArray> j_fov(env, env->NewFloatArray(4));
+ Java_CardboardVRDevice_getFieldOfView(env, j_cardboard_device_.obj(),
+ j_fov.obj());
+
+ std::vector<float> fov;
+ base::android::JavaFloatArrayToFloatVector(env, j_fov.obj(), &fov);
+
+ device->hmdInfo = VRHMDInfo::New();
+ VRHMDInfoPtr& hmdInfo = device->hmdInfo;
+
+ hmdInfo->leftEye = VREyeParameters::New();
+ hmdInfo->rightEye = VREyeParameters::New();
+ VREyeParametersPtr& leftEye = hmdInfo->leftEye;
+ VREyeParametersPtr& rightEye = hmdInfo->rightEye;
+
+ leftEye->recommendedFieldOfView = VRFieldOfView::New();
+ leftEye->recommendedFieldOfView->upDegrees = fov[0];
+ leftEye->recommendedFieldOfView->downDegrees = fov[1];
+ leftEye->recommendedFieldOfView->leftDegrees = fov[2];
+ leftEye->recommendedFieldOfView->rightDegrees = fov[3];
+
+ // Cardboard devices always assume a mirrored FOV, so this is just the left
+ // eye FOV with the left and right degrees swapped.
+ rightEye->recommendedFieldOfView = VRFieldOfView::New();
+ rightEye->recommendedFieldOfView->upDegrees = fov[0];
+ rightEye->recommendedFieldOfView->downDegrees = fov[1];
+ rightEye->recommendedFieldOfView->leftDegrees = fov[3];
+ rightEye->recommendedFieldOfView->rightDegrees = fov[2];
+
+ // Cardboard does not support configurable FOV.
+ leftEye->maximumFieldOfView = leftEye->recommendedFieldOfView.Clone();
+ rightEye->maximumFieldOfView = rightEye->recommendedFieldOfView.Clone();
+ leftEye->minimumFieldOfView = leftEye->recommendedFieldOfView.Clone();
+ rightEye->minimumFieldOfView = rightEye->recommendedFieldOfView.Clone();
+
+ float ipd = Java_CardboardVRDevice_getIpd(env, j_cardboard_device_.obj());
+
+ leftEye->eyeTranslation = VRVector3::New();
+ leftEye->eyeTranslation->x = ipd * -0.5f;
+ leftEye->eyeTranslation->y = 0.0f;
+ leftEye->eyeTranslation->z = 0.0f;
+
+ rightEye->eyeTranslation = VRVector3::New();
+ rightEye->eyeTranslation->x = ipd * 0.5f;
+ rightEye->eyeTranslation->y = 0.0f;
+ rightEye->eyeTranslation->z = 0.0f;
+
+ ScopedJavaLocalRef<jintArray> j_screen_size(env, env->NewIntArray(2));
+ Java_CardboardVRDevice_getScreenSize(env, j_cardboard_device_.obj(),
+ j_screen_size.obj());
+
+ std::vector<int> screen_size;
+ base::android::JavaIntArrayToIntVector(env, j_screen_size.obj(),
+ &screen_size);
+
+ leftEye->renderRect = VRRect::New();
+ leftEye->renderRect->x = 0;
+ leftEye->renderRect->y = 0;
+ leftEye->renderRect->width = screen_size[0] / 2.0;
+ leftEye->renderRect->height = screen_size[1];
+
+ rightEye->renderRect = VRRect::New();
+ rightEye->renderRect->x = screen_size[0] / 2.0;
+ rightEye->renderRect->y = 0;
+ rightEye->renderRect->width = screen_size[0] / 2.0;
+ rightEye->renderRect->height = screen_size[1];
+
+ return device.Pass();
+}
+
+VRSensorStatePtr CardboardVRDevice::GetSensorState() {
+ VRSensorStatePtr state = VRSensorState::New();
+
+ state->timestamp = base::Time::Now().ToJsTime();
+ state->frameIndex = frame_index_;
+
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jfloatArray> j_head_matrix(env, env->NewFloatArray(16));
+ Java_CardboardVRDevice_getSensorState(env, j_cardboard_device_.obj(),
+ j_head_matrix.obj());
+
+ std::vector<float> head_matrix;
+ base::android::JavaFloatArrayToFloatVector(env, j_head_matrix.obj(),
+ &head_matrix);
+
+ state->orientation = MatrixToOrientationQuat(&head_matrix[0]);
+
+ state->position = VRVector3::New();
+ state->position->x = -head_matrix[12];
+ state->position->y = head_matrix[13];
+ state->position->z = head_matrix[14];
+
+ frame_index_++;
+
+ return state.Pass();
+}
+
+void CardboardVRDevice::ResetSensor() {
+ Java_CardboardVRDevice_resetSensor(AttachCurrentThread(),
+ j_cardboard_device_.obj());
+}
+
+} // namespace content
diff --git a/content/browser/vr/android/cardboard/cardboard_vr_device.h b/content/browser/vr/android/cardboard/cardboard_vr_device.h
new file mode 100644
index 0000000..5d7baa9
--- /dev/null
+++ b/content/browser/vr/android/cardboard/cardboard_vr_device.h
@@ -0,0 +1,37 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_H
+#define CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_H
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/basictypes.h"
+#include "content/browser/vr/vr_device.h"
+
+namespace content {
+
+class CardboardVRDevice : public VRDevice {
+ public:
+ static bool RegisterCardboardVRDevice(JNIEnv* env);
+
+ explicit CardboardVRDevice(VRDeviceProvider* provider);
+ ~CardboardVRDevice() override;
+
+ VRDeviceInfoPtr GetVRDevice() override;
+ VRSensorStatePtr GetSensorState() override;
+ void ResetSensor() override;
+
+ private:
+ base::android::ScopedJavaGlobalRef<jobject> j_cardboard_device_;
+
+ unsigned int frame_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(CardboardVRDevice);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_H
diff --git a/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc b/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc
new file mode 100644
index 0000000..eeb5baf
--- /dev/null
+++ b/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc
@@ -0,0 +1,29 @@
+// 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 "content/browser/vr/android/cardboard/cardboard_vr_device_provider.h"
+
+#include "content/browser/vr/android/cardboard/cardboard_vr_device.h"
+
+namespace content {
+
+CardboardVRDeviceProvider::CardboardVRDeviceProvider() : VRDeviceProvider() {
+}
+
+CardboardVRDeviceProvider::~CardboardVRDeviceProvider() {
+}
+
+void CardboardVRDeviceProvider::GetDevices(std::vector<VRDevice*>& devices) {
+ if (!cardboard_device_) {
+ cardboard_device_.reset(new CardboardVRDevice(this));
+ }
+
+ devices.push_back(cardboard_device_.get());
+}
+
+void CardboardVRDeviceProvider::Initialize() {
+ // No initialization needed for Cardboard devices.
+}
+
+} // namespace content
diff --git a/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h b/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h
new file mode 100644
index 0000000..18efa5c
--- /dev/null
+++ b/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h
@@ -0,0 +1,33 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_PROVIDER_H
+#define CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_PROVIDER_H
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/vr/vr_device.h"
+#include "content/browser/vr/vr_device_provider.h"
+
+namespace content {
+
+class CardboardVRDeviceProvider : public VRDeviceProvider {
+ public:
+ CardboardVRDeviceProvider();
+ ~CardboardVRDeviceProvider() override;
+
+ void GetDevices(std::vector<VRDevice*>& devices) override;
+ void Initialize() override;
+
+ private:
+ scoped_ptr<VRDevice> cardboard_device_;
+
+ DISALLOW_COPY_AND_ASSIGN(CardboardVRDeviceProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_PROVIDER_H
diff --git a/content/browser/vr/test/fake_vr_device.cc b/content/browser/vr/test/fake_vr_device.cc
new file mode 100644
index 0000000..7ee5e06
--- /dev/null
+++ b/content/browser/vr/test/fake_vr_device.cc
@@ -0,0 +1,33 @@
+// 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 "content/browser/vr/test/fake_vr_device.h"
+
+namespace content {
+
+FakeVRDevice::FakeVRDevice(VRDeviceProvider* provider) : VRDevice(provider) {
+ device_ = VRDeviceInfo::New();
+ state_ = VRSensorState::New();
+}
+
+FakeVRDevice::~FakeVRDevice() {
+}
+
+void FakeVRDevice::SetVRDevice(const VRDeviceInfoPtr& device) {
+ device_ = device.Clone();
+}
+
+void FakeVRDevice::SetSensorState(const VRSensorStatePtr& state) {
+ state_ = state.Clone();
+}
+
+VRDeviceInfoPtr FakeVRDevice::GetVRDevice() {
+ return device_.Clone();
+}
+
+VRSensorStatePtr FakeVRDevice::GetSensorState() {
+ return state_.Clone();
+}
+
+} // namespace content \ No newline at end of file
diff --git a/content/browser/vr/test/fake_vr_device.h b/content/browser/vr/test/fake_vr_device.h
new file mode 100644
index 0000000..2cb7384
--- /dev/null
+++ b/content/browser/vr/test/fake_vr_device.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_VR_TEST_FAKE_VR_DEVICE_H_
+#define CONTENT_BROWSER_VR_TEST_FAKE_VR_DEVICE_H_
+
+#include "content/browser/vr/vr_device.h"
+#include "content/browser/vr/vr_device_provider.h"
+
+namespace content {
+
+class FakeVRDevice : public VRDevice {
+ public:
+ explicit FakeVRDevice(VRDeviceProvider* provider);
+ ~FakeVRDevice() override;
+
+ void SetVRDevice(const VRDeviceInfoPtr& device);
+ void SetSensorState(const VRSensorStatePtr& state);
+
+ VRDeviceInfoPtr GetVRDevice() override;
+ VRSensorStatePtr GetSensorState() override;
+ void ResetSensor() override{};
+
+ private:
+ VRDeviceInfoPtr device_;
+ VRSensorStatePtr state_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeVRDevice);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_VR_TEST_FAKE_VR_DEVICE_H_
diff --git a/content/browser/vr/test/fake_vr_device_provider.cc b/content/browser/vr/test/fake_vr_device_provider.cc
new file mode 100644
index 0000000..d69802b
--- /dev/null
+++ b/content/browser/vr/test/fake_vr_device_provider.cc
@@ -0,0 +1,43 @@
+// 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 "content/browser/vr/test/fake_vr_device_provider.h"
+
+namespace content {
+
+FakeVRDeviceProvider::FakeVRDeviceProvider() : VRDeviceProvider() {
+ initialized_ = false;
+}
+
+FakeVRDeviceProvider::~FakeVRDeviceProvider() {
+}
+
+void FakeVRDeviceProvider::AddDevice(VRDevice* device) {
+ devices_.push_back(device);
+}
+
+void FakeVRDeviceProvider::RemoveDevice(VRDevice* device) {
+ std::vector<VRDevice*>::iterator iter = devices_.begin();
+ while (iter != devices_.end()) {
+ if (device == *iter) {
+ iter = devices_.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+void FakeVRDeviceProvider::GetDevices(std::vector<VRDevice*>& devices) {
+ std::vector<VRDevice*>::iterator iter;
+
+ for (auto device : devices_) {
+ devices.push_back(device);
+ }
+}
+
+void FakeVRDeviceProvider::Initialize() {
+ initialized_ = true;
+}
+
+} // namespace content \ No newline at end of file
diff --git a/content/browser/vr/test/fake_vr_device_provider.h b/content/browser/vr/test/fake_vr_device_provider.h
new file mode 100644
index 0000000..e5877a3
--- /dev/null
+++ b/content/browser/vr/test/fake_vr_device_provider.h
@@ -0,0 +1,35 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_VR_TEST_FAKE_VR_DEVICE_PROVIDER_H_
+#define CONTENT_BROWSER_VR_TEST_FAKE_VR_DEVICE_PROVIDER_H_
+
+#include <vector>
+#include "content/browser/vr/vr_device.h"
+#include "content/browser/vr/vr_device_provider.h"
+
+namespace content {
+
+class FakeVRDeviceProvider : public VRDeviceProvider {
+ public:
+ FakeVRDeviceProvider();
+ ~FakeVRDeviceProvider() override;
+
+ // Adds devices to the provider with the given device, which will be
+ // returned when GetDevices is queried.
+ void AddDevice(VRDevice* device);
+ void RemoveDevice(VRDevice* device);
+ bool IsInitialized() { return initialized_; }
+
+ void GetDevices(std::vector<VRDevice*>& devices) override;
+ void Initialize() override;
+
+ private:
+ std::vector<VRDevice*> devices_;
+ bool initialized_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_VR_TEST_FAKE_VR_DEVICE_PROVIDER_H_
diff --git a/content/browser/vr/vr_device.cc b/content/browser/vr/vr_device.cc
new file mode 100644
index 0000000..ab7a7bc
--- /dev/null
+++ b/content/browser/vr/vr_device.cc
@@ -0,0 +1,22 @@
+// 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 "content/browser/vr/vr_device.h"
+#include "content/browser/vr/vr_device_provider.h"
+
+namespace content {
+
+unsigned int VRDevice::next_id_ = 1;
+
+VRDevice::VRDevice(VRDeviceProvider* provider)
+ : provider_(provider), id_(next_id_) {
+ // Prevent wraparound. Devices with this ID will be treated as invalid.
+ if (next_id_ != VR_DEVICE_LAST_ID)
+ next_id_++;
+}
+
+VRDevice::~VRDevice() {
+}
+
+} // namespace content
diff --git a/content/browser/vr/vr_device.h b/content/browser/vr/vr_device.h
new file mode 100644
index 0000000..e3026d7
--- /dev/null
+++ b/content/browser/vr/vr_device.h
@@ -0,0 +1,48 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_VR_VR_DEVICE_H
+#define CONTENT_BROWSER_VR_VR_DEVICE_H
+
+#include "base/macros.h"
+#include "content/common/vr_service.mojom.h"
+
+namespace blink {
+struct WebHMDSensorState;
+}
+
+namespace ui {
+class BaseWindow;
+}
+
+namespace content {
+
+class VRDeviceProvider;
+
+const unsigned int VR_DEVICE_LAST_ID = 0xFFFFFFFF;
+
+class VRDevice {
+ public:
+ explicit VRDevice(VRDeviceProvider* provider);
+ virtual ~VRDevice();
+
+ VRDeviceProvider* provider() const { return provider_; }
+ unsigned int id() const { return id_; }
+
+ virtual VRDeviceInfoPtr GetVRDevice() = 0;
+ virtual VRSensorStatePtr GetSensorState() = 0;
+ virtual void ResetSensor() = 0;
+
+ private:
+ VRDeviceProvider* provider_;
+ unsigned int id_;
+
+ static unsigned int next_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(VRDevice);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_VR_VR_DEVICE_H
diff --git a/content/browser/vr/vr_device_manager.cc b/content/browser/vr/vr_device_manager.cc
new file mode 100644
index 0000000..1451056
--- /dev/null
+++ b/content/browser/vr/vr_device_manager.cc
@@ -0,0 +1,148 @@
+// 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 "content/browser/vr/vr_device_manager.h"
+
+#include "base/memory/singleton.h"
+#include "third_party/WebKit/public/platform/modules/vr/WebVR.h"
+
+#if defined(OS_ANDROID)
+#include "content/browser/vr/android/cardboard/cardboard_vr_device_provider.h"
+#endif
+
+namespace content {
+
+namespace {
+VRDeviceManager* g_vr_device_manager = nullptr;
+}
+
+VRDeviceManager::VRDeviceManager()
+ : vr_initialized_(false), keep_alive_(false) {
+ bindings_.set_error_handler(this);
+
+#if defined(OS_ANDROID)
+ scoped_ptr<VRDeviceProvider> cardboard_provider(
+ new CardboardVRDeviceProvider());
+ RegisterProvider(cardboard_provider.Pass());
+#endif
+}
+
+VRDeviceManager::VRDeviceManager(scoped_ptr<VRDeviceProvider> provider)
+ : vr_initialized_(false), keep_alive_(true) {
+ thread_checker_.DetachFromThread();
+ RegisterProvider(provider.Pass());
+ SetInstance(this);
+}
+
+VRDeviceManager::~VRDeviceManager() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ g_vr_device_manager = nullptr;
+}
+
+void VRDeviceManager::BindRequest(mojo::InterfaceRequest<VRService> request) {
+ VRDeviceManager* device_manager = GetInstance();
+ device_manager->bindings_.AddBinding(device_manager, request.Pass());
+}
+
+void VRDeviceManager::OnConnectionError() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (bindings_.empty() && !keep_alive_) {
+ // Delete the device manager when it has no active connections.
+ delete g_vr_device_manager;
+ }
+}
+
+VRDeviceManager* VRDeviceManager::GetInstance() {
+ if (!g_vr_device_manager)
+ g_vr_device_manager = new VRDeviceManager();
+ return g_vr_device_manager;
+}
+
+void VRDeviceManager::SetInstance(VRDeviceManager* instance) {
+ // Unit tests can create multiple instances but only one should exist at any
+ // given time so g_vr_device_manager should only go from nullptr to
+ // non-nullptr and vica versa.
+ CHECK_NE(!!instance, !!g_vr_device_manager);
+ g_vr_device_manager = instance;
+}
+
+bool VRDeviceManager::HasInstance() {
+ // For testing. Checks to see if a VRDeviceManager instance is active.
+ return !!g_vr_device_manager;
+}
+
+mojo::Array<VRDeviceInfoPtr> VRDeviceManager::GetVRDevices() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ InitializeProviders();
+
+ std::vector<VRDevice*> devices;
+ for (const auto& provider : providers_)
+ provider->GetDevices(devices);
+
+ mojo::Array<VRDeviceInfoPtr> out_devices(0);
+ for (const auto& device : devices) {
+ if (device->id() == VR_DEVICE_LAST_ID)
+ continue;
+
+ if (devices_.find(device->id()) == devices_.end())
+ devices_[device->id()] = device;
+
+ VRDeviceInfoPtr vr_device_info = device->GetVRDevice();
+ if (vr_device_info.is_null())
+ continue;
+
+ vr_device_info->index = device->id();
+ out_devices.push_back(vr_device_info.Pass());
+ }
+
+ return out_devices;
+}
+
+VRDevice* VRDeviceManager::GetDevice(unsigned int index) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ DeviceMap::iterator iter = devices_.find(index);
+ if (iter == devices_.end()) {
+ return nullptr;
+ }
+ return iter->second;
+}
+
+void VRDeviceManager::InitializeProviders() {
+ if (vr_initialized_) {
+ return;
+ }
+
+ for (const auto& provider : providers_)
+ provider->Initialize();
+
+ vr_initialized_ = true;
+}
+
+void VRDeviceManager::RegisterProvider(scoped_ptr<VRDeviceProvider> provider) {
+ providers_.push_back(make_linked_ptr(provider.release()));
+}
+
+void VRDeviceManager::GetDevices(const GetDevicesCallback& callback) {
+ callback.Run(GetVRDevices());
+}
+
+void VRDeviceManager::GetSensorState(uint32_t index,
+ const GetSensorStateCallback& callback) {
+ VRDevice* device = GetDevice(index);
+ if (device) {
+ callback.Run(device->GetSensorState());
+ } else {
+ callback.Run(nullptr);
+ }
+}
+
+void VRDeviceManager::ResetSensor(uint32_t index) {
+ VRDevice* device = GetDevice(index);
+ if (device)
+ device->ResetSensor();
+}
+
+} // namespace content
diff --git a/content/browser/vr/vr_device_manager.h b/content/browser/vr/vr_device_manager.h
new file mode 100644
index 0000000..6c8dc96
--- /dev/null
+++ b/content/browser/vr/vr_device_manager.h
@@ -0,0 +1,78 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_VR_VR_DEVICE_MANAGER_H
+#define CONTENT_BROWSER_VR_VR_DEVICE_MANAGER_H
+
+#include <map>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "content/browser/vr/vr_device.h"
+#include "content/browser/vr/vr_device_provider.h"
+#include "content/common/content_export.h"
+#include "content/common/vr_service.mojom.h"
+#include "mojo/common/weak_binding_set.h"
+
+namespace content {
+
+class VRDeviceManager : public VRService, public mojo::ErrorHandler {
+ public:
+ ~VRDeviceManager() override;
+
+ static void BindRequest(mojo::InterfaceRequest<VRService> request);
+
+ // Returns the VRDeviceManager singleton.
+ static VRDeviceManager* GetInstance();
+
+ mojo::Array<VRDeviceInfoPtr> GetVRDevices();
+ VRDevice* GetDevice(unsigned int index);
+
+ private:
+ friend class VRDeviceManagerTest;
+
+ VRDeviceManager();
+ // Constructor for testing.
+ explicit VRDeviceManager(scoped_ptr<VRDeviceProvider> provider);
+
+ static void SetInstance(VRDeviceManager* service);
+ static bool HasInstance();
+
+ void InitializeProviders();
+ void RegisterProvider(scoped_ptr<VRDeviceProvider> provider);
+
+ // VRService implementation
+ void GetDevices(const GetDevicesCallback& callback) override;
+ void GetSensorState(uint32_t index,
+ const GetSensorStateCallback& callback) override;
+ void ResetSensor(uint32_t index) override;
+
+ // mojo::ErrorHandler implementation
+ void OnConnectionError() override;
+
+ using ProviderList = std::vector<linked_ptr<VRDeviceProvider>>;
+ ProviderList providers_;
+
+ // Devices are owned by their providers.
+ using DeviceMap = std::map<unsigned int, VRDevice*>;
+ DeviceMap devices_;
+
+ bool vr_initialized_;
+
+ mojo::WeakBindingSet<VRService> bindings_;
+
+ // For testing. If true will not delete self when consumer count reaches 0.
+ bool keep_alive_;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(VRDeviceManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_VR_VR_DEVICE_MANAGER_H
diff --git a/content/browser/vr/vr_device_manager_unittest.cc b/content/browser/vr/vr_device_manager_unittest.cc
new file mode 100644
index 0000000..873a296
--- /dev/null
+++ b/content/browser/vr/vr_device_manager_unittest.cc
@@ -0,0 +1,96 @@
+// 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 "base/memory/linked_ptr.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/vr/test/fake_vr_device.h"
+#include "content/browser/vr/test/fake_vr_device_provider.h"
+#include "content/browser/vr/vr_device_manager.h"
+#include "content/browser/vr/vr_device_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class VRDeviceManagerTest : public testing::Test {
+ protected:
+ VRDeviceManagerTest();
+ ~VRDeviceManagerTest() override;
+
+ void SetUp() override;
+
+ bool HasServiceInstance() { return VRDeviceManager::HasInstance(); }
+
+ protected:
+ FakeVRDeviceProvider* provider_;
+ scoped_ptr<VRDeviceManager> device_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(VRDeviceManagerTest);
+};
+
+VRDeviceManagerTest::VRDeviceManagerTest() {
+}
+
+VRDeviceManagerTest::~VRDeviceManagerTest() {
+}
+
+void VRDeviceManagerTest::SetUp() {
+ scoped_ptr<FakeVRDeviceProvider> provider(new FakeVRDeviceProvider());
+ provider_ = provider.get();
+ device_manager_.reset(new VRDeviceManager(provider.Pass()));
+}
+
+TEST_F(VRDeviceManagerTest, InitializationTest) {
+ EXPECT_FALSE(provider_->IsInitialized());
+
+ // Calling GetDevices should initialize the service if it hasn't been
+ // initialized yet or the providesr have been released.
+ // The VRService should initialize each of it's providers upon it's own
+ // initialization.
+ mojo::Array<VRDeviceInfoPtr> webvr_devices;
+ webvr_devices = device_manager_->GetVRDevices();
+ EXPECT_TRUE(provider_->IsInitialized());
+}
+
+TEST_F(VRDeviceManagerTest, GetDevicesBasicTest) {
+ mojo::Array<VRDeviceInfoPtr> webvr_devices;
+ webvr_devices = device_manager_->GetVRDevices();
+ // Calling GetVRDevices should initialize the providers.
+ EXPECT_TRUE(provider_->IsInitialized());
+ // Should successfully return zero devices when none are available.
+ EXPECT_EQ(0u, webvr_devices.size());
+
+ // GetDeviceByIndex should return nullptr if an invalid index in queried.
+ VRDevice* queried_device = device_manager_->GetDevice(1);
+ EXPECT_EQ(nullptr, queried_device);
+
+ scoped_ptr<FakeVRDevice> device1(new FakeVRDevice(provider_));
+ provider_->AddDevice(device1.get());
+ webvr_devices = device_manager_->GetVRDevices();
+ // Should have successfully returned one device.
+ EXPECT_EQ(1u, webvr_devices.size());
+ // The WebVRDevice index should match the device id.
+ EXPECT_EQ(webvr_devices[0]->index, device1->id());
+
+ scoped_ptr<FakeVRDevice> device2(new FakeVRDevice(provider_));
+ provider_->AddDevice(device2.get());
+ webvr_devices = device_manager_->GetVRDevices();
+ // Should have successfully returned two devices.
+ EXPECT_EQ(2u, webvr_devices.size());
+ // NOTE: Returned WebVRDevices are not required to be in any particular order.
+
+ // Querying the WebVRDevice index should return the correct device.
+ queried_device = device_manager_->GetDevice(device1->id());
+ EXPECT_EQ(device1.get(), queried_device);
+ queried_device = device_manager_->GetDevice(device2->id());
+ EXPECT_EQ(device2.get(), queried_device);
+
+ provider_->RemoveDevice(device1.get());
+ webvr_devices = device_manager_->GetVRDevices();
+ // Should have successfully returned one device.
+ EXPECT_EQ(1u, webvr_devices.size());
+ // The WebVRDevice index should match the only remaining device id.
+ EXPECT_EQ(webvr_devices[0]->index, device2->id());
+}
+
+} // namespace content
diff --git a/content/browser/vr/vr_device_provider.h b/content/browser/vr/vr_device_provider.h
new file mode 100644
index 0000000..7a0207c
--- /dev/null
+++ b/content/browser/vr/vr_device_provider.h
@@ -0,0 +1,27 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_VR_VR_DEVICE_PROVIDER_H
+#define CONTENT_BROWSER_VR_VR_DEVICE_PROVIDER_H
+
+#include <vector>
+
+namespace content {
+
+class VRDevice;
+
+class VRDeviceProvider {
+ public:
+ VRDeviceProvider() {}
+ virtual ~VRDeviceProvider() {}
+
+ virtual void GetDevices(std::vector<VRDevice*>& devices) = 0;
+
+ // If the VR API requires initialization that should happen here.
+ virtual void Initialize() = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_VR_VR_DEVICE_PROVIDER_H
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 5ce09de..8309415 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -203,6 +203,11 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kEnableUnsafeES3APIs))
WebRuntimeFeatures::enableUnsafeES3APIs(true);
+ if (command_line.HasSwitch(switches::kEnableWebVR)) {
+ WebRuntimeFeatures::enableWebVR(true);
+ WebRuntimeFeatures::enableFeatureFromString("GeometryInterfaces", true);
+ }
+
// Enable explicitly enabled features, and then disable explicitly disabled
// ones.
if (command_line.HasSwitch(switches::kEnableBlinkFeatures)) {
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 2e82056..9f9c1e9 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -492,6 +492,7 @@ mojom("mojo_bindings") {
"presentation/presentation_service.mojom",
"process_control.mojom",
"render_frame_setup.mojom",
+ "vr_service.mojom",
]
import_dirs = [ "//mojo/services" ]
diff --git a/content/common/vr_service.mojom b/content/common/vr_service.mojom
new file mode 100644
index 0000000..2d81ec7
--- /dev/null
+++ b/content/common/vr_service.mojom
@@ -0,0 +1,73 @@
+// 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.
+
+module content;
+
+struct VRVector3 {
+ float x;
+ float y;
+ float z;
+};
+
+struct VRVector4 {
+ float x;
+ float y;
+ float z;
+ float w;
+};
+
+struct VRRect {
+ int32 x;
+ int32 y;
+ int32 width;
+ int32 height;
+};
+
+// A field of view, given by 4 degrees describing the view from a center point.
+struct VRFieldOfView {
+ float upDegrees;
+ float downDegrees;
+ float leftDegrees;
+ float rightDegrees;
+};
+
+// A sensor's position, orientation, velocity, and acceleration state at the
+// given timestamp.
+struct VRSensorState {
+ double timestamp;
+ uint32 frameIndex;
+ VRVector4? orientation;
+ VRVector3? position;
+ VRVector3? angularVelocity;
+ VRVector3? linearVelocity;
+ VRVector3? angularAcceleration;
+ VRVector3? linearAcceleration;
+};
+
+// Information about the optical properties for an eye in an HMD.
+struct VREyeParameters {
+ VRFieldOfView minimumFieldOfView;
+ VRFieldOfView maximumFieldOfView;
+ VRFieldOfView recommendedFieldOfView;
+ VRVector3 eyeTranslation;
+ VRRect renderRect;
+};
+
+// Information pertaining to Head Mounted Displays.
+struct VRHMDInfo {
+ VREyeParameters leftEye;
+ VREyeParameters rightEye;
+};
+
+struct VRDeviceInfo {
+ uint32 index;
+ string deviceName;
+ VRHMDInfo? hmdInfo;
+};
+
+interface VRService {
+ GetDevices() => (array<VRDeviceInfo> devices);
+ GetSensorState(uint32 index) => (VRSensorState state);
+ ResetSensor(uint32 index);
+};
diff --git a/content/content.gyp b/content/content.gyp
index 13a8385..beffec2 100644
--- a/content/content.gyp
+++ b/content/content.gyp
@@ -589,6 +589,16 @@
'motionevent_jni_headers'
],
'includes': [ 'content_jni.gypi' ],
+ 'conditions': [
+ ['enable_webvr==1', {
+ 'sources': [
+ 'public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java',
+ ],
+ 'dependencies': [
+ '../third_party/cardboard-java/cardboard.gyp:cardboard_jar',
+ ],
+ }],
+ ],
},
{
'target_name': 'content_icudata',
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index b406173..1ac6bb2 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -2091,5 +2091,22 @@
'../third_party/boringssl/boringssl.gyp:boringssl',
],
}],
+ ['enable_webvr==1', {
+ 'sources': [
+ 'browser/vr/vr_device.cc',
+ 'browser/vr/vr_device.h',
+ 'browser/vr/vr_device_manager.cc',
+ 'browser/vr/vr_device_manager.h',
+ 'browser/vr/vr_device_provider.h',
+ ]
+ }],
+ ['enable_webvr==1 and OS=="android"', {
+ 'sources': [
+ 'browser/vr/android/cardboard/cardboard_vr_device.cc',
+ 'browser/vr/android/cardboard/cardboard_vr_device.h',
+ 'browser/vr/android/cardboard/cardboard_vr_device_provider.cc',
+ 'browser/vr/android/cardboard/cardboard_vr_device_provider.h',
+ ],
+ }],
],
}
diff --git a/content/content_common_mojo_bindings.gyp b/content/content_common_mojo_bindings.gyp
index 4f01043..528fa67 100644
--- a/content/content_common_mojo_bindings.gyp
+++ b/content/content_common_mojo_bindings.gyp
@@ -18,6 +18,7 @@
'common/presentation/presentation_service.mojom',
'common/process_control.mojom',
'common/render_frame_setup.mojom',
+ 'common/vr_service.mojom',
# NOTE: Sources duplicated in
# //content/public/common/BUILD.gn:mojo_bindings.
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index aaf0c40..1089688 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -837,6 +837,14 @@
['use_seccomp_bpf==1', {
'defines': ['USE_SECCOMP_BPF'],
}],
+ ['enable_webvr==1', {
+ 'sources': [
+ 'renderer/vr/vr_dispatcher.cc',
+ 'renderer/vr/vr_dispatcher.h',
+ 'renderer/vr/vr_type_converters.cc',
+ 'renderer/vr/vr_type_converters.h',
+ ]
+ }],
],
'target_conditions': [
['OS=="android"', {
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 988a87a..b4ce419 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -57,6 +57,10 @@ android_library("content_java") {
]
DEPRECATED_java_in_dir = "java/src"
+
+ if (enable_webvr) {
+ deps += [ "//third_party/cardboard-java:cardboard-java" ]
+ }
}
java_strings_grd("content_strings_grd") {
@@ -151,6 +155,13 @@ generate_jar_jni("jar_jni") {
generate_jni("content_jni_headers") {
sources = rebase_path(content_jni_gypi_values.sources, "", "../..")
jni_package = "content"
+
+ if (enable_webvr) {
+ sources += [ "//content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java" ]
+ deps = [
+ "//third_party/cardboard-java:cardboard-java",
+ ]
+ }
}
group("jni") {
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java b/content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java
new file mode 100644
index 0000000..280e3bf
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java
@@ -0,0 +1,88 @@
+// 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.
+
+package org.chromium.content.browser.input;
+
+import android.content.Context;
+
+import com.google.vrtoolkit.cardboard.CardboardDeviceParams;
+import com.google.vrtoolkit.cardboard.FieldOfView;
+import com.google.vrtoolkit.cardboard.HeadMountedDisplay;
+import com.google.vrtoolkit.cardboard.HeadMountedDisplayManager;
+import com.google.vrtoolkit.cardboard.ScreenParams;
+import com.google.vrtoolkit.cardboard.sensors.HeadTracker;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+
+/**
+ * This is the implementation of the C++ counterpart CardboardVRDevice.
+ */
+@JNINamespace("content")
+class CardboardVRDevice {
+ private static final String TAG = "CardboardVRDevice";
+ private final HeadMountedDisplayManager mHMDManager;
+ private final HeadTracker mHeadTracker;
+
+ @CalledByNative
+ private static CardboardVRDevice create(Context context) {
+ return new CardboardVRDevice(context);
+ }
+
+ private CardboardVRDevice(Context context) {
+ mHMDManager = new HeadMountedDisplayManager(context);
+
+ mHeadTracker = HeadTracker.createFromContext(context);
+ mHeadTracker.setNeckModelEnabled(true);
+ mHeadTracker.startTracking();
+ }
+
+ @CalledByNative
+ private void getFieldOfView(float[] outFov) {
+ HeadMountedDisplay hmd = mHMDManager.getHeadMountedDisplay();
+ CardboardDeviceParams deviceParams = hmd.getCardboardDeviceParams();
+ FieldOfView fov = deviceParams.getLeftEyeMaxFov();
+ outFov[0] = fov.getTop();
+ outFov[1] = fov.getBottom();
+ outFov[2] = fov.getLeft();
+ outFov[3] = fov.getRight();
+ }
+
+ @CalledByNative
+ private float getIpd() {
+ HeadMountedDisplay hmd = mHMDManager.getHeadMountedDisplay();
+ CardboardDeviceParams deviceParams = hmd.getCardboardDeviceParams();
+ return deviceParams.getInterLensDistance();
+ }
+
+ @CalledByNative
+ private String getDeviceName() {
+ HeadMountedDisplay hmd = mHMDManager.getHeadMountedDisplay();
+ CardboardDeviceParams deviceParams = hmd.getCardboardDeviceParams();
+ return deviceParams.getVendor() + " " + deviceParams.getModel();
+ }
+
+ @CalledByNative
+ private void getScreenSize(int[] outSize) {
+ HeadMountedDisplay hmd = mHMDManager.getHeadMountedDisplay();
+ ScreenParams screenParams = hmd.getScreenParams();
+ outSize[0] = screenParams.getWidth();
+ outSize[1] = screenParams.getHeight();
+ }
+
+ @CalledByNative
+ private void getSensorState(float[] outMatrix) {
+ mHeadTracker.getLastHeadView(outMatrix, 0);
+ }
+
+ @CalledByNative
+ private void stopTracking() {
+ mHeadTracker.stopTracking();
+ }
+
+ @CalledByNative
+ private void resetSensor() {
+ mHeadTracker.resetTracker();
+ }
+}
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 1f7e4b0..5c8efcd 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -477,6 +477,9 @@ const char kEnableWebGLDraftExtensions[] = "enable-webgl-draft-extensions";
// Enables WebGL rendering into a scanout buffer for overlay support.
const char kEnableWebGLImageChromium[] = "enable-webgl-image-chromium";
+// Enables interaction with virtual reality devices.
+const char kEnableWebVR[] = "enable-webvr";
+
// Enable rasterizer that writes directly to GPU memory associated with tiles.
const char kEnableZeroCopy[] = "enable-zero-copy";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index aead5ac..4b45d2e 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -142,6 +142,7 @@ CONTENT_EXPORT extern const char kInvertViewportScrollOrder[];
CONTENT_EXPORT extern const char kEnableVtune[];
CONTENT_EXPORT extern const char kEnableWebGLDraftExtensions[];
CONTENT_EXPORT extern const char kEnableWebGLImageChromium[];
+CONTENT_EXPORT extern const char kEnableWebVR[];
CONTENT_EXPORT extern const char kEnableZeroCopy[];
CONTENT_EXPORT extern const char kExplicitlyAllowedPorts[];
CONTENT_EXPORT extern const char kExtraPluginDir[];
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 9287ccb..9c078e4 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -199,4 +199,13 @@ source_set("renderer") {
]
deps += [ "//media/mojo/services:proxy" ]
}
+
+ if (enable_webvr) {
+ sources += [
+ "vr/vr_dispatcher.cc",
+ "vr/vr_dispatcher.h",
+ "vr/vr_type_converters.cc",
+ "vr/vr_type_converters.h",
+ ]
+ }
}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 8060019..92603ba 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -186,6 +186,10 @@
#include "media/renderers/default_renderer_factory.h"
#endif
+#if defined(ENABLE_WEBVR)
+#include "content/renderer/vr/vr_dispatcher.h"
+#endif
+
using blink::WebContextMenuData;
using blink::WebData;
using blink::WebDataSource;
@@ -3738,6 +3742,15 @@ blink::WebAppBannerClient* RenderFrameImpl::appBannerClient() {
return app_banner_client_.get();
}
+#if defined(ENABLE_WEBVR)
+blink::WebVRClient* RenderFrameImpl::webVRClient() {
+ if (!vr_dispatcher_)
+ vr_dispatcher_.reset(new VRDispatcher(GetServiceRegistry()));
+
+ return vr_dispatcher_.get();
+}
+#endif
+
void RenderFrameImpl::DidPlay(blink::WebMediaPlayer* player) {
Send(new FrameHostMsg_MediaPlayingNotification(
routing_id_, reinterpret_cast<int64>(player), player->hasVideo(),
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 281dd86..6af9e99 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -114,6 +114,7 @@ struct RequestNavigationParams;
struct ResourceResponseHead;
struct StartNavigationParams;
struct StreamOverrideParameters;
+class VRDispatcher;
class CONTENT_EXPORT RenderFrameImpl
: public RenderFrame,
@@ -530,6 +531,10 @@ class CONTENT_EXPORT RenderFrameImpl
virtual blink::WebPermissionClient* permissionClient();
virtual blink::WebAppBannerClient* appBannerClient();
+#if defined(ENABLE_WEBVR)
+ blink::WebVRClient* webVRClient() override;
+#endif
+
// WebMediaPlayerDelegate implementation:
void DidPlay(blink::WebMediaPlayer* player) override;
void DidPause(blink::WebMediaPlayer* player) override;
@@ -973,6 +978,11 @@ class CONTENT_EXPORT RenderFrameImpl
scoped_ptr<blink::WebAppBannerClient> app_banner_client_;
+#if defined(ENABLE_WEBVR)
+ // The VR dispatcher attached to the frame, lazily initialized.
+ scoped_ptr<VRDispatcher> vr_dispatcher_;
+#endif
+
#if defined(OS_MACOSX) || defined(OS_ANDROID)
// The external popup for the currently showing select popup.
scoped_ptr<ExternalPopupMenu> external_popup_menu_;
diff --git a/content/renderer/vr/vr_dispatcher.cc b/content/renderer/vr/vr_dispatcher.cc
new file mode 100644
index 0000000..43e2572
--- /dev/null
+++ b/content/renderer/vr/vr_dispatcher.cc
@@ -0,0 +1,69 @@
+// 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 "content/renderer/vr/vr_dispatcher.h"
+
+#include "content/public/common/service_registry.h"
+#include "content/renderer/vr/vr_type_converters.h"
+
+namespace content {
+
+VRDispatcher::VRDispatcher(ServiceRegistry* service_registry)
+ : service_registry_(service_registry) {
+}
+
+VRDispatcher::~VRDispatcher() {
+}
+
+VRServicePtr& VRDispatcher::GetVRServicePtr() {
+ if (!vr_service_) {
+ service_registry_->ConnectToRemoteService(mojo::GetProxy(&vr_service_));
+ }
+ return vr_service_;
+}
+
+void VRDispatcher::getDevices(blink::WebVRGetDevicesCallback* callback) {
+ int request_id = pending_requests_.Add(callback);
+ GetVRServicePtr()->GetDevices(base::Bind(&VRDispatcher::OnGetDevices,
+ base::Unretained(this), request_id));
+}
+
+void VRDispatcher::getSensorState(unsigned int index,
+ blink::WebHMDSensorState& state) {
+ GetVRServicePtr()->GetSensorState(
+ index,
+ base::Bind(&VRDispatcher::OnGetSensorState, base::Unretained(&state)));
+
+ // This call needs to return results synchronously in order to be useful and
+ // provide the lowest latency results possible.
+ GetVRServicePtr().WaitForIncomingResponse();
+}
+
+void VRDispatcher::resetSensor(unsigned int index) {
+ GetVRServicePtr()->ResetSensor(index);
+}
+
+void VRDispatcher::OnGetDevices(int request_id,
+ const mojo::Array<VRDeviceInfoPtr>& devices) {
+ blink::WebVector<blink::WebVRDevice> web_devices(devices.size());
+
+ blink::WebVRGetDevicesCallback* callback =
+ pending_requests_.Lookup(request_id);
+ if (!callback)
+ return;
+
+ for (size_t i = 0; i < devices.size(); ++i) {
+ web_devices[i] = devices[i].To<blink::WebVRDevice>();
+ }
+
+ callback->onSuccess(&web_devices);
+ pending_requests_.Remove(request_id);
+}
+
+void VRDispatcher::OnGetSensorState(blink::WebHMDSensorState* state,
+ const VRSensorStatePtr& mojo_state) {
+ *state = mojo_state.To<blink::WebHMDSensorState>();
+}
+
+} // namespace content
diff --git a/content/renderer/vr/vr_dispatcher.h b/content/renderer/vr/vr_dispatcher.h
new file mode 100644
index 0000000..7e5d56b
--- /dev/null
+++ b/content/renderer/vr/vr_dispatcher.h
@@ -0,0 +1,55 @@
+// 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.
+
+#ifndef CONTENT_RENDERER_VR_DISPATCHER_H_
+#define CONTENT_RENDERER_VR_DISPATCHER_H_
+
+#include <vector>
+
+#include "base/id_map.h"
+#include "content/common/vr_service.mojom.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+#include "third_party/WebKit/public/platform/modules/vr/WebVR.h"
+#include "third_party/WebKit/public/platform/modules/vr/WebVRClient.h"
+
+namespace content {
+
+class ServiceRegistry;
+
+class VRDispatcher : NON_EXPORTED_BASE(public blink::WebVRClient) {
+ public:
+ explicit VRDispatcher(ServiceRegistry* service_registry);
+ ~VRDispatcher();
+
+ // blink::WebVRClient implementation.
+ void getDevices(blink::WebVRGetDevicesCallback* callback) override;
+
+ void getSensorState(unsigned int index,
+ blink::WebHMDSensorState& state) override;
+
+ void resetSensor(unsigned int index) override;
+
+ private:
+ // Helper method that returns an initialized PermissionServicePtr.
+ VRServicePtr& GetVRServicePtr();
+
+ // Callback handlers
+ void OnGetDevices(int request_id,
+ const mojo::Array<VRDeviceInfoPtr>& devices);
+ static void OnGetSensorState(blink::WebHMDSensorState* state,
+ const VRSensorStatePtr& mojo_state);
+
+ // Tracks requests sent to browser to match replies with callbacks.
+ // Owns callback objects.
+ IDMap<blink::WebVRGetDevicesCallback, IDMapOwnPointer> pending_requests_;
+
+ ServiceRegistry* service_registry_;
+ VRServicePtr vr_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(VRDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_VR_DISPATCHER_H_
diff --git a/content/renderer/vr/vr_type_converters.cc b/content/renderer/vr/vr_type_converters.cc
new file mode 100644
index 0000000..68d686c
--- /dev/null
+++ b/content/renderer/vr/vr_type_converters.cc
@@ -0,0 +1,147 @@
+// 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 "content/renderer/vr/vr_type_converters.h"
+
+#include <algorithm>
+
+using content::VRVector3Ptr;
+using content::VRVector4Ptr;
+using content::VRRectPtr;
+using content::VRFieldOfViewPtr;
+using content::VREyeParametersPtr;
+using content::VRHMDInfoPtr;
+using content::VRDeviceInfoPtr;
+using content::VRSensorStatePtr;
+
+namespace mojo {
+
+// static
+blink::WebVRVector3 TypeConverter<blink::WebVRVector3, VRVector3Ptr>::Convert(
+ const VRVector3Ptr& input) {
+ blink::WebVRVector3 output;
+ output.x = input->x;
+ output.y = input->y;
+ output.z = input->z;
+ return output;
+}
+
+// static
+blink::WebVRVector4 TypeConverter<blink::WebVRVector4, VRVector4Ptr>::Convert(
+ const VRVector4Ptr& input) {
+ blink::WebVRVector4 output;
+ output.x = input->x;
+ output.y = input->y;
+ output.z = input->z;
+ output.w = input->w;
+ return output;
+}
+
+// static
+blink::WebVRRect TypeConverter<blink::WebVRRect, VRRectPtr>::Convert(
+ const VRRectPtr& input) {
+ blink::WebVRRect output;
+ output.x = input->x;
+ output.y = input->y;
+ output.width = input->width;
+ output.height = input->height;
+ return output;
+}
+
+// static
+blink::WebVRFieldOfView
+TypeConverter<blink::WebVRFieldOfView, VRFieldOfViewPtr>::Convert(
+ const VRFieldOfViewPtr& input) {
+ blink::WebVRFieldOfView output;
+ output.upDegrees = input->upDegrees;
+ output.downDegrees = input->downDegrees;
+ output.leftDegrees = input->leftDegrees;
+ output.rightDegrees = input->rightDegrees;
+ return output;
+}
+
+// static
+blink::WebVREyeParameters
+TypeConverter<blink::WebVREyeParameters, VREyeParametersPtr>::Convert(
+ const VREyeParametersPtr& input) {
+ blink::WebVREyeParameters output;
+ output.minimumFieldOfView =
+ input->minimumFieldOfView.To<blink::WebVRFieldOfView>();
+ output.maximumFieldOfView =
+ input->maximumFieldOfView.To<blink::WebVRFieldOfView>();
+ output.recommendedFieldOfView =
+ input->recommendedFieldOfView.To<blink::WebVRFieldOfView>();
+ output.eyeTranslation = input->eyeTranslation.To<blink::WebVRVector3>();
+ output.renderRect = input->renderRect.To<blink::WebVRRect>();
+ return output;
+}
+
+// static
+blink::WebVRHMDInfo TypeConverter<blink::WebVRHMDInfo, VRHMDInfoPtr>::Convert(
+ const VRHMDInfoPtr& input) {
+ blink::WebVRHMDInfo output;
+ output.leftEye = input->leftEye.To<blink::WebVREyeParameters>();
+ output.rightEye = input->rightEye.To<blink::WebVREyeParameters>();
+ return output;
+}
+
+// static
+blink::WebVRDevice TypeConverter<blink::WebVRDevice, VRDeviceInfoPtr>::Convert(
+ const VRDeviceInfoPtr& input) {
+ blink::WebVRDevice output;
+ memset(&output, 0, sizeof(blink::WebVRDevice));
+
+ output.index = input->index;
+ output.flags = blink::WebVRDeviceTypePosition;
+ output.deviceName = blink::WebString::fromUTF8(input->deviceName.data(),
+ input->deviceName.size());
+
+ if (!input->hmdInfo.is_null()) {
+ output.flags |= blink::WebVRDeviceTypeHMD;
+ output.hmdInfo = input->hmdInfo.To<blink::WebVRHMDInfo>();
+ }
+
+ return output;
+}
+
+// static
+blink::WebHMDSensorState
+TypeConverter<blink::WebHMDSensorState, VRSensorStatePtr>::Convert(
+ const VRSensorStatePtr& input) {
+ blink::WebHMDSensorState output;
+ output.timestamp = input->timestamp;
+ output.frameIndex = input->frameIndex;
+ output.flags = 0;
+
+ if (!input->orientation.is_null()) {
+ output.flags |= blink::WebVRSensorStateOrientation;
+ output.orientation = input->orientation.To<blink::WebVRVector4>();
+ }
+ if (!input->position.is_null()) {
+ output.flags |= blink::WebVRSensorStatePosition;
+ output.position = input->position.To<blink::WebVRVector3>();
+ }
+ if (!input->angularVelocity.is_null()) {
+ output.flags |= blink::WebVRSensorStateAngularVelocity;
+ output.angularVelocity = input->angularVelocity.To<blink::WebVRVector3>();
+ }
+ if (!input->linearVelocity.is_null()) {
+ output.flags |= blink::WebVRSensorStateLinearVelocity;
+ output.linearVelocity = input->linearVelocity.To<blink::WebVRVector3>();
+ }
+ if (!input->angularAcceleration.is_null()) {
+ output.flags |= blink::WebVRSensorStateAngularAcceleration;
+ output.angularAcceleration =
+ input->angularAcceleration.To<blink::WebVRVector3>();
+ }
+ if (!input->linearAcceleration.is_null()) {
+ output.flags |= blink::WebVRSensorStateLinearAcceleration;
+ output.linearAcceleration =
+ input->linearAcceleration.To<blink::WebVRVector3>();
+ }
+
+ return output;
+}
+
+} // namespace mojo
diff --git a/content/renderer/vr/vr_type_converters.h b/content/renderer/vr/vr_type_converters.h
new file mode 100644
index 0000000..8902cd5
--- /dev/null
+++ b/content/renderer/vr/vr_type_converters.h
@@ -0,0 +1,62 @@
+// 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.
+
+#ifndef CHROME_CONTENT_RENDERER_VR_VR_TYPE_CONVERTERS_H_
+#define CHROME_CONTENT_RENDERER_VR_VR_TYPE_CONVERTERS_H_
+
+#include "content/common/vr_service.mojom.h"
+#include "mojo/common/common_type_converters.h"
+#include "third_party/WebKit/public/platform/modules/vr/WebVR.h"
+
+namespace mojo {
+
+// Type/enum conversions from WebVR data types to Mojo data types
+// and vice versa.
+
+template <>
+struct TypeConverter<blink::WebVRVector3, content::VRVector3Ptr> {
+ static blink::WebVRVector3 Convert(const content::VRVector3Ptr& input);
+};
+
+template <>
+struct TypeConverter<blink::WebVRVector4, content::VRVector4Ptr> {
+ static blink::WebVRVector4 Convert(const content::VRVector4Ptr& input);
+};
+
+template <>
+struct TypeConverter<blink::WebVRRect, content::VRRectPtr> {
+ static blink::WebVRRect Convert(const content::VRRectPtr& input);
+};
+
+template <>
+struct TypeConverter<blink::WebVRFieldOfView, content::VRFieldOfViewPtr> {
+ static blink::WebVRFieldOfView Convert(
+ const content::VRFieldOfViewPtr& input);
+};
+
+template <>
+struct TypeConverter<blink::WebVREyeParameters, content::VREyeParametersPtr> {
+ static blink::WebVREyeParameters Convert(
+ const content::VREyeParametersPtr& input);
+};
+
+template <>
+struct TypeConverter<blink::WebVRHMDInfo, content::VRHMDInfoPtr> {
+ static blink::WebVRHMDInfo Convert(const content::VRHMDInfoPtr& input);
+};
+
+template <>
+struct TypeConverter<blink::WebVRDevice, content::VRDeviceInfoPtr> {
+ static blink::WebVRDevice Convert(const content::VRDeviceInfoPtr& input);
+};
+
+template <>
+struct TypeConverter<blink::WebHMDSensorState, content::VRSensorStatePtr> {
+ static blink::WebHMDSensorState Convert(
+ const content::VRSensorStatePtr& input);
+};
+
+} // namespace mojo
+
+#endif // CHROME_CONTENT_RENDERER_VR_VR_TYPE_CONVERTERS_H_ \ No newline at end of file
diff --git a/mojo/common/weak_binding_set.h b/mojo/common/weak_binding_set.h
index 8738388..aeeefe9 100644
--- a/mojo/common/weak_binding_set.h
+++ b/mojo/common/weak_binding_set.h
@@ -42,6 +42,8 @@ class WeakBindingSet : public ErrorHandler {
bindings_.clear();
}
+ bool empty() const { return bindings_.empty(); }
+
private:
// ErrorHandler implementation.
void OnConnectionError() override {
diff --git a/third_party/cardboard-java/BUILD.gn b/third_party/cardboard-java/BUILD.gn
index a6ff1b6c..4effd70 100644
--- a/third_party/cardboard-java/BUILD.gn
+++ b/third_party/cardboard-java/BUILD.gn
@@ -5,9 +5,9 @@
import("//build/config/android/rules.gni")
# GYP: //third_party/cardboard-java/cardboard.gyp:cardboard_jar
-java_prebuilt("cardboard-java") {
+android_java_prebuilt("cardboard-java") {
jar_path = "src/CardboardSample/libs/cardboard.jar"
deps = [
- "//third_party/android_protobuf/android_protobuf.gyp:protobuf_nano_javalib",
+ "//third_party/android_protobuf:protobuf_nano_javalib",
]
}
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index d149cc7..3172332 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -58895,6 +58895,7 @@ To add a new entry, add it with any value and run test to compute valid value.
<int value="-1346722635" label="gesture-selection"/>
<int value="-1341092934" label="enable-accelerated-overflow-scroll"/>
<int value="-1340055960" label="enable-streamlined-hosted-apps"/>
+ <int value="-1337185440" label="enable-webvr"/>
<int value="-1334327410" label="ash-enable-touch-view-testing"/>
<int value="-1322882747" label="disable-datasaver-prompt"/>
<int value="-1319688939" label="ignore-gpu-blacklist"/>