device-motion-sender.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Copyright 2016 Google Inc. All Rights Reserved.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. /**
  16. * Sends DeviceMotion events to all embedded VR views via postMessage. Note:
  17. * each iframe must have a class 'vrview'.
  18. *
  19. * This is a workaround for https://bugs.webkit.org/show_bug.cgi?id=150072.
  20. */
  21. function DeviceMotionSender() {
  22. // This is an iOS-specific workaround.
  23. if (!this.isIOS_()) {
  24. return;
  25. }
  26. window.addEventListener('devicemotion', this.onDeviceMotion_.bind(this), false);
  27. // Find the right iFrame to send data to.
  28. this.iframes = document.querySelectorAll('iframe.vrview');
  29. }
  30. DeviceMotionSender.prototype.onDeviceMotion_ = function(e) {
  31. var message = {
  32. type: 'DeviceMotion',
  33. deviceMotionEvent: this.cloneDeviceMotionEvent_(e)
  34. };
  35. for (var i = 0; i < this.iframes.length; i++) {
  36. // Only send data if we're on iOS and we are dealing with a cross-domain
  37. // iframe.
  38. var iframe = this.iframes[i];
  39. var iframeWindow = iframe.contentWindow;
  40. if (this.isCrossDomainIframe_(iframe)) {
  41. iframeWindow.postMessage(message, '*');
  42. }
  43. }
  44. };
  45. DeviceMotionSender.prototype.cloneDeviceMotionEvent_ = function(e) {
  46. return {
  47. acceleration: {
  48. x: e.acceleration.x,
  49. y: e.acceleration.y,
  50. z: e.acceleration.z,
  51. },
  52. accelerationIncludingGravity: {
  53. x: e.accelerationIncludingGravity.x,
  54. y: e.accelerationIncludingGravity.y,
  55. z: e.accelerationIncludingGravity.z,
  56. },
  57. rotationRate: {
  58. alpha: e.rotationRate.alpha,
  59. beta: e.rotationRate.beta,
  60. gamma: e.rotationRate.gamma,
  61. },
  62. interval: e.interval
  63. };
  64. };
  65. DeviceMotionSender.prototype.isIOS_ = function() {
  66. return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
  67. };
  68. // From http://stackoverflow.com/questions/12381334/foolproof-way-to-detect-if-iframe-is-cross-domain.
  69. DeviceMotionSender.prototype.isCrossDomainIframe_ = function(iframe) {
  70. var html = null;
  71. try {
  72. var doc = iframe.contentDocument || iframe.contentWindow.document;
  73. html = doc.body.innerHTML;
  74. } catch (err) {
  75. }
  76. return (html === null);
  77. };
  78. var dms = new DeviceMotionSender();