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("helpScreen.css");
39    this.element.addStyleClass("fill");
40    this.element.addStyleClass("help-window-main");
41    this.element.addStyleClass("settings-tab-container");
42
43    var paneContent = this.element.createChild("div", "tabbed-pane-content");
44
45    function appendBlockTo(targetElement, contentElement)
46    {
47        var blockElement = targetElement.createChild("div", "help-block");
48        blockElement.appendChild(contentElement);
49    }
50
51    var headerTitle = paneContent.createChild("header").createChild("h3");
52    headerTitle.appendChild(document.createTextNode(WebInspector.UIString("Overrides")));
53
54    var container = paneContent.createChild("div", "help-container-wrapper").createChild("div", "settings-tab help-content help-container");
55    this.containerElement = container;
56    appendBlockTo(container, this._createUserAgentControl());
57    if (Capabilities.canOverrideDeviceMetrics)
58        appendBlockTo(container, this._createDeviceMetricsControl());
59    if (Capabilities.canOverrideGeolocation)
60        appendBlockTo(container, this._createGeolocationOverrideControl());
61    if (Capabilities.canOverrideDeviceOrientation)
62        appendBlockTo(container, this._createDeviceOrientationOverrideControl());
63    appendBlockTo(container, this._createCheckboxSetting(WebInspector.UIString("Emulate touch events"), WebInspector.settings.emulateTouchEvents));
64    appendBlockTo(container, this._createMediaEmulationElement());
65
66    this._statusElement = document.createElement("span");
67    this._statusElement.textContent = WebInspector.UIString("Overrides");
68}
69
70WebInspector.OverridesView.showInDrawer = function()
71{
72    if (!WebInspector.OverridesView._view)
73        WebInspector.OverridesView._view = new WebInspector.OverridesView();
74    var view = WebInspector.OverridesView._view;
75    WebInspector.showViewInDrawer(view._statusElement, view);
76}
77
78WebInspector.OverridesView.prototype = {
79    /**
80     * @param {boolean=} omitParagraphElement
81     * @param {Element=} inputElement
82     */
83    _createCheckboxSetting: function(name, setting, omitParagraphElement, inputElement)
84    {
85        var input = inputElement || document.createElement("input");
86        input.type = "checkbox";
87        input.name = name;
88        input.checked = setting.get();
89
90        function listener()
91        {
92            setting.set(input.checked);
93        }
94        input.addEventListener("click", listener, false);
95
96        var label = document.createElement("label");
97        label.appendChild(input);
98        label.appendChild(document.createTextNode(name));
99        if (omitParagraphElement)
100            return label;
101
102        var p = document.createElement("p");
103        p.appendChild(label);
104        return p;
105    },
106
107    _createUserAgentControl: function()
108    {
109        var userAgent = WebInspector.settings.userAgent.get();
110
111        var p = document.createElement("p");
112        var labelElement = p.createChild("label");
113        var checkboxElement = labelElement.createChild("input");
114        checkboxElement.type = "checkbox";
115        checkboxElement.checked = false;
116        labelElement.appendChild(document.createTextNode(WebInspector.UIString("User Agent")));
117        p.appendChild(this._createUserAgentSelectRowElement(checkboxElement));
118        return p;
119    },
120
121    _createUserAgentSelectRowElement: function(checkboxElement)
122    {
123        var userAgent = WebInspector.settings.userAgent.get();
124
125        // When present, the third element lists device metrics separated by 'x':
126        // - screen width,
127        // - screen height,
128        // - font scale factor.
129        const userAgents = [
130            ["Internet Explorer 9", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"],
131            ["Internet Explorer 8", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)"],
132            ["Internet Explorer 7", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"],
133
134            ["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"],
135            ["Firefox 7 \u2014 Mac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"],
136            ["Firefox 4 \u2014 Windows", "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"],
137            ["Firefox 4 \u2014 Mac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"],
138            ["Firefox 14 \u2014 Android Mobile", "Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0"],
139            ["Firefox 14 \u2014 Android Tablet", "Mozilla/5.0 (Android; Tablet; rv:14.0) Gecko/14.0 Firefox/14.0"],
140
141            ["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"],
142            ["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"],
143
144            ["iPhone \u2014 iOS 5", "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3", "640x960x1"],
145            ["iPhone \u2014 iOS 4", "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5", "640x960x1"],
146            ["iPad \u2014 iOS 5", "Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3", "1024x768x1"],
147            ["iPad \u2014 iOS 4", "Mozilla/5.0 (iPad; CPU OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5", "1024x768x1"],
148
149            ["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", "480x800x1.1"],
150            ["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", "720x1280x1.1"],
151
152            ["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+", "1024x600x1"],
153            ["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+", "640x480x1"],
154            ["BlackBerry \u2014 BB10", "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.1+ (KHTML, like Gecko) Version/10.0.0.1337 Mobile Safari/537.1+", "768x1280x1"],
155
156            ["MeeGo \u2014 Nokia N9", "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", "480x854x1"],
157
158            [WebInspector.UIString("Other..."), "Other"]
159        ];
160
161        var fieldsetElement = document.createElement("fieldset");
162        this._selectElement = fieldsetElement.createChild("select");
163        this._otherUserAgentElement = fieldsetElement.createChild("input");
164        this._otherUserAgentElement.type = "text";
165        this._otherUserAgentElement.value = userAgent;
166        this._otherUserAgentElement.title = userAgent;
167        this._userAgentFieldsetElement = fieldsetElement;
168
169        var selectionRestored = false;
170        for (var i = 0; i < userAgents.length; ++i) {
171            var agent = userAgents[i];
172            var option = new Option(agent[0], agent[1]);
173            option._metrics = agent[2] ? agent[2] : "";
174            this._selectElement.add(option);
175            if (userAgent === agent[1]) {
176                this._selectElement.selectedIndex = i;
177                selectionRestored = true;
178            }
179        }
180
181        if (!selectionRestored) {
182            if (!userAgent)
183                this._selectElement.selectedIndex = 0;
184            else
185                this._selectElement.selectedIndex = userAgents.length - 1;
186        }
187
188        this._selectElement.addEventListener("change", this._selectionChanged.bind(this, true), false);
189
190        fieldsetElement.addEventListener("dblclick", textDoubleClicked.bind(this), false);
191        this._otherUserAgentElement.addEventListener("blur", textChanged.bind(this), false);
192
193        function textDoubleClicked()
194        {
195            this._selectElement.selectedIndex = userAgents.length - 1;
196            this._selectionChanged();
197        }
198
199        function textChanged()
200        {
201            WebInspector.settings.userAgent.set(this._otherUserAgentElement.value);
202        }
203
204        function checkboxClicked()
205        {
206            if (checkboxElement.checked) {
207                this._userAgentFieldsetElement.disabled = false;
208                this._selectionChanged();
209            } else {
210                this._userAgentFieldsetElement.disabled = true;
211                this._otherUserAgentElement.disabled = true;
212            }
213            WebInspector.userAgentSupport.toggleUserAgentOverride(checkboxElement.checked);
214        }
215        checkboxElement.addEventListener("click", checkboxClicked.bind(this), false);
216
217        checkboxClicked.call(this);
218        return fieldsetElement;
219    },
220
221    /**
222     * @param {boolean=} isUserGesture
223     */
224    _selectionChanged: function(isUserGesture)
225    {
226        var value = this._selectElement.options[this._selectElement.selectedIndex].value;
227        if (value !== "Other") {
228            WebInspector.settings.userAgent.set(value);
229            this._otherUserAgentElement.value = value;
230            this._otherUserAgentElement.title = value;
231            this._otherUserAgentElement.disabled = true;
232        } else {
233            this._otherUserAgentElement.disabled = false;
234            this._otherUserAgentElement.focus();
235        }
236
237        if (isUserGesture && Capabilities.canOverrideDeviceMetrics) {
238            var metrics = this._selectElement.options[this._selectElement.selectedIndex]._metrics;
239            this._setDeviceMetricsOverride(WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(metrics), false, true);
240        }
241    },
242
243    /**
244     * Creates an input element under the parentElement with the given id and defaultText.
245     * It also sets an onblur event listener.
246     * @param {Element} parentElement
247     * @param {string} id
248     * @param {string} defaultText
249     * @param {function(*)} eventListener
250     * @param {boolean=} numeric
251     * @return {Element} element
252     */
253    _createInput: function(parentElement, id, defaultText, eventListener, numeric)
254    {
255        var element = parentElement.createChild("input");
256        element.id = id;
257        element.type = "text";
258        element.maxLength = 12;
259        element.style.width = "80px";
260        element.value = defaultText;
261        element.align = "right";
262        if (numeric)
263            element.className = "numeric";
264        element.addEventListener("blur", eventListener, false);
265        return element;
266    },
267
268    _createDeviceMetricsControl: function()
269    {
270        const metricsSetting = WebInspector.settings.deviceMetrics.get();
271        var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(metricsSetting);
272
273        const p = document.createElement("p");
274        const labelElement = p.createChild("label");
275        const checkboxElement = labelElement.createChild("input");
276        checkboxElement.id = "metrics-override-checkbox";
277        checkboxElement.type = "checkbox";
278        checkboxElement.checked = false;
279        checkboxElement.addEventListener("click", this._onMetricsCheckboxClicked.bind(this), false);
280        this._metricsCheckboxElement = checkboxElement;
281        labelElement.appendChild(document.createTextNode(WebInspector.UIString("Device metrics")));
282
283        const metricsSectionElement = this._createDeviceMetricsElement(metrics);
284        p.appendChild(metricsSectionElement);
285        this._metricsSectionElement = metricsSectionElement;
286        this._onMetricsCheckboxClicked();
287
288        return p;
289    },
290
291    _onMetricsCheckboxClicked: function()
292    {
293        var controlsDisabled = !this._metricsCheckboxElement.checked;
294        this._deviceMetricsFieldsetElement.disabled = controlsDisabled;
295
296        if (controlsDisabled) {
297            WebInspector.userAgentSupport.toggleDeviceMetricsOverride(false);
298            return;
299        }
300
301        var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput(this._widthOverrideElement.value, this._heightOverrideElement.value, this._fontScaleFactorOverrideElement.value);
302        if (metrics && metrics.isValid() && metrics.width && metrics.height) {
303            this._setDeviceMetricsOverride(metrics, false, false);
304            WebInspector.userAgentSupport.toggleDeviceMetricsOverride(true);
305        }
306        if (!this._widthOverrideElement.value)
307            this._widthOverrideElement.focus();
308    },
309
310    _applyDeviceMetricsUserInput: function()
311    {
312        this._setDeviceMetricsOverride(WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput(this._widthOverrideElement.value.trim(), this._heightOverrideElement.value.trim(), this._fontScaleFactorOverrideElement.value.trim()), true, false);
313    },
314
315    /**
316     * @param {?WebInspector.UserAgentSupport.DeviceMetrics} metrics
317     * @param {boolean} userInputModified
318     */
319    _setDeviceMetricsOverride: function(metrics, userInputModified, updateCheckbox)
320    {
321        function setValid(condition, element)
322        {
323            if (condition)
324                element.removeStyleClass("error-input");
325            else
326                element.addStyleClass("error-input");
327        }
328
329        setValid(metrics && metrics.isWidthValid(), this._widthOverrideElement);
330        setValid(metrics && metrics.isHeightValid(), this._heightOverrideElement);
331        setValid(metrics && metrics.isFontScaleFactorValid(), this._fontScaleFactorOverrideElement);
332
333        if (!metrics)
334            return;
335
336        if (!userInputModified) {
337            this._widthOverrideElement.value = metrics.widthToInput();
338            this._heightOverrideElement.value = metrics.heightToInput();
339            this._fontScaleFactorOverrideElement.value = metrics.fontScaleFactorToInput();
340        }
341
342        if (metrics.isValid()) {
343            var value = metrics.toSetting();
344            if (value !== WebInspector.settings.deviceMetrics.get())
345                WebInspector.settings.deviceMetrics.set(value);
346        }
347
348        if (this._metricsCheckboxElement && updateCheckbox) {
349            this._metricsCheckboxElement.checked = !!metrics.toSetting();
350            this._onMetricsCheckboxClicked();
351        }
352    },
353
354    /**
355     * @param {WebInspector.UserAgentSupport.DeviceMetrics} metrics
356     */
357    _createDeviceMetricsElement: function(metrics)
358    {
359        var fieldsetElement = document.createElement("fieldset");
360        fieldsetElement.id = "metrics-override-section";
361        this._deviceMetricsFieldsetElement = fieldsetElement;
362
363        function swapDimensionsClicked(event)
364        {
365            var widthValue = this._widthOverrideElement.value;
366            this._widthOverrideElement.value = this._heightOverrideElement.value;
367            this._heightOverrideElement.value = widthValue;
368            this._applyDeviceMetricsUserInput();
369        }
370
371        var tableElement = fieldsetElement.createChild("table", "nowrap");
372
373        var rowElement = tableElement.createChild("tr");
374        var cellElement = rowElement.createChild("td");
375        cellElement.appendChild(document.createTextNode(WebInspector.UIString("Screen resolution:")));
376        cellElement = rowElement.createChild("td");
377        this._widthOverrideElement = this._createInput(cellElement, "metrics-override-width", String(metrics.width || screen.width), this._applyDeviceMetricsUserInput.bind(this), true);
378        cellElement.appendChild(document.createTextNode(" \u00D7 ")); // MULTIPLICATION SIGN.
379        this._heightOverrideElement = this._createInput(cellElement, "metrics-override-height", String(metrics.height || screen.height), this._applyDeviceMetricsUserInput.bind(this), true);
380        cellElement.appendChild(document.createTextNode(" \u2014 ")); // EM DASH.
381        this._swapDimensionsElement = cellElement.createChild("button");
382        this._swapDimensionsElement.appendChild(document.createTextNode(" \u21C4 ")); // RIGHTWARDS ARROW OVER LEFTWARDS ARROW.
383        this._swapDimensionsElement.title = WebInspector.UIString("Swap dimensions");
384        this._swapDimensionsElement.addEventListener("click", swapDimensionsClicked.bind(this), false);
385
386        rowElement = tableElement.createChild("tr");
387        cellElement = rowElement.createChild("td");
388        cellElement.appendChild(document.createTextNode(WebInspector.UIString("Font scale factor:")));
389        cellElement = rowElement.createChild("td");
390        this._fontScaleFactorOverrideElement = this._createInput(cellElement, "metrics-override-font-scale", String(metrics.fontScaleFactor || 1), this._applyDeviceMetricsUserInput.bind(this), true);
391
392        rowElement = tableElement.createChild("tr");
393        cellElement = rowElement.createChild("td");
394        cellElement.colSpan = 2;
395        this._fitWindowCheckboxElement = document.createElement("input");
396        cellElement.appendChild(this._createCheckboxSetting(WebInspector.UIString("Fit in window"), WebInspector.settings.deviceFitWindow, true, this._fitWindowCheckboxElement));
397
398        return fieldsetElement;
399    },
400
401    _createGeolocationOverrideControl: function()
402    {
403        const geolocationSetting = WebInspector.settings.geolocationOverride.get();
404        var geolocation = WebInspector.UserAgentSupport.GeolocationPosition.parseSetting(geolocationSetting);
405        var p = document.createElement("p");
406        var labelElement = p.createChild("label");
407        var checkboxElement = labelElement.createChild("input");
408        checkboxElement.id = "geolocation-override-checkbox";
409        checkboxElement.type = "checkbox";
410        checkboxElement.checked = false;
411        checkboxElement.addEventListener("click", this._onGeolocationOverrideCheckboxClicked.bind(this), false);
412        this._geolocationOverrideCheckboxElement = checkboxElement;
413        labelElement.appendChild(document.createTextNode(WebInspector.UIString("Override Geolocation")));
414
415        var geolocationSectionElement = this._createGeolocationOverrideElement(geolocation);
416        p.appendChild(geolocationSectionElement);
417        this._geolocationSectionElement = geolocationSectionElement;
418        this._onGeolocationOverrideCheckboxClicked();
419        return p;
420    },
421
422    _onGeolocationOverrideCheckboxClicked: function()
423    {
424        var controlsDisabled = !this._geolocationOverrideCheckboxElement.checked;
425        this._geolocationFieldsetElement.disabled = controlsDisabled;
426
427        if (controlsDisabled) {
428            WebInspector.userAgentSupport.toggleGeolocationPositionOverride(false);
429            return;
430        }
431
432        var geolocation = WebInspector.UserAgentSupport.GeolocationPosition.parseUserInput(this._latitudeElement.value, this._longitudeElement.value, this._geolocationErrorElement.checked);
433        if (geolocation) {
434            this._setGeolocationPosition(geolocation, false, false);
435            WebInspector.userAgentSupport.toggleGeolocationPositionOverride(true);
436        }
437        if (!this._latitudeElement.value)
438            this._latitudeElement.focus();
439    },
440
441    _applyGeolocationUserInput: function()
442    {
443        this._setGeolocationPosition(WebInspector.UserAgentSupport.GeolocationPosition.parseUserInput(this._latitudeElement.value.trim(), this._longitudeElement.value.trim(), this._geolocationErrorElement.checked), true, false);
444    },
445
446    /**
447     * @param {?WebInspector.UserAgentSupport.GeolocationPosition} geolocation
448     * @param {boolean} userInputModified
449     * @param {boolean} updateCheckbox
450     */
451    _setGeolocationPosition: function(geolocation, userInputModified, updateCheckbox)
452    {
453        if (!geolocation)
454            return;
455
456        if (!userInputModified) {
457            this._latitudeElement.value = geolocation.latitude;
458            this._longitudeElement.value = geolocation.longitude;
459        }
460
461        var value = geolocation.toSetting();
462        WebInspector.settings.geolocationOverride.set(value);
463
464        if (this._geolocationOverrideCheckboxElement && updateCheckbox) {
465            this._geolocationOverrideCheckboxElement.checked = !!geolocation.toSetting();
466            this._onGeolocationOverrideCheckboxClicked();
467        }
468    },
469
470    /**
471     * @param {WebInspector.UserAgentSupport.GeolocationPosition} geolocation
472     */
473    _createGeolocationOverrideElement: function(geolocation)
474    {
475        var fieldsetElement = document.createElement("fieldset");
476        fieldsetElement.id = "geolocation-override-section";
477        this._geolocationFieldsetElement = fieldsetElement;
478
479        var tableElement = fieldsetElement.createChild("table");
480        var rowElement = tableElement.createChild("tr");
481        var cellElement = rowElement.createChild("td");
482        cellElement.appendChild(document.createTextNode(WebInspector.UIString("Geolocation Position") + ":"));
483        cellElement = rowElement.createChild("td");
484        cellElement.appendChild(document.createTextNode(WebInspector.UIString("Lat = ")));
485        this._latitudeElement = this._createInput(cellElement, "geolocation-override-latitude", String(geolocation.latitude), this._applyGeolocationUserInput.bind(this), true);
486        cellElement.appendChild(document.createTextNode(" , "));
487        cellElement.appendChild(document.createTextNode(WebInspector.UIString("Lon = ")));
488        this._longitudeElement = this._createInput(cellElement, "geolocation-override-longitude", String(geolocation.longitude), this._applyGeolocationUserInput.bind(this), true);
489        rowElement = tableElement.createChild("tr");
490        cellElement = rowElement.createChild("td");
491        cellElement.colSpan = 2;
492        var geolocationErrorLabelElement = document.createElement("label");
493        var geolocationErrorCheckboxElement = geolocationErrorLabelElement.createChild("input");
494        geolocationErrorCheckboxElement.id = "geolocation-error";
495        geolocationErrorCheckboxElement.type = "checkbox";
496        geolocationErrorCheckboxElement.checked = !geolocation || geolocation.error;
497        geolocationErrorCheckboxElement.addEventListener("click", this._applyGeolocationUserInput.bind(this), false);
498        geolocationErrorLabelElement.appendChild(document.createTextNode(WebInspector.UIString("Emulate position unavailable")));
499        this._geolocationErrorElement = geolocationErrorCheckboxElement;
500        cellElement.appendChild(geolocationErrorLabelElement);
501
502        return fieldsetElement;
503    },
504
505    _createDeviceOrientationOverrideControl: function()
506    {
507        const deviceOrientationSetting = WebInspector.settings.deviceOrientationOverride.get();
508        var deviceOrientation = WebInspector.UserAgentSupport.DeviceOrientation.parseSetting(deviceOrientationSetting);
509
510        var p = document.createElement("p");
511        var labelElement = p.createChild("label");
512        var checkboxElement = labelElement.createChild("input");
513        checkboxElement.id = "device-orientation-override-checkbox";
514        checkboxElement.type = "checkbox";
515        checkboxElement.checked = false;
516        checkboxElement.addEventListener("click", this._onDeviceOrientationOverrideCheckboxClicked.bind(this), false);
517        this._deviceOrientationOverrideCheckboxElement = checkboxElement;
518        labelElement.appendChild(document.createTextNode(WebInspector.UIString("Override Device Orientation")));
519
520        var deviceOrientationSectionElement = this._createDeviceOrientationOverrideElement(deviceOrientation);
521        p.appendChild(deviceOrientationSectionElement);
522        this._deviceOrientationSectionElement = deviceOrientationSectionElement;
523        this._onDeviceOrientationOverrideCheckboxClicked();
524        return p;
525    },
526
527    _onDeviceOrientationOverrideCheckboxClicked: function()
528    {
529        var controlsDisabled = !this._deviceOrientationOverrideCheckboxElement.checked;
530        this._deviceOrientationFieldsetElement.disabled = controlsDisabled;
531
532        if (controlsDisabled) {
533            WebInspector.userAgentSupport.toggleDeviceOrientationOverride(false);
534            return;
535        }
536
537        var deviceOrientation = WebInspector.UserAgentSupport.DeviceOrientation.parseUserInput(this._alphaElement.value, this._betaElement.value, this._gammaElement.value);
538        if (deviceOrientation) {
539            this._setDeviceOrientation(deviceOrientation, false, false);
540            WebInspector.userAgentSupport.toggleDeviceOrientationOverride(true);
541        }
542        if (!this._alphaElement.value)
543            this._alphaElement.focus();
544    },
545
546    _applyDeviceOrientationUserInput: function()
547    {
548        this._setDeviceOrientation(WebInspector.UserAgentSupport.DeviceOrientation.parseUserInput(this._alphaElement.value.trim(), this._betaElement.value.trim(), this._gammaElement.value.trim()), true, false);
549    },
550
551    /**
552     * @param {?WebInspector.UserAgentSupport.DeviceOrientation} deviceOrientation
553     * @param {boolean} userInputModified
554     * @param {boolean} updateCheckbox
555     */
556    _setDeviceOrientation: function(deviceOrientation, userInputModified, updateCheckbox)
557    {
558        if (!deviceOrientation)
559            return;
560
561        if (!userInputModified) {
562            this._alphaElement.value = deviceOrientation.alpha;
563            this._betaElement.value = deviceOrientation.beta;
564            this._gammaElement.value = deviceOrientation.gamma;
565        }
566
567        var value = deviceOrientation.toSetting();
568        WebInspector.settings.deviceOrientationOverride.set(value);
569
570        if (this._deviceOrientationOverrideCheckboxElement && updateCheckbox) {
571            this._deviceOrientationOverrideCheckboxElement.checked = !!deviceOrientation.toSetting();
572            this._onDeviceOrientationOverrideCheckboxClicked();
573        }
574    },
575
576    /**
577     * @param {WebInspector.UserAgentSupport.DeviceOrientation} deviceOrientation
578     */
579    _createDeviceOrientationOverrideElement: function(deviceOrientation)
580    {
581        var fieldsetElement = document.createElement("fieldset");
582        fieldsetElement.id = "device-orientation-override-section";
583        this._deviceOrientationFieldsetElement = fieldsetElement;
584
585        var tableElement = fieldsetElement.createChild("table");
586
587        var rowElement = tableElement.createChild("tr");
588        var cellElement = rowElement.createChild("td");
589        cellElement.appendChild(document.createTextNode("\u03B1: "));
590        this._alphaElement = this._createInput(cellElement, "device-orientation-override-alpha", String(deviceOrientation.alpha), this._applyDeviceOrientationUserInput.bind(this), true);
591        cellElement.appendChild(document.createTextNode(" \u03B2: "));
592        this._betaElement = this._createInput(cellElement, "device-orientation-override-beta", String(deviceOrientation.beta), this._applyDeviceOrientationUserInput.bind(this), true);
593        cellElement.appendChild(document.createTextNode(" \u03B3: "));
594        this._gammaElement = this._createInput(cellElement, "device-orientation-override-gamma", String(deviceOrientation.gamma), this._applyDeviceOrientationUserInput.bind(this), true);
595
596        return fieldsetElement;
597    },
598
599    _createMediaEmulationElement: function()
600    {
601        const p = document.createElement("p");
602        const labelElement = p.createChild("label");
603        const checkboxElement = labelElement.createChild("input");
604        checkboxElement.type = "checkbox";
605        checkboxElement.checked = false;
606        labelElement.appendChild(document.createTextNode(WebInspector.UIString("Emulate CSS media")));
607
608        var mediaSelectElement = p.createChild("select");
609        var mediaTypes = WebInspector.CSSStyleModel.MediaTypes;
610        var defaultMedia = WebInspector.settings.emulatedCSSMedia.get();
611        for (var i = 0; i < mediaTypes.length; ++i) {
612            var mediaType = mediaTypes[i];
613            if (mediaType === "all") {
614                // "all" is not a device-specific media type.
615                continue;
616            }
617            var option = document.createElement("option");
618            option.text = mediaType;
619            option.value = mediaType;
620            mediaSelectElement.add(option);
621            if (mediaType === defaultMedia)
622                mediaSelectElement.selectedIndex = mediaSelectElement.options.length - 1;
623        }
624        mediaSelectElement.disabled = true;
625        var boundListener = this._emulateMediaChanged.bind(this, checkboxElement, mediaSelectElement);
626        checkboxElement.addEventListener("click", boundListener, false);
627        mediaSelectElement.addEventListener("change", boundListener, false);
628        return p;
629    },
630
631    _emulateMediaChanged: function(checkbox, select)
632    {
633        select.disabled = !checkbox.checked;
634        if (checkbox.checked) {
635            var media = select.options[select.selectedIndex].value;
636            WebInspector.settings.emulatedCSSMedia.set(media);
637            PageAgent.setEmulatedMedia(media);
638        } else
639            PageAgent.setEmulatedMedia("");
640        WebInspector.cssModel.mediaQueryResultChanged();
641    },
642
643    __proto__: WebInspector.View.prototype
644}
645