Merging changes
authorWes Kocher <wkocher@mozilla.com>
Mon, 15 Oct 2012 14:34:12 -0700
changeset 110469 cf57fcfc0e6da48f37cbc06d2504d295e64c56c2
parent 110468 f4ba543e1d5a0df459e02e5e3d9d9ee5761f4528 (current diff)
parent 110467 6593f27f18985a359a8d4df7e747099d9b692fe5 (diff)
child 110470 bab34419c024914dd87d0f32701d40e706ee1d6e
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone19.0a1
Merging changes
content/canvas/test/test_mozGetAsFile.html
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -45,16 +45,17 @@ MOCHITEST_FILES = \
 	test_2d.composite.image.destination-in.html \
 	test_2d.composite.image.source-in.html \
 	test_2d.composite.image.source-out.html \
 	test_2d.composite.uncovered.image.destination-in.html \
 	test_2d.composite.uncovered.image.source-in.html \
 	test_2d.composite.uncovered.image.source-out.html \
 	test_2d.drawImage.zerocanvas.html \
 	test_2d.strokeRect.zero.5.html \
+	test_toBlob.html \
 	test_toDataURL_alpha.html \
 	test_toDataURL_lowercase_ascii.html \
 	test_toDataURL_parameters.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
 	test_bug753758.html \
 	test_bug764125.html \
copy from content/canvas/test/test_mozGetAsFile.html
copy to content/canvas/test/test_toBlob.html
--- a/content/canvas/test/test_mozGetAsFile.html
+++ b/content/canvas/test/test_toBlob.html
@@ -2,22 +2,22 @@
 <title>Canvas test: mozGetAsFile</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 
-var gCompares = 0;
+var gCompares = 2;
 
-function compareAsync(file, canvas, type)
+function BlobListener(type, canvas, file)
 {
-  ++gCompares;
-
+  is(file.type, type,
+     "When a valid type is specified that should be returned");
   var reader = new FileReader();
   reader.onload = 
     function(e) {
       is(e.target.result, canvas.toDataURL(type),
  "<canvas>.mozGetAsFile().getAsDataURL() should equal <canvas>.toDataURL()");
       if (--gCompares == 0) {
         SimpleTest.finish();
       }
@@ -28,23 +28,15 @@ function compareAsync(file, canvas, type
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function () {
 
 var canvas = document.getElementById('c');
 var ctx = canvas.getContext('2d');
 
 ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
 
-var pngfile = canvas.mozGetAsFile("foo.png");
-is(pngfile.type, "image/png", "Default type for mozGetAsFile should be PNG");
-compareAsync(pngfile, canvas, "image/png");
-is(pngfile.name, "foo.png", "File name should be what we passed in");
-
-var jpegfile = canvas.mozGetAsFile("bar.jpg", "image/jpeg");
-is(jpegfile.type, "image/jpeg",
-   "When a valid type is specified that should be returned");
-compareAsync(jpegfile, canvas, "image/jpeg");
-is(jpegfile.name, "bar.jpg", "File name should be what we passed in");
+canvas.toBlob(BlobListener.bind(undefined, "image/png", canvas));
+canvas.toBlob(BlobListener.bind(undefined, "image/jpeg", canvas), "image/jpeg");
 
 });
 </script>
 <img src="image_yellow75.png" id="yellow75.png" class="resource">
 
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -35,16 +35,42 @@
 
 #define DEFAULT_CANVAS_WIDTH 300
 #define DEFAULT_CANVAS_HEIGHT 150
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 
+namespace {
+
+class ToBlobRunnable : public nsRunnable
+{
+public:
+  ToBlobRunnable(nsIFileCallback* aCallback,
+                 nsIDOMBlob* aBlob)
+    : mCallback(aCallback),
+      mBlob(aBlob)
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  }
+
+  NS_IMETHOD Run()
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+    mCallback->Receive(mBlob);
+    return NS_OK;
+  }
+private:
+  nsCOMPtr<nsIFileCallback> mCallback;
+  nsCOMPtr<nsIDOMBlob> mBlob;
+};
+
+} // anonymous namespace
+
 class nsHTMLCanvasPrintState : public nsIDOMMozCanvasPrintState
 {
 public:
   nsHTMLCanvasPrintState(nsHTMLCanvasElement* aCanvas,
                          nsICanvasRenderingContextInternal* aContext,
                          nsITimerCallback* aCallback)
     : mIsDone(false), mPendingNotify(false), mCanvas(aCanvas),
       mContext(aContext), mCallback(aCallback)
@@ -545,16 +571,62 @@ nsHTMLCanvasElement::ToDataURLImpl(const
   uint64_t count;
   rv = stream->Available(&count);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(count <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
 
   return Base64EncodeInputStream(stream, aDataURL, (uint32_t)count, aDataURL.Length());
 }
 
+// XXXkhuey the encoding should be off the main thread, but we're lazy.
+NS_IMETHODIMP
+nsHTMLCanvasElement::ToBlob(nsIFileCallback* aCallback,
+                            const nsAString& aType,
+                            nsIVariant* aParams,
+                            uint8_t optional_argc)
+{
+  // do a trust check if this is a write-only canvas
+  if (mWriteOnly && !nsContentUtils::IsCallerTrustedForRead()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  nsAutoString type;
+  nsresult rv = nsContentUtils::ASCIIToLower(aType, type);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  bool fallbackToPNG = false;
+
+  nsCOMPtr<nsIInputStream> stream;
+  nsresult rv = ExtractData(type, EmptyString(), getter_AddRefs(stream),
+                            fallbackToPNG);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (fallbackToPNG) {
+    type.AssignLiteral("image/png");
+  }
+
+  uint64_t imgSize;
+  rv = stream->Available(&imgSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(imgSize <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
+
+  void* imgData = nullptr;
+  rv = NS_ReadInputStreamToBuffer(stream, &imgData, imgSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // The DOMFile takes ownership of the buffer
+  nsRefPtr<nsDOMMemoryFile> blob =
+    new nsDOMMemoryFile(imgData, imgSize, type);
+
+  nsRefPtr<ToBlobRunnable> runnable = new ToBlobRunnable(aCallback, blob);
+  return NS_DispatchToCurrentThread(runnable);
+}
+
 NS_IMETHODIMP
 nsHTMLCanvasElement::MozGetAsFile(const nsAString& aName,
                                   const nsAString& aType,
                                   uint8_t optional_argc,
                                   nsIDOMFile** aResult)
 {
   // do a trust check if this is a write-only canvas
   if ((mWriteOnly) &&
--- a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl
@@ -15,16 +15,17 @@
  * <canvas> element.
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#graphics
  *
  * @status UNDER_DEVELOPMENT
  */
 
+interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIVariant;
 interface nsIInputStreamCallback;
 
 [scriptable, builtinclass, uuid(8d5fb8a0-7782-11e1-b0c4-0800200c9a67)]
 interface nsIDOMMozCanvasPrintState : nsISupports
 {
   // A canvas rendering context.
@@ -35,16 +36,21 @@ interface nsIDOMMozCanvasPrintState : ns
 };
 
 [scriptable, function, uuid(8d5fb8a0-7782-11e1-b0c4-0800200c9a66)]
 interface nsIPrintCallback : nsISupports
 {
   void render(in nsIDOMMozCanvasPrintState ctx);
 };
 
+[scriptable, function, uuid(6e9ffb59-2067-4aef-a51c-65e65a3e0d81)]
+interface nsIFileCallback : nsISupports {
+  void receive(in nsIDOMBlob file);
+};
+
 [scriptable, uuid(a7062fca-41c6-4520-b777-3bb30fd77273)]
 interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
 {
   attribute unsigned long width;
   attribute unsigned long height;
   attribute boolean mozOpaque;
 
   nsISupports getContext(in DOMString contextId,
@@ -59,16 +65,20 @@ interface nsIDOMHTMLCanvasElement : nsID
                                       [optional] in nsIVariant params);
 
   // Valid calls are
   // mozGetAsFile(name);              -- defaults to image/png
   // mozGetAsFile(name, type);        -- uses given type
   [optional_argc] nsIDOMFile mozGetAsFile(in DOMString name,
                                           [optional] in DOMString type);
 
+  [optional_argc] void toBlob(in nsIFileCallback callback,
+                              [optional] in DOMString type,
+                              [optional] in nsIVariant params);
+
   // A Mozilla-only extension to get a canvas context backed by double-buffered
   // shared memory. Only privileged callers can call this.
   nsISupports MozGetIPCContext(in DOMString contextId);
 
   // A Mozilla-only extension that returns the canvas' image data as a data
   // stream in the desired image format.
   void mozFetchAsStream(in nsIInputStreamCallback callback,
                                         [optional] in DOMString type);
--- a/gfx/layers/basic/BasicTiledThebesLayer.cpp
+++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp
@@ -258,22 +258,16 @@ BasicTiledThebesLayer::PaintThebes(gfxCo
 
   gfxSize resolution(1, 1);
   for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
     const FrameMetrics& metrics = parent->GetFrameMetrics();
     resolution.width *= metrics.mResolution.width;
     resolution.height *= metrics.mResolution.height;
   }
 
-  // If the resolution has changed, discard all the old tiles.
-  // They will end up being retained on the shadow side by ReusableTileStoreOGL
-  if (mTiledBuffer.GetResolution() != resolution) {
-    mValidRegion = nsIntRegion();
-  }
-
   // Calculate the scroll offset since the last transaction. Progressive tile
   // painting is only used when scrolling.
   gfx::Point scrollOffset(0, 0);
   Layer* primaryScrollable = BasicManager()->GetPrimaryScrollableLayer();
   if (primaryScrollable) {
     const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
     scrollOffset = metrics.mScrollOffset;
   }
--- a/gfx/layers/opengl/ReusableTileStoreOGL.cpp
+++ b/gfx/layers/opengl/ReusableTileStoreOGL.cpp
@@ -54,29 +54,43 @@ ReusableTileStoreOGL::InvalidateTiles(Ti
 
   // Iterate over existing harvested tiles and release any that are contained
   // within the new valid region, the display-port or the widget area. The
   // assumption is that anything within this area should be valid, so there's
   // no need to keep invalid tiles there.
   mContext->MakeCurrent();
   for (uint32_t i = 0; i < mTiles.Length();) {
     ReusableTiledTextureOGL* tile = mTiles[i];
+
+    // Check if the tile region is contained within the new valid region.
+    nsIntRect tileRect;
     bool release = false;
-
-    nsIntRect tileRect = tile->mTileRegion.GetBounds();
-    if (tile->mResolution != aResolution) {
+    if (tile->mResolution == aResolution) {
+      if (aValidRegion.Contains(tile->mTileRegion)) {
+        release = true;
+      } else {
+        tileRect = tile->mTileRegion.GetBounds();
+      }
+    } else {
       nsIntRegion transformedTileRegion(tile->mTileRegion);
       transformedTileRegion.ScaleRoundOut(tile->mResolution.width / aResolution.width,
                                           tile->mResolution.height / aResolution.height);
-      tileRect = transformedTileRegion.GetBounds();
+      if (aValidRegion.Contains(transformedTileRegion))
+        release = true;
+      else
+        tileRect = transformedTileRegion.GetBounds();
     }
 
-    // Check if the tile region is contained within the new valid region.
-    if (aValidRegion.Contains(tileRect)) {
-      release = true;
+    // If the tile region wasn't contained within the valid region, check if
+    // it intersects with the currently rendered region.
+    if (!release) {
+      // Transform the tile region to see if it falls inside the rendered bounds
+      gfxRect tileBounds = aLayer->GetEffectiveTransform().TransformBounds(gfxRect(tileRect));
+      if (renderBounds.Contains(tileBounds))
+        release = true;
     }
 
     if (release) {
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
       nsIntRect tileBounds = tile->mTileRegion.GetBounds();
       printf_stderr("Releasing obsolete reused tile at %d,%d, x%f\n",
                     tileBounds.x, tileBounds.y, tile->mResolution.width);
 #endif
@@ -112,34 +126,21 @@ ReusableTileStoreOGL::HarvestTiles(Tiled
   //     to make it simpler.
   uint16_t tileSize = aVideoMemoryTiledBuffer->GetTileLength();
   nsIntRect validBounds = aOldValidRegion.GetBounds();
   for (int x = validBounds.x; x < validBounds.XMost();) {
     int w = tileSize - aVideoMemoryTiledBuffer->GetTileStart(x);
     if (x + w > validBounds.x + validBounds.width)
       w = validBounds.x + validBounds.width - x;
 
-    // A tile will consume 256^2 of memory, don't retain small tile trims.
-    // This works around the display port sometimes creating a small 1 pixel wide
-    // tile because of rounding error.
-    if (w < 16) {
-      x += w;
-      continue;
-    }
-
     for (int y = validBounds.y; y < validBounds.YMost();) {
       int h = tileSize - aVideoMemoryTiledBuffer->GetTileStart(y);
       if (y + h > validBounds.y + validBounds.height)
         h = validBounds.y + validBounds.height - y;
 
-      if (h < 16) {
-        y += h;
-        continue;
-      }
-
       // If the new valid region doesn't contain this tile region,
       // harvest the tile.
       nsIntRegion tileRegion;
       tileRegion.And(aOldValidRegion, nsIntRect(x, y, w, h));
 
       nsIntRegion intersectingRegion;
       bool retainTile = false;
       if (aNewResolution != aOldResolution) {
@@ -151,50 +152,25 @@ ReusableTileStoreOGL::HarvestTiles(Tiled
         transformedTileRegion.ScaleRoundOut(scaleFactor.width, scaleFactor.height);
         if (!aNewValidRegion.Contains(transformedTileRegion))
           retainTile = true;
       } else if (intersectingRegion.And(tileRegion, aNewValidRegion).IsEmpty()) {
         retainTile = true;
       }
 
       if (retainTile) {
+#ifdef GFX_TILEDLAYER_PREF_WARNINGS
+        printf_stderr("Retaining tile at %d,%d, x%f for reuse\n", x, y, aOldResolution.width);
+#endif
         TiledTexture removedTile;
         if (aVideoMemoryTiledBuffer->RemoveTile(nsIntPoint(x, y), removedTile)) {
           ReusableTiledTextureOGL* reusedTile =
             new ReusableTiledTextureOGL(removedTile, nsIntPoint(x, y), tileRegion,
                                         tileSize, aOldResolution);
           mTiles.AppendElement(reusedTile);
-
-#ifdef GFX_TILEDLAYER_PREF_WARNINGS
-          bool replacedATile = false;
-#endif
-          // Remove any tile that is superseded by this new tile.
-          // (same resolution, same area)
-          for (int i = 0; i < mTiles.Length() - 1; i++) {
-            // XXX Perhaps we should check the region instead of the origin
-            //     so a partial tile doesn't replace a full older tile?
-            if (aVideoMemoryTiledBuffer->RoundDownToTileEdge(mTiles[i]->mTileOrigin.x) == aVideoMemoryTiledBuffer->RoundDownToTileEdge(x) &&
-                aVideoMemoryTiledBuffer->RoundDownToTileEdge(mTiles[i]->mTileOrigin.y) == aVideoMemoryTiledBuffer->RoundDownToTileEdge(y) &&
-                mTiles[i]->mResolution == aOldResolution) {
-              mContext->fDeleteTextures(1, &mTiles[i]->mTexture.mTextureHandle);
-              mTiles.RemoveElementAt(i);
-#ifdef GFX_TILEDLAYER_PREF_WARNINGS
-              replacedATile = true;
-#endif
-              // There should only be one similar tile
-              break;
-            }
-          }
-#ifdef GFX_TILEDLAYER_PREF_WARNINGS
-          if (replacedATile) {
-            printf_stderr("Replaced tile at %d,%d, x%f for reuse\n", x, y, aOldResolution.width);
-          } else {
-            printf_stderr("New tile at %d,%d, x%f for reuse\n", x, y, aOldResolution.width);
-          }
-#endif
         }
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
         else
           printf_stderr("Failed to retain tile for reuse\n");
 #endif
       }
 
       y += h;
@@ -213,17 +189,16 @@ ReusableTileStoreOGL::HarvestTiles(Tiled
     printf_stderr("Releasing old reused tile at %d,%d, x%f\n",
                   tileBounds.x, tileBounds.y, mTiles[0]->mResolution.width);
 #endif
     mContext->fDeleteTextures(1, &mTiles[0]->mTexture.mTextureHandle);
     mTiles.RemoveElementAt(0);
   }
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
-  printf_stderr("Retained tile limit: %f\n", aVideoMemoryTiledBuffer->GetTileCount() * mSizeLimit);
   printf_stderr("Retained %d tiles\n", mTiles.Length());
 #endif
 }
 
 void
 ReusableTileStoreOGL::DrawTiles(TiledThebesLayerOGL* aLayer,
                                 const nsIntRegion& aValidRegion,
                                 const gfxSize& aResolution,
@@ -270,17 +245,16 @@ ReusableTileStoreOGL::DrawTiles(TiledThe
                                   aResolution.height / tile->mResolution.height);
 
     // Reconcile the resolution difference by adjusting the transform.
     gfx3DMatrix transform = aTransform;
     if (aResolution != tile->mResolution)
       transform.Scale(scaleFactor.width, scaleFactor.height, 1);
 
     // Subtract the layer's valid region from the tile region.
-    // This region will be drawn by the layer itself.
     nsIntRegion transformedValidRegion(aValidRegion);
     if (aResolution != tile->mResolution)
       transformedValidRegion.ScaleRoundOut(1.0f/scaleFactor.width,
                                            1.0f/scaleFactor.height);
     nsIntRegion tileRegion;
     tileRegion.Sub(tile->mTileRegion, transformedValidRegion);
 
     // Subtract the display-port from the tile region.
--- a/js/src/tests/ecma_5/extensions/strict-function-toSource.js
+++ b/js/src/tests/ecma_5/extensions/strict-function-toSource.js
@@ -5,11 +5,13 @@
 
 options("strict_mode");
 function testRunOptionStrictMode(str, arg, result) {
     var strict_inner = new Function('return typeof this == "undefined";');
     return strict_inner;
 }
 assertEq(eval(uneval(testRunOptionStrictMode()))(), true);
 
-assertEq(decompileBody(new Function('x', 'return x*2;')).contains('\n"use strict"'), true)
+if (typeof decompileBody !== "undefined") {
+    assertEq(decompileBody(new Function('x', 'return x*2;')).contains('\n"use strict"'), true);
+}
 
 reportCompare(true, true);
--- a/netwerk/test/TestPageLoad.cpp
+++ b/netwerk/test/TestPageLoad.cpp
@@ -23,17 +23,17 @@ namespace TestPageLoad {
 int getStrLine(const char *src, char *str, int ind, int max);
 nsresult auxLoad(char *uriBuf);
 //----------------------------------------------------------------------
 
 
 #define RETURN_IF_FAILED(rv, ret, step) \
     PR_BEGIN_MACRO \
     if (NS_FAILED(rv)) { \
-        printf(">>> %s failed: rv=%x\n", step, rv); \
+        printf(">>> %s failed: rv=%x\n", step, static_cast<uint32_t>(rv)); \
         return ret;\
     } \
     PR_END_MACRO
 
 static nsCString globalStream;
 //static char urlBuf[256];
 static nsCOMPtr<nsIURI> baseURI;
 static nsCOMArray<nsIURI> uriList;
--- a/rdf/tests/rdfcat/rdfcat.cpp
+++ b/rdf/tests/rdfcat/rdfcat.cpp
@@ -42,17 +42,17 @@
 // rdf
 static NS_DEFINE_CID(kRDFXMLDataSourceCID,  NS_RDFXMLDATASOURCE_CID);
 
 ////////////////////////////////////////////////////////////////////////
 // Blatantly stolen from netwerk/test/
 #define RETURN_IF_FAILED(rv, step) \
     PR_BEGIN_MACRO \
     if (NS_FAILED(rv)) { \
-        printf(">>> %s failed: rv=%x\n", step, rv); \
+        printf(">>> %s failed: rv=%x\n", step, static_cast<uint32_t>(rv)); \
         return 1;\
     } \
     PR_END_MACRO
 
 ////////////////////////////////////////////////////////////////////////
 
 class ConsoleOutputStreamImpl : public nsIOutputStream
 {
--- a/rdf/tests/triplescat/triplescat.cpp
+++ b/rdf/tests/triplescat/triplescat.cpp
@@ -40,17 +40,17 @@
 #include "rdfITripleVisitor.h"
 #include "rdfISerializer.h"
 
 ////////////////////////////////////////////////////////////////////////
 // Blatantly stolen from netwerk/test/
 #define RETURN_IF_FAILED(rv, step) \
     PR_BEGIN_MACRO \
     if (NS_FAILED(rv)) { \
-        printf(">>> %s failed: rv=%x\n", step, rv); \
+        printf(">>> %s failed: rv=%x\n", step, static_cast<uint32_t>(rv)); \
         return 1;\
     } \
     PR_END_MACRO
 
 ////////////////////////////////////////////////////////////////////////
 
 class ConsoleOutputStreamImpl : public nsIOutputStream
 {
--- a/toolkit/components/aboutmemory/content/aboutMemory.js
+++ b/toolkit/components/aboutmemory/content/aboutMemory.js
@@ -1568,39 +1568,37 @@ function updateAboutCompartments()
   // updateAboutCompartments() might be called more than once due to the
   // "child-memory-reporter-update" observer.
   let body = clearBody();
 
   let compartmentsByProcess = getCompartmentsByProcess();
   let ghostWindowsByProcess = getGhostWindowsByProcess();
 
   function handleProcess(aProcess) {
-    appendProcessAboutCompartmentsElements(body, aProcess,
+    let section = appendElement(body, 'div', 'section');
+    appendProcessAboutCompartmentsElements(section, aProcess,
                                            compartmentsByProcess[aProcess],
                                            ghostWindowsByProcess[aProcess]);
   }
 
   // Generate output for one process at a time.  Always start with the
   // Main process.
   handleProcess(gUnnamedProcessStr);
   for (let process in compartmentsByProcess) {
     if (process !== gUnnamedProcessStr) {
       handleProcess(process);
     }
   }
 
-  appendElement(body, "hr");
-
-  let div1 = appendElement(body, "div");
-  let a;
+  let section = appendElement(body, 'div', 'footer');
   if (gVerbose) {
-    let a = appendElementWithText(div1, "a", "option", "Less verbose");
+    let a = appendElementWithText(section, "a", "option", "Less verbose");
     a.href = "about:compartments";
   } else {
-    let a = appendElementWithText(div1, "a", "option", "More verbose");
+    let a = appendElementWithText(section, "a", "option", "More verbose");
     a.href = "about:compartments?verbose";
   }
 }
 
 //---------------------------------------------------------------------------
 
 function Compartment(aUnsafeName, aIsSystemCompartment)
 {