1/* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/** 32 * @constructor 33 * @extends {WebInspector.View} 34 */ 35WebInspector.OverridesView = function() 36{ 37 WebInspector.View.call(this); 38 this.registerRequiredCSS("overrides.css"); 39 this.registerRequiredCSS("helpScreen.css"); 40 this.element.classList.add("overrides-view", "fill", "vbox"); 41 42 this._tabbedPane = new WebInspector.TabbedPane(); 43 this._tabbedPane.shrinkableTabs = false; 44 this._tabbedPane.verticalTabLayout = true; 45 46 new WebInspector.OverridesView.DeviceTab().appendAsTab(this._tabbedPane); 47 new WebInspector.OverridesView.ViewportTab().appendAsTab(this._tabbedPane); 48 new WebInspector.OverridesView.UserAgentTab().appendAsTab(this._tabbedPane); 49 new WebInspector.OverridesView.SensorsTab().appendAsTab(this._tabbedPane); 50 51 this._lastSelectedTabSetting = WebInspector.settings.createSetting("lastSelectedEmulateTab", "device"); 52 this._tabbedPane.selectTab(this._lastSelectedTabSetting.get()); 53 this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); 54 this._tabbedPane.show(this.element); 55 56 this._warningFooter = this.element.createChild("div", "overrides-footer"); 57 this._overridesWarningUpdated(); 58 WebInspector.overridesSupport.addEventListener(WebInspector.OverridesSupport.Events.OverridesWarningUpdated, this._overridesWarningUpdated, this); 59} 60 61WebInspector.OverridesView.prototype = { 62 /** 63 * @param {!WebInspector.Event} event 64 */ 65 _tabSelected: function(event) 66 { 67 this._lastSelectedTabSetting.set(this._tabbedPane.selectedTabId); 68 }, 69 70 _overridesWarningUpdated: function() 71 { 72 var message = WebInspector.overridesSupport.warningMessage(); 73 this._warningFooter.enableStyleClass("hidden", !message); 74 this._warningFooter.textContent = message; 75 }, 76 77 __proto__: WebInspector.View.prototype 78} 79 80/** 81 * @constructor 82 * @extends {WebInspector.View} 83 * @param {string} id 84 * @param {string} name 85 * @param {!Array.<!WebInspector.Setting>} settings 86 */ 87WebInspector.OverridesView.Tab = function(id, name, settings) 88{ 89 WebInspector.View.call(this); 90 this._id = id; 91 this._name = name; 92 this._settings = settings; 93 for (var i = 0; i < settings.length; ++i) 94 settings[i].addChangeListener(this._updateActiveState, this); 95} 96 97WebInspector.OverridesView.Tab.prototype = { 98 /** 99 * @param {!WebInspector.TabbedPane} tabbedPane 100 */ 101 appendAsTab: function(tabbedPane) 102 { 103 this._tabbedPane = tabbedPane; 104 tabbedPane.appendTab(this._id, this._name, this); 105 this._updateActiveState(); 106 }, 107 108 _updateActiveState: function() 109 { 110 var active = false; 111 for (var i = 0; !active && i < this._settings.length; ++i) 112 active = this._settings[i].get(); 113 this._tabbedPane.element.enableStyleClass("overrides-activate-" + this._id, active); 114 this._tabbedPane.changeTabTitle(this._id, active ? this._name + " \u2713" : this._name); 115 }, 116 117 /** 118 * Creates an input element under the parentElement with the given id and defaultText. 119 * It also sets an onblur event listener. 120 * @param {!Element} parentElement 121 * @param {string} id 122 * @param {string} defaultText 123 * @param {function(*)} eventListener 124 * @param {boolean=} numeric 125 * @return {!Element} element 126 */ 127 _createInput: function(parentElement, id, defaultText, eventListener, numeric) 128 { 129 var element = parentElement.createChild("input"); 130 element.id = id; 131 element.type = "text"; 132 element.maxLength = 12; 133 element.style.width = "80px"; 134 element.value = defaultText; 135 element.align = "right"; 136 if (numeric) 137 element.className = "numeric"; 138 element.addEventListener("input", eventListener, false); 139 element.addEventListener("keydown", keyDownListener, false); 140 function keyDownListener(event) 141 { 142 if (isEnterKey(event)) 143 eventListener(event); 144 } 145 return element; 146 }, 147 148 /** 149 * @param {string} title 150 * @param {function(boolean)} callback 151 */ 152 _createNonPersistedCheckbox: function(title, callback) 153 { 154 var labelElement = document.createElement("label"); 155 var checkboxElement = labelElement.createChild("input"); 156 checkboxElement.type = "checkbox"; 157 checkboxElement.checked = false; 158 checkboxElement.addEventListener("click", onclick, false); 159 labelElement.appendChild(document.createTextNode(title)); 160 return labelElement; 161 162 function onclick() 163 { 164 callback(checkboxElement.checked); 165 } 166 }, 167 168 /** 169 * @param {string} name 170 * @param {!WebInspector.Setting} setting 171 * @param {function(boolean)=} callback 172 */ 173 _createSettingCheckbox: function(name, setting, callback) 174 { 175 var checkbox = WebInspector.SettingsTab.createCheckbox(name, setting.get.bind(setting), listener, true); 176 177 function listener(value) 178 { 179 if (setting.get() === value) 180 return; 181 182 setting.set(value); 183 if (callback) 184 callback(value); 185 } 186 187 setting.addChangeListener(changeListener); 188 189 function changeListener() 190 { 191 if (checkbox.firstChild.checked !== setting.get()) 192 checkbox.firstChild.checked = setting.get(); 193 } 194 return checkbox; 195 } 196} 197 198WebInspector.OverridesView.Tab.prototype.__proto__ = WebInspector.View.prototype; 199 200/** 201 * @constructor 202 * @extends {WebInspector.OverridesView.Tab} 203 */ 204WebInspector.OverridesView.DeviceTab = function() 205{ 206 WebInspector.OverridesView.Tab.call(this, "device", WebInspector.UIString("Device"), []); 207 this.element.classList.add("overrides-device"); 208 209 this._emulatedDeviceSetting = WebInspector.settings.createSetting("emulatedDevice", "Google Nexus 4"); 210 this._emulateDeviceViewportSetting = WebInspector.settings.overrideDeviceMetrics; 211 this._emulateDeviceUserAgentSetting = WebInspector.settings.overrideUserAgent; 212 213 this._deviceSelectElement = this.element.createChild("select"); 214 215 var devices = WebInspector.OverridesView.DeviceTab._phones.concat(WebInspector.OverridesView.DeviceTab._tablets); 216 devices.sort(); 217 var selectionRestored = false; 218 for (var i = 0; i < devices.length; ++i) { 219 var device = devices[i]; 220 var option = new Option(device[0], device[0]); 221 option._userAgent = device[1]; 222 option._metrics = device[2]; 223 this._deviceSelectElement.add(option); 224 if (this._emulatedDeviceSetting.get() === device[0]) { 225 this._deviceSelectElement.selectedIndex = i; 226 selectionRestored = true; 227 } 228 } 229 230 if (!selectionRestored) 231 this._deviceSelectElement.selectedIndex = devices.length - 1; 232 233 this._deviceSelectElement.addEventListener("change", this._deviceSelected.bind(this), false); 234 this._deviceSelectElement.addEventListener("dblclick", this._emulateButtonClicked.bind(this), false); 235 this._deviceSelectElement.addEventListener("keypress", this._keyPressed.bind(this), false); 236 this._deviceSelectElement.disabled = WebInspector.isInspectingDevice(); 237 238 var buttonsBar = this.element.createChild("div"); 239 var emulateButton = buttonsBar.createChild("button", "settings-tab-text-button"); 240 emulateButton.textContent = WebInspector.UIString("Emulate"); 241 emulateButton.addEventListener("click", this._emulateButtonClicked.bind(this), false); 242 emulateButton.disabled = WebInspector.isInspectingDevice(); 243 this._emulateButton = emulateButton; 244 245 var resetButton = buttonsBar.createChild("button", "settings-tab-text-button"); 246 resetButton.textContent = WebInspector.UIString("Reset"); 247 resetButton.addEventListener("click", this._resetButtonClicked.bind(this), false); 248 249 this._viewportValueLabel = this.element.createChild("div", "overrides-device-value-label"); 250 this._viewportValueLabel.textContent = WebInspector.UIString("Viewport:"); 251 this._viewportValueElement = this._viewportValueLabel.createChild("span", "overrides-device-value"); 252 253 this._userAgentLabel = this.element.createChild("div", "overrides-device-value-label"); 254 this._userAgentLabel.textContent = WebInspector.UIString("User agent:"); 255 this._userAgentValueElement = this._userAgentLabel.createChild("span", "overrides-device-value"); 256 257 this._updateValueLabels(); 258} 259 260// Third element lists device metrics separated by 'x': 261// - screen width, 262// - screen height, 263// - device scale factor, 264// - use text autosizing. 265WebInspector.OverridesView.DeviceTab._phones = [ 266 ["Apple iPhone 3GS", 267 "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", 268 "320x480x1"], 269 ["Apple iPhone 4", 270 "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", 271 "640x960x2"], 272 ["Apple iPhone 5", 273 "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53", 274 "640x1136x2"], 275 ["BlackBerry Z10", 276 "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+", 277 "768x1280x2"], 278 ["BlackBerry Z30", 279 "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+", 280 "720x1280x2"], 281 ["Google Nexus 4", 282 "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19", 283 "768x1280x2"], 284 ["Google Nexus 5", 285 "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19", 286 "1080x1920x3"], 287 ["Google Nexus S", 288 "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Nexus S Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 289 "480x800x1.5"], 290 ["HTC Evo, Touch HD, Desire HD, Desire", 291 "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 292 "480x800x1.5"], 293 ["HTC One X, EVO LTE", 294 "Mozilla/5.0 (Linux; Android 4.0.3; HTC One X Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19", 295 "720x1280x2"], 296 ["HTC Sensation, Evo 3D", 297 "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", 298 "540x960x1.5"], 299 ["LG Optimus 2X, Optimus 3D, Optimus Black", 300 "Mozilla/5.0 (Linux; U; Android 2.2; en-us; LG-P990/V08c Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2", 301 "480x800x1.5"], 302 ["LG Optimus G", 303 "Mozilla/5.0 (Linux; Android 4.0; LG-E975 Build/IMM76L) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19", 304 "768x1280x2"], 305 ["LG Optimus LTE, Optimus 4X HD", 306 "Mozilla/5.0 (Linux; U; Android 2.3; en-us; LG-P930 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 307 "720x1280x1.7"], 308 ["LG Optimus One", 309 "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; LG-MS690 Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 310 "320x480x1.5"], 311 ["Motorola Defy, Droid, Droid X, Milestone", 312 "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Milestone Build/ SHOLS_U2_01.03.1) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", 313 "480x854x1.5"], 314 ["Motorola Droid 3, Droid 4, Droid Razr, Atrix 4G, Atrix 2", 315 "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG22D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 316 "540x960x1"], 317 ["Motorola Droid Razr HD", 318 "Mozilla/5.0 (Linux; U; Android 2.3; en-us; DROID RAZR 4G Build/6.5.1-73_DHD-11_M1-29) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 319 "720x1280x1"], 320 ["Nokia C5, C6, C7, N97, N8, X7", 321 "NokiaN97/21.1.107 (SymbianOS/9.4; Series60/5.0 Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebkit/525 (KHTML, like Gecko) BrowserNG/7.1.4", 322 "360x640x1"], 323 ["Nokia Lumia 7X0, Lumia 8XX, Lumia 900, N800, N810, N900", 324 "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 820)", 325 "480x800x1.5"], 326 ["Samsung Galaxy Note 3", 327 "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", 328 "1080x1920x2"], 329 ["Samsung Galaxy Note II", 330 "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", 331 "720x1280x2"], 332 ["Samsung Galaxy Note", 333 "Mozilla/5.0 (Linux; U; Android 2.3; en-us; SAMSUNG-SGH-I717 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 334 "800x1280x2"], 335 ["Samsung Galaxy S III, Galaxy Nexus", 336 "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", 337 "720x1280x2"], 338 ["Samsung Galaxy S, S II, W", 339 "Mozilla/5.0 (Linux; U; Android 2.1; en-us; GT-I9000 Build/ECLAIR) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", 340 "480x800x1.5"], 341 ["Samsung Galaxy S4", 342 "Mozilla/5.0 (Linux; U; Android 2.1; en-us; GT-I9000 Build/ECLAIR) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", 343 "1080x1920x3"], 344 ["Sony Xperia S, Ion", 345 "Mozilla/5.0 (Linux; U; Android 4.0; en-us; LT28at Build/6.1.C.1.111) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", 346 "720x1280x2"], 347 ["Sony Xperia Sola, U", 348 "Mozilla/5.0 (Linux; U; Android 2.3; en-us; SonyEricssonST25i Build/6.0.B.1.564) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 349 "480x854x1"], 350 ["Sony Xperia Z, Z1", 351 "Mozilla/5.0 (Linux; U; Android 4.2; en-us; SonyC6903 Build/14.1.G.1.518) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", 352 "1080x1920x3"], 353]; 354 355WebInspector.OverridesView.DeviceTab._tablets = [ 356 ["Amazon Amazon Kindle Fire HD 7\"", 357 "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Kindle Fire HD Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 358 "1280x800x1.5"], 359 ["Amazon Amazon Kindle Fire HD 8.9\"", 360 "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Kindle Fire HD Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 361 "1920x1200x1.5"], 362 ["Amazon Amazon Kindle Fire", 363 "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Kindle Fire Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 364 "1024x600x1"], 365 ["Apple iPad 1 / 2 / iPad Mini", 366 "Mozilla/5.0 (iPad; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5", 367 "1024x768x1"], 368 ["Apple iPad 3 / 4", 369 "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53", 370 "2048x1536x2"], 371 ["BlackBerry PlayBook", 372 "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+", 373 "1024x600x1"], 374 ["Google Nexus 10", 375 "Mozilla/5.0 (Linux; Android 4.3; Nexus 10 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari/537.36", 376 "2560x1600x2"], 377 ["Google Nexus 7 2", 378 "Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari/537.36", 379 "1920x1200x2"], 380 ["Google Nexus 7", 381 "Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari/537.36", 382 "1280x800x1.325"], 383 ["Motorola Xoom, Xyboard", 384 "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", 385 "1280x800x1"], 386 ["Samsung Galaxy Tab 7.7, 8.9, 10.1", 387 "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 388 "1280x800x1"], 389 ["Samsung Galaxy Tab", 390 "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", 391 "1024x600x1"], 392]; 393 394WebInspector.OverridesView.DeviceTab.prototype = { 395 /** 396 * @param {!Event} e 397 */ 398 _keyPressed: function(e) 399 { 400 if (e.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code) 401 this._emulateButtonClicked(); 402 }, 403 404 _emulateButtonClicked: function() 405 { 406 var option = this._deviceSelectElement.options[this._deviceSelectElement.selectedIndex]; 407 WebInspector.overridesSupport.emulateDevice(option._metrics, option._userAgent); 408 }, 409 410 _resetButtonClicked: function() 411 { 412 WebInspector.overridesSupport.reset(); 413 }, 414 415 _deviceSelected: function() 416 { 417 var option = this._deviceSelectElement.options[this._deviceSelectElement.selectedIndex]; 418 this._emulatedDeviceSetting.set(option.value); 419 this._updateValueLabels(); 420 }, 421 422 _updateValueLabels: function() 423 { 424 var option = this._deviceSelectElement.options[this._deviceSelectElement.selectedIndex]; 425 var metrics; 426 if (option._metrics && (metrics = WebInspector.OverridesSupport.DeviceMetrics.parseSetting(option._metrics))) 427 this._viewportValueElement.textContent = WebInspector.UIString("%s \u00D7 %s, devicePixelRatio = %s", metrics.width, metrics.height, metrics.deviceScaleFactor); 428 else 429 this._viewportValueElement.textContent = ""; 430 this._userAgentValueElement.textContent = option._userAgent || ""; 431 } 432} 433 434WebInspector.OverridesView.DeviceTab.prototype.__proto__ = WebInspector.OverridesView.Tab.prototype; 435 436 437/** 438 * @constructor 439 * @extends {WebInspector.OverridesView.Tab} 440 */ 441WebInspector.OverridesView.ViewportTab = function() 442{ 443 WebInspector.OverridesView.Tab.call(this, "viewport", WebInspector.UIString("Screen"), [WebInspector.settings.overrideDeviceMetrics, WebInspector.settings.overrideCSSMedia]); 444 this.element.classList.add("overrides-viewport"); 445 446 const metricsSetting = WebInspector.settings.deviceMetrics.get(); 447 var metrics = WebInspector.OverridesSupport.DeviceMetrics.parseSetting(metricsSetting); 448 var checkbox = this._createSettingCheckbox(WebInspector.UIString("Emulate screen"), WebInspector.settings.overrideDeviceMetrics, this._onMetricsCheckboxClicked.bind(this)); 449 checkbox.firstChild.disabled = WebInspector.isInspectingDevice(); 450 WebInspector.settings.deviceMetrics.addChangeListener(this._updateDeviceMetricsElement, this); 451 452 this.element.appendChild(checkbox); 453 this.element.appendChild(this._createDeviceMetricsElement(metrics)); 454 this.element.appendChild(this._createMediaEmulationElement()); 455 456 var footnote = this.element.createChild("p", "help-footnote"); 457 var footnoteLink = footnote.createChild("a"); 458 footnoteLink.href = "https://developers.google.com/chrome-developer-tools/docs/mobile-emulation"; 459 footnoteLink.target = "_blank"; 460 footnoteLink.createTextChild(WebInspector.UIString("More information about screen emulation")); 461 462 this._onMetricsCheckboxClicked(WebInspector.settings.overrideDeviceMetrics.get()); 463} 464 465WebInspector.OverridesView.ViewportTab.prototype = { 466 /** 467 * @param {boolean} enabled 468 */ 469 _onMetricsCheckboxClicked: function(enabled) 470 { 471 if (enabled && !this._widthOverrideElement.value) 472 this._widthOverrideElement.focus(); 473 this._applyDeviceMetricsUserInput(); 474 }, 475 476 _applyDeviceMetricsUserInput: function() 477 { 478 this._muteRangeListener = true; 479 this._widthRangeInput.value = this._widthOverrideElement.value; 480 delete this._muteRangeListener; 481 if (this._applyDeviceMetricsTimer) 482 clearTimeout(this._applyDeviceMetricsTimer); 483 this._applyDeviceMetricsTimer = setTimeout(this._doApplyDeviceMetricsUserInput.bind(this), 50); 484 }, 485 486 _doApplyDeviceMetricsUserInput: function() 487 { 488 delete this._applyDeviceMetricsTimer; 489 this._setDeviceMetricsOverride(WebInspector.OverridesSupport.DeviceMetrics.parseUserInput(this._widthOverrideElement.value.trim(), this._heightOverrideElement.value.trim(), this._deviceScaleFactorOverrideElement.value.trim(), this._textAutosizingOverrideCheckbox.checked), true); 490 }, 491 492 /** 493 * @param {?WebInspector.OverridesSupport.DeviceMetrics} metrics 494 * @param {boolean} userInputModified 495 */ 496 _setDeviceMetricsOverride: function(metrics, userInputModified) 497 { 498 function setValid(condition, element) 499 { 500 if (condition) 501 element.classList.remove("error-input"); 502 else 503 element.classList.add("error-input"); 504 } 505 506 setValid(metrics && metrics.isWidthValid(), this._widthOverrideElement); 507 setValid(metrics && metrics.isHeightValid(), this._heightOverrideElement); 508 setValid(metrics && metrics.isDeviceScaleFactorValid(), this._deviceScaleFactorOverrideElement); 509 510 if (!metrics) 511 return; 512 513 if (!userInputModified) { 514 this._widthOverrideElement.value = metrics.widthToInput(); 515 this._heightOverrideElement.value = metrics.heightToInput(); 516 this._deviceScaleFactorOverrideElement.value = metrics.deviceScaleFactorToInput(); 517 this._textAutosizingOverrideCheckbox.checked = metrics.textAutosizing; 518 } 519 520 if (metrics.isValid()) { 521 var value = metrics.toSetting(); 522 if (value !== WebInspector.settings.deviceMetrics.get()) 523 WebInspector.settings.deviceMetrics.set(value); 524 } 525 }, 526 527 /** 528 * @param {!WebInspector.OverridesSupport.DeviceMetrics} metrics 529 */ 530 _createDeviceMetricsElement: function(metrics) 531 { 532 var fieldsetElement = WebInspector.SettingsTab.createSettingFieldset(WebInspector.settings.overrideDeviceMetrics); 533 if (WebInspector.isInspectingDevice()) 534 fieldsetElement.disabled = true; 535 fieldsetElement.id = "metrics-override-section"; 536 537 /** 538 * @this {WebInspector.OverridesView.ViewportTab} 539 */ 540 function swapDimensionsClicked() 541 { 542 var widthValue = this._widthOverrideElement.value; 543 this._widthOverrideElement.value = this._heightOverrideElement.value; 544 this._heightOverrideElement.value = widthValue; 545 this._applyDeviceMetricsUserInput(); 546 } 547 548 var tableElement = fieldsetElement.createChild("table", "nowrap"); 549 550 var rowElement = tableElement.createChild("tr"); 551 var cellElement = rowElement.createChild("td"); 552 cellElement.appendChild(document.createTextNode(WebInspector.UIString("Resolution:"))); 553 cellElement = rowElement.createChild("td"); 554 this._widthOverrideElement = this._createInput(cellElement, "metrics-override-width", String(metrics.width || screen.width), this._applyDeviceMetricsUserInput.bind(this), true); 555 this._swapDimensionsElement = cellElement.createChild("button", "overrides-swap"); 556 this._swapDimensionsElement.appendChild(document.createTextNode(" \u21C4 ")); // RIGHTWARDS ARROW OVER LEFTWARDS ARROW. 557 this._swapDimensionsElement.title = WebInspector.UIString("Swap dimensions"); 558 this._swapDimensionsElement.addEventListener("click", swapDimensionsClicked.bind(this), false); 559 this._swapDimensionsElement.tabIndex = -1; 560 this._heightOverrideElement = this._createInput(cellElement, "metrics-override-height", String(metrics.height || screen.height), this._applyDeviceMetricsUserInput.bind(this), true); 561 562 rowElement = tableElement.createChild("tr"); 563 cellElement = rowElement.createChild("td"); 564 cellElement.colSpan = 4; 565 this._widthRangeInput = cellElement.createChild("input"); 566 this._widthRangeInput.type = "range"; 567 this._widthRangeInput.min = 100; 568 this._widthRangeInput.max = 2000; 569 this._widthRangeInput.addEventListener("change", this._rangeValueChanged.bind(this), false); 570 this._widthRangeInput.value = this._widthOverrideElement.value; 571 572 rowElement = tableElement.createChild("tr"); 573 rowElement.title = WebInspector.UIString("Ratio between a device's physical pixels and device-independent pixels."); 574 cellElement = rowElement.createChild("td"); 575 cellElement.appendChild(document.createTextNode(WebInspector.UIString("Device pixel ratio:"))); 576 cellElement = rowElement.createChild("td"); 577 this._deviceScaleFactorOverrideElement = this._createInput(cellElement, "metrics-override-device-scale", String(metrics.deviceScaleFactor || 1), this._applyDeviceMetricsUserInput.bind(this), true); 578 579 var textAutosizingOverrideElement = this._createNonPersistedCheckbox(WebInspector.UIString("Enable text autosizing "), this._applyDeviceMetricsUserInput.bind(this)); 580 textAutosizingOverrideElement.title = WebInspector.UIString("Text autosizing is the feature that boosts font sizes on mobile devices."); 581 this._textAutosizingOverrideCheckbox = textAutosizingOverrideElement.firstChild; 582 this._textAutosizingOverrideCheckbox.checked = metrics.textAutosizing; 583 fieldsetElement.appendChild(textAutosizingOverrideElement); 584 585 var checkbox = this._createSettingCheckbox(WebInspector.UIString("Emulate viewport"), WebInspector.settings.emulateViewport); 586 fieldsetElement.appendChild(checkbox); 587 588 checkbox = this._createSettingCheckbox(WebInspector.UIString("Shrink to fit"), WebInspector.settings.deviceFitWindow); 589 fieldsetElement.appendChild(checkbox); 590 591 return fieldsetElement; 592 }, 593 594 _updateDeviceMetricsElement: function() 595 { 596 const metricsSetting = WebInspector.settings.deviceMetrics.get(); 597 var metrics = WebInspector.OverridesSupport.DeviceMetrics.parseSetting(metricsSetting); 598 599 if (this._widthOverrideElement.value !== metrics.width) 600 this._widthOverrideElement.value = metrics.width || screen.width; 601 this._muteRangeListener = true; 602 if (this._widthRangeInput.value != metrics.width) 603 this._widthRangeInput.value = metrics.width || screen.width; 604 delete this._muteRangeListener; 605 if (this._heightOverrideElement.value !== metrics.height) 606 this._heightOverrideElement.value = metrics.height || screen.height; 607 if (this._deviceScaleFactorOverrideElement.value !== metrics.deviceScaleFactor) 608 this._deviceScaleFactorOverrideElement.value = metrics.deviceScaleFactor || 1; 609 if (this._textAutosizingOverrideCheckbox.checked !== metrics.textAutosizing) 610 this._textAutosizingOverrideCheckbox.checked = metrics.textAutosizing || false; 611 }, 612 613 _createMediaEmulationElement: function() 614 { 615 var checkbox = WebInspector.SettingsTab.createSettingCheckbox(WebInspector.UIString("CSS media"), WebInspector.settings.overrideCSSMedia, true); 616 var fieldsetElement = WebInspector.SettingsTab.createSettingFieldset(WebInspector.settings.overrideCSSMedia); 617 if (WebInspector.isInspectingDevice()) 618 fieldsetElement.disabled = true; 619 checkbox.appendChild(fieldsetElement); 620 621 var mediaSelectElement = fieldsetElement.createChild("select"); 622 var mediaTypes = WebInspector.CSSStyleModel.MediaTypes; 623 var defaultMedia = WebInspector.settings.emulatedCSSMedia.get(); 624 for (var i = 0; i < mediaTypes.length; ++i) { 625 var mediaType = mediaTypes[i]; 626 if (mediaType === "all") { 627 // "all" is not a device-specific media type. 628 continue; 629 } 630 var option = document.createElement("option"); 631 option.text = mediaType; 632 option.value = mediaType; 633 mediaSelectElement.add(option); 634 if (mediaType === defaultMedia) 635 mediaSelectElement.selectedIndex = mediaSelectElement.options.length - 1; 636 } 637 638 mediaSelectElement.addEventListener("change", this._emulateMediaChanged.bind(this, mediaSelectElement), false); 639 return checkbox; 640 }, 641 642 _emulateMediaChanged: function(select) 643 { 644 var media = select.options[select.selectedIndex].value; 645 WebInspector.settings.emulatedCSSMedia.set(media); 646 }, 647 648 _rangeValueChanged: function() 649 { 650 if (this._muteRangeListener) 651 return; 652 this._widthOverrideElement.value = this._widthRangeInput.value; 653 this._applyDeviceMetricsUserInput(); 654 } 655} 656 657WebInspector.OverridesView.ViewportTab.prototype.__proto__ = WebInspector.OverridesView.Tab.prototype; 658 659 660/** 661 * @constructor 662 * @extends {WebInspector.OverridesView.Tab} 663 */ 664WebInspector.OverridesView.UserAgentTab = function() 665{ 666 WebInspector.OverridesView.Tab.call(this, "user-agent", WebInspector.UIString("User Agent"), [WebInspector.settings.overrideUserAgent]); 667 this.element.classList.add("overrides-user-agent"); 668 var checkbox = this._createSettingCheckbox(WebInspector.UIString("Spoof user agent"), WebInspector.settings.overrideUserAgent); 669 checkbox.firstChild.disabled = WebInspector.isInspectingDevice(); 670 this.element.appendChild(checkbox); 671 this.element.appendChild(this._createUserAgentSelectRowElement()); 672} 673 674WebInspector.OverridesView.UserAgentTab._userAgents = [ 675 ["Internet Explorer 10", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"], 676 ["Internet Explorer 9", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"], 677 ["Internet Explorer 8", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)"], 678 ["Internet Explorer 7", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"], 679 680 ["Firefox 7 \u2014 Windows", "Mozilla/5.0 (Windows NT 6.1; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"], 681 ["Firefox 7 \u2014 Mac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"], 682 ["Firefox 4 \u2014 Windows", "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"], 683 ["Firefox 4 \u2014 Mac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"], 684 ["Firefox 14 \u2014 Android Mobile", "Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0"], 685 ["Firefox 14 \u2014 Android Tablet", "Mozilla/5.0 (Android; Tablet; rv:14.0) Gecko/14.0 Firefox/14.0"], 686 687 ["Chrome \u2014 Android Mobile", "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19"], 688 ["Chrome \u2014 Android Tablet", "Mozilla/5.0 (Linux; Android 4.1.2; Nexus 7 Build/JZ054K) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19"], 689 690 ["iPhone \u2014 iOS 7", "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A4449d Safari/9537.53"], 691 ["iPhone \u2014 iOS 6", "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25"], 692 ["iPad \u2014 iOS 7", "Mozilla/5.0 (iPad; CPU OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53"], 693 ["iPad \u2014 iOS 6", "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25"], 694 695 ["Android 2.3 \u2014 Nexus S", "Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus S Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"], 696 ["Android 4.0.2 \u2014 Galaxy Nexus", "Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"], 697 698 ["BlackBerry \u2014 PlayBook 2.1", "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+"], 699 ["BlackBerry \u2014 9900", "Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.187 Mobile Safari/534.11+"], 700 ["BlackBerry \u2014 BB10", "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.1+ (KHTML, like Gecko) Version/10.0.0.1337 Mobile Safari/537.1+"], 701 702 ["MeeGo \u2014 Nokia N9", "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13"], 703]; 704 705WebInspector.OverridesView.UserAgentTab.prototype = { 706 /** 707 * @return {!Element} 708 */ 709 _createUserAgentSelectRowElement: function() 710 { 711 var userAgent = WebInspector.settings.userAgent.get(); 712 var userAgents = WebInspector.OverridesView.UserAgentTab._userAgents.concat([[WebInspector.UIString("Other"), "Other"]]); 713 714 var fieldsetElement = WebInspector.SettingsTab.createSettingFieldset(WebInspector.settings.overrideUserAgent); 715 if (WebInspector.isInspectingDevice()) 716 fieldsetElement.disabled = true; 717 718 this._selectElement = fieldsetElement.createChild("select"); 719 fieldsetElement.createChild("br"); 720 this._otherUserAgentElement = fieldsetElement.createChild("input"); 721 this._otherUserAgentElement.type = "text"; 722 this._otherUserAgentElement.value = userAgent; 723 this._otherUserAgentElement.title = userAgent; 724 725 var selectionRestored = false; 726 for (var i = 0; i < userAgents.length; ++i) { 727 var agent = userAgents[i]; 728 var option = new Option(agent[0], agent[1]); 729 option._metrics = agent[2] ? agent[2] : ""; 730 this._selectElement.add(option); 731 if (userAgent === agent[1]) { 732 this._selectElement.selectedIndex = i; 733 selectionRestored = true; 734 } 735 } 736 737 if (!selectionRestored) { 738 if (!userAgent) 739 this._selectElement.selectedIndex = 0; 740 else 741 this._selectElement.selectedIndex = userAgents.length - 1; 742 } 743 744 this._selectElement.addEventListener("change", this._userAgentChanged.bind(this, true), false); 745 WebInspector.settings.userAgent.addChangeListener(this._userAgentSettingChanged, this); 746 747 fieldsetElement.addEventListener("dblclick", textDoubleClicked.bind(this), false); 748 this._otherUserAgentElement.addEventListener("blur", textChanged.bind(this), false); 749 750 /** 751 * @this {WebInspector.OverridesView.UserAgentTab} 752 */ 753 function textDoubleClicked() 754 { 755 this._selectElement.selectedIndex = userAgents.length - 1; 756 this._userAgentChanged(); 757 } 758 759 /** 760 * @this {WebInspector.OverridesView.UserAgentTab} 761 */ 762 function textChanged() 763 { 764 if (WebInspector.settings.userAgent.get() !== this._otherUserAgentElement.value) 765 WebInspector.settings.userAgent.set(this._otherUserAgentElement.value); 766 } 767 768 return fieldsetElement; 769 }, 770 771 /** 772 * @param {boolean=} isUserGesture 773 */ 774 _userAgentChanged: function(isUserGesture) 775 { 776 var value = this._selectElement.options[this._selectElement.selectedIndex].value; 777 if (value !== "Other") { 778 WebInspector.settings.userAgent.set(value); 779 this._otherUserAgentElement.value = value; 780 this._otherUserAgentElement.title = value; 781 this._otherUserAgentElement.disabled = true; 782 } else { 783 this._otherUserAgentElement.disabled = false; 784 this._otherUserAgentElement.focus(); 785 } 786 }, 787 788 _userAgentSettingChanged: function() 789 { 790 var value = WebInspector.settings.userAgent.get(); 791 var options = this._selectElement.options; 792 var foundMatch = false; 793 for (var i = 0; i < options.length; ++i) { 794 if (options[i].value === value) { 795 if (this._selectElement.selectedIndex !== i) 796 this._selectElement.selectedIndex = i; 797 foundMatch = true; 798 break; 799 } 800 } 801 802 this._otherUserAgentElement.disabled = foundMatch; 803 if (!foundMatch) 804 this._selectElement.selectedIndex = options.length - 1; 805 806 if (this._otherUserAgentElement.value !== value) { 807 this._otherUserAgentElement.value = value; 808 this._otherUserAgentElement.title = value; 809 } 810 } 811} 812 813WebInspector.OverridesView.UserAgentTab.prototype.__proto__ = WebInspector.OverridesView.Tab.prototype; 814 815 816/** 817 * @constructor 818 * @extends {WebInspector.OverridesView.Tab} 819 */ 820WebInspector.OverridesView.SensorsTab = function() 821{ 822 WebInspector.OverridesView.Tab.call(this, "sensors", WebInspector.UIString("Sensors"), [WebInspector.settings.emulateTouchEvents, WebInspector.settings.overrideGeolocation, WebInspector.settings.overrideDeviceOrientation]); 823 this.element.classList.add("overrides-sensors"); 824 this.registerRequiredCSS("accelerometer.css"); 825 if (!WebInspector.isInspectingDevice()) 826 this.element.appendChild(this._createSettingCheckbox(WebInspector.UIString("Emulate touch screen"), WebInspector.settings.emulateTouchEvents)); 827 this._appendGeolocationOverrideControl(); 828 if (!WebInspector.isInspectingDevice()) 829 this._apendDeviceOrientationOverrideControl(); 830} 831 832WebInspector.OverridesView.SensorsTab.prototype = { 833 _appendGeolocationOverrideControl: function() 834 { 835 const geolocationSetting = WebInspector.settings.geolocationOverride.get(); 836 var geolocation = WebInspector.OverridesSupport.GeolocationPosition.parseSetting(geolocationSetting); 837 this.element.appendChild(this._createSettingCheckbox(WebInspector.UIString("Emulate geolocation coordinates"), WebInspector.settings.overrideGeolocation, this._geolocationOverrideCheckboxClicked.bind(this))); 838 this.element.appendChild(this._createGeolocationOverrideElement(geolocation)); 839 this._geolocationOverrideCheckboxClicked(WebInspector.settings.overrideGeolocation.get()); 840 }, 841 842 /** 843 * @param {boolean} enabled 844 */ 845 _geolocationOverrideCheckboxClicked: function(enabled) 846 { 847 if (enabled && !this._latitudeElement.value) 848 this._latitudeElement.focus(); 849 }, 850 851 _applyGeolocationUserInput: function() 852 { 853 this._setGeolocationPosition(WebInspector.OverridesSupport.GeolocationPosition.parseUserInput(this._latitudeElement.value.trim(), this._longitudeElement.value.trim(), this._geolocationErrorElement.checked), true); 854 }, 855 856 /** 857 * @param {?WebInspector.OverridesSupport.GeolocationPosition} geolocation 858 * @param {boolean} userInputModified 859 */ 860 _setGeolocationPosition: function(geolocation, userInputModified) 861 { 862 if (!geolocation) 863 return; 864 865 if (!userInputModified) { 866 this._latitudeElement.value = geolocation.latitude; 867 this._longitudeElement.value = geolocation.longitude; 868 } 869 870 var value = geolocation.toSetting(); 871 WebInspector.settings.geolocationOverride.set(value); 872 }, 873 874 /** 875 * @param {!WebInspector.OverridesSupport.GeolocationPosition} geolocation 876 * @return {!Element} 877 */ 878 _createGeolocationOverrideElement: function(geolocation) 879 { 880 var fieldsetElement = WebInspector.SettingsTab.createSettingFieldset(WebInspector.settings.overrideGeolocation); 881 fieldsetElement.id = "geolocation-override-section"; 882 883 var tableElement = fieldsetElement.createChild("table"); 884 var rowElement = tableElement.createChild("tr"); 885 var cellElement = rowElement.createChild("td"); 886 cellElement = rowElement.createChild("td"); 887 cellElement.appendChild(document.createTextNode(WebInspector.UIString("Lat = "))); 888 this._latitudeElement = this._createInput(cellElement, "geolocation-override-latitude", String(geolocation.latitude), this._applyGeolocationUserInput.bind(this), true); 889 cellElement.appendChild(document.createTextNode(" , ")); 890 cellElement.appendChild(document.createTextNode(WebInspector.UIString("Lon = "))); 891 this._longitudeElement = this._createInput(cellElement, "geolocation-override-longitude", String(geolocation.longitude), this._applyGeolocationUserInput.bind(this), true); 892 rowElement = tableElement.createChild("tr"); 893 cellElement = rowElement.createChild("td"); 894 cellElement.colSpan = 2; 895 var geolocationErrorLabelElement = document.createElement("label"); 896 var geolocationErrorCheckboxElement = geolocationErrorLabelElement.createChild("input"); 897 geolocationErrorCheckboxElement.id = "geolocation-error"; 898 geolocationErrorCheckboxElement.type = "checkbox"; 899 geolocationErrorCheckboxElement.checked = !geolocation || geolocation.error; 900 geolocationErrorCheckboxElement.addEventListener("click", this._applyGeolocationUserInput.bind(this), false); 901 geolocationErrorLabelElement.appendChild(document.createTextNode(WebInspector.UIString("Emulate position unavailable"))); 902 this._geolocationErrorElement = geolocationErrorCheckboxElement; 903 cellElement.appendChild(geolocationErrorLabelElement); 904 905 return fieldsetElement; 906 }, 907 908 _apendDeviceOrientationOverrideControl: function() 909 { 910 const deviceOrientationSetting = WebInspector.settings.deviceOrientationOverride.get(); 911 var deviceOrientation = WebInspector.OverridesSupport.DeviceOrientation.parseSetting(deviceOrientationSetting); 912 this.element.appendChild(this._createSettingCheckbox(WebInspector.UIString("Accelerometer"), WebInspector.settings.overrideDeviceOrientation, this._deviceOrientationOverrideCheckboxClicked.bind(this))); 913 this.element.appendChild(this._createDeviceOrientationOverrideElement(deviceOrientation)); 914 this._deviceOrientationOverrideCheckboxClicked(WebInspector.settings.overrideDeviceOrientation.get()); 915 }, 916 917 /** 918 * @param {boolean} enabled 919 */ 920 _deviceOrientationOverrideCheckboxClicked: function(enabled) 921 { 922 if (enabled && !this._alphaElement.value) 923 this._alphaElement.focus(); 924 }, 925 926 _applyDeviceOrientationUserInput: function() 927 { 928 this._setDeviceOrientation(WebInspector.OverridesSupport.DeviceOrientation.parseUserInput(this._alphaElement.value.trim(), this._betaElement.value.trim(), this._gammaElement.value.trim()), WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.UserInput); 929 }, 930 931 _resetDeviceOrientation: function() 932 { 933 this._setDeviceOrientation(new WebInspector.OverridesSupport.DeviceOrientation(0, 0, 0), WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.ResetButton); 934 }, 935 936 /** 937 * @param {?WebInspector.OverridesSupport.DeviceOrientation} deviceOrientation 938 * @param {!WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource} modificationSource 939 */ 940 _setDeviceOrientation: function(deviceOrientation, modificationSource) 941 { 942 if (!deviceOrientation) 943 return; 944 945 if (modificationSource != WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.UserInput) { 946 this._alphaElement.value = deviceOrientation.alpha; 947 this._betaElement.value = deviceOrientation.beta; 948 this._gammaElement.value = deviceOrientation.gamma; 949 } 950 951 if (modificationSource != WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.UserDrag) 952 this._setBoxOrientation(deviceOrientation); 953 954 var value = deviceOrientation.toSetting(); 955 WebInspector.settings.deviceOrientationOverride.set(value); 956 }, 957 958 /** 959 * @param {!Element} parentElement 960 * @param {string} id 961 * @param {string} label 962 * @param {string} defaultText 963 * @return {!Element} 964 */ 965 _createAxisInput: function(parentElement, id, label, defaultText) 966 { 967 var div = parentElement.createChild("div", "accelerometer-axis-input-container"); 968 div.appendChild(document.createTextNode(label)); 969 return this._createInput(div, id, defaultText, this._applyDeviceOrientationUserInput.bind(this), true); 970 }, 971 972 /** 973 * @param {!WebInspector.OverridesSupport.DeviceOrientation} deviceOrientation 974 */ 975 _createDeviceOrientationOverrideElement: function(deviceOrientation) 976 { 977 var fieldsetElement = WebInspector.SettingsTab.createSettingFieldset(WebInspector.settings.overrideDeviceOrientation); 978 fieldsetElement.id = "device-orientation-override-section"; 979 var tableElement = fieldsetElement.createChild("table"); 980 var rowElement = tableElement.createChild("tr"); 981 var cellElement = rowElement.createChild("td", "accelerometer-inputs-cell"); 982 983 this._alphaElement = this._createAxisInput(cellElement, "device-orientation-override-alpha", "\u03B1: ", String(deviceOrientation.alpha)); 984 this._betaElement = this._createAxisInput(cellElement, "device-orientation-override-beta", "\u03B2: ", String(deviceOrientation.beta)); 985 this._gammaElement = this._createAxisInput(cellElement, "device-orientation-override-gamma", "\u03B3: ", String(deviceOrientation.gamma)); 986 987 var resetButton = cellElement.createChild("button", "settings-tab-text-button accelerometer-reset-button"); 988 resetButton.textContent = WebInspector.UIString("Reset"); 989 resetButton.addEventListener("click", this._resetDeviceOrientation.bind(this), false); 990 991 this._stageElement = rowElement.createChild("td","accelerometer-stage"); 992 this._boxElement = this._stageElement.createChild("section", "accelerometer-box"); 993 994 this._boxElement.createChild("section", "front"); 995 this._boxElement.createChild("section", "top"); 996 this._boxElement.createChild("section", "back"); 997 this._boxElement.createChild("section", "left"); 998 this._boxElement.createChild("section", "right"); 999 this._boxElement.createChild("section", "bottom"); 1000 1001 WebInspector.installDragHandle(this._stageElement, this._onBoxDragStart.bind(this), this._onBoxDrag.bind(this), this._onBoxDragEnd.bind(this), "move"); 1002 this._setBoxOrientation(deviceOrientation); 1003 return fieldsetElement; 1004 }, 1005 1006 /** 1007 * @param {!WebInspector.OverridesSupport.DeviceOrientation} deviceOrientation 1008 */ 1009 _setBoxOrientation: function(deviceOrientation) 1010 { 1011 var matrix = new WebKitCSSMatrix(); 1012 this._boxMatrix = matrix.rotate(-deviceOrientation.beta, deviceOrientation.gamma, -deviceOrientation.alpha); 1013 this._boxElement.style.webkitTransform = this._boxMatrix.toString(); 1014 }, 1015 1016 /** 1017 * @param {!MouseEvent} event 1018 * @return {boolean} 1019 */ 1020 _onBoxDrag: function(event) 1021 { 1022 var mouseMoveVector = this._calculateRadiusVector(event.x, event.y); 1023 if (!mouseMoveVector) 1024 return true; 1025 1026 event.consume(true); 1027 var axis = WebInspector.Geometry.crossProduct(this._mouseDownVector, mouseMoveVector); 1028 axis.normalize(); 1029 var angle = WebInspector.Geometry.calculateAngle(this._mouseDownVector, mouseMoveVector); 1030 var matrix = new WebKitCSSMatrix(); 1031 var rotationMatrix = matrix.rotateAxisAngle(axis.x, axis.y, axis.z, angle); 1032 this._currentMatrix = rotationMatrix.multiply(this._boxMatrix) 1033 this._boxElement.style.webkitTransform = this._currentMatrix; 1034 var eulerAngles = WebInspector.Geometry.EulerAngles.fromRotationMatrix(this._currentMatrix); 1035 var newOrientation = new WebInspector.OverridesSupport.DeviceOrientation(-eulerAngles.alpha, -eulerAngles.beta, eulerAngles.gamma); 1036 this._setDeviceOrientation(newOrientation, WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource.UserDrag); 1037 return false; 1038 }, 1039 1040 /** 1041 * @param {!MouseEvent} event 1042 * @return {boolean} 1043 */ 1044 _onBoxDragStart: function(event) 1045 { 1046 if (!WebInspector.settings.overrideDeviceOrientation.get()) 1047 return false; 1048 1049 this._mouseDownVector = this._calculateRadiusVector(event.x, event.y); 1050 1051 if (!this._mouseDownVector) 1052 return false; 1053 1054 event.consume(true); 1055 return true; 1056 }, 1057 1058 _onBoxDragEnd: function() 1059 { 1060 this._boxMatrix = this._currentMatrix; 1061 }, 1062 1063 /** 1064 * @param {number} x 1065 * @param {number} y 1066 * @return {?WebInspector.Geometry.Vector} 1067 */ 1068 _calculateRadiusVector: function(x, y) 1069 { 1070 var rect = this._stageElement.getBoundingClientRect(); 1071 var radius = Math.max(rect.width, rect.height) / 2; 1072 var sphereX = (x - rect.left - rect.width / 2) / radius; 1073 var sphereY = (y - rect.top - rect.height / 2) / radius; 1074 var sqrSum = sphereX * sphereX + sphereY * sphereY; 1075 if (sqrSum > 0.5) 1076 return new WebInspector.Geometry.Vector(sphereX, sphereY, 0.5 / Math.sqrt(sqrSum)); 1077 1078 return new WebInspector.Geometry.Vector(sphereX, sphereY, Math.sqrt(1 - sqrSum)); 1079 }, 1080 1081 __proto__ : WebInspector.OverridesView.Tab.prototype 1082} 1083 1084/** @enum {string} */ 1085WebInspector.OverridesView.SensorsTab.DeviceOrientationModificationSource = { 1086 UserInput: "userInput", 1087 UserDrag: "userDrag", 1088 ResetButton: "resetButton" 1089} 1090