Bug 708746 - Part 2: Key viewport metadata to each content document instead of each tab. r=mbrubeck a=akeybl
authorPatrick Walton <pwalton@mozilla.com>
Fri, 06 Jan 2012 16:42:44 -0800
changeset 84960 77e173e171088f1f096cca951a385aea57ac5cef
parent 84959 5a7e2ca2c8c56673b521ad9dbd4fde28a8246977
child 84961 4cf9a42a8de71048f01cedbf75d8d6db5eefd8be
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck, akeybl
bugs708746
milestone11.0a2
Bug 708746 - Part 2: Key viewport metadata to each content document instead of each tab. r=mbrubeck a=akeybl
mobile/android/chrome/content/browser.js
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1261,31 +1261,28 @@ nsBrowserAccess.prototype = {
   isTabContentWindow: function(aWindow) {
     return BrowserApp.getBrowserForWindow(aWindow) != null;
   }
 };
 
 
 let gTabIDFactory = 0;
 
-const kDefaultMetadata = { autoSize: false, allowZoom: true, autoScale: true };
-
 // track the last known screen size so that new tabs
 // get created with the right size rather than being 1x1
 let gScreenWidth = 1;
 let gScreenHeight = 1;
 
 function Tab(aURL, aParams) {
   this.browser = null;
   this.vbox = null;
   this.id = 0;
   this.agentMode = UA_MODE_MOBILE;
   this.lastHost = null;
   this.create(aURL, aParams);
-  this._metadata = null;
   this._viewport = { x: 0, y: 0, width: gScreenWidth, height: gScreenHeight, offsetX: 0, offsetY: 0,
                      pageWidth: gScreenWidth, pageHeight: gScreenHeight, zoom: 1.0 };
   this.viewportExcess = { x: 0, y: 0 };
   this.userScrollPos = { x: 0, y: 0 };
   this._pluginsToPlay = [];
   this._pluginOverlayShowing = false;
 }
 
@@ -1845,32 +1842,32 @@ Tab.prototype = {
   },
 
   OnHistoryPurge: function(aNumEntries) {
     this._sendHistoryEvent("Purge", -1, null);
     return true;
   },
 
   get metadata() {
-    return this._metadata || kDefaultMetadata;
+    return ViewportHandler.getMetadataForDocument(this.browser.contentDocument);
   },
 
   /** Update viewport when the metadata changes. */
   updateViewportMetadata: function updateViewportMetadata(aMetadata) {
     if (aMetadata && aMetadata.autoScale) {
       let scaleRatio = aMetadata.scaleRatio = ViewportHandler.getScaleRatio();
 
       if ("defaultZoom" in aMetadata && aMetadata.defaultZoom > 0)
         aMetadata.defaultZoom *= scaleRatio;
       if ("minZoom" in aMetadata && aMetadata.minZoom > 0)
         aMetadata.minZoom *= scaleRatio;
       if ("maxZoom" in aMetadata && aMetadata.maxZoom > 0)
         aMetadata.maxZoom *= scaleRatio;
     }
-    this._metadata = aMetadata;
+    ViewportHandler.setMetadataForDocument(this.browser.contentDocument, aMetadata);
     this.updateViewportSize();
     this.updateViewport(true);
   },
 
   /** Update viewport when the metadata or the window size changes. */
   updateViewportSize: function updateViewportSize() {
     let browser = this.browser;
     if (!browser)
@@ -2875,16 +2872,21 @@ var XPInstallObserver = {
 const kViewportMinScale  = 0;
 const kViewportMaxScale  = 10;
 const kViewportMinWidth  = 200;
 const kViewportMaxWidth  = 10000;
 const kViewportMinHeight = 223;
 const kViewportMaxHeight = 10000;
 
 var ViewportHandler = {
+  // The cached viewport metadata for each document. We tie viewport metadata to each document
+  // instead of to each tab so that we don't have to update it when the document changes. Using an
+  // ES6 weak map lets us avoid leaks.
+  _metadata: new WeakMap(),
+
   init: function init() {
     addEventListener("DOMWindowCreated", this, false);
     addEventListener("DOMMetaAdded", this, false);
     addEventListener("DOMContentLoaded", this, false);
     addEventListener("pageshow", this, false);
     addEventListener("resize", this, false);
   },
 
@@ -3021,16 +3023,43 @@ var ViewportHandler = {
     // For very high-density displays like the iPhone 4, calculate an integer ratio.
     return Math.floor(dpi / 150);
   },
 
   get displayDPI() {
     let utils = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     delete this.displayDPI;
     return this.displayDPI = utils.displayDPI;
+  },
+
+  /**
+   * Returns the viewport metadata for the given document, or the default metrics if no viewport
+   * metadata is available for that document.
+   */
+  getMetadataForDocument: function getMetadataForDocument(aDocument) {
+    let metadata = this._metadata.get(aDocument, this.getDefaultMetadata());
+    return metadata;
+  },
+
+  /** Updates the saved viewport metadata for the given content document. */
+  setMetadataForDocument: function setMetadataForDocument(aDocument, aMetadata) {
+    if (!aMetadata)
+      this._metadata.delete(aDocument);
+    else
+      this._metadata.set(aDocument, aMetadata);
+  },
+
+  /** Returns the default viewport metadata for a document. */
+  getDefaultMetadata: function getDefaultMetadata() {
+    return {
+      autoSize: false,
+      allowZoom: true,
+      autoScale: true,
+      scaleRatio: ViewportHandler.getScaleRatio()
+    };
   }
 };
 
 /**
  * Handler for blocked popups, triggered by DOMUpdatePageReport events in browser.xml
  */
 var PopupBlockerObserver = {
   onUpdatePageReport: function onUpdatePageReport(aEvent) {