Bug 561870 - Enforce min/max limits on viewport values [r=mfinkle]
--- a/mobile/chrome/content/Util.js
+++ b/mobile/chrome/content/Util.js
@@ -36,16 +36,24 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
let Ci = Components.interfaces;
+// Blindly copied from Safari documentation for now.
+const kViewportMinScale = 0;
+const kViewportMaxScale = 10;
+const kViewportMinWidth = 200;
+const kViewportMaxWidth = 10000;
+const kViewportMinHeight = 223;
+const kViewportMaxHeight = 10000;
+
// -----------------------------------------------------------
// General util/convenience tools
//
let Util = {
bind: function bind(f, thisObj) {
return function() {
return f.apply(thisObj, arguments);
@@ -128,28 +136,37 @@ let Util = {
if (browser.contentDocument instanceof XULDocument)
return { reason: "chrome", result: true, scale: 1.0, autoSize: true, allowZoom: false };
// viewport details found here
// http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html
// http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html
+ // Note: These values will be NaN if parseFloat or parseInt doesn't find a number.
+ // Remember that NaN is contagious: Math.max(1, NaN) == Math.min(1, NaN) == NaN.
let viewportScale = parseFloat(windowUtils.getDocumentMetadata("viewport-initial-scale"));
let viewportMinScale = parseFloat(windowUtils.getDocumentMetadata("viewport-minimum-scale"));
let viewportMaxScale = parseFloat(windowUtils.getDocumentMetadata("viewport-maximum-scale"));
let viewportWidthStr = windowUtils.getDocumentMetadata("viewport-width");
let viewportHeightStr = windowUtils.getDocumentMetadata("viewport-height");
+ viewportScale = Util.clamp(viewportScale, kViewportMinScale, kViewportMaxScale);
+ viewportMinScale = Util.clamp(viewportMinScale, kViewportMinScale, kViewportMaxScale);
+ viewportMaxScale = Util.clamp(viewportMaxScale, kViewportMinScale, kViewportMaxScale);
+
// If initial scale is 1.0 and width is not set, assume width=device-width
if (viewportScale == 1.0 && !viewportWidthStr)
viewportWidthStr = "device-width";
let viewportWidth = viewportWidthStr == "device-width" ? window.innerWidth : parseInt(viewportWidthStr);
let viewportHeight = viewportHeightStr == "device-height" ? window.innerHeight : parseInt(viewportHeightStr);
+
+ viewportWidth = Util.clamp(viewportWidth, kViewportMinWidth, kViewportMaxWidth);
+ viewportHeight = Util.clamp(viewportHeight, kViewportMinHeight, kViewportMaxHeight);
// If (scale * width) < device-width, increase the width (bug 561413).
let maxInitialScale = viewportScale || viewportMaxScale;
if (maxInitialScale && viewportWidth)
viewportWidth = Math.max(viewportWidth, window.innerWidth / maxInitialScale);
if (viewportScale > 0 || viewportWidth > 0 || viewportHeight > 0 || viewportMinScale > 0 || viewportMaxScale > 0) {
return {
@@ -163,16 +180,20 @@ let Util = {
autoSize: viewportWidthStr == "device-width" || viewportHeightStr == "device-height",
allowZoom: windowUtils.getDocumentMetadata("viewport-user-scalable") != "no"
};
}
return { reason: "", result: false, allowZoom: true };
},
+ clamp: function(num, min, max) {
+ return Math.max(min, Math.min(max, num));
+ },
+
/**
* Determines whether a home page override is needed.
* Returns:
* "new profile" if this is the first run with a new profile.
* "new version" if this is the first run with a build with a different
* Gecko milestone (i.e. right after an upgrade).
* "none" otherwise.
*/
--- a/mobile/chrome/tests/Makefile.in
+++ b/mobile/chrome/tests/Makefile.in
@@ -64,12 +64,13 @@ include $(topsrcdir)/config/rules.mk
browser_viewport_00.html \
browser_viewport_01.html \
browser_viewport_02.html \
browser_viewport_03.html \
browser_viewport_04.html \
browser_viewport_05.html \
browser_viewport_06.html \
browser_viewport_07.html \
+ browser_viewport_08.html \
$(NULL)
libs:: $(_BROWSER_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/mobile/chrome/tests/browser_viewport.js
+++ b/mobile/chrome/tests/browser_viewport.js
@@ -52,17 +52,18 @@ let isLoading = function() { return !wor
let testData = [
{ width: undefined, scale: undefined },
{ width: deviceWidth, scale: 1 },
{ width: 320, scale: 1 },
{ width: undefined, scale: 1, disableZoom: true },
{ width: 200, scale: undefined },
{ width: 2000, minScale: 0.75 },
{ width: 100, maxScale: 2 },
- { width: 2000, scale: 0.75 }
+ { width: 2000, scale: 0.75 },
+ { width: 10000, scale: 10 }
];
//------------------------------------------------------------------------------
// Entry point (must be named "test")
function test() {
// This test is async
waitForExplicitFinish();
new file mode 100644
--- /dev/null
+++ b/mobile/chrome/tests/browser_viewport_08.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>Browser Viewport Page 08</title>
+ <meta name="viewport" content="width=20000, initial-scale=100"/>
+</head>
+<body>
+ <p>Browser Viewport Page 08</p>
+ <p>width=20000, initial-scale=100</p>
+</body>
+</html>