Bug 604765 - Change viewport size based on page size [r=mbrubeck]
authorWes Johnston <wjohnston@mozilla.com>
Thu, 06 Jan 2011 13:17:47 -0800
changeset 67221 8da2c6e41eea107fa7fe9428deb46d8c8fa946d5
parent 67220 9d54ca82e3c116c721d0805eab0709fc2a14641c
child 67222 54c5e6dd4596977b1fc7522374130b55e7851cc4
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs604765
Bug 604765 - Change viewport size based on page size [r=mbrubeck]
mobile/chrome/content/browser.js
mobile/chrome/tests/browser_viewport.js
mobile/chrome/tests/browser_viewport.sjs
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -52,21 +52,22 @@ let Cc = Components.classes;
 let Ci = Components.interfaces;
 let Cu = Components.utils;
 let Cr = Components.results;
 
 function getBrowser() {
   return Browser.selectedBrowser;
 }
 
-const kDefaultBrowserWidth = 980;
 const kBrowserFormZoomLevelMin = 0.8;
 const kBrowserFormZoomLevelMax = 2.0;
 const kBrowserViewZoomLevelPrecision = 10000;
 
+const kDefaultBrowserWidth = 800;
+const kFallbackBrowserWidth = 980;
 const kDefaultMetadata = { autoSize: false, allowZoom: true, autoScale: true };
 
 // Override sizeToContent in the main window. It breaks things (bug 565887)
 window.sizeToContent = function() {
   Cu.reportError("window.sizeToContent is not allowed in this window");
 }
 
 #ifdef MOZ_CRASH_REPORTER
@@ -2289,16 +2290,18 @@ ProgressController.prototype = {
       this._tab.resetZoomLevel();
 
       if (this._tab == Browser.selectedTab) {
         // We're about to have new page content, so scroll the content area
         // to the top so the new paints will draw correctly.
         // (background tabs are delayed scrolled to top in _documentStop)
         Browser.scrollContentToTop({ x: 0 });
       }
+      this._tab.useFallbackWidth = false;
+      this._tab.updateViewportSize();
     }
 
     let event = document.createEvent("UIEvents");
     event.initUIEvent("URLChanged", true, false, window, locationHasChanged);
     this.browser.dispatchEvent(event);
   },
 
   /**
@@ -2444,16 +2447,17 @@ function Tab(aURI, aParams) {
   this._id = null;
   this._browser = null;
   this._notification = null;
   this._state = null;
   this._listener = null;
   this._loading = false;
   this._chromeTab = null;
   this._metadata = null;
+  this.useFallbackWidth = false;
   this.owner = null;
 
   // Set to 0 since new tabs that have not been viewed yet are good tabs to
   // toss if app needs more memory.
   this.lastSelected = 0;
 
   // aParams is an object that contains some properties for the initial tab
   // loading like flags, a referrerURI, a charset or even a postData.
@@ -2538,17 +2542,17 @@ Tab.prototype = {
       let validW = viewportW > 0;
       let validH = viewportH > 0;
 
       if (validW && !validH) {
         viewportH = viewportW * (screenH / screenW);
       } else if (!validW && validH) {
         viewportW = viewportH * (screenW / screenH);
       } else if (!validW && !validH) {
-        viewportW = kDefaultBrowserWidth;
+        viewportW = this.useFallbackWidth ? kFallbackBrowserWidth : kDefaultBrowserWidth;
         viewportH = kDefaultBrowserWidth * (screenH / screenW);
       }
     }
 
     browser.setWindowSize(viewportW, viewportH);
   },
 
   restoreViewportPosition: function restoreViewportPosition(aOldWidth, aNewWidth) {
@@ -2638,20 +2642,20 @@ Tab.prototype = {
 
     // Append the browser to the document, which should start the page load
     notification.appendChild(browser);
     Elements.browsers.insertBefore(notification, aInsertBefore);
 
     // stop about:blank from loading
     browser.stop();
 
-    let self = this;
-    browser.messageManager.addMessageListener("MozScrolledAreaChanged", function() {
-      self.updateDefaultZoomLevel();
-    });
+    browser.messageManager.addMessageListener("MozScrolledAreaChanged", (function() {
+      // ensure that the browser's contentDocumentWidth property adjusts first
+      setTimeout(this.scrolledAreaChanged.bind(this), 0);
+    }).bind(this));
 
     // Attach a separate progress listener to the browser
     let flags = Ci.nsIWebProgress.NOTIFY_LOCATION |
                 Ci.nsIWebProgress.NOTIFY_SECURITY |
                 Ci.nsIWebProgress.NOTIFY_STATE_NETWORK |
                 Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT;
     this._listener = new ProgressController(this);
     browser.webProgress.addProgressListener(this._listener, flags);
@@ -2691,16 +2695,25 @@ Tab.prototype = {
     return rounded || 1.0;
   },
 
   /** Record the initial zoom level when a page first loads. */
   resetZoomLevel: function resetZoomLevel() {
     this._defaultZoomLevel = this._browser.scale;
   },
 
+  scrolledAreaChanged: function scrolledAreaChanged() {
+    this.updateDefaultZoomLevel();
+
+    if (!this.useFallbackWidth && this._browser.contentDocumentWidth > kDefaultBrowserWidth)
+      this.useFallbackWidth = true;
+
+    this.updateViewportSize();
+  },
+
   /**
    * Recalculate default zoom level when page size changes, and update zoom
    * level if we are at default.
    */
   updateDefaultZoomLevel: function updateDefaultZoomLevel() {
     let browser = this._browser;
     if (!browser)
       return;
--- a/mobile/chrome/tests/browser_viewport.js
+++ b/mobile/chrome/tests/browser_viewport.js
@@ -36,16 +36,18 @@
  * 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 baseURI = "http://mochi.test:8888/browser/mobile/chrome/";
 let testURL_blank = baseURI + "browser_blank_01.html";
 
+const DEFAULT_WIDTH = 800;
+
 function testURL(n) {
   return baseURI + "browser_viewport.sjs?" + encodeURIComponent(gTestData[n].metadata);
 }
 
 function scaleRatio(n) {
   if ("scaleRatio" in gTestData[n])
     return gTestData[n].scaleRatio;
   return 150; // Default value matches our main target hardware (N900, Nexus One, etc.)
@@ -66,17 +68,17 @@ let loadURL = function loadURL(aPageURL,
       });
     }
   });
 
   BrowserUI.goToURI(aPageURL);
 };
 
 let gTestData = [
-  { metadata: "", width: 980, scale: 1 },
+  { metadata: "", width: DEFAULT_WIDTH, scale: 1 },
   { metadata: "width=device-width, initial-scale=1", width: 533.33, scale: 1.5 },
   { metadata: "width=device-width", width: 533.33, scale: 1.5 },
   { metadata: "width=device-width, initial-scale=1", scaleRatio: 100, width: 800, scale: 1 },
   { metadata: "width=320, initial-scale=1", width: 533.33, scale: 1.5 },
   { metadata: "initial-scale=1.0, user-scalable=no", width: 533.33, scale: 1.5, disableZoom: true },
   { metadata: "initial-scale=1.0, user-scalable=0", width: 533.33, scale: 1.5, disableZoom: true },
   { metadata: "initial-scale=1.0, user-scalable=false", width: 533.33, scale: 1.5, disableZoom: true },
   { metadata: "initial-scale=1.0, user-scalable=NO", width: 533.33, scale: 1.5, disableZoom: false }, // values are case-sensitive
@@ -87,17 +89,21 @@ let gTestData = [
   { metadata: "width=20000, initial-scale=100", width: 10000, scale: 4 },
   { metadata: "XHTML", width: 533.33, scale: 1.5, disableZoom: false },
   /* testing spaces between arguments (bug 572696) */
   { metadata: "width= 2000, minimum-scale=0.75", width: 2000, scale: 1.125 },
   { metadata: "width = 2000, minimum-scale=0.75", width: 2000, scale: 1.125 },
   { metadata: "width = 2000 , minimum-scale=0.75", width: 2000, scale: 1.125 },
   { metadata: "width = 2000 , minimum-scale =0.75", width: 2000, scale: 1.125 },
   { metadata: "width = 2000 , minimum-scale = 0.75", width: 2000, scale: 1.125 },
-  { metadata: "width =  2000   ,    minimum-scale      =       0.75", width: 2000, scale: 1.125 }
+  { metadata: "width =  2000   ,    minimum-scale      =       0.75", width: 2000, scale: 1.125 },
+  /* testing opening and switching between pages without a viewport */
+  { metadata: "style=width:400px;margin:0px;", width: DEFAULT_WIDTH, scale: 1 },
+  { metadata: "style=width:1000px;margin:0px;", width: 980, scale: window.innerWidth/1000 },
+  { metadata: "style=width:800px;margin:0px;", width: DEFAULT_WIDTH, scale: 1 },
 ];
 
 
 
 //------------------------------------------------------------------------------
 // Entry point (must be named "test")
 function test() {
   // This test is async
@@ -118,19 +124,23 @@ function startTest(n) {
 
 function verifyBlank(n) {
   return function() {
     // Do sanity tests
     let uri = currentTab.browser.currentURI.spec;
     is(uri, testURL_blank, "URL Matches blank page " + n);
 
     // Check viewport settings
-    is(currentTab.browser.contentWindowWidth, 980, "Normal 'browser' width is 980 pixels");
-
-    loadURL(testURL(n), verifyTest(n), gTestData[n].scale);
+    waitFor(function() {
+      is(currentTab.browser.contentWindowWidth, DEFAULT_WIDTH, "Normal 'browser' width is " + DEFAULT_WIDTH + " pixels");
+      loadURL(testURL(n), verifyTest(n), gTestData[n].scale);
+    }, function() {
+      return currentTab.browser.scale == 1;
+    })
+    
   }
 }
 
 function is_approx(actual, expected, fuzz, description) {
   ok(Math.abs(actual - expected) <= fuzz,
      description + " [got " + actual + ", expected " + expected + "]");
 }
 
--- a/mobile/chrome/tests/browser_viewport.sjs
+++ b/mobile/chrome/tests/browser_viewport.sjs
@@ -35,28 +35,36 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 function handleRequest(request, response) {
   response.setStatusLine(request.httpVersion, 200, "OK");
   response.setHeader("Content-Type", "text/html", false);
 
   let metadata = "";
+  let style = "";
   let xhtml = false;
   let query = decodeURIComponent(request.queryString || "");
 
   switch (query) {
     case "XHTML":
       xhtml = true;
       break;
     default:
       metadata = query;
       break;
   }
+  if (/^style/.test(query))
+    style = query.replace("style=", "");
 
   if (xhtml) {
     response.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
     response.write("<!DOCTYPE html PUBLIC \"-//WAPFORUM//DTD XHTML Mobile 1.0//EN\" \"http://www.wapforum.org/DTD/xhtml-mobile10.dtd\">");
   }
   response.write("<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>Browser Viewport Test</title>");
-  response.write("<meta name=\"viewport\" content=\"" + metadata + "\"/>");
-  response.write("</head><body>" + query + "</body></html>");
+  if (metadata)
+    response.write("<meta name=\"viewport\" content=\"" + metadata + "\"/>");
+  response.write("</head><body");
+
+  if (style)
+    response.write(" style=\"" + style + "\"");
+  response.write(">" + query + "</body></html>");
 }