Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: chrome/browser/resources/vr_shell/vr_shell_ui.js

Issue 2435623003: Implement (but do not enable) HTML UI-driven WebVR security warnings. (Closed)
Patch Set: Fix CONST_CASE Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 var vrShellUi = (function() { 5 var vrShellUi = (function() {
6 'use strict'; 6 'use strict';
7 7
8 var scene = new ui.Scene(); 8 let scene = new ui.Scene();
9 var state; 9 let sceneManager;
10 10
11 class DomUiElement { 11 class DomUiElement {
12 constructor(domId) { 12 constructor(domId) {
13 var domElement = document.querySelector(domId); 13 let domElement = document.querySelector(domId);
14 var style = window.getComputedStyle(domElement); 14 let style = window.getComputedStyle(domElement);
15 15
16 // Pull copy rectangle from DOM element properties. 16 // Pull copy rectangle from DOM element properties.
17 var pixelX = domElement.offsetLeft; 17 let pixelX = domElement.offsetLeft;
18 var pixelY = domElement.offsetTop; 18 let pixelY = domElement.offsetTop;
19 var pixelWidth = parseInt(style.getPropertyValue('width')); 19 let pixelWidth = parseInt(style.getPropertyValue('width'));
20 var pixelHeight = parseInt(style.getPropertyValue('height')); 20 let pixelHeight = parseInt(style.getPropertyValue('height'));
21 21
22 var element = new api.UiElement(pixelX, pixelY, pixelWidth, pixelHeight); 22 let element = new api.UiElement(pixelX, pixelY, pixelWidth, pixelHeight);
23 element.setSize(pixelWidth / 1000, pixelHeight / 1000); 23 element.setSize(pixelWidth / 1000, pixelHeight / 1000);
24 24
25 this.uiElementId = scene.addElement(element); 25 this.uiElementId = scene.addElement(element);
26 this.uiAnimationId = -1; 26 this.uiAnimationId = -1;
27 this.domElement = domElement; 27 this.domElement = domElement;
28 } 28 }
29 }; 29 };
30 30
31 class RoundButton extends DomUiElement { 31 class RoundButton extends DomUiElement {
32 constructor(domId, callback) { 32 constructor(domId, callback) {
33 super(domId); 33 super(domId);
34 34
35 var button = this.domElement.querySelector('.button'); 35 let button = this.domElement.querySelector('.button');
36 button.addEventListener('mouseenter', this.onMouseEnter.bind(this)); 36 button.addEventListener('mouseenter', this.onMouseEnter.bind(this));
37 button.addEventListener('mouseleave', this.onMouseLeave.bind(this)); 37 button.addEventListener('mouseleave', this.onMouseLeave.bind(this));
38 button.addEventListener('click', callback); 38 button.addEventListener('click', callback);
39 } 39 }
40 40
41 configure(buttonOpacity, captionOpacity, distanceForward) { 41 configure(buttonOpacity, captionOpacity, distanceForward) {
42 var button = this.domElement.querySelector('.button'); 42 let button = this.domElement.querySelector('.button');
43 var caption = this.domElement.querySelector('.caption'); 43 let caption = this.domElement.querySelector('.caption');
44 button.style.opacity = buttonOpacity; 44 button.style.opacity = buttonOpacity;
45 caption.style.opacity = captionOpacity; 45 caption.style.opacity = captionOpacity;
46 var anim = new api.Animation(this.uiElementId, 150); 46 let anim = new api.Animation(this.uiElementId, 150);
47 anim.setTranslation(0, 0, distanceForward); 47 anim.setTranslation(0, 0, distanceForward);
48 if (this.uiAnimationId >= 0) { 48 if (this.uiAnimationId >= 0) {
49 scene.removeAnimation(this.uiAnimationId); 49 scene.removeAnimation(this.uiAnimationId);
50 } 50 }
51 this.uiAnimationId = scene.addAnimation(anim); 51 this.uiAnimationId = scene.addAnimation(anim);
52 scene.flush(); 52 scene.flush();
53 } 53 }
54 54
55 onMouseEnter() { 55 onMouseEnter() {
56 this.configure(1, 1, 0.015); 56 this.configure(1, 1, 0.015);
57 } 57 }
58 58
59 onMouseLeave() { 59 onMouseLeave() {
60 this.configure(0.8, 0, 0); 60 this.configure(0.8, 0, 0);
61 } 61 }
62 }; 62 };
63 63
64 class Controls { 64 class Controls {
65 constructor() { 65 constructor() {
66 this.buttons = []; 66 this.buttons = [];
67 var descriptors = [ 67 let descriptors = [
68 ['#back', function() { 68 ['#back', function() {
69 api.doAction(api.Action.HISTORY_BACK); 69 api.doAction(api.Action.HISTORY_BACK);
70 }], 70 }],
71 ['#reload', function() { 71 ['#reload', function() {
72 api.doAction(api.Action.RELOAD); 72 api.doAction(api.Action.RELOAD);
73 }], 73 }],
74 ['#forward', function() { 74 ['#forward', function() {
75 api.doAction(api.Action.HISTORY_FORWARD); 75 api.doAction(api.Action.HISTORY_FORWARD);
76 }], 76 }],
77 ]; 77 ];
78 78
79 var spacing = 0.3; 79 /** @const */ var BUTTON_SPACING = 0.3;
80 var startPosition = -spacing * (descriptors.length / 2.0 - 0.5);
81 80
82 for (var i = 0; i < descriptors.length; i++) { 81 let startPosition = -BUTTON_SPACING * (descriptors.length / 2.0 - 0.5);
82 for (let i = 0; i < descriptors.length; i++) {
83 // Use an invisible parent to simplify Z-axis movement on hover. 83 // Use an invisible parent to simplify Z-axis movement on hover.
84 var position = new api.UiElement(0, 0, 0, 0); 84 let position = new api.UiElement(0, 0, 0, 0);
85 position.setParentId(api.getContentElementId()); 85 position.setParentId(api.getContentElementId());
86 position.setVisible(false); 86 position.setVisible(false);
87 position.setAnchoring(api.XAnchoring.XNONE, api.YAnchoring.YBOTTOM); 87 position.setAnchoring(api.XAnchoring.XNONE, api.YAnchoring.YBOTTOM);
88 position.setTranslation( 88 position.setTranslation(
89 startPosition + i * spacing, -0.3, 0.3); 89 startPosition + i * BUTTON_SPACING, -0.3, 0.3);
90 var id = scene.addElement(position); 90 let id = scene.addElement(position);
91 91
92 var domId = descriptors[i][0]; 92 let domId = descriptors[i][0];
93 var callback = descriptors[i][1]; 93 let callback = descriptors[i][1];
94 var element = new RoundButton(domId, callback); 94 let element = new RoundButton(domId, callback);
95 this.buttons.push(element); 95 this.buttons.push(element);
96 96
97 var update = new api.UiElementUpdate(); 97 let update = new api.UiElementUpdate();
98 update.setParentId(id); 98 update.setParentId(id);
99 update.setVisible(false); 99 update.setVisible(false);
100 update.setScale(2.2, 2.2, 1); 100 update.setScale(2.2, 2.2, 1);
101 scene.updateElement(element.uiElementId, update); 101 scene.updateElement(element.uiElementId, update);
102 } 102 }
103 } 103 }
104 104
105 show(visible) { 105 show(visible) {
106 for (var i = 0; i < this.buttons.length; i++) { 106 for (let i = 0; i < this.buttons.length; i++) {
107 var update = new api.UiElementUpdate(); 107 let update = new api.UiElementUpdate();
108 update.setVisible(visible); 108 update.setVisible(visible);
109 scene.updateElement(this.buttons[i].uiElementId, update); 109 scene.updateElement(this.buttons[i].uiElementId, update);
110 } 110 }
111 } 111 }
112 }; 112 };
113 113
114 class UiState { 114 class SecureOriginWarnings {
115 constructor() {
116 /** @const */ var DISTANCE = 0.7;
117 /** @const */ var ANGLE_UP = 16.3 * Math.PI / 180.0;
118
119 // Permanent WebVR security warning. This warning is shown near the top of
120 // the field of view.
121 this.webVrSecureWarning = new DomUiElement('#webvr-not-secure-permanent');
122 let update = new api.UiElementUpdate();
123 update.setScale(DISTANCE, DISTANCE, 1);
124 update.setTranslation(0, DISTANCE * Math.sin(ANGLE_UP),
125 -DISTANCE * Math.cos(ANGLE_UP));
126 update.setRotation(1.0, 0.0, 0.0, ANGLE_UP);
127 update.setHitTestable(false);
128 update.setVisible(false);
129 update.setLockToFieldOfView(true);
130 scene.updateElement(this.webVrSecureWarning.uiElementId, update);
131
132 // Temporary WebVR security warning. This warning is shown in the center
133 // of the field of view, for a limited period of time.
134 this.transientWarning = new DomUiElement(
135 '#webvr-not-secure-transient');
136 update = new api.UiElementUpdate();
137 update.setScale(DISTANCE, DISTANCE, 1);
138 update.setTranslation(0, 0, -DISTANCE);
139 update.setHitTestable(false);
140 update.setVisible(false);
141 update.setLockToFieldOfView(true);
142 scene.updateElement(this.transientWarning.uiElementId, update);
143 }
144
145 show(visible) {
146 this.enabled = visible;
147 this.updateState();
148 }
149
150 setSecureOrigin(secure) {
151 this.isSecureOrigin = secure;
152 this.updateState();
153 }
154
155 updateState() {
156 /** @const */ var TRANSIENT_TIMEOUT_MS = 30000;
157
158 let visible = (this.enabled && !this.isSecureOrigin);
159 if (this.secureOriginTimer) {
160 clearInterval(this.secureOriginTimer);
161 this.secureOriginTimer = null;
162 }
163 if (visible) {
164 this.secureOriginTimer = setTimeout(
165 this.onTransientTimer.bind(this), TRANSIENT_TIMEOUT_MS);
166 }
167 this.showOrHideWarnings(visible);
168 }
169
170 showOrHideWarnings(visible) {
171 let update = new api.UiElementUpdate();
172 update.setVisible(visible);
173 scene.updateElement(this.webVrSecureWarning.uiElementId, update);
174 update = new api.UiElementUpdate();
175 update.setVisible(visible);
176 scene.updateElement(this.transientWarning.uiElementId, update);
177 }
178
179 onTransientTimer() {
180 let update = new api.UiElementUpdate();
181 update.setVisible(false);
182 scene.updateElement(this.transientWarning.uiElementId, update);
183 this.secureOriginTimer = null;
184 scene.flush();
185 }
186
187 };
188
189 class SceneManager {
115 constructor() { 190 constructor() {
116 this.mode = api.Mode.UNKNOWN; 191 this.mode = api.Mode.UNKNOWN;
117 this.controls = new Controls(); 192 this.controls = new Controls();
118 scene.flush(); 193 this.secureOriginWarnings = new SecureOriginWarnings();
119 } 194 }
120 195
121 setMode(mode) { 196 setMode(mode) {
197 this.mode = mode;
122 this.controls.show(mode == api.Mode.STANDARD); 198 this.controls.show(mode == api.Mode.STANDARD);
123 scene.flush(); 199 this.secureOriginWarnings.show(mode == api.Mode.WEB_VR);
200 }
201
202 setSecureOrigin(secure) {
203 this.secureOriginWarnings.setSecureOrigin(secure);
124 } 204 }
125 }; 205 };
126 206
127 function initialize() { 207 function initialize() {
128 208
129 // Change the body background so that the transparency applies. 209 // Change the body background so that the transparency applies.
130 window.setTimeout(function() { 210 window.setTimeout(function() {
131 document.body.parentNode.style.backgroundColor = 'rgba(255,255,255,0)'; 211 document.body.parentNode.style.backgroundColor = 'rgba(255,255,255,0)';
132 }, 100); 212 }, 100);
133 213
134 state = new UiState(); 214 sceneManager = new SceneManager();
215 scene.flush();
135 216
136 api.domLoaded(); 217 api.domLoaded();
137 } 218 }
138 219
139 function command(dict) { 220 function command(dict) {
140 if ('mode' in dict) { 221 if ('mode' in dict) {
141 state.setMode(dict['mode']); 222 sceneManager.setMode(dict['mode']);
142 } 223 }
224 if ('secureOrigin' in dict) {
225 sceneManager.setSecureOrigin(dict['secureOrigin']);
226 }
227 scene.flush();
143 } 228 }
144 229
145 return { 230 return {
146 initialize: initialize, 231 initialize: initialize,
147 command: command, 232 command: command,
148 }; 233 };
149 })(); 234 })();
150 235
151 document.addEventListener('DOMContentLoaded', vrShellUi.initialize); 236 document.addEventListener('DOMContentLoaded', vrShellUi.initialize);
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698