Bug 716575 (1/4) - Add a scriptable interface to GetViewportInfo [r=dbaron]
authorMatt Brubeck <mbrubeck@mozilla.com>
Wed, 22 Aug 2012 13:17:20 -0700
changeset 107776 ab874d12dcde471855f0a5de5b40d3400018f86d
parent 107775 e96de94819152214bc21bbdcd6bcd5222a948a97
child 107777 39803b4c2b9d0bf3011379ec6079b2cf5878af27
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-esr52@2704e441363f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs716575
milestone18.0a1
Bug 716575 (1/4) - Add a scriptable interface to GetViewportInfo [r=dbaron]
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
layout/base/nsLayoutUtils.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1532,20 +1532,27 @@ public:
 
   /**
    * Retrieve information about the viewport as a data structure.
    * This will return information in the viewport META data section
    * of the document. This can be used in lieu of ProcessViewportInfo(),
    * which places the viewport information in the document header instead
    * of returning it directly.
    *
+   * @param aDisplayWidth width of the on-screen display area for this
+   * document, in device pixels.
+   * @param aDisplayHeight height of the on-screen display area for this
+   * document, in device pixels.
+   *
    * NOTE: If the site is optimized for mobile (via the doctype), this
    * will return viewport information that specifies default information.
    */
-  static ViewportInfo GetViewportInfo(nsIDocument* aDocument);
+  static ViewportInfo GetViewportInfo(nsIDocument* aDocument,
+                                      uint32_t aDisplayWidth,
+                                      uint32_t aDisplayHeight);
 
   // Call EnterMicroTask when you're entering JS execution.
   // Usually the best way to do this is to use nsAutoMicroTask.
   static void EnterMicroTask() { ++sMicroTaskLevel; }
   static void LeaveMicroTask();
 
   static bool IsInMicroTask() { return sMicroTaskLevel != 0; }
   static uint32_t MicroTaskLevel() { return sMicroTaskLevel; }
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -5078,17 +5078,19 @@ static void ProcessViewportToken(nsIDocu
     aDocument->SetHeaderData(nsGkAtoms::viewport_user_scalable, value);
 }
 
 #define IS_SEPARATOR(c) ((c == '=') || (c == ',') || (c == ';') || \
                          (c == '\t') || (c == '\n') || (c == '\r'))
 
 /* static */
 ViewportInfo
-nsContentUtils::GetViewportInfo(nsIDocument *aDocument)
+nsContentUtils::GetViewportInfo(nsIDocument *aDocument,
+                                uint32_t aDisplayWidth,
+                                uint32_t aDisplayHeight)
 {
   ViewportInfo ret;
   ret.defaultZoom = 1.0;
   ret.autoSize = true;
   ret.allowZoom = true;
 
   nsAutoString viewport;
   aDocument->GetHeaderData(nsGkAtoms::viewport, viewport);
@@ -5167,82 +5169,57 @@ nsContentUtils::GetViewportInfo(nsIDocum
 
   if (widthStr.IsEmpty() &&
      (heightStr.EqualsLiteral("device-height") ||
           scaleFloat == 1.0))
   {
     autoSize = true;
   }
 
-  // XXXjwir3:
-  // See bug 706918, comment 23 for more information on this particular section
-  // of the code. We're using "screen size" in place of the size of the content
-  // area, because on mobile, these are close or equal. This will work for our
-  // purposes (bug 706198), but it will need to be changed in the future to be
-  // more correct when we bring the rest of the viewport code into platform.
-  // We actually want the size of the content area, in the event that we don't
-  // have any metadata about the width and/or height. On mobile, the screen size
-  // and the size of the content area are very close, or the same value.
-  // In XUL fennec, the content area is the size of the <browser> widget, but
-  // in native fennec, the content area is the size of the Gecko LayerView
-  // object.
-
-  // TODO:
-  // Once bug 716575 has been resolved, this code should be changed so that it
-  // does the right thing on all platforms.
-  nsresult result;
-  int32_t screenLeft, screenTop, screenWidth, screenHeight;
-  nsCOMPtr<nsIScreenManager> screenMgr =
-    do_GetService("@mozilla.org/gfx/screenmanager;1", &result);
-
-  nsCOMPtr<nsIScreen> screen;
-  screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
-  screen->GetRect(&screenLeft, &screenTop, &screenWidth, &screenHeight);
-
   uint32_t width = widthStr.ToInteger(&errorCode);
   if (NS_FAILED(errorCode)) {
     if (autoSize) {
-      width = screenWidth;
+      width = aDisplayWidth;
     } else {
       width = Preferences::GetInt("browser.viewport.desktopWidth", 0);
     }
   }
 
   width = NS_MIN(width, kViewportMaxWidth);
   width = NS_MAX(width, kViewportMinWidth);
 
   // Also recalculate the default zoom, if it wasn't specified in the metadata,
   // and the width is specified.
   if (scaleStr.IsEmpty() && !widthStr.IsEmpty()) {
-    scaleFloat = NS_MAX(scaleFloat, (float)(screenWidth/width));
+    scaleFloat = NS_MAX(scaleFloat, (float)(aDisplayWidth/width));
   }
 
   uint32_t height = heightStr.ToInteger(&errorCode);
 
   if (NS_FAILED(errorCode)) {
-    height = width * ((float)screenHeight / screenWidth);
+    height = width * ((float)aDisplayHeight / aDisplayWidth);
   }
 
   // If height was provided by the user, but width wasn't, then we should
   // calculate the width.
   if (widthStr.IsEmpty() && !heightStr.IsEmpty()) {
-    width = (uint32_t) ((height * screenWidth) / screenHeight);
+    width = (uint32_t) ((height * aDisplayWidth) / aDisplayHeight);
   }
 
   height = NS_MIN(height, kViewportMaxHeight);
   height = NS_MAX(height, kViewportMinHeight);
 
   // We need to perform a conversion, but only if the initial or maximum
   // scale were set explicitly by the user.
   if (!scaleStr.IsEmpty() && NS_SUCCEEDED(scaleErrorCode)) {
-    width = NS_MAX(width, (uint32_t)(screenWidth / scaleFloat));
-    height = NS_MAX(height, (uint32_t)(screenHeight / scaleFloat));
+    width = NS_MAX(width, (uint32_t)(aDisplayWidth / scaleFloat));
+    height = NS_MAX(height, (uint32_t)(aDisplayHeight / scaleFloat));
   } else if (!maxScaleStr.IsEmpty() && NS_SUCCEEDED(scaleMaxErrorCode)) {
-    width = NS_MAX(width, (uint32_t)(screenWidth / scaleMaxFloat));
-    height = NS_MAX(height, (uint32_t)(screenHeight / scaleMaxFloat));
+    width = NS_MAX(width, (uint32_t)(aDisplayWidth / scaleMaxFloat));
+    height = NS_MAX(height, (uint32_t)(aDisplayHeight / scaleMaxFloat));
   }
 
   bool allowZoom = true;
   nsAutoString userScalable;
   aDocument->GetHeaderData(nsGkAtoms::viewport_user_scalable, userScalable);
 
   if ((userScalable.EqualsLiteral("0")) ||
       (userScalable.EqualsLiteral("no")) ||
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -172,17 +172,17 @@ nsDOMWindowUtils::GetDocCharsetIsForced(
   *aIsForced = false;
 
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   if (window) {
-    nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
+    nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
     *aIsForced = doc &&
       doc->GetDocumentCharacterSetSource() >= kCharsetFromParentForced;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetDocumentMetadata(const nsAString& aName,
@@ -258,16 +258,41 @@ nsDOMWindowUtils::SetCSSViewport(float a
   nscoord width = nsPresContext::CSSPixelsToAppUnits(aWidthPx);
   nscoord height = nsPresContext::CSSPixelsToAppUnits(aHeightPx);
 
   presShell->ResizeReflowOverride(width, height);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDOMWindowUtils::GetViewportInfo(uint32_t aDisplayWidth,
+                                  uint32_t aDisplayHeight,
+                                  double *aDefaultZoom, bool *aAllowZoom,
+                                  double *aMinZoom, double *aMaxZoom,
+                                  uint32_t *aWidth, uint32_t *aHeight,
+                                  bool *aAutoSize)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
+  NS_ENSURE_STATE(doc);
+
+  ViewportInfo info = nsContentUtils::GetViewportInfo(doc, aDisplayWidth, aDisplayHeight);
+  *aDefaultZoom = info.defaultZoom;
+  *aAllowZoom = info.allowZoom;
+  *aMinZoom = info.minZoom;
+  *aMaxZoom = info.maxZoom;
+  *aWidth = info.width;
+  *aHeight = info.height;
+  *aAutoSize = info.autoSize;
+  return NS_OK;
+}
+
 static void DestroyNsRect(void* aObject, nsIAtom* aPropertyName,
                           void* aPropertyValue, void* aData)
 {
   nsRect* rect = static_cast<nsRect*>(aPropertyValue);
   delete rect;
 }
 
 static void
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -35,17 +35,17 @@ interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMTouch;
 interface nsIDOMClientRect;
 interface nsIURI;
 
-[scriptable, uuid(6cf3e8f0-fb82-11e1-a21f-0800200c9a66)]
+[scriptable, uuid(90d8e97b-2c61-4c05-9f1c-e568d22f5bdc)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -99,16 +99,26 @@ interface nsIDOMWindowUtils : nsISupport
    * This will trigger reflow.
    *
    * The caller of this method must have UniversalXPConnect
    * privileges.
    */
   void setCSSViewport(in float aWidthPx, in float aHeightPx);
 
   /**
+   * Information retrieved from the <meta name="viewport"> tag.
+   * See nsContentUtils::GetViewportInfo for more information.
+   */
+  void getViewportInfo(in uint32_t aDisplayWidth, in uint32_t aDisplayHeight,
+                       out double aDefaultZoom, out boolean aAllowZoom,
+                       out double aMinZoom, out double aMaxZoom,
+                       out uint32_t aWidth, out uint32_t aHeight,
+                       out boolean aAutoSize);
+
+  /**
    * For any scrollable element, this allows you to override the
    * visible region and draw more than what is visible, which is
    * useful for asynchronous drawing. The "displayport" will be
    * <xPx, yPx, widthPx, heightPx> in units of CSS pixels,
    * regardless of the size of the enclosing container.  This
    * will *not* trigger reflow.
    *
    * For the root scroll area, pass in the root document element.
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -5061,17 +5061,46 @@ nsLayoutUtils::FontSizeInflationEnabled(
 
   if (!presShell ||
       (presShell->FontSizeInflationEmPerLine() == 0 &&
        presShell->FontSizeInflationMinTwips() == 0) ||
        aPresContext->IsChrome()) {
     return false;
   }
 
-  ViewportInfo vInf =
-    nsContentUtils::GetViewportInfo(aPresContext->PresShell()->GetDocument());
-
-  if (vInf.defaultZoom >= 1.0 || vInf.autoSize) {
-    return false;
+  // XXXjwir3:
+  // See bug 706918, comment 23 for more information on this particular section
+  // of the code. We're using "screen size" in place of the size of the content
+  // area, because on mobile, these are close or equal. This will work for our
+  // purposes (bug 706198), but it will need to be changed in the future to be
+  // more correct when we bring the rest of the viewport code into platform.
+  // We actually want the size of the content area, in the event that we don't
+  // have any metadata about the width and/or height. On mobile, the screen size
+  // and the size of the content area are very close, or the same value.
+  // In XUL fennec, the content area is the size of the <browser> widget, but
+  // in native fennec, the content area is the size of the Gecko LayerView
+  // object.
+
+  // TODO:
+  // Once bug 716575 has been resolved, this code should be changed so that it
+  // does the right thing on all platforms.
+  nsresult rv;
+  nsCOMPtr<nsIScreenManager> screenMgr =
+    do_GetService("@mozilla.org/gfx/screenmanager;1", &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIScreen> screen;
+  screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
+  if (screen) {
+    int32_t screenLeft, screenTop, screenWidth, screenHeight;
+    screen->GetRect(&screenLeft, &screenTop, &screenWidth, &screenHeight);
+
+    ViewportInfo vInf =
+      nsContentUtils::GetViewportInfo(aPresContext->PresShell()->GetDocument(),
+                                      screenWidth, screenHeight);
+
+    if (vInf.defaultZoom >= 1.0 || vInf.autoSize) {
+      return false;
+    }
   }
 
   return true;
 }