Web Inspector: Implement frontend for device metrics emulation
authorapavlov@chromium.org <apavlov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Apr 2012 14:45:29 +0000 (14:45 +0000)
committerapavlov@chromium.org <apavlov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Apr 2012 14:45:29 +0000 (14:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=82891

This change implements the backend-based device metrics emulation capability discovery,
UI (enablement checkbox + input controls), and a persistence setting
for the user-specified device metrics (screen width/height and an auxiliary font scale factor).

Reviewed by Pavel Feldman.

* English.lproj/localizedStrings.js:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* inspector/compile-front-end.py:
* inspector/front-end/Settings.js:
* inspector/front-end/SettingsScreen.js:
(WebInspector.SettingsScreen):
(WebInspector.SettingsScreen.prototype._createUserAgentSelectRowElement.get const):
(WebInspector.SettingsScreen.prototype._showPaintRectsChanged):
(WebInspector.SettingsScreen.prototype.set _applyDeviceMetricsUserInput):
(WebInspector.SettingsScreen.prototype._setDeviceMetricsOverride):
(WebInspector.SettingsScreen.prototype._setDeviceMetricsOverride.set if):
(WebInspector.SettingsScreen.prototype._createDeviceMetricsElement.createInput):
(WebInspector.SettingsScreen.prototype._createDeviceMetricsElement):
* inspector/front-end/UserAgentSupport.js: Added.
(WebInspector.UserAgentSupport.DeviceMetrics):
(WebInspector.UserAgentSupport.DeviceMetrics.parseSetting):
(WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput):
(WebInspector.UserAgentSupport.DeviceMetrics.prototype.isValid):
(WebInspector.UserAgentSupport.DeviceMetrics.prototype.isWidthValid):
(WebInspector.UserAgentSupport.DeviceMetrics.prototype.isHeightValid):
(WebInspector.UserAgentSupport.DeviceMetrics.prototype.isFontScaleFactorValid):
(WebInspector.UserAgentSupport.DeviceMetrics.prototype.toSetting):
(WebInspector.UserAgentSupport.DeviceMetrics.prototype.widthToInput):
(WebInspector.UserAgentSupport.DeviceMetrics.prototype.heightToInput):
(WebInspector.UserAgentSupport.DeviceMetrics.prototype.fontScaleFactorToInput):
* inspector/front-end/WebKit.qrc:
* inspector/front-end/helpScreen.css:
(.help-table > tr > th):
(.help-table > tr > td):
(#resolution-override-section):
* inspector/front-end/inspector.css:
(.hidden):
(.error-input):
* inspector/front-end/inspector.html:
* inspector/front-end/inspector.js:
(WebInspector.doLoadedDone):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@112884 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/English.lproj/localizedStrings.js
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/inspector/compile-front-end.py
Source/WebCore/inspector/front-end/Settings.js
Source/WebCore/inspector/front-end/SettingsScreen.js
Source/WebCore/inspector/front-end/UserAgentSupport.js [new file with mode: 0644]
Source/WebCore/inspector/front-end/WebKit.qrc
Source/WebCore/inspector/front-end/helpScreen.css
Source/WebCore/inspector/front-end/inspector.css
Source/WebCore/inspector/front-end/inspector.html
Source/WebCore/inspector/front-end/inspector.js

index 3ff658a..fcc3ca6 100644 (file)
@@ -1,3 +1,52 @@
+2012-04-02  Alexander Pavlov  <apavlov@chromium.org>
+
+        Web Inspector: Implement frontend for device metrics emulation
+        https://bugs.webkit.org/show_bug.cgi?id=82891
+
+        This change implements the backend-based device metrics emulation capability discovery,
+        UI (enablement checkbox + input controls), and a persistence setting
+        for the user-specified device metrics (screen width/height and an auxiliary font scale factor).
+
+        Reviewed by Pavel Feldman.
+
+        * English.lproj/localizedStrings.js:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * inspector/compile-front-end.py:
+        * inspector/front-end/Settings.js:
+        * inspector/front-end/SettingsScreen.js:
+        (WebInspector.SettingsScreen):
+        (WebInspector.SettingsScreen.prototype._createUserAgentSelectRowElement.get const):
+        (WebInspector.SettingsScreen.prototype._showPaintRectsChanged):
+        (WebInspector.SettingsScreen.prototype.set _applyDeviceMetricsUserInput):
+        (WebInspector.SettingsScreen.prototype._setDeviceMetricsOverride):
+        (WebInspector.SettingsScreen.prototype._setDeviceMetricsOverride.set if):
+        (WebInspector.SettingsScreen.prototype._createDeviceMetricsElement.createInput):
+        (WebInspector.SettingsScreen.prototype._createDeviceMetricsElement):
+        * inspector/front-end/UserAgentSupport.js: Added.
+        (WebInspector.UserAgentSupport.DeviceMetrics):
+        (WebInspector.UserAgentSupport.DeviceMetrics.parseSetting):
+        (WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput):
+        (WebInspector.UserAgentSupport.DeviceMetrics.prototype.isValid):
+        (WebInspector.UserAgentSupport.DeviceMetrics.prototype.isWidthValid):
+        (WebInspector.UserAgentSupport.DeviceMetrics.prototype.isHeightValid):
+        (WebInspector.UserAgentSupport.DeviceMetrics.prototype.isFontScaleFactorValid):
+        (WebInspector.UserAgentSupport.DeviceMetrics.prototype.toSetting):
+        (WebInspector.UserAgentSupport.DeviceMetrics.prototype.widthToInput):
+        (WebInspector.UserAgentSupport.DeviceMetrics.prototype.heightToInput):
+        (WebInspector.UserAgentSupport.DeviceMetrics.prototype.fontScaleFactorToInput):
+        * inspector/front-end/WebKit.qrc:
+        * inspector/front-end/helpScreen.css:
+        (.help-table > tr > th):
+        (.help-table > tr > td):
+        (#resolution-override-section):
+        * inspector/front-end/inspector.css:
+        (.hidden):
+        (.error-input):
+        * inspector/front-end/inspector.html:
+        * inspector/front-end/inspector.js:
+        (WebInspector.doLoadedDone):
+
 2012-04-02  Alexis Menard  <alexis.menard@openbossa.org>
 
         Rename CSSPropertyLonghand class to StylePropertyShorthand.
index 7ac014d..438d08a 100644 (file)
Binary files a/Source/WebCore/English.lproj/localizedStrings.js and b/Source/WebCore/English.lproj/localizedStrings.js differ
index bed4eb1..b0c69cc 100644 (file)
             'inspector/front-end/treeoutline.js',
             'inspector/front-end/UISourceCode.js',
             'inspector/front-end/UIUtils.js',
+            'inspector/front-end/UserAgentSupport.js',
             'inspector/front-end/UserMetrics.js',
             'inspector/front-end/utilities.js',
             'inspector/front-end/View.js',
index 409707c..f32fc3c 100755 (executable)
                                        >
                                </File>
                                <File
+                                       RelativePath="..\inspector\front-end\UserAgentSupport.js"
+                                       >
+                               </File>
+                               <File
                                        RelativePath="..\inspector\front-end\UserMetrics.js"
                                        >
                                </File>
index feee8d8..34b2624 100755 (executable)
@@ -93,6 +93,7 @@ modules = [
             "ResourceUtils.js",
             "NetworkManager.js",
             "UISourceCode.js",
+            "UserAgentSupport.js",
         ]
     },
     {
index 26f2543..50c423f 100644 (file)
@@ -52,7 +52,8 @@ var Capabilities = {
     debuggerCausesRecompilation: true,
     profilerCausesRecompilation: true,
     nativeInstrumentationEnabled: false,
-    heapProfilerPresent: false
+    heapProfilerPresent: false,
+    canOverrideDeviceMetrics: false
 }
 
 /**
@@ -86,6 +87,7 @@ WebInspector.Settings = function()
     this.cacheDisabled = this.createSetting("cacheDisabled", false);
     this.overrideUserAgent = this.createSetting("overrideUserAgent", "");
     this.userAgent = this.createSetting("userAgent", "");
+    this.deviceMetrics = this.createSetting("deviceMetrics", "");
     this.showScriptFolders = this.createSetting("showScriptFolders", true);
     this.dockToRight = this.createSetting("dockToRight", false);
     this.emulateTouchEvents = this.createSetting("emulateTouchEvents", false);
index f92fb1e..1090652 100644 (file)
@@ -72,7 +72,9 @@ WebInspector.SettingsScreen = function()
         ], WebInspector.settings.textEditorIndent));
 
     p = this._appendSection(WebInspector.UIString("User Agent"), true);
-    p.appendChild(this._createUserActionControl());
+    p.appendChild(this._createUserAgentControl());
+    if (Capabilities.canOverrideDeviceMetrics)
+        p.appendChild(this._createDeviceMetricsControl());
     p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Emulate touch events"), WebInspector.settings.emulateTouchEvents));
 
     p = this._appendSection(WebInspector.UIString("Scripts"), true);
@@ -101,7 +103,7 @@ WebInspector.SettingsScreen = function()
         for (var i = 0; i < experiments.length; ++i)
             experimentsSection.appendChild(this._createExperimentCheckbox(experiments[i]));
     }
-    
+
     var table = document.createElement("table");
     table.className = "help-table";
     var tr = document.createElement("tr");
@@ -262,7 +264,7 @@ WebInspector.SettingsScreen.prototype = {
         return p;
     },
 
-    _createUserActionControl: function()
+    _createUserAgentControl: function()
     {
         var userAgent = WebInspector.settings.userAgent.get();
 
@@ -296,6 +298,11 @@ WebInspector.SettingsScreen.prototype = {
     _createUserAgentSelectRowElement: function()
     {
         var userAgent = WebInspector.settings.userAgent.get();
+
+        // When present, the third element lists device metrics separated by 'x':
+        // - screen width,
+        // - screen height,
+        // - font scale factor.
         const userAgents = [
             ["Internet Explorer 9", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"],
             ["Internet Explorer 8", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)"],
@@ -306,18 +313,18 @@ WebInspector.SettingsScreen.prototype = {
             ["Firefox 4 \u2014 Windows", "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"],
             ["Firefox 4 \u2014 Mac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"],
 
-            ["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"],
-            ["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"],
-            ["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"],
-            ["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"],
+            ["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"],
+            ["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"],
+            ["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"],
+            ["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"],
 
-            ["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"],
+            ["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"],
 
-            ["BlackBerry \u2014 PlayBook 1.0","Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.7 Safari/534.11+"],
-            ["BlackBerry \u2014 PlayBook 2.0", "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.0.0; en-US) AppleWebKit/535.8+ (KHTML, like Gecko) Version/7.2.0.0 Safari/535.8+"],
-            ["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+"],
+            ["BlackBerry \u2014 PlayBook 1.0","Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.7 Safari/534.11+", "1024x600x1"],
+            ["BlackBerry \u2014 PlayBook 2.0", "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.0.0; en-US) AppleWebKit/535.8+ (KHTML, like Gecko) Version/7.2.0.0 Safari/535.8+", "1024x600x1"],
+            ["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"],
 
-            ["MeeGo \u2014 Nokia N9", "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13"],
+            ["MeeGo \u2014 Nokia N9", "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", "480x854x1"],
 
             [WebInspector.UIString("Other..."), "Other"]
         ];
@@ -331,7 +338,9 @@ WebInspector.SettingsScreen.prototype = {
         var selectionRestored = false;
         for (var i = 0; i < userAgents.length; ++i) {
             var agent = userAgents[i];
-            selectElement.add(new Option(agent[0], agent[1]));
+            var option = new Option(agent[0], agent[1]);
+            option._metrics = agent[2] ? agent[2] : "";
+            selectElement.add(option);
             if (userAgent === agent[1]) {
                 selectElement.selectedIndex = i;
                 selectionRestored = true;
@@ -345,9 +354,12 @@ WebInspector.SettingsScreen.prototype = {
                 selectElement.selectedIndex = userAgents.length - 1;
         }
 
-        selectElement.addEventListener("change", selectionChanged.bind(this), false);
+        selectElement.addEventListener("change", selectionChanged.bind(this, true), false);
 
-        function selectionChanged()
+        /**
+         * @param {boolean=} isUserGesture
+         */
+        function selectionChanged(isUserGesture)
         {
             var value = selectElement.options[selectElement.selectedIndex].value;
             if (value !== "Other") {
@@ -359,6 +371,11 @@ WebInspector.SettingsScreen.prototype = {
                 otherUserAgentElement.disabled = false;
                 otherUserAgentElement.focus();
             }
+
+            if (isUserGesture && Capabilities.canOverrideDeviceMetrics) {
+                var metrics = selectElement.options[selectElement.selectedIndex]._metrics;
+                this._setDeviceMetricsOverride(WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(metrics), false, true);
+            }
         }
 
         fieldsetElement.addEventListener("dblclick", textDoubleClicked.bind(this), false);
@@ -382,6 +399,127 @@ WebInspector.SettingsScreen.prototype = {
     _showPaintRectsChanged: function()
     {
         PageAgent.setShowPaintRects(WebInspector.settings.showPaintRects.get());
+    },
+
+    _createDeviceMetricsControl: function()
+    {
+        const metricsSetting = WebInspector.settings.deviceMetrics.get();
+        var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(metricsSetting);
+
+        const p = document.createElement("p");
+        const labelElement = p.createChild("label");
+        const checkboxElement = labelElement.createChild("input");
+        checkboxElement.id = "metrics-override-checkbox";
+        checkboxElement.type = "checkbox";
+        checkboxElement.checked = !metrics || (metrics.width && metrics.height && metrics.fontScaleFactor);
+        checkboxElement.addEventListener("click", this._onMetricsCheckboxClicked.bind(this), false);
+        this._metricsCheckboxElement = checkboxElement;
+        labelElement.appendChild(document.createTextNode(WebInspector.UIString("Override device metrics")));
+
+        const metricsSectionElement = this._createDeviceMetricsElement(metrics);
+        p.appendChild(metricsSectionElement);
+        this._metricsSectionElement = metricsSectionElement;
+
+        this._setDeviceMetricsOverride(metrics, false, true);
+
+        return p;
+    },
+
+    _onMetricsCheckboxClicked: function()
+    {
+        if (this._metricsCheckboxElement.checked) {
+            this._metricsSectionElement.removeStyleClass("hidden");
+            var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput(this._widthOverrideElement.value, this._heightOverrideElement.value, this._fontScaleFactorOverrideElement.value);
+            if (metrics && metrics.isValid() && metrics.width && metrics.height)
+                this._setDeviceMetricsOverride(metrics, false, false);
+            if (!this._widthOverrideElement.value)
+                this._widthOverrideElement.focus();
+        } else {
+            this._metricsSectionElement.addStyleClass("hidden");
+            if (WebInspector.settings.deviceMetrics.get())
+                WebInspector.settings.deviceMetrics.set("");
+        }
+    },
+
+    _applyDeviceMetricsUserInput: function()
+    {
+        this._setDeviceMetricsOverride(WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput(this._widthOverrideElement.value.trim(), this._heightOverrideElement.value.trim(), this._fontScaleFactorOverrideElement.value.trim()), true, false);
+    },
+
+    /**
+     * @param {?WebInspector.UserAgentSupport.DeviceMetrics} metrics
+     * @param {boolean} userInputModified
+     */
+    _setDeviceMetricsOverride: function(metrics, userInputModified, updateCheckbox)
+    {
+        function setValid(condition, element)
+        {
+            if (condition)
+                element.removeStyleClass("error-input");
+            else
+                element.addStyleClass("error-input");
+        }
+
+        setValid(metrics && metrics.isWidthValid(), this._widthOverrideElement);
+        setValid(metrics && metrics.isHeightValid(), this._heightOverrideElement);
+        setValid(metrics && metrics.isFontScaleFactorValid(), this._fontScaleFactorOverrideElement);
+
+        if (!metrics)
+            return;
+
+        if (!userInputModified) {
+            this._widthOverrideElement.value = metrics.widthToInput();
+            this._heightOverrideElement.value = metrics.heightToInput();
+            this._fontScaleFactorOverrideElement.value = metrics.fontScaleFactorToInput();
+        }
+
+        if (metrics.isValid()) {
+            var value = metrics.toSetting();
+            if (value !== WebInspector.settings.deviceMetrics.get())
+                WebInspector.settings.deviceMetrics.set(value);
+        }
+
+        if (this._metricsCheckboxElement && updateCheckbox) {
+            this._metricsCheckboxElement.checked = !!metrics.toSetting();
+            this._onMetricsCheckboxClicked();
+        }
+    },
+
+    /**
+     * @param {WebInspector.UserAgentSupport.DeviceMetrics} metrics
+     */
+    _createDeviceMetricsElement: function(metrics)
+    {
+        var fieldsetElement = document.createElement("fieldset");
+        fieldsetElement.id = "metrics-override-section";
+
+        function createInput(parentElement, id, defaultText)
+        {
+            var element = parentElement.createChild("input");
+            element.id = id;
+            element.maxLength = 6;
+            element.style.width = "48px";
+            element.value = defaultText;
+            element.addEventListener("blur", this._applyDeviceMetricsUserInput.bind(this), false);
+            return element;
+        }
+
+        var tableElement = fieldsetElement.createChild("table");
+
+        var rowElement = tableElement.createChild("tr");
+        var cellElement = rowElement.createChild("td");
+        cellElement.appendChild(document.createTextNode(WebInspector.UIString("Screen resolution:")));
+        cellElement = rowElement.createChild("td");
+        this._widthOverrideElement = createInput.call(this, cellElement, "metrics-override-width", String(metrics.width || screen.width));
+        cellElement.appendChild(document.createTextNode(" \u00D7 "));
+        this._heightOverrideElement = createInput.call(this, cellElement, "metrics-override-height", String(metrics.height || screen.height));
+
+        rowElement = tableElement.createChild("tr");
+        cellElement = rowElement.createChild("td");
+        cellElement.appendChild(document.createTextNode(WebInspector.UIString("Font scale factor:")));
+        cellElement = rowElement.createChild("td");
+        this._fontScaleFactorOverrideElement = createInput.call(this, cellElement, "metrics-override-font-scale", String(metrics.fontScaleFactor || 1));
+        return fieldsetElement;
     }
 }
 
diff --git a/Source/WebCore/inspector/front-end/UserAgentSupport.js b/Source/WebCore/inspector/front-end/UserAgentSupport.js
new file mode 100644 (file)
index 0000000..ddf7dac
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @constructor
+ */
+WebInspector.UserAgentSupport = function()
+{
+    if (WebInspector.settings.deviceMetrics.get())
+        this._deviceMetricsSettingChanged();
+    WebInspector.settings.deviceMetrics.addChangeListener(this._deviceMetricsSettingChanged, this);
+}
+
+/**
+ * @constructor
+ * @param {number} width
+ * @param {number} height
+ * @param {number} fontScaleFactor
+ */
+WebInspector.UserAgentSupport.DeviceMetrics = function(width, height, fontScaleFactor)
+{
+    this.width = width;
+    this.height = height;
+    this.fontScaleFactor = fontScaleFactor;
+}
+
+/**
+ * @return {WebInspector.UserAgentSupport.DeviceMetrics}
+ */
+WebInspector.UserAgentSupport.DeviceMetrics.parseSetting = function(value)
+{
+    if (value) {
+        var splitMetrics = value.split("x");
+        if (splitMetrics.length === 3)
+            return new WebInspector.UserAgentSupport.DeviceMetrics(parseInt(splitMetrics[0], 10), parseInt(splitMetrics[1], 10), parseFloat(splitMetrics[2]));
+    }
+    return new WebInspector.UserAgentSupport.DeviceMetrics(0, 0, 1);
+}
+
+/**
+ * @return {?WebInspector.UserAgentSupport.DeviceMetrics}
+ */
+WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput = function(widthString, heightString, fontScaleFactorString)
+{
+    function isUserInputValid(value, isInteger)
+    {
+        if (!value)
+            return true;
+        return isInteger ? /^[0]*[1-9][\d]*$/.test(value) : /^[0]*([1-9][\d]*(\.\d+)?|\.\d+)$/.test(value);
+    }
+
+    if (!widthString ^ !heightString)
+        return null;
+
+    var isWidthValid = isUserInputValid(widthString, true);
+    var isHeightValid = isUserInputValid(heightString, true);
+    var isFontScaleFactorValid = isUserInputValid(fontScaleFactorString, false);
+
+    if (!isWidthValid && !isHeightValid && !isFontScaleFactorValid)
+        return null;
+
+    var width = isWidthValid ? parseInt(widthString || "0", 10) : -1;
+    var height = isHeightValid ? parseInt(heightString || "0", 10) : -1;
+    var fontScaleFactor = isFontScaleFactorValid ? parseFloat(fontScaleFactorString) : -1;
+
+    return new WebInspector.UserAgentSupport.DeviceMetrics(width, height, fontScaleFactor);
+}
+
+WebInspector.UserAgentSupport.DeviceMetrics.prototype = {
+    /**
+     * @return {boolean}
+     */
+    isValid: function()
+    {
+        return this.isWidthValid() && this.isHeightValid() && this.isFontScaleFactorValid();
+    },
+
+    /**
+     * @return {boolean}
+     */
+    isWidthValid: function()
+    {
+        return this.width >= 0;
+    },
+
+    /**
+     * @return {boolean}
+     */
+    isHeightValid: function()
+    {
+        return this.height >= 0;
+    },
+
+    /**
+     * @return {boolean}
+     */
+    isFontScaleFactorValid: function()
+    {
+        return this.fontScaleFactor > 0;
+    },
+
+    /**
+     * @return {string}
+     */
+    toSetting: function()
+    {
+        if (!this.isValid())
+            return "";
+
+        return this.width && this.height ? this.width + "x" + this.height + "x" + this.fontScaleFactor : "";
+    },
+
+    /**
+     * @return {string}
+     */
+    widthToInput: function()
+    {
+        return this.isWidthValid() && this.width ? String(this.width) : "";
+    },
+
+    /**
+     * @return {string}
+     */
+    heightToInput: function()
+    {
+        return this.isHeightValid() && this.height ? String(this.height) : "";
+    },
+
+    /**
+     * @return {string}
+     */
+    fontScaleFactorToInput: function()
+    {
+        return this.isFontScaleFactorValid() && this.fontScaleFactor ? String(this.fontScaleFactor) : "";
+    }
+}
+
+WebInspector.UserAgentSupport.prototype = {
+    _deviceMetricsSettingChanged: function()
+    {
+        var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(WebInspector.settings.deviceMetrics.get());
+        if (metrics.isValid())
+            PageAgent.setDeviceMetricsOverride(metrics.width, metrics.height, metrics.fontScaleFactor);
+    }
+}
\ No newline at end of file
index 3c38d18..38963e5 100644 (file)
     <file>treeoutline.js</file>
     <file>UISourceCode.js</file>
     <file>UIUtils.js</file>
+    <file>UserAgentSupport.js</file>
     <file>UserMetrics.js</file>
     <file>utilities.js</file>
     <file>View.js</file>
index 7816696..ec0cbef 100644 (file)
@@ -121,13 +121,13 @@ body:not(.platform-mac) .help-close-button {
     -webkit-user-select: auto;
 }
 
-.help-table th {
+.help-table > tr > th {
     padding-top: 6px;
     text-align: left;
     color: yellow;
 }
 
-.help-table td {
+.help-table > tr > td {
     white-space: nowrap;
     vertical-align: top;
     width: 50%;
@@ -196,6 +196,10 @@ body.platform-mac .help-key {
     color: rgb(150, 150, 150);
 }
 
+#resolution-override-section {
+    margin-left: 13px;
+}
+
 .help-content input[type=checkbox] {
     height: 13px;
     width: 13px;
index 628a97c..0d9bfe0 100644 (file)
@@ -39,6 +39,10 @@ input[type="search"]:focus, input[type="text"]:focus {
     bottom: 0;
 }
 
+.hidden {
+    display: none;
+}
+
 #toolbar {
     position: absolute;
     top: 0;
@@ -925,6 +929,10 @@ body.platform-linux .monospace, body.platform-linux .source-code {
     color: red;
 }
 
+.error-input {
+    background-color: rgb(220, 130, 130);
+}
+
 .auto-complete-text, .editing .auto-complete-text {
     color: rgb(128, 128, 128) !important;
     -webkit-user-select: none;
index 04fdeb0..a4d0348 100644 (file)
@@ -73,6 +73,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     <script type="text/javascript" src="ResourceCategory.js"></script>
     <script type="text/javascript" src="TimelineManager.js"></script>
     <script type="text/javascript" src="TimelineModel.js"></script>
+    <script type="text/javascript" src="UserAgentSupport.js"></script>
     <script type="text/javascript" src="Database.js"></script>
     <script type="text/javascript" src="DOMStorage.js"></script>
     <script type="text/javascript" src="DOMStorageItemsView.js"></script>
index 312d09f..27510ad 100644 (file)
@@ -378,7 +378,8 @@ WebInspector.doLoadedDone = function()
     DebuggerAgent.supportsNativeBreakpoints(WebInspector._initializeCapability.bind(WebInspector, "nativeInstrumentationEnabled", null));
     ProfilerAgent.causesRecompilation(WebInspector._initializeCapability.bind(WebInspector, "profilerCausesRecompilation", null));
     ProfilerAgent.isSampling(WebInspector._initializeCapability.bind(WebInspector, "samplingCPUProfiler", null));
-    ProfilerAgent.hasHeapProfiler(WebInspector._initializeCapability.bind(WebInspector, "heapProfilerPresent", WebInspector._doLoadedDoneWithCapabilities.bind(WebInspector)));
+    ProfilerAgent.hasHeapProfiler(WebInspector._initializeCapability.bind(WebInspector, "heapProfilerPresent", null));
+    PageAgent.canOverrideDeviceMetrics(WebInspector._initializeCapability.bind(WebInspector, "canOverrideDeviceMetrics", WebInspector._doLoadedDoneWithCapabilities.bind(WebInspector)));
 }
 
 WebInspector._doLoadedDoneWithCapabilities = function()
@@ -412,6 +413,7 @@ WebInspector._doLoadedDoneWithCapabilities = function()
 
     this.cssModel = new WebInspector.CSSStyleModel();
     this.timelineManager = new WebInspector.TimelineManager();
+    this.userAgentSupport = new WebInspector.UserAgentSupport();
     InspectorBackend.registerDatabaseDispatcher(new WebInspector.DatabaseDispatcher());
     InspectorBackend.registerDOMStorageDispatcher(new WebInspector.DOMStorageDispatcher());