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