Bug 707571 (part 1) - Make viewport calculations respect zoom limits set by the page [r=mfinkle]
authorMatt Brubeck <mbrubeck@mozilla.com>
Fri, 18 May 2012 08:24:27 -0700
changeset 94370 93318e2225d61910ab04a3be45970a5f5f803535
parent 94369 fba69d39cea702108ed3d08dde9700ad0758a85e
child 94371 59336341809918452d79b277cfa7a21e08788a44
push id22712
push userryanvm@gmail.com
push dateSat, 19 May 2012 00:52:01 +0000
treeherdermozilla-central@642d1a36702f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs707571
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 707571 (part 1) - Make viewport calculations respect zoom limits set by the page [r=mfinkle]
mobile/android/app/mobile.js
mobile/android/chrome/content/browser.js
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -32,48 +32,28 @@
  * 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 ***** */
 
 #filter substitution
 
-// For browser.xml binding
-//
-// cacheRatio* is a ratio that determines the amount of pixels to cache. The
-// ratio is multiplied by the viewport width or height to get the displayport's
-// width or height, respectively.
-//
-// (divide integer value by 1000 to get the ratio)
-//
-// For instance: cachePercentageWidth is 1500
-//               viewport height is 500
-//               => display port height will be 500 * 1.5 = 750
-//
-pref("toolkit.browser.cacheRatioWidth", 2000);
-pref("toolkit.browser.cacheRatioHeight", 3000);
-
 // How long before a content view (a handle to a remote scrollable object)
 // expires.
 pref("toolkit.browser.contentViewExpire", 3000);
 
 pref("toolkit.defaultChromeURI", "chrome://browser/content/browser.xul");
 pref("browser.chromeURL", "chrome://browser/content/");
 
 pref("browser.tabs.warnOnClose", true);
 pref("browser.tabs.remote", true);
 
 pref("toolkit.screen.lock", false);
 
-// From libpref/src/init/all.js, extended to allow a slightly wider zoom range.
-pref("zoom.minPercent", 20);
-pref("zoom.maxPercent", 400);
-pref("toolkit.zoomManager.zoomValues", ".2,.3,.5,.67,.8,.9,1,1.1,1.2,1.33,1.5,1.7,2,2.4,3,4");
-
 // Mobile will use faster, less durable mode.
 pref("toolkit.storage.synchronous", 0);
 
 // Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
 pref("browser.viewport.scaleRatio", -1);
 pref("browser.viewport.desktopWidth", 980);
 
 #ifndef ANDROID
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2410,23 +2410,17 @@ Tab.prototype = {
     // Make sure the viewport height is not shorter than the window when
     // the page is zoomed out to show its full width. Note that before
     // we set the viewport width, the "full width" of the page isn't properly
     // defined, so that's why we have to call setBrowserSize twice - once
     // to set the width, and the second time to figure out the height based
     // on the layout at that width.
     let oldBrowserWidth = this.browserWidth;
     this.setBrowserSize(viewportW, viewportH);
-    let minScale = 1.0;
-    if (this.browser.contentDocument) {
-      // this may get run during a Viewport:Change message while the document
-      // has not yet loaded, so need to guard against a null document.
-      let [pageWidth, pageHeight] = this.getPageSize(this.browser.contentDocument, viewportW, viewportH);
-      minScale = gScreenWidth / pageWidth;
-    }
+    let minScale = this.clampZoom(kViewportMinScale);
     viewportH = Math.max(viewportH, screenH / minScale);
     this.setBrowserSize(viewportW, viewportH);
 
     // Avoid having the scroll position jump around after device rotation.
     let win = this.browser.contentWindow;
     this.userScrollPos.x = win.scrollX;
     this.userScrollPos.y = win.scrollY;
 
@@ -2438,29 +2432,59 @@ Tab.prototype = {
     // 3. screen size remains constant, but CSS viewport changes (meta viewport
     //    tag is added or removed)
     // 4. neither screen size nor CSS viewport changes
     //
     // In all of these cases, we maintain how much actual content is visible
     // within the screen width. Note that "actual content" may be different
     // with respect to CSS pixels because of the CSS viewport size changing.
     let zoomScale = (screenW * oldBrowserWidth) / (aOldScreenWidth * viewportW);
-    this.setResolution(this._zoom * zoomScale, false);
+    let zoom = this.clampZoom(this._zoom * zoomScale);
+    this.setResolution(zoom, false);
     this.sendViewportUpdate();
   },
 
   setBrowserSize: function(aWidth, aHeight) {
     this.browserWidth = aWidth;
+    this.browserHeight = aHeight;
 
     if (!this.browser.contentWindow)
       return;
     let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     cwu.setCSSViewport(aWidth, aHeight);
   },
 
+  /** Returns the scale at which the page width will equal the screen width. */
+  getPageZoom: function getPageZoom(aZoom) {
+    // this may get run during a Viewport:Change message while the document
+    // has not yet loaded, so need to guard against a null document.
+    let doc = this.browser.contentDocument;
+    if (!doc)
+      return 1;
+
+    let [pageWidth, pageHeight] = this.getPageSize(doc, this.browserWidth, this.browserHeight);
+    return gScreenWidth / pageWidth;
+  },
+
+  /** Takes a scale and restricts it based on this tab's zoom limits. */
+  clampZoom: function clampZoom(aZoom) {
+    let md = this.metadata;
+    if (!md.allowZoom)
+      return md.defaultZoom || this.getPageZoom();
+
+    let zoom = ViewportHandler.clamp(aZoom, kViewportMinScale, kViewportMaxScale);
+    if (md && md.minZoom)
+      zoom = Math.max(zoom, md.minZoom);
+    if (md && md.maxZoom)
+      zoom = Math.min(zoom, md.maxZoom);
+    zoom = Math.max(zoom, this.getPageZoom());
+
+    return zoom;
+  },
+
   getRequestLoadContext: function(aRequest) {
     if (aRequest && aRequest.notificationCallbacks) {
       try {
         return aRequest.notificationCallbacks.getInterface(Ci.nsILoadContext);
       } catch (ex) { }
     }
 
     if (aRequest && aRequest.loadGroup && aRequest.loadGroup.notificationCallbacks) {
@@ -3655,21 +3679,21 @@ var ViewportHandler = {
     let width = this.clamp(parseInt(widthStr), kViewportMinWidth, kViewportMaxWidth);
     let height = this.clamp(parseInt(heightStr), kViewportMinHeight, kViewportMaxHeight);
 
     let allowZoomStr = windowUtils.getDocumentMetadata("viewport-user-scalable");
     let allowZoom = !/^(0|no|false)$/.test(allowZoomStr); // WebKit allows 0, "no", or "false"
 
 
     if (scale == NaN && minScale == NaN && maxScale == NaN && allowZoomStr == "" && widthStr == "" && heightStr == "") {
-	// Only check for HandheldFriendly if we don't have a viewport meta tag
-	let handheldFriendly = windowUtils.getDocumentMetadata("HandheldFriendly");
-
-	if (handheldFriendly == "true")
-	    return { defaultZoom: 1, autoSize: true, allowZoom: true, autoScale: true };
+      // Only check for HandheldFriendly if we don't have a viewport meta tag
+      let handheldFriendly = windowUtils.getDocumentMetadata("HandheldFriendly");
+
+      if (handheldFriendly == "true")
+        return { defaultZoom: 1, autoSize: true, allowZoom: true, autoScale: true };
     }
 
     scale = this.clamp(scale, kViewportMinScale, kViewportMaxScale);
     minScale = this.clamp(minScale, kViewportMinScale, kViewportMaxScale);
     maxScale = this.clamp(maxScale, kViewportMinScale, kViewportMaxScale);
 
     // If initial scale is 1.0 and width is not set, assume width=device-width
     let autoSize = (widthStr == "device-width" ||