diff --git a/extensions/b2g/viewer.html b/extensions/b2g/viewer.html
index d39ed5724..f8a24fc97 100644
--- a/extensions/b2g/viewer.html
+++ b/extensions/b2g/viewer.html
@@ -102,6 +102,47 @@ limitations under the License.
         </div>
       </div>  <!-- sidebarContainer -->
 
+      <button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="17" data-l10n-id="tools">
+        <span data-l10n-id="tools_label">Tools</span>
+      </button>
+      <div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight">
+        <div id="secondaryToolbarButtonContainer">
+          <button id="secondaryPresentationMode" class="secondaryToolbarButton presentationMode visibleLargeView" title="Switch to Presentation Mode" tabindex="18" data-l10n-id="presentation_mode">
+            <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
+          </button>
+
+          <button id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView" title="Open File" tabindex="19" data-l10n-id="open_file">
+            <span data-l10n-id="open_file_label">Open</span>
+          </button>
+
+          <button id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="20" data-l10n-id="print">
+            <span data-l10n-id="print_label">Print</span>
+          </button>
+
+          <button id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView" title="Download" tabindex="21" data-l10n-id="download">
+            <span data-l10n-id="download_label">Download</span>
+          </button>
+
+          <div class="horizontalToolbarSeparator visibleLargeView"></div>
+
+          <button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="22" data-l10n-id="first_page">
+            <span data-l10n-id="first_page_label">Go to First Page</span>
+          </button>
+          <button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page" tabindex="23" data-l10n-id="last_page">
+            <span data-l10n-id="last_page_label">Go to Last Page</span>
+          </button>
+
+          <div class="horizontalToolbarSeparator"></div>
+
+          <button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise" tabindex="24" data-l10n-id="page_rotate_cw">
+            <span data-l10n-id="page_rotate_cw_label">Rotate Clockwise</span>
+          </button>
+          <button id="pageRotateCcw" class="secondaryToolbarButton rotateCcw" title="Rotate Counterclockwise" tabindex="25" data-l10n-id="page_rotate_ccw">
+            <span data-l10n-id="page_rotate_ccw_label">Rotate Counterclockwise</span>
+          </button>
+        </div>
+      </div>  <!-- secondaryToolbar -->
+
       <div id="mainContainer">
         <div id="findbar">
           <input id="findInput">
@@ -148,10 +189,14 @@ limitations under the License.
           </div>
         </div>
         <menu type="context" id="viewerContextMenu">
-          <menuitem id="firstPage"></menuitem>
-          <menuitem id="lastPage"></menuitem>
-          <menuitem id="pageRotateCcw"></menuitem>
-          <menuitem id="pageRotateCw"></menuitem>
+          <menuitem id="contextFirstPage" label="First Page"
+                    data-l10n-id="first_page"></menuitem>
+          <menuitem id="contextLastPage" label="Last Page"
+                    data-l10n-id="last_page"></menuitem>
+          <menuitem id="contextPageRotateCw" label="Rotate Clockwise"
+                    data-l10n-id="page_rotate_cw"></menuitem>
+          <menuitem id="contextPageRotateCcw" label="Rotate Counter-Clockwise"
+                    data-l10n-id="page_rotate_ccw"></menuitem>
         </menu>
 
       </div> <!-- mainContainer -->
diff --git a/web/page_view.js b/web/page_view.js
index 2acfb7094..7f26f6a65 100644
--- a/web/page_view.js
+++ b/web/page_view.js
@@ -17,7 +17,7 @@
 /* globals RenderingStates, PDFView, PDFHistory, PDFFindBar, PDFJS, mozL10n,
            CustomStyle, PresentationMode, scrollIntoView, SCROLLBAR_PADDING,
            CSS_UNITS, UNKNOWN_SCALE, DEFAULT_SCALE, getOutputScale,
-           TextLayerBuilder, cache, Stats */
+           TextLayerBuilder, cache, Stats, USE_ONLY_CSS_ZOOM */
 
 'use strict';
 
@@ -36,6 +36,8 @@ var PageView = function pageView(container, id, scale,
   this.textContent = null;
   this.textLayer = null;
 
+  this.zoomLayer = null;
+
   this.annotationLayer = null;
 
   var anchor = document.createElement('a');
@@ -53,42 +55,36 @@ var PageView = function pageView(container, id, scale,
   this.setPdfPage = function pageViewSetPdfPage(pdfPage) {
     this.pdfPage = pdfPage;
     this.pdfPageRotate = pdfPage.rotate;
-    this.viewport = pdfPage.getViewport(this.scale);
+    this.viewport = pdfPage.getViewport(this.scale * CSS_UNITS);
     this.stats = pdfPage.stats;
-    this.update();
+    this.reset();
   };
 
   this.destroy = function pageViewDestroy() {
-    this.update();
+    this.zoomLayer = null;
+    this.reset();
     if (this.pdfPage) {
       this.pdfPage.destroy();
     }
   };
 
-  this.update = function pageViewUpdate(scale, rotation) {
+  this.reset = function pageViewReset() {
     if (this.renderTask) {
       this.renderTask.cancel();
     }
     this.resume = null;
     this.renderingState = RenderingStates.INITIAL;
 
-    if (typeof rotation !== 'undefined') {
-      this.rotation = rotation;
-    }
-
-    this.scale = scale || this.scale;
-
-    var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
-    this.viewport = this.viewport.clone({
-      scale: this.scale,
-      rotation: totalRotation
-    });
-
     div.style.width = Math.floor(this.viewport.width) + 'px';
     div.style.height = Math.floor(this.viewport.height) + 'px';
 
-    while (div.hasChildNodes()) {
-      div.removeChild(div.lastChild);
+    var childNodes = div.childNodes;
+    for (var i = div.childNodes.length - 1; i >= 0; i--) {
+      var node = childNodes[i];
+      if (this.zoomLayer && this.zoomLayer === node) {
+        continue;
+      }
+      div.removeChild(node);
     }
     div.removeAttribute('data-loaded');
 
@@ -101,6 +97,47 @@ var PageView = function pageView(container, id, scale,
     div.appendChild(this.loadingIconDiv);
   };
 
+  this.update = function pageViewUpdate(scale, rotation) {
+    this.scale = scale || this.scale;
+
+    if (typeof rotation !== 'undefined') {
+      this.rotation = rotation;
+    }
+
+    var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+    this.viewport = this.viewport.clone({
+      scale: this.scale * CSS_UNITS,
+      rotation: totalRotation
+    });
+
+    if (USE_ONLY_CSS_ZOOM && this.canvas) {
+      this.cssZoom(this.canvas);
+      return;
+    } else if (this.canvas && !this.zoomLayer) {
+      this.zoomLayer = this.canvas.parentNode;
+      this.zoomLayer.style.position = 'absolute';
+    }
+    if (this.zoomLayer) {
+      this.cssZoom(this.zoomLayer.firstChild);
+    }
+    this.reset();
+  };
+
+  this.cssZoom = function pageViewRescale(canvas) {
+    // Need to adjust canvas, canvas wrapepr, and page container.
+    canvas.style.width = canvas.parentNode.style.width = div.style.width =
+        Math.floor(this.viewport.width) + 'px';
+    canvas.style.height = canvas.parentNode.style.height = div.style.height =
+        Math.floor(this.viewport.height) + 'px';
+    if (this.textLayer) {
+      var scale = (this.viewport.width / canvas.width);
+      var cssScale = 'scale(' + scale + ', ' + scale + ')';
+      var textLayerDiv = this.textLayer.textLayerDiv;
+      CustomStyle.setProp('transform', textLayerDiv, cssScale);
+      CustomStyle.setProp('transformOrigin', textLayerDiv, '0% 0%');
+    }
+  };
+
   Object.defineProperty(this, 'width', {
     get: function PageView_getWidth() {
       return this.viewport.width;
@@ -362,8 +399,17 @@ var PageView = function pageView(container, id, scale,
     var ctx = canvas.getContext('2d');
     var outputScale = getOutputScale(ctx);
 
-    canvas.width = Math.floor(viewport.width) * outputScale.sx;
-    canvas.height = Math.floor(viewport.height) * outputScale.sy;
+    if (USE_ONLY_CSS_ZOOM) {
+      var actualSizeViewport = viewport.clone({ scale: CSS_UNITS });
+      // Use a scale that will make the canvas be the original intended size
+      // of the page.
+      outputScale.sx *= actualSizeViewport.width / viewport.width;
+      outputScale.sy *= actualSizeViewport.height / viewport.height;
+      outputScale.scaled = true;
+    }
+
+    canvas.width = Math.floor(viewport.width * outputScale.sx);
+    canvas.height = Math.floor(viewport.height * outputScale.sy);
     canvas.style.width = Math.floor(viewport.width) + 'px';
     canvas.style.height = Math.floor(viewport.height) + 'px';
 
@@ -423,6 +469,11 @@ var PageView = function pageView(container, id, scale,
         delete self.loadingIconDiv;
       }
 
+      if (self.zoomLayer) {
+        div.removeChild(self.zoomLayer);
+        self.zoomLayer = null;
+      }
+
 //#if (FIREFOX || MOZCENTRAL)
 //    if (checkIfDocumentFontsUsed && PDFView.pdfDocument.embeddedFontsUsed &&
 //        PDFJS.disableFontFace) {
diff --git a/web/viewer.js b/web/viewer.js
index e56c34992..293e765f7 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -35,6 +35,10 @@ var MAX_SCALE = 4.0;
 var SETTINGS_MEMORY = 20;
 var SCALE_SELECT_CONTAINER_PADDING = 8;
 var SCALE_SELECT_PADDING = 22;
+var USE_ONLY_CSS_ZOOM = false;
+//#if B2G
+//USE_ONLY_CSS_ZOOM = true;
+//#endif
 var RenderingStates = {
   INITIAL: 0,
   RUNNING: 1,
@@ -195,7 +199,7 @@ var PDFView = {
 
     var pages = this.pages;
     for (var i = 0; i < pages.length; i++)
-      pages[i].update(val * CSS_UNITS);
+      pages[i].update(val);
 
     if (!noScroll && this.currentScale != val)
       this.pages[this.page - 1].scrollIntoView();
@@ -226,9 +230,9 @@ var PDFView = {
     }
 
     var pageWidthScale = (container.clientWidth - SCROLLBAR_PADDING) /
-                          currentPage.width * currentPage.scale / CSS_UNITS;
+                          currentPage.width * currentPage.scale;
     var pageHeightScale = (container.clientHeight - VERTICAL_PADDING) /
-                           currentPage.height * currentPage.scale / CSS_UNITS;
+                           currentPage.height * currentPage.scale;
     switch (value) {
       case 'page-actual':
         scale = 1;
@@ -817,7 +821,7 @@ var PDFView = {
     // Fetch a single page so we can get a viewport that will be the default
     // viewport for all pages
     firstPagePromise.then(function(pdfPage) {
-      var viewport = pdfPage.getViewport(scale || 1.0);
+      var viewport = pdfPage.getViewport((scale || 1.0) * CSS_UNITS);
       var pagePromises = [];
       for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
         var viewportClone = viewport.clone();
@@ -1514,6 +1518,10 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
     PDFJS.disableHistory = (hashParams['disableHistory'] === 'true');
   }
 
+  if ('useOnlyCssZoom' in hashParams) {
+    USE_ONLY_CSS_ZOOM = (hashParams['useOnlyCssZoom'] === 'true');
+  }
+
 //#if !(FIREFOX || MOZCENTRAL)
   var locale = navigator.language;
   if ('locale' in hashParams)