Merge mozilla-central into services-central
authorGregory Szorc <gps@mozilla.com>
Mon, 20 Aug 2012 09:34:02 -0700
changeset 111038 4431277116bbe89f1a548d1d08688d4d8d520a76
parent 111037 a8db42aa1b2820c73aade9acc4de9909562a2a03 (current diff)
parent 104764 5b057a27cd0e77f2208705bdf9dad9624bb28dd7 (diff)
child 111039 b852b572cd64fc32e195b0b5f0e699ed28c01566
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone17.0a1
Merge mozilla-central into services-central
content/canvas/test/webgl/resources/js-test-post.js
content/events/test/test_bug422132.html
content/media/ogg/nsOggDecoderStateMachine.cpp
content/media/ogg/nsOggDecoderStateMachine.h
gfx/harfbuzz/src/hb-fallback-shape-private.hh
gfx/harfbuzz/src/hb-graphite2-private.hh
gfx/harfbuzz/src/hb-ot-shape.h
gfx/harfbuzz/src/hb-uniscribe-private.hh
js/src/jitstats.tbl
js/xpconnect/tests/chrome/test_bug758563.xul
js/xpconnect/tests/mochitest/file_bug758563.html
mobile/android/themes/core/images/reader-dark-bg.png
mobile/android/themes/core/images/reader-light-bg.png
mobile/android/themes/core/images/reader-sepia-bg.png
netwerk/base/public/nsIIPCSerializable.idl
webapprt/test/chrome/install.html
webapprt/test/content/helpers.js
webapprt/test/content/sample.html
webapprt/test/content/sample.webapp
--- a/Makefile.in
+++ b/Makefile.in
@@ -32,17 +32,16 @@ tier_base_dirs = \
   probes \
   mfbt \
   $(NULL)
 
 ifndef LIBXUL_SDK
 ifeq (android,$(MOZ_WIDGET_TOOLKIT))
 tier_base_dirs += \
   other-licenses/android \
-  other-licenses/skia-npapi \
   $(NULL)
 endif
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 tier_base_dirs += \
   other-licenses/android \
   $(NULL)
 endif
 
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -1208,23 +1208,23 @@ HTMLTableAccessible::IsProbablyLayoutTab
     RETURN_LAYOUT_ANSWER(false, ">=5 columns");
   }
 
   // Now we know there are 2-4 columns and 2 or more rows
   // Check to see if there are visible borders on the cells
   // XXX currently, we just check the first cell -- do we really need to do more?
   nsCOMPtr<nsIDOMElement> cellElement;
   nsresult rv = GetCellAt(0, 0, *getter_AddRefs(cellElement));
-  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+  NS_ENSURE_SUCCESS(rv, false);
 
   nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElement));
-  NS_ENSURE_TRUE(cellContent, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(cellContent, false);
   nsIFrame *cellFrame = cellContent->GetPrimaryFrame();
   if (!cellFrame) {
-    return NS_OK;
+    RETURN_LAYOUT_ANSWER(false, "Could not get frame for cellContent");
   }
   nsMargin border;
   cellFrame->GetBorder(border);
   if (border.top && border.bottom && border.left && border.right) {
     RETURN_LAYOUT_ANSWER(false, "Has nonzero border-width on table cell");
   }
 
   /**
--- a/accessible/src/jsat/AccessFu.css
+++ b/accessible/src/jsat/AccessFu.css
@@ -1,22 +1,30 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#virtual-cursor-box { 
+#virtual-cursor-box {
   position: fixed;
   border: 1px solid orange;
   pointer-events: none;
   display: none;
   border-radius: 2px;
   box-shadow: 1px 1px 1px #444;
 }
 
-#virtual-cursor-inset { 
+#virtual-cursor-inset {
   border-radius: 1px;
   box-shadow: inset 1px 1px 1px #444;
   display: block;
   box-sizing: border-box;
   width: 100%;
   height: 100%;
   pointer-events: none;
-}
\ No newline at end of file
+}
+
+#accessfu-glass {
+  width: 100%;
+  height: 100%;
+  position: fixed;
+  top: 0px;
+  left: 0px;
+}
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -11,16 +11,17 @@ const Cr = Components.results;
 
 var EXPORTED_SYMBOLS = ['AccessFu'];
 
 Cu.import('resource://gre/modules/Services.jsm');
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
 Cu.import('resource://gre/modules/accessibility/Presenters.jsm');
 Cu.import('resource://gre/modules/accessibility/VirtualCursorController.jsm');
+Cu.import('resource://gre/modules/accessibility/TouchAdapter.jsm');
 
 const ACCESSFU_DISABLE = 0;
 const ACCESSFU_ENABLE = 1;
 const ACCESSFU_AUTO = 2;
 
 var AccessFu = {
   /**
    * Attach chrome-layer accessibility functionality to the given chrome window.
@@ -39,32 +40,55 @@ var AccessFu = {
     this.chromeWin = aWindow;
     this.presenters = [];
 
     this.prefsBranch = Cc['@mozilla.org/preferences-service;1']
       .getService(Ci.nsIPrefService).getBranch('accessibility.accessfu.');
     this.prefsBranch.addObserver('activate', this, false);
     this.prefsBranch.addObserver('explorebytouch', this, false);
 
-    if (Utils.OS == 'Android')
-      Services.obs.addObserver(this, 'Accessibility:Settings', false);
+    this.touchAdapter = TouchAdapter;
+
+    switch(Utils.MozBuildApp) {
+      case 'mobile/android':
+        Services.obs.addObserver(this, 'Accessibility:Settings', false);
+        this.touchAdapter = AndroidTouchAdapter;
+        break;
+      case 'b2g':
+        aWindow.addEventListener(
+          'ContentStart',
+          (function(event) {
+             let content = aWindow.shell.contentBrowser.contentWindow;
+             content.addEventListener('mozContentEvent', this, false, true);
+           }).bind(this), false);
+        break;
+      default:
+        break;
+    }
 
     this._processPreferences();
   },
 
   /**
    * Start AccessFu mode, this primarily means controlling the virtual cursor
    * with arrow keys.
    */
   _enable: function _enable() {
     if (this._enabled)
       return;
     this._enabled = true;
 
     Logger.info('enable');
+
+    // Add stylesheet
+    let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
+    this.stylesheet = this.chromeWin.document.createProcessingInstruction(
+      'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
+    this.chromeWin.document.insertBefore(this.stylesheet, this.chromeWin.document.firstChild);
+
     this.addPresenter(new VisualPresenter());
 
     // Implicitly add the Android presenter on Android.
     if (Utils.MozBuildApp == 'mobile/android')
       this.addPresenter(new AndroidPresenter());
     else if (Utils.MozBuildApp == 'b2g')
       this.addPresenter(new SpeechPresenter());
 
@@ -83,16 +107,18 @@ var AccessFu = {
    */
   _disable: function _disable() {
     if (!this._enabled)
       return;
     this._enabled = false;
 
     Logger.info('disable');
 
+    this.chromeWin.document.removeChild(this.stylesheet);
+
     this.presenters.forEach(function(p) { p.detach(); });
     this.presenters = [];
 
     VirtualCursorController.detach();
 
     Services.obs.removeObserver(this, 'accessible-event');
     this.chromeWin.removeEventListener('DOMActivate', this, true);
     this.chromeWin.removeEventListener('resize', this, true);
@@ -111,32 +137,34 @@ var AccessFu = {
 
     let ebtPref = ACCESSFU_DISABLE;
     try {
       ebtPref = (aTouchEnabled == undefined) ?
         this.prefsBranch.getIntPref('explorebytouch') : aTouchEnabled;
     } catch (x) {
     }
 
-    if (Utils.OS == 'Android') {
+    if (Utils.MozBuildApp == 'mobile/android') {
       if (accessPref == ACCESSFU_AUTO) {
         Cc['@mozilla.org/android/bridge;1'].
           getService(Ci.nsIAndroidBridge).handleGeckoMessage(
             JSON.stringify({ gecko: { type: 'Accessibility:Ready' } }));
         return;
       }
     }
 
     if (accessPref == ACCESSFU_ENABLE)
       this._enable();
     else
       this._disable();
 
-    VirtualCursorController.exploreByTouch = ebtPref == ACCESSFU_ENABLE;
-    Logger.info('Explore by touch:', VirtualCursorController.exploreByTouch);
+    if (ebtPref == ACCESSFU_ENABLE)
+      this.touchAdapter.attach(this.chromeWin);
+    else
+      this.touchAdapter.detach(this.chromeWin);
   },
 
   addPresenter: function addPresenter(presenter) {
     this.presenters.push(presenter);
     presenter.attach(this.chromeWin);
   },
 
   handleEvent: function handleEvent(aEvent) {
@@ -187,16 +215,24 @@ var AccessFu = {
         break;
       }
       case 'scroll':
       case 'resize':
       {
         this.presenters.forEach(function(p) { p.viewportChanged(); });
         break;
       }
+      case 'mozContentEvent':
+      {
+        if (aEvent.detail.type == 'accessibility-screenreader') {
+          let pref = aEvent.detail.enabled + 0;
+          this._processPreferences(pref, pref);
+        }
+        break;
+      }
     }
   },
 
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case 'Accessibility:Settings':
         this._processPreferences(JSON.parse(aData).enabled + 0,
                                  JSON.parse(aData).exploreByTouch + 0);
--- a/accessible/src/jsat/Presenters.jsm
+++ b/accessible/src/jsat/Presenters.jsm
@@ -112,38 +112,31 @@ VisualPresenter.prototype = {
   /**
    * The padding in pixels between the object and the highlight border.
    */
   BORDER_PADDING: 2,
 
   attach: function VisualPresenter_attach(aWindow) {
     this.chromeWin = aWindow;
 
-    // Add stylesheet
-    let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
-    this.stylesheet = aWindow.document.createProcessingInstruction(
-      'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
-    aWindow.document.insertBefore(this.stylesheet, aWindow.document.firstChild);
-
     // Add highlight box
     this.highlightBox = this.chromeWin.document.
       createElementNS('http://www.w3.org/1999/xhtml', 'div');
     this.chromeWin.document.documentElement.appendChild(this.highlightBox);
     this.highlightBox.id = 'virtual-cursor-box';
 
     // Add highlight inset for inner shadow
     let inset = this.chromeWin.document.
       createElementNS('http://www.w3.org/1999/xhtml', 'div');
     inset.id = 'virtual-cursor-inset';
 
     this.highlightBox.appendChild(inset);
   },
 
   detach: function VisualPresenter_detach() {
-    this.chromeWin.document.removeChild(this.stylesheet);
     this.highlightBox.parentNode.removeChild(this.highlightBox);
     this.highlightBox = this.stylesheet = null;
   },
 
   viewportChanged: function VisualPresenter_viewportChanged() {
     if (this._currentObject)
       this._highlight(this._currentObject);
   },
new file mode 100644
--- /dev/null
+++ b/accessible/src/jsat/TouchAdapter.jsm
@@ -0,0 +1,402 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+const Cr = Components.results;
+
+var EXPORTED_SYMBOLS = ['TouchAdapter', 'AndroidTouchAdapter'];
+
+Cu.import('resource://gre/modules/accessibility/Utils.jsm');
+
+// We should not be emitting explore events more than 10 times a second.
+// It is granular enough to feel natural, and it does not hammer the CPU.
+const EXPLORE_THROTTLE = 100;
+
+var TouchAdapter = {
+  // minimal swipe distance in inches
+  SWIPE_MIN_DISTANCE: 0.4,
+
+  // maximum duration of swipe
+  SWIPE_MAX_DURATION: 400,
+
+  // how straight does a swipe need to be
+  SWIPE_DIRECTNESS: 1.2,
+
+  // maximum consecutive
+  MAX_CONSECUTIVE_GESTURE_DELAY: 400,
+
+  // delay before tap turns into dwell
+  DWELL_THRESHOLD: 500,
+
+  // delay before distinct dwell events
+  DWELL_REPEAT_DELAY: 300,
+
+  // maximum distance the mouse could move during a tap in inches
+  TAP_MAX_RADIUS: 0.2,
+
+  attach: function TouchAdapter_attach(aWindow) {
+    if (this.chromeWin)
+      return;
+
+    Logger.info('TouchAdapter.attach');
+
+    this.chromeWin = aWindow;
+    this._touchPoints = {};
+    this._dwellTimeout = 0;
+    this._prevGestures = {};
+    this._lastExploreTime = 0;
+    this._dpi = this.chromeWin.QueryInterface(Ci.nsIInterfaceRequestor).
+      getInterface(Ci.nsIDOMWindowUtils).displayDPI;
+
+    this.glass = this.chromeWin.document.
+      createElementNS('http://www.w3.org/1999/xhtml', 'div');
+    this.glass.id = 'accessfu-glass';
+    this.chromeWin.document.documentElement.appendChild(this.glass);
+
+    this.glass.addEventListener('touchend', this, true, true);
+    this.glass.addEventListener('touchmove', this, true, true);
+    this.glass.addEventListener('touchstart', this, true, true);
+
+    if (Utils.OS != 'Android')
+      Mouse2Touch.attach(aWindow);
+  },
+
+  detach: function TouchAdapter_detach(aWindow) {
+    if (!this.chromeWin)
+      return;
+
+    Logger.info('TouchAdapter.detach');
+
+    this.glass.removeEventListener('touchend', this, true, true);
+    this.glass.removeEventListener('touchmove', this, true, true);
+    this.glass.removeEventListener('touchstart', this, true, true);
+    this.glass.parentNode.removeChild(this.glass);
+
+    if (Utils.OS != 'Android')
+      Mouse2Touch.detach(aWindow);
+
+    delete this.chromeWin;
+  },
+
+  handleEvent: function TouchAdapter_handleEvent(aEvent) {
+    let touches = aEvent.changedTouches;
+    switch (aEvent.type) {
+      case 'touchstart':
+        for (var i = 0; i < touches.length; i++) {
+          let touch = touches[i];
+          let touchPoint = new TouchPoint(touch, aEvent.timeStamp, this._dpi);
+          this._touchPoints[touch.identifier] = touchPoint;
+          this._lastExploreTime = aEvent.timeStamp + this.SWIPE_MAX_DURATION;
+        }
+        this._dwellTimeout = this.chromeWin.setTimeout(
+          (function () {
+             this.compileAndEmit(aEvent.timeStamp + this.DWELL_THRESHOLD);
+           }).bind(this), this.DWELL_THRESHOLD);
+        break;
+      case 'touchmove':
+        for (var i = 0; i < touches.length; i++) {
+          let touch = touches[i];
+          let touchPoint = this._touchPoints[touch.identifier];
+          touchPoint.update(touch, aEvent.timeStamp);
+        }
+        if (aEvent.timeStamp - this._lastExploreTime >= EXPLORE_THROTTLE) {
+          this.compileAndEmit(aEvent.timeStamp);
+          this._lastExploreTime = aEvent.timeStamp;
+        }
+        break;
+      case 'touchend':
+        for (var i = 0; i < touches.length; i++) {
+          let touch = touches[i];
+          let touchPoint = this._touchPoints[touch.identifier];
+          touchPoint.update(touch, aEvent.timeStamp);
+          touchPoint.finish();
+        }
+        this.compileAndEmit(aEvent.timeStamp);
+        break;
+    }
+  },
+
+  cleanupTouches: function cleanupTouches() {
+    for (var identifier in this._touchPoints) {
+      if (!this._touchPoints[identifier].done)
+        continue;
+
+      delete this._touchPoints[identifier];
+    }
+  },
+
+  compile: function TouchAdapter_compile(aTime) {
+    let multiDetails = {};
+
+    // Compound multiple simultaneous touch gestures.
+    for (let identifier in this._touchPoints) {
+      let touchPoint = this._touchPoints[identifier];
+      let details = touchPoint.compile(aTime);
+
+      if (!details)
+        continue;
+
+      details.touches = [identifier];
+
+      let otherTouches = multiDetails[details.type];
+      if (otherTouches) {
+        otherTouches.touches.push(identifier);
+        otherTouches.startTime =
+          Math.min(otherTouches.startTime, touchPoint.startTime);
+      } else {
+        details.startTime = touchPoint.startTime;
+        details.endTime = aTime;
+        multiDetails[details.type] = details;
+      }
+    }
+
+    // Compound multiple consecutive touch gestures.
+    for each (let details in multiDetails) {
+      let idhash = details.touches.slice().sort().toString();
+      let prevGesture = this._prevGestures[idhash];
+
+      if (prevGesture) {
+        // The time delta is calculated as the period between the end of the
+        // last gesture and the start of this one.
+        let timeDelta = details.startTime - prevGesture.endTime;
+        if (timeDelta > this.MAX_CONSECUTIVE_GESTURE_DELAY) {
+          delete this._prevGestures[idhash];
+        } else {
+          if (details.type == 'tap' && prevGesture.type == 'tap')
+            details.type = 'doubletap';
+          if (details.type == 'tap' && prevGesture.type == 'doubletap')
+            details.type = 'tripletap';
+          if (details.type == 'dwell' && prevGesture.type == 'tap')
+            details.type = 'taphold';
+        }
+      }
+
+      this._prevGestures[idhash] = details;
+    }
+
+    this.chromeWin.clearTimeout(this._dwellTimeout);
+    this.cleanupTouches();
+
+    return multiDetails;
+  },
+
+  emitGesture: function TouchAdapter_emitGesture(aDetails) {
+    let evt = this.chromeWin.document.createEvent('CustomEvent');
+    evt.initCustomEvent('mozAccessFuGesture', true, true, aDetails);
+    this.chromeWin.dispatchEvent(evt);
+  },
+
+  compileAndEmit: function TouchAdapter_compileAndEmit(aTime) {
+    for each (let details in this.compile(aTime)) {
+      this.emitGesture(details);
+    }
+  }
+};
+
+/***
+ * A TouchPoint represents a single touch from the moment of contact until it is
+ * lifted from the surface. It is capable of compiling gestures from the scope
+ * of one single touch.
+ */
+function TouchPoint(aTouch, aTime, aDPI) {
+  this.startX = aTouch.screenX;
+  this.startY = aTouch.screenY;
+  this.startTime = aTime;
+  this.distanceTraveled = 0;
+  this.dpi = aDPI;
+  this.done = false;
+}
+
+TouchPoint.prototype = {
+  update: function TouchPoint_update(aTouch, aTime) {
+    let lastX = this.x;
+    let lastY = this.y;
+    this.x = aTouch.screenX;
+    this.y = aTouch.screenY;
+    this.time = aTime;
+
+    if (lastX != undefined && lastY != undefined)
+      this.distanceTraveled += this.getDistanceToCoord(lastX, lastY);
+  },
+
+  getDistanceToCoord: function TouchPoint_getDistanceToCoord(aX, aY) {
+    return Math.sqrt(Math.pow(this.x - aX, 2) + Math.pow(this.y - aY, 2));
+  },
+
+  finish: function TouchPoint_finish() {
+    this.done = true;
+  },
+
+  /**
+   * Compile a gesture from an individual touch point. This is used by the
+   * TouchAdapter to compound multiple single gestures in to higher level
+   * gestures.
+   */
+  compile: function TouchPoint_compile(aTime) {
+    let directDistance = this.directDistanceTraveled;
+    let duration = aTime - this.startTime;
+
+    // To be considered a tap/dwell...
+    if ((this.distanceTraveled / this.dpi) < TouchAdapter.TAP_MAX_RADIUS) { // Didn't travel
+      if (duration < TouchAdapter.DWELL_THRESHOLD) {
+        // Mark it as done so we don't use this touch for another gesture.
+        this.finish();
+        return {type: 'tap', x: this.startX, y: this.startY};
+      } else if (!this.done && duration == TouchAdapter.DWELL_THRESHOLD) {
+        return {type: 'dwell', x: this.startX, y: this.startY};
+      }
+    }
+
+    // To be considered a swipe...
+    if (duration <= TouchAdapter.SWIPE_MAX_DURATION && // Quick enough
+        (directDistance / this.dpi) >= TouchAdapter.SWIPE_MIN_DISTANCE && // Traveled far
+        (directDistance * 1.2) >= this.distanceTraveled) { // Direct enough
+
+      let swipeGesture = {x1: this.startX, y1: this.startY,
+                          x2: this.x, y2: this.y};
+      let deltaX = this.x - this.startX;
+      let deltaY = this.y - this.startY;
+
+      if (Math.abs(deltaX) > Math.abs(deltaY)) {
+        // Horizontal swipe.
+        if (deltaX > 0)
+          swipeGesture.type = 'swiperight';
+        else
+          swipeGesture.type = 'swipeleft';
+      } else if (Math.abs(deltaX) < Math.abs(deltaY)) {
+        // Vertical swipe.
+        if (deltaY > 0)
+          swipeGesture.type = 'swipedown';
+        else
+          swipeGesture.type = 'swipeup';
+      } else {
+        // A perfect 45 degree swipe?? Not in our book.
+          return null;
+      }
+
+      this.finish();
+
+      return swipeGesture;
+    }
+
+    // To be considered an explore...
+    if (!this.done &&
+        duration > TouchAdapter.SWIPE_MAX_DURATION &&
+        (this.distanceTraveled / this.dpi) > TouchAdapter.TAP_MAX_RADIUS) {
+      return {type: 'explore', x: this.x, y: this.y};
+    }
+
+    return null;
+  },
+
+  get directDistanceTraveled() {
+    return this.getDistanceToCoord(this.startX, this.startY);
+  }
+};
+
+var Mouse2Touch = {
+  _MouseToTouchMap: {
+    mousedown: 'touchstart',
+    mouseup: 'touchend',
+    mousemove: 'touchmove'
+  },
+
+  attach: function Mouse2Touch_attach(aWindow) {
+    this.chromeWin = aWindow;
+    this.chromeWin.addEventListener('mousedown', this, true, true);
+    this.chromeWin.addEventListener('mouseup', this, true, true);
+    this.chromeWin.addEventListener('mousemove', this, true, true);
+  },
+
+  detach: function Mouse2Touch_detach(aWindow) {
+    this.chromeWin.removeEventListener('mousedown', this, true, true);
+    this.chromeWin.removeEventListener('mouseup', this, true, true);
+    this.chromeWin.removeEventListener('mousemove', this, true, true);
+  },
+
+  handleEvent: function Mouse2Touch_handleEvent(aEvent) {
+    if (aEvent.buttons == 0)
+      return;
+
+    let name = this._MouseToTouchMap[aEvent.type];
+    let evt = this.chromeWin.document.createEvent("touchevent");
+    let points = [this.chromeWin.document.createTouch(
+                    this.chromeWin, aEvent.target, 0,
+                    aEvent.pageX, aEvent.pageY, aEvent.screenX, aEvent.screenY,
+                    aEvent.clientX, aEvent.clientY, 1, 1, 0, 0)];
+
+    // Simulate another touch point at a 5px offset when ctrl is pressed.
+    if (aEvent.ctrlKey)
+      points.push(this.chromeWin.document.createTouch(
+                    this.chromeWin, aEvent.target, 1,
+                    aEvent.pageX + 5, aEvent.pageY + 5,
+                    aEvent.screenX + 5, aEvent.screenY + 5,
+                    aEvent.clientX + 5, aEvent.clientY + 5,
+                    1, 1, 0, 0));
+
+    // Simulate another touch point at a -5px offset when alt is pressed.
+    if (aEvent.altKey)
+      points.push(this.chromeWin.document.createTouch(
+                    this.chromeWin, aEvent.target, 2,
+                    aEvent.pageX - 5, aEvent.pageY - 5,
+                    aEvent.screenX - 5, aEvent.screenY - 5,
+                    aEvent.clientX - 5, aEvent.clientY - 5,
+                    1, 1, 0, 0));
+
+    let touches = this.chromeWin.document.createTouchList(points);
+    if (name == "touchend") {
+      let empty = this.chromeWin.document.createTouchList();
+      evt.initTouchEvent(name, true, true, this.chromeWin, 0,
+                         false, false, false, false, empty, empty, touches);
+    } else {
+      evt.initTouchEvent(name, true, true, this.chromeWin, 0,
+                         false, false, false, false, touches, touches, touches);
+    }
+    aEvent.target.dispatchEvent(evt);
+    aEvent.preventDefault();
+    aEvent.stopImmediatePropagation();
+  }
+};
+
+var AndroidTouchAdapter = {
+  attach: function AndroidTouchAdapter_attach(aWindow) {
+    if (this.chromeWin)
+      return;
+
+    Logger.info('AndroidTouchAdapter.attach');
+
+    this.chromeWin = aWindow;
+    this.chromeWin.addEventListener('mousemove', this, true, true);
+    this._lastExploreTime = 0;
+  },
+
+  detach: function AndroidTouchAdapter_detach(aWindow) {
+    if (!this.chromeWin)
+      return;
+
+    Logger.info('AndroidTouchAdapter.detach');
+
+    this.chromeWin.removeEventListener('mousemove', this, true, true);
+    delete this.chromeWin;
+  },
+
+  handleEvent: function AndroidTouchAdapter_handleEvent(aEvent) {
+    // On non-Android we use the shift key to simulate touch.
+    if (Utils.MozBuildApp != 'mobile/android' && !aEvent.shiftKey)
+      return;
+
+    if (aEvent.timeStamp - this._lastExploreTime >= EXPLORE_THROTTLE) {
+      let evt = this.chromeWin.document.createEvent('CustomEvent');
+      evt.initCustomEvent(
+        'mozAccessFuGesture', true, true,
+        {type: 'explore', x: aEvent.screenX, y: aEvent.screenY});
+      this.chromeWin.dispatchEvent(evt);
+      this._lastExploreTime = aEvent.timeStamp;
+    }
+  }
+};
\ No newline at end of file
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -66,16 +66,30 @@ var Utils = {
   },
 
   getCurrentContentDoc: function getCurrentContentDoc(aWindow) {
     if (this.MozBuildApp == "b2g")
       return this.getBrowserApp(aWindow).contentBrowser.contentDocument;
     return this.getBrowserApp(aWindow).selectedBrowser.contentDocument;
   },
 
+  getAllDocuments: function getAllDocuments(aWindow) {
+    let doc = gAccRetrieval.
+      getAccessibleFor(this.getCurrentContentDoc(aWindow)).
+      QueryInterface(Ci.nsIAccessibleDocument);
+    let docs = [];
+    function getAllDocuments(aDocument) {
+      docs.push(aDocument.DOMDocument);
+      for (let i = 0; i < aDocument.childDocumentCount; i++)
+        getAllDocuments(aDocument.getChildDocumentAt(i));
+    }
+    getAllDocuments(doc);
+    return docs;
+  },
+
   getViewport: function getViewport(aWindow) {
     switch (this.MozBuildApp) {
       case 'mobile/android':
         return aWindow.BrowserApp.selectedTab.getViewport();
       default:
         return null;
     }
   },
@@ -98,16 +112,93 @@ var Utils = {
       try {
         return doc.QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor;
       } catch (x) {
         doc = doc.parentDocument;
       }
     }
 
     return null;
+  },
+
+  scroll: function scroll(aWindow, aPage, aHorizontal) {
+    for each (let doc in this.getAllDocuments(aWindow)) {
+      // First see if we could scroll a window.
+      let win = doc.defaultView;
+      if (!aHorizontal && win.scrollMaxY &&
+          ((aPage > 0 && win.scrollY < win.scrollMaxY) ||
+           (aPage < 0 && win.scrollY > 0))) {
+        win.scroll(0, win.innerHeight);
+        return true;
+      } else if (aHorizontal && win.scrollMaxX &&
+                 ((aPage > 0 && win.scrollX < win.scrollMaxX) ||
+                  (aPage < 0 && win.scrollX > 0))) {
+        win.scroll(win.innerWidth, 0);
+        return true;
+      }
+
+      // Second, try to scroll main section or current target if there is no
+      // main section.
+      let main = doc.querySelector('[role=main]') ||
+        doc.querySelector(':target');
+
+      if (main) {
+        if ((!aHorizontal && main.clientHeight < main.scrollHeight) ||
+          (aHorizontal && main.clientWidth < main.scrollWidth)) {
+          let s = win.getComputedStyle(main);
+          if (!aHorizontal) {
+            if (s.overflowY == 'scroll' || s.overflowY == 'auto') {
+              main.scrollTop += aPage * main.clientHeight;
+              return true;
+            }
+          } else {
+            if (s.overflowX == 'scroll' || s.overflowX == 'auto') {
+              main.scrollLeft += aPage * main.clientWidth;
+              return true;
+            }
+          }
+        }
+      }
+    }
+
+    return false;
+  },
+
+  changePage: function changePage(aWindow, aPage) {
+    for each (let doc in this.getAllDocuments(aWindow)) {
+      // Get current main section or active target.
+      let main = doc.querySelector('[role=main]') ||
+        doc.querySelector(':target');
+      if (!main)
+        continue;
+
+      let mainAcc = gAccRetrieval.getAccessibleFor(main);
+      if (!mainAcc)
+        continue;
+
+      let controllers = mainAcc.
+        getRelationByType(Ci.nsIAccessibleRelation.RELATION_CONTROLLED_BY);
+
+      for (var i=0; controllers.targetsCount > i; i++) {
+        let controller = controllers.getTarget(i);
+        // If the section has a controlling slider, it should be considered
+        // the page-turner.
+        if (controller.role == Ci.nsIAccessibleRole.ROLE_SLIDER) {
+          // Sliders are controlled with ctrl+right/left. I just decided :)
+          let evt = doc.createEvent("KeyboardEvent");
+          evt.initKeyEvent('keypress', true, true, null,
+                           true, false, false, false,
+                           (aPage > 0) ? evt.DOM_VK_RIGHT : evt.DOM_VK_LEFT, 0);
+          controller.DOMNode.dispatchEvent(evt);
+          return true;
+        }
+      }
+    }
+
+    return false;
   }
 };
 
 var Logger = {
   DEBUG: 0,
   INFO: 1,
   WARNING: 2,
   ERROR: 3,
--- a/accessible/src/jsat/UtteranceGenerator.jsm
+++ b/accessible/src/jsat/UtteranceGenerator.jsm
@@ -147,17 +147,17 @@ var UtteranceGenerator = {
     'toolbar': INCLUDE_DESC,
     'table': INCLUDE_DESC | INCLUDE_NAME,
     'link': INCLUDE_DESC,
     'listitem': INCLUDE_DESC,
     'outline': INCLUDE_DESC,
     'outlineitem': INCLUDE_DESC,
     'pagetab': INCLUDE_DESC,
     'graphic': INCLUDE_DESC,
-    'pushbutton': INCLUDE_DESC,
+    'pushbutton': INCLUDE_DESC | INCLUDE_NAME,
     'checkbutton': INCLUDE_DESC,
     'radiobutton': INCLUDE_DESC,
     'combobox': INCLUDE_DESC,
     'droplist': INCLUDE_DESC,
     'progressbar': INCLUDE_DESC,
     'slider': INCLUDE_DESC,
     'spinbutton': INCLUDE_DESC,
     'diagram': INCLUDE_DESC,
--- a/accessible/src/jsat/VirtualCursorController.jsm
+++ b/accessible/src/jsat/VirtualCursorController.jsm
@@ -192,101 +192,102 @@ var TraversalRules = {
 
 var VirtualCursorController = {
   exploreByTouch: false,
   editableState: 0,
 
   attach: function attach(aWindow) {
     this.chromeWin = aWindow;
     this.chromeWin.document.addEventListener('keypress', this, true);
-    this.chromeWin.document.addEventListener('mousemove', this, true);
+    this.chromeWin.addEventListener('mozAccessFuGesture', this, true);
   },
 
   detach: function detach() {
     this.chromeWin.document.removeEventListener('keypress', this, true);
-    this.chromeWin.document.removeEventListener('mousemove', this, true);
+    this.chromeWin.removeEventListener('mozAccessFuGesture', this, true);
   },
 
   handleEvent: function VirtualCursorController_handleEvent(aEvent) {
     switch (aEvent.type) {
       case 'keypress':
         this._handleKeypress(aEvent);
         break;
-      case 'mousemove':
-        this._handleMousemove(aEvent);
+      case 'mozAccessFuGesture':
+        this._handleGesture(aEvent);
         break;
     }
   },
 
-  _handleMousemove: function _handleMousemove(aEvent) {
-    // Explore by touch is disabled.
-    if (!this.exploreByTouch)
-      return;
+  _handleGesture: function _handleGesture(aEvent) {
+    let document = Utils.getCurrentContentDoc(this.chromeWin);
+    let detail = aEvent.detail;
+    Logger.info('Gesture', detail.type,
+                '(fingers: ' + detail.touches.length + ')');
 
-    // On non-Android we use the shift key to simulate touch.
-    if (Utils.OS != 'Android' && !aEvent.shiftKey)
-      return;
-
-    // We should not be calling moveToPoint more than 10 times a second.
-    // It is granular enough to feel natural, and it does not hammer the CPU.
-    if (!this._handleMousemove._lastEventTime ||
-        aEvent.timeStamp - this._handleMousemove._lastEventTime >= 100) {
-      this.moveToPoint(Utils.getCurrentContentDoc(this.chromeWin),
-                       aEvent.screenX, aEvent.screenY);
-      this._handleMousemove._lastEventTime = aEvent.timeStamp;
+    if (detail.touches.length == 1) {
+      switch (detail.type) {
+        case 'swiperight':
+          this.moveForward(document, aEvent.shiftKey);
+          break;
+        case 'swipeleft':
+          this.moveBackward(document, aEvent.shiftKey);
+          break;
+        case 'doubletap':
+          this.activateCurrent(document);
+          break;
+        case 'explore':
+          this.moveToPoint(document, detail.x, detail.y);
+          break;
+      }
     }
 
-    aEvent.preventDefault();
-    aEvent.stopImmediatePropagation();
+    if (detail.touches.length == 3) {
+      switch (detail.type) {
+        case 'swiperight':
+          if (!Utils.scroll(this.chromeWin, -1, true))
+            Utils.changePage(this.chromeWin, -1);
+          break;
+        case 'swipedown':
+          Utils.scroll(this.chromeWin, -1);
+          break;
+        case 'swipeleft':
+          if (!Utils.scroll(this.chromeWin, 1, true))
+            Utils.changePage(this.chromeWin, 1);
+        case 'swipeup':
+          Utils.scroll(this.chromeWin, 1);
+          break;
+      }
+    }
   },
 
   _handleKeypress: function _handleKeypress(aEvent) {
     let document = Utils.getCurrentContentDoc(this.chromeWin);
     let target = aEvent.target;
 
+    // Ignore keys with modifiers so the content could take advantage of them.
+    if (aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
+      return;
+
     switch (aEvent.keyCode) {
       case 0:
         // an alphanumeric key was pressed, handle it separately.
         // If it was pressed with either alt or ctrl, just pass through.
         // If it was pressed with meta, pass the key on without the meta.
-        if (this.editableState ||
-            aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
+        if (this.editableState)
           return;
 
         let key = String.fromCharCode(aEvent.charCode);
         let methodName = '', rule = {};
         try {
           [methodName, rule] = this.keyMap[key];
         } catch (x) {
           return;
         }
         this[methodName](document, false, rule);
         break;
-      case aEvent.DOM_VK_END:
-        if (this.editableState) {
-          if (target.selectionEnd != target.textLength)
-            // Don't move forward if caret is not at end of entry.
-            // XXX: Fix for rtl
-            return;
-          else
-            target.blur();
-        }
-        this.moveForward(document, true);
-        break;
-      case aEvent.DOM_VK_HOME:
-        if (this.editableState) {
-          if (target.selectionEnd != 0)
-            // Don't move backward if caret is not at start of entry.
-            // XXX: Fix for rtl
-            return;
-          else
-            target.blur();
-        }
-        this.moveBackward(document, true);
-        break;
       case aEvent.DOM_VK_RIGHT:
         if (this.editableState) {
           if (target.selectionEnd != target.textLength)
             // Don't move forward if caret is not at end of entry.
             // XXX: Fix for rtl
             return;
           else
             target.blur();
@@ -308,17 +309,17 @@ var VirtualCursorController = {
         if (this.editableState & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) {
           if (target.selectionEnd != 0)
             // Don't blur content if caret is not at start of text area.
             return;
           else
             target.blur();
         }
 
-        if (Utils.OS == 'Android')
+        if (Utils.MozBuildApp == 'mobile/android')
           // Return focus to native Android browser chrome.
           Cc['@mozilla.org/android/bridge;1'].
             getService(Ci.nsIAndroidBridge).handleGeckoMessage(
               JSON.stringify({ gecko: { type: 'ToggleChrome:Focus' } }));
         break;
       case aEvent.DOM_VK_RETURN:
       case aEvent.DOM_VK_ENTER:
         if (this.editableState)
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -483,22 +483,35 @@ pref("dom.experimental_forms", true);
 pref("gfx.gralloc.enabled", false);
 
 // XXXX REMOVE FOR PRODUCTION. Turns on GC and CC logging 
 pref("javascript.options.mem.log", true);
 
 // Increase mark slice time from 10ms to 30ms
 pref("javascript.options.mem.gc_incremental_slice_ms", 30);
 
+pref("javascript.options.mem.gc_high_frequency_heap_growth_max", 120);
+pref("javascript.options.mem.gc_high_frequency_heap_growth_min", 101);
+pref("javascript.options.mem.gc_high_frequency_high_limit_mb", 40);
+pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 10);
+pref("javascript.options.mem.gc_low_frequency_heap_growth", 105);
+pref("javascript.options.mem.high_water_mark", 16);
+
 // Show/Hide scrollbars when active/inactive
 pref("ui.showHideScrollbars", 1);
 
 // Enable the ProcessPriorityManager, and give processes with no visible
 // documents a 1s grace period before they're eligible to be marked as
 // background.
 pref("dom.ipc.processPriorityManager.enabled", true);
 pref("dom.ipc.processPriorityManager.gracePeriodMS", 1000);
 pref("hal.processPriorityManager.gonk.masterOomAdjust", 0);
 pref("hal.processPriorityManager.gonk.foregroundOomAdjust", 1);
 pref("hal.processPriorityManager.gonk.backgroundOomAdjust", 2);
 pref("hal.processPriorityManager.gonk.masterNice", -1);
 pref("hal.processPriorityManager.gonk.foregroundNice", 0);
 pref("hal.processPriorityManager.gonk.backgroundNice", 10);
+
+// Enable pre-launching content processes for improved startup time
+// (hiding latency).
+pref("dom.ipc.processPrelauch.enabled", true);
+// Wait this long before pre-launching a new subprocess.
+pref("dom.ipc.processPrelauch.delayMs", 1000);
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/arrow.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="11px" style="position: absolute; top: -moz-calc(50% - 2px);">
+  <polyline points="1 1 5 6 9 1" stroke="#414141" stroke-width="2" stroke-linecap="round" fill="transparent" stroke-linejoin="round"/>
+</svg>
--- a/b2g/chrome/content/content.css
+++ b/b2g/chrome/content/content.css
@@ -69,8 +69,221 @@ xul|thumb {
   border: 1px solid rgba(255, 255, 255, 0.4) !important;
   border-radius: 3px;
 }
 
 /* -moz-touch-enabled? media elements */
 :-moz-any(video, audio) > xul|videocontrols {
   -moz-binding: url("chrome://global/content/bindings/videocontrols.xml#touchControls");
 }
+
+select:not([size]):not([multiple]) > xul|scrollbar,
+select[size="1"] > xul|scrollbar,
+select:not([size]):not([multiple]) xul|scrollbarbutton,
+select[size="1"] xul|scrollbarbutton {
+  display: block;
+  margin-left: 0;
+  min-width: 16px;
+}
+
+/* Override inverse OS themes */
+select,
+textarea,
+button,
+xul|button,
+* > input:not([type="image"]) {
+  -moz-appearance: none !important;  /* See bug 598421 for fixing the platform */
+  border-radius: 3px;
+}
+
+select[size],
+select[multiple],
+select[size][multiple],
+textarea,
+* > input:not([type="image"]) {
+  border-style: solid;
+  border-color: #7d7d7d;
+  color: #414141;
+  background: white -moz-linear-gradient(top, rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 3px, rgba(255,255,255,0.2) 16px);
+}
+
+/* Selects are handled by the form helper, see bug 685197 */
+select option, select optgroup {
+  pointer-events: none;
+}
+
+input:-moz-placeholder,
+textarea:-moz-placeholder {
+  color: GrayText;
+}
+
+select:not([size]):not([multiple]),
+select[size="0"],
+select[size="1"],
+* > input[type="button"],
+* > input[type="submit"],
+* > input[type="reset"],
+button {
+  border-style: solid;
+  border-color: #7d7d7d;
+  color: #414141;
+  background: white -moz-linear-gradient(top, rgba(255,255,255,0.2) 0, rgba(215,215,215,0.5) 18px, rgba(115,115,115,0.5) 100%);
+}
+
+input[type="checkbox"] {
+  background: white -moz-linear-gradient(top, rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 2px, rgba(255,255,255,0.2) 6px);
+}
+
+input[type="radio"] {
+  background: -moz-radial-gradient(6px 6px, cover, rgba(255,255,255,0.2) 3px, rgba(195,195,195,0.5) 5px, rgba(115,115,115,0.5) 100%);
+}
+
+select {
+  border-width: 1px;
+  padding: 1px;
+}
+
+select:not([size]):not([multiple]),
+select[size="0"],
+select[size="1"] {
+  padding: 0 1px 0 1px;
+}
+
+* > input:not([type="image"]) {
+  border-width: 1px;
+  padding: 1px;
+}
+
+textarea {
+  resize: none;
+  border-width: 1px;
+  padding: 2px 1px 2px 1px;
+}
+
+input[type="button"],
+input[type="submit"],
+input[type="reset"],
+button {
+  border-width: 1px;
+  padding: 0 7px 0 7px;
+}
+
+input[type="radio"],
+input[type="checkbox"] {
+  max-width: 14px;
+  max-height: 14px;
+  border: 1px solid #a7a7a7 !important;
+  padding: 2px 1px 2px 1px;
+}
+
+select > button {
+  border-width: 0px !important;
+  margin: 0px !important;
+  padding: 0px !important;
+  border-radius: 0;
+  color: #414141;
+
+  background-image: -moz-radial-gradient(bottom left, #bbbbbb 40%, #f5f5f5), url(arrow.svg) !important;
+  background-color: transparent;
+  background-position: -15px center, 4px center !important;
+  background-repeat: no-repeat, no-repeat !important;
+  background-size: 100% 90%, normal normal;
+
+  -moz-binding: none !important;
+  position: relative !important;
+  font-size: inherit;
+}
+
+select[size]:focus,
+select[multiple]:focus,
+select[size][multiple]:focus,
+textarea:focus,
+input[type="file"]:focus > input[type="text"],
+* > input:not([type="image"]):focus {
+  outline: 0px !important;
+  border-style: solid;
+  border-color: rgb(94,128,153);
+  background: white -moz-linear-gradient(top, rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 3px, rgba(255,255,255,0.2) 16px);
+}
+
+select:not([size]):not([multiple]):focus,
+select[size="0"]:focus,
+select[size="1"]:focus,
+input[type="button"]:focus,
+input[type="submit"]:focus,
+input[type="reset"]:focus,
+button:focus {
+  outline: 0px !important;
+  border-style: solid;
+  border-color: rgb(94,128,153);
+  background: white -moz-linear-gradient(top, rgba(255,255,255,0.2) 0, rgba(198,225,256,0.2) 18px, rgba(27,113,177,0.5) 100%);
+}
+
+input[type="checkbox"]:focus,
+input[type="radio"]:focus {
+  border-color: #99c6e0 !important;
+}
+
+input[type="checkbox"]:focus {
+  background: white -moz-linear-gradient(top, rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 2px, rgba(255,255,255,0.2) 6px);
+}
+
+input[type="radio"]:focus {
+  background: -moz-radial-gradient(6px 6px, cover, rgba(255,255,255,0.2) 3px, rgba(198,225,246,0.2) 5px, rgba(27,113,177,0.5) 100%);
+}
+
+/* we need to be specific for selects because the above rules are specific too */
+textarea[disabled],
+select[size][disabled],
+select[multiple][disabled],
+select[size][multiple][disabled],
+select:not([size]):not([multiple])[disabled],
+select[size="0"][disabled],
+select[size="1"][disabled],
+button[disabled],
+* > input:not([type="image"])[disabled] {
+  color: rgba(0,0,0,0.3);
+  border-color: rgba(125,125,125,0.4);
+  border-style: solid;
+  border-width: 1px;
+  background: transparent -moz-linear-gradient(top, rgba(185,185,185,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(255,255,255,0.4) 100%);
+}
+
+select:not([size]):not([multiple])[disabled],
+select[size="0"][disabled],
+select[size="1"][disabled] {
+  background: transparent -moz-linear-gradient(top, rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
+}
+
+input[type="button"][disabled],
+input[type="submit"][disabled],
+input[type="reset"][disabled],
+button[disabled="true"] {
+  padding: 0 7px 0 7px;
+  background: transparent -moz-linear-gradient(top, rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
+}
+
+input[type="radio"][disabled],
+input[type="radio"][disabled]:active,
+input[type="radio"][disabled]:hover,
+input[type="radio"][disabled]:hover:active,
+input[type="checkbox"][disabled],
+input[type="checkbox"][disabled]:active,
+input[type="checkbox"][disabled]:hover,
+input[type="checkbox"][disabled]:hover:active {
+  border:1px solid rgba(125,125,125,0.4) !important;
+}
+
+select[disabled] > button {
+  opacity: 0.6;
+  padding: 1px 7px 1px 7px;
+}
+
+*:-moz-any-link:active,
+*[role=button]:active,
+button:active,
+input:active,
+option:active,
+select:active,
+label:active,
+textarea:active {
+  background-color: rgba(141, 184, 216, 0.5);
+}
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/runapp.js
@@ -0,0 +1,93 @@
+// runapp.js:
+// Provide a --runapp APPNAME command-line option.
+
+window.addEventListener('load', function() {
+  // Get the command line arguments that were passed to the b2g client
+  let args = window.arguments[0].QueryInterface(Ci.nsICommandLine);
+  let appname;
+
+  // - Check if the argument is present before doing any work.
+  try {
+    // Returns null if the argument was not specified.  Throws
+    // NS_ERROR_INVALID_ARG if there is no parameter specified (because
+    // it was the last argument or the next argument starts with '-').
+    // However, someone could still explicitly pass an empty argument!
+    appname = args.handleFlagWithParam('runapp', false);
+  }
+  catch(e) {
+    // treat a missing parameter like an empty parameter (=> show usage)
+    appname = '';
+  }
+
+  // not specified, bail.
+  if (appname === null)
+    return;
+
+  // - Get the list of apps since the parameter was specified
+  let appsReq = navigator.mozApps.mgmt.getAll();
+  appsReq.onsuccess = function() {
+    let apps = appsReq.result;
+    function findAppWithName(name) {
+      let normalizedSearchName = name.replace(/[- ]+/g, '').toLowerCase();
+
+      for (let i = 0; i < apps.length; i++) {
+        let app = apps[i];
+        let normalizedAppName =
+              app.manifest.name.replace(/[- ]+/g, '').toLowerCase();
+        if (normalizedSearchName === normalizedAppName) {
+          return app;
+        }
+      }
+      return null;
+    }
+
+    function usageAndDie(justApps) {
+      if (!justApps)
+        dump(
+          'The --runapp argument specifies an app to automatically run at\n'+
+          'startup.  We match against app names per their manifest and \n' +
+          'ignoring capitalization, dashes, and whitespace.\n' +
+          '\nThe system will load as usual except the lock screen will be ' +
+          'automatically be disabled.\n\n' +
+          'Known apps:\n');
+
+      for (let i = 0; i < apps.length; i++) {
+        dump('  ' + apps[i].manifest.name + '\n');
+      }
+
+      // Exit the b2g client
+      Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
+    }
+
+    if (appname === '') {
+      usageAndDie();
+      return;
+    }
+
+    let app = findAppWithName(appname);
+    if (!app) {
+      dump('Could not find app: "' + appname + '". Maybe you meant one of:\n');
+      usageAndDie(true);
+      return;
+    }
+
+    let setReq =
+      navigator.mozSettings.getLock().set({'lockscreen.enabled': false});
+    setReq.onsuccess = function() {
+      // give the event loop another turn to disable the lock screen
+      window.setTimeout(function() {
+        dump('--runapp launching app: ' + app.manifest.name + '\n');
+        app.launch();
+      }, 0);
+    };
+    setReq.onerror = function() {
+      dump('--runapp failed to disable lock-screen.  Giving up.\n');
+    };
+
+    dump('--runapp found app: ' + app.manifest.name +
+         ', disabling lock screen...\n');
+ };
+ appsReq.onerror = function() {
+   dump('Problem getting the list of all apps!');
+ };
+});
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -11,16 +11,18 @@ const Cr = Components.results;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/ContactService.jsm');
 Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
 Cu.import('resource://gre/modules/Webapps.jsm');
 Cu.import('resource://gre/modules/AlarmService.jsm');
 Cu.import('resource://gre/modules/ActivitiesService.jsm');
+Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
+Cu.import('resource://gre/modules/ObjectWrapper.jsm');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'env',
                                    '@mozilla.org/process/environment;1',
                                    'nsIEnvironment');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'ss',
                                    '@mozilla.org/content/style-sheet-service;1',
                                    'nsIStyleSheetService');
@@ -39,16 +41,21 @@ XPCOMUtils.defineLazyServiceGetter(Servi
                                    '@mozilla.org/focus-manager;1',
                                    'nsIFocusManager');
 
 XPCOMUtils.defineLazyGetter(this, 'DebuggerServer', function() {
   Cu.import('resource://gre/modules/devtools/dbg-server.jsm');
   return DebuggerServer;
 });
 
+XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
+  return Cc["@mozilla.org/parentprocessmessagemanager;1"]
+         .getService(Ci.nsIFrameMessageManager);
+});
+
 function getContentWindow() {
   return shell.contentBrowser.contentWindow;
 }
 
 var shell = {
 
   get CrashSubmit() {
     delete this.CrashSubmit;
@@ -144,26 +151,29 @@ var shell = {
     SettingsListener.observe("debug.fps.enabled", false, function(value) {
       Services.prefs.setBoolPref("layers.acceleration.draw-fps", value);
     });
     SettingsListener.observe("debug.paint-flashing.enabled", false, function(value) {
       Services.prefs.setBoolPref("nglayout.debug.paint_flashing", value);
     });
 
     this.contentBrowser.src = homeURL;
+
+    ppmm.addMessageListener("content-handler", this);
   },
 
   stop: function shell_stop() {
     window.removeEventListener('keydown', this, true);
     window.removeEventListener('keypress', this, true);
     window.removeEventListener('keyup', this, true);
     window.removeEventListener('MozApplicationManifest', this);
     window.removeEventListener('mozfullscreenchange', this);
     window.removeEventListener('sizemodechange', this);
     this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
+    ppmm.removeMessageListener("content-handler", this);
 
 #ifndef MOZ_WIDGET_GONK
     delete Services.audioManager;
 #endif
   },
 
   // If this key event actually represents a hardware button, filter it here
   // and send a mozChromeEvent with detail.type set to xxx-button-press or
@@ -293,23 +303,40 @@ var shell = {
                               .getService(Ci.nsIOfflineCacheUpdateService);
           updateService.scheduleUpdate(manifestURI, documentURI, window);
         } catch (e) {
           dump('Error while creating offline cache: ' + e + '\n');
         }
         break;
     }
   },
+
   sendEvent: function shell_sendEvent(content, type, details) {
     let event = content.document.createEvent('CustomEvent');
     event.initCustomEvent(type, true, true, details ? details : {});
     content.dispatchEvent(event);
   },
+
   sendChromeEvent: function shell_sendChromeEvent(details) {
-    this.sendEvent(getContentWindow(), "mozChromeEvent", details);
+    this.sendEvent(getContentWindow(), "mozChromeEvent",
+                   ObjectWrapper.wrap(details, getContentWindow()));
+  },
+
+  receiveMessage: function shell_receiveMessage(message) {
+    if (message.name != 'content-handler') {
+      return;
+    }
+    let handler = message.json;
+    new MozActivity({
+      name: 'view',
+      data: {
+        type: handler.type,
+        url: handler.url
+      }
+    });
   }
 };
 
 function nsBrowserAccess() {
 }
 
 nsBrowserAccess.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow]),
@@ -342,24 +369,25 @@ nsBrowserAccess.prototype = {
 // Listen for system messages and relay them to Gaia.
 Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
   let msg = JSON.parse(data);
   let origin = Services.io.newURI(msg.manifest, null, null).prePath;
   shell.sendChromeEvent({
     type: 'open-app',
     url: msg.uri,
     origin: origin,
-    manifest: msg.manifest
+    manifest: msg.manifest,
+    isActivity: (msg.type == 'activity'),
+    target: msg.target
   });
 }, 'system-messages-open-app', false);
 
 Services.obs.addObserver(function(aSubject, aTopic, aData) {
-  shell.sendEvent(shell.contentBrowser.contentWindow,
-                  "mozChromeEvent", { type: "fullscreenoriginchange",
-                                      fullscreenorigin: aData } );
+  shell.sendChromeEvent({ type: "fullscreenoriginchange",
+                          fullscreenorigin: aData });
 }, "fullscreen-origin-change", false);
 
 (function Repl() {
   if (!Services.prefs.getBoolPref('b2g.remote-js.enabled')) {
     return;
   }
   const prompt = 'JS> ';
   let output;
@@ -596,27 +624,16 @@ window.addEventListener('ContentStart', 
       shell.sendChromeEvent({
         type: 'take-screenshot-error',
         error: String(e)
       });
     }
   });
 });
 
-Services.obs.addObserver(function ContentHandler(subject, topic, data) {
-  let handler = JSON.parse(data);
-  new MozActivity({
-    name: 'view',
-    data: {
-      type: handler.type,
-      url: handler.url
-    }
-  });
-}, 'content-handler', false);
-
 (function geolocationStatusTracker() {
   let gGeolocationActiveCount = 0;
 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     let oldCount = gGeolocationActiveCount;
     if (aData == "starting") {
       gGeolocationActiveCount += 1;
     } else if (aData == "shutdown") {
--- a/b2g/chrome/content/shell.xul
+++ b/b2g/chrome/content/shell.xul
@@ -15,11 +15,13 @@
         onunload="shell.stop();">
 
   <script type="application/javascript" src="chrome://browser/content/settings.js"/>
   <script type="application/javascript" src="chrome://browser/content/shell.js"/>
 
 #ifndef ANDROID
   <!-- this script handles the screen argument for desktop builds -->
   <script type="application/javascript" src="chrome://browser/content/screen.js"/>
+  <!-- this script handles the "runapp" argument for desktop builds -->
+  <script type="application/javascript" src="chrome://browser/content/runapp.js"/>
 #endif
   <!-- The html:iframe containing the UI is created here. -->
 </window>
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -3,23 +3,25 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 chrome.jar:
 % content branding %content/branding/
 % content browser %content/
 
+  content/arrow.svg                     (content/arrow.svg)
   content/dbg-browser-actors.js         (content/dbg-browser-actors.js)
   content/forms.js                      (content/forms.js)
   content/settings.js                   (content/settings.js)
 * content/shell.xul                     (content/shell.xul)
 * content/shell.js                      (content/shell.js)
 #ifndef ANDROID
   content/screen.js                     (content/screen.js)
+  content/runapp.js                     (content/runapp.js)
 #endif
   content/content.css                   (content/content.css)
   content/touchcontrols.css             (content/touchcontrols.css)
 
 % override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
 % override chrome://global/skin/netError.css chrome://browser/content/netError.css
 % override chrome://global/skin/media/videocontrols.css chrome://browser/content/touchcontrols.css
 
--- a/b2g/components/ActivitiesGlue.js
+++ b/b2g/components/ActivitiesGlue.js
@@ -28,35 +28,34 @@ ActivitiesDialog.prototype = {
     });
 
 
     // Keep up the frond-end of an activity choice. The messages contains
     // a list of {names, icons} for applications able to handle this particular
     // activity. The front-end should display a UI to pick one.
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     let content = browser.getContentWindow();
-    let event = content.document.createEvent("CustomEvent");
-    event.initCustomEvent("mozChromeEvent", true, true, {
+    let detail = {
       type: "activity-choice",
       id: id,
       name: activity.name,
       choices: choices
-    });
+    };
 
     // Listen the resulting choice from the front-end. If there is no choice,
     // let's return -1, which means the user has cancelled the dialog.
     content.addEventListener("mozContentEvent", function act_getChoice(evt) {
       if (evt.detail.id != id)
         return;
 
       content.removeEventListener("mozContentEvent", act_getChoice);
       activity.callback.handleEvent(evt.detail.value ? evt.detail.value : -1);
     });
 
-    content.dispatchEvent(event);
+    browser.shell.sendChromeEvent(detail);
   },
 
   chooseActivity: function ap_chooseActivity(aName, aActivities, aCallback) {
     this.activities.push({
       name: aName,
       list: aActivities,
       callback: aCallback
     });
--- a/b2g/components/ContentHandler.js
+++ b/b2g/components/ContentHandler.js
@@ -8,16 +8,20 @@ const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 
 const PDF_CONTENT_TYPE = "application/pdf";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
+  return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+});
+
 function log(aMsg) {
   let msg = "ContentHandler.js: " + (aMsg.join ? aMsg.join("") : aMsg);
   Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
                                      .logStringMessage(msg);
   dump(msg + "\n");
 }
 
 const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
@@ -31,17 +35,17 @@ ContentHandler.prototype = {
 
     if (!(aRequest instanceof Ci.nsIChannel))
       throw NS_ERROR_WONT_HANDLE_CONTENT;
 
     let detail = {
       "type": aMimetype,
       "url": aRequest.URI.spec
     };
-    Services.obs.notifyObservers(this, "content-handler", JSON.stringify(detail)); 
+    cpmm.sendAsyncMessage("content-handler", detail);
 
     aRequest.cancel(Cr.NS_BINDING_ABORTED);
   },
 
   classID: Components.ID("{d18d0216-d50c-11e1-ba54-efb18d0ef0ac}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler])
 };
 
--- a/b2g/components/ContentPermissionPrompt.js
+++ b/b2g/components/ContentPermissionPrompt.js
@@ -53,19 +53,17 @@ ContentPermissionPrompt.prototype = {
     });
 
     let details = {
       "type": "permission-prompt",
       "permission": request.type,
       "id": requestId,
       "url": request.principal.URI.spec
     };
-    let event = content.document.createEvent("CustomEvent");
-    event.initCustomEvent("mozChromeEvent", true, true, details);
-    content.dispatchEvent(event);
+    browser.shell.sendChromeEvent(details);
   },
 
   classID: Components.ID("{8c719f03-afe0-4aac-91ff-6c215895d467}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt])
 };
 
 
--- a/b2g/components/MozKeyboard.js
+++ b/b2g/components/MozKeyboard.js
@@ -6,16 +6,17 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const kFormsFrameScript = "chrome://browser/content/forms.js";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 
 const messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
                          .getService(Ci.nsIChromeFrameMessageManager);
 
 
 // -----------------------------------------------------------------------
 // MozKeyboard
 // -----------------------------------------------------------------------
@@ -98,17 +99,18 @@ MozKeyboard.prototype = {
     let handler = this._focusHandler;
     if (!handler || !(handler instanceof Ci.nsIDOMEventListener))
       return;
 
     let detail = {
       "detail": msg.json
     };
 
-    let evt = new this._window.CustomEvent("focuschanged", detail);
+    let evt = new this._window.CustomEvent("focuschanged",
+                                           ObjectWrapper.wrap(detail, this._window));
     handler.handleEvent(evt);
   },
 
   observe: function mozKeyboardObserve(subject, topic, data) {
     switch (topic) {
     case "inner-window-destroyed": {
       let wId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
       if (wId == this.innerWindowID) {
--- a/b2g/config/mozconfigs/macosx64_gecko/nightly
+++ b/b2g/config/mozconfigs/macosx64_gecko/nightly
@@ -1,8 +1,10 @@
+. $topsrcdir/build/macosx/common
+
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-codesighs
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
@@ -11,17 +13,16 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 #ac_add_options --with-macbundlename-prefix=Firefox
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
-ac_add_options --with-ccache
 
 # B2G Stuff
 ac_add_options --enable-application=b2g
 ac_add_options --enable-debug-symbols
 ac_add_options --with-ccache
 ac_add_options --enable-marionette
 
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
--- a/b2g/config/mozconfigs/win32_gecko/nightly
+++ b/b2g/config/mozconfigs/win32_gecko/nightly
@@ -17,19 +17,13 @@ export MOZ_TELEMETRY_REPORTING=1
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
-# For known full-clobber builds on Windows (like nightlies/try), 
-# this speeds things up. IS_NIGHTLY is set by the build automation.
-if test "$IS_NIGHTLY" != ""; then 
-  ac_add_options --disable-auto-deps
-fi
-
 # B2G Options
 ac_add_options --enable-application=b2g
 ac_add_options --enable-marionette
 
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,227 +1,100 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1344613852000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1345147390000">
   <emItems>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i71" id="youtube@2youtube.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i8" id="{B13721C7-F507-4982-B2E5-502A71474FED}">
                         <versionRange  minVersion=" " severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i43" id="supportaccessplugin@gmail.com">
-                        </emItem>
-      <emItem  blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i107" os="WINNT" id="{ABDE892B-13A8-4d1b-88E6-365A6E755758}">
                         <versionRange  minVersion="0" maxVersion="15.0.5" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i88" id="anttoolbar@ant.com">
                         <versionRange  minVersion="2.4.6.4" maxVersion="2.4.6.4" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
-                        <versionRange  minVersion="2.2" maxVersion="2.2">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i98" id="youtubeeing@youtuberie.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}">
-                        <versionRange  minVersion="0.1" maxVersion="*">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="9.0a1" maxVersion="9.0" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i65" id="activity@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i66" id="youtubeer@youtuber.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i54" id="applebeegifts@mozilla.doslash.org">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i16" id="{27182e60-b5f3-411c-b545-b44205977502}">
-                        <versionRange  minVersion="1.0" maxVersion="1.0">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i39" id="{c2d64ff7-0ab8-4263-89c9-ea3b0f8f050c}">
-                        <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i92" id="play5@vide04flash.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i108" id="{28bfb930-7620-11e1-b0c4-0800200c9a66}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i105" id="{95ff02bc-ffc6-45f0-a5c8-619b8226a9de}">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i93" id="{68b8676b-99a5-46d1-b390-22411d8bcd61}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i61" id="youtube@youtube3.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                                <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
-                        </emItem>
-      <emItem  blockID="i1" id="mozilla_cc@internetdownloadmanager.com">
-                        <versionRange  minVersion="2.1" maxVersion="3.3">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.0a1" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                                <versionRange  minVersion=" " maxVersion="6.9.8">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.7a1pre" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i63" id="youtube@youtuber.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i101" id="{3a12052a-66ef-49db-8c39-e5b0bd5c83fa}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i18" id="msntoolbar@msn.com">
-                        <versionRange  minVersion=" " maxVersion="6.*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}">
-                        </emItem>
       <emItem  blockID="i117" id="{ce7e73df-6a44-4028-8079-5927a588c948}">
                         <versionRange  minVersion="0" maxVersion="1.0.8" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">
-                        <versionRange  minVersion="0.1" maxVersion="1.3.328.4" severity="1">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.7a1pre" maxVersion="*" />
-                          </targetApplication>
+      <emItem  blockID="i100" id="{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}">
+                        <versionRange  minVersion="2.5.0" maxVersion="2.5.0" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i64" id="royal@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i72" os="WINNT" id="{4ED1F68A-5463-4931-9384-8FFF5ED91D92}">
                         <versionRange  minVersion="3.4.1" maxVersion="3.4.1.194" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i97" id="support3_en@adobe122.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i4" id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
-                        <versionRange  minVersion="1.2" maxVersion="1.2">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.0a1" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i75" os="Darwin,Linux" id="firebug@software.joehewitt.com">
-                        <versionRange  minVersion="1.9.0" maxVersion="1.9.0" severity="1">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="9.0a1" maxVersion="9.*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i100" id="{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}">
-                        <versionRange  minVersion="2.5.0" maxVersion="2.5.0" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i83" id="flash@adobee.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i59" id="ghostviewer@youtube2.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i78" id="socialnetworktools@mozilla.doslash.org">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i53" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}">
-                        <versionRange  minVersion="2.0.3" maxVersion="2.0.3">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i51" id="admin@youtubeplayer.com">
+      <emItem  blockID="i101" id="{3a12052a-66ef-49db-8c39-e5b0bd5c83fa}">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i68" id="flashupdate@adobe.com">
-                        <versionRange  minVersion="0" maxVersion="*">
+      <emItem  blockID="i5" id="support@daemon-tools.cc">
+                        <versionRange  minVersion=" " maxVersion="1.0.0.5">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
-                        </emItem>
-      <emItem  blockID="i90" id="videoplugin@player.com">
+      <emItem  blockID="i97" id="support3_en@adobe122.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i91" id="crossriderapp4926@crossrider.com">
-                        <versionRange  minVersion="0" maxVersion="0.81.43" severity="1">
+      <emItem  blockID="i11" id="yslow@yahoo-inc.com">
+                        <versionRange  minVersion="2.0.5" maxVersion="2.0.5">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.5.7" maxVersion="*" />
+                          </targetApplication>
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i84" id="pink@rosaplugin.info">
+      <emItem  blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i42" id="{D19CA586-DD6C-4a0a-96F8-14644F340D60}">
-                        <versionRange  minVersion="0.1" maxVersion="14.4.0" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i67" id="youtube2@youtube2.com">
+      <emItem  blockID="i99" id="pfzPXmnzQRXX6@2iABkVe.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i60" id="youtb3@youtb3.com">
-                        <versionRange  minVersion="0" maxVersion="*">
+      <emItem  blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
+                        <versionRange  minVersion="1.1b1" maxVersion="1.1b1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i111" os="WINNT" id="{C3949AC2-4B17-43ee-B4F1-D26B9D42404D}">
                         <versionRange  minVersion="0" maxVersion="15.0.5" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i38" id="{B7082FAA-CB62-4872-9106-E42DD88EDE45}">
                         <versionRange  minVersion="0.1" maxVersion="3.3.0.*">
@@ -230,207 +103,347 @@
                           </targetApplication>
                     </versionRange>
                                 <versionRange  minVersion="3.3.1" maxVersion="*">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="5.0a1" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i98" id="youtubeeing@youtuberie.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i39" id="{c2d64ff7-0ab8-4263-89c9-ea3b0f8f050c}">
+                        <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i42" id="{D19CA586-DD6C-4a0a-96F8-14644F340D60}">
+                        <versionRange  minVersion="0.1" maxVersion="14.4.0" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i93" id="{68b8676b-99a5-46d1-b390-22411d8bcd61}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i53" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}">
+                        <versionRange  minVersion="2.0.3" maxVersion="2.0.3">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i63" id="youtube@youtuber.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i18" id="msntoolbar@msn.com">
+                        <versionRange  minVersion=" " maxVersion="6.*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i4" id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
+                        <versionRange  minVersion="1.2" maxVersion="1.2">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.0a1" maxVersion="*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i75" os="Darwin,Linux" id="firebug@software.joehewitt.com">
+                        <versionRange  minVersion="1.9.0" maxVersion="1.9.0" severity="1">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="9.0a1" maxVersion="9.*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i127" id="plugin@youtubeplayer.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i59" id="ghostviewer@youtube2.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i51" id="admin@youtubeplayer.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}">
+                        <versionRange  minVersion="0.1" maxVersion="*">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="9.0a1" maxVersion="9.0" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i22" id="ShopperReports@ShopperReports.com">
+                        <versionRange  minVersion="3.1.22.0" maxVersion="3.1.22.0">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i44" id="sigma@labs.mozilla">
+                        </emItem>
+      <emItem  blockID="i48" id="admin@youtubespeedup.com">
+                        </emItem>
+      <emItem  blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i79" id="GifBlock@facebook.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i69" id="{977f3b97-5461-4346-92c8-a14c749b77c9}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
+                        <versionRange  minVersion="2.2" maxVersion="2.2">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i115" id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
+                        </emItem>
+      <emItem  blockID="i52" id="ff-ext@youtube">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i43" id="supportaccessplugin@gmail.com">
+                        </emItem>
+      <emItem  blockID="i54" id="applebeegifts@mozilla.doslash.org">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i16" id="{27182e60-b5f3-411c-b545-b44205977502}">
+                        <versionRange  minVersion="1.0" maxVersion="1.0">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i92" id="play5@vide04flash.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
+                        </emItem>
+      <emItem  blockID="i1" id="mozilla_cc@internetdownloadmanager.com">
+                        <versionRange  minVersion="2.1" maxVersion="3.3">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.0a1" maxVersion="*" />
+                          </targetApplication>
+                    </versionRange>
+                                <versionRange  minVersion=" " maxVersion="6.9.8">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.7a1pre" maxVersion="*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}">
+                        </emItem>
+      <emItem  blockID="i83" id="flash@adobee.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i104" id="yasd@youasdr3.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i76" id="crossriderapp3924@crossrider.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i91" id="crossriderapp4926@crossrider.com">
+                        <versionRange  minVersion="0" maxVersion="0.81.43" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i67" id="youtube2@youtube2.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i56" id="flash@adobe.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i2" id="fdm_ffext@freedownloadmanager.org">
+                        <versionRange  minVersion="1.0" maxVersion="1.3.1">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.0a1" maxVersion="*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
+                        <versionRange  minVersion=" " maxVersion="8.5">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i12" id="masterfiler@gmail.com">
+                        <versionRange  severity="3">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i20" id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}">
+                        <versionRange  minVersion="0.1" maxVersion="5.2.0.7164" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i47" id="youtube@youtube2.com">
+                        </emItem>
+      <emItem  blockID="i103" id="kdrgun@gmail.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i3" id="langpack-vi-VN@firefox.mozilla.org">
+                        <versionRange  minVersion="2.0" maxVersion="2.0">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i106" os="WINNT" id="{97E22097-9A2F-45b1-8DAF-36AD648C7EF4}">
+                        <versionRange  minVersion="0" maxVersion="15.0.5" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i15" id="personas@christopher.beard">
+                        <versionRange  minVersion="1.6" maxVersion="1.6">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.6" maxVersion="3.6.*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i108" id="{28bfb930-7620-11e1-b0c4-0800200c9a66}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i61" id="youtube@youtube3.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                                <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i84" id="pink@rosaplugin.info">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i70" id="psid-vhvxQHMZBOzUZA@jetpack">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i60" id="youtb3@youtb3.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i23" id="firefox@bandoo.com">
                         <versionRange  minVersion="5.0" maxVersion="5.0" severity="1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="3.7a1pre" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
       <emItem  blockID="i55" id="youtube@youtube7.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i47" id="youtube@youtube2.com">
-                        </emItem>
-      <emItem  blockID="i22" id="ShopperReports@ShopperReports.com">
-                        <versionRange  minVersion="3.1.22.0" maxVersion="3.1.22.0">
+      <emItem  blockID="i90" id="videoplugin@player.com">
+                        <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i2" id="fdm_ffext@freedownloadmanager.org">
-                        <versionRange  minVersion="1.0" maxVersion="1.3.1">
+      <emItem  blockID="i68" id="flashupdate@adobe.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i45" id="{22119944-ED35-4ab1-910B-E619EA06A115}">
+                        <versionRange  minVersion="0.1" maxVersion="7.6.1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.0a1" maxVersion="*" />
+                              <versionRange  minVersion="8.0a1" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i44" id="sigma@labs.mozilla">
-                        </emItem>
-      <emItem  blockID="i5" id="support@daemon-tools.cc">
-                        <versionRange  minVersion=" " maxVersion="1.0.0.5">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i69" id="{977f3b97-5461-4346-92c8-a14c749b77c9}">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
-                        <versionRange  minVersion=" " maxVersion="8.5">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i12" id="masterfiler@gmail.com">
-                        <versionRange  severity="3">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i48" id="admin@youtubespeedup.com">
-                        </emItem>
-      <emItem  blockID="i20" id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}">
-                        <versionRange  minVersion="0.1" maxVersion="5.2.0.7164" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i104" id="yasd@youasdr3.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i76" id="crossriderapp3924@crossrider.com">
+      <emItem  blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i79" id="GifBlock@facebook.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i70" id="psid-vhvxQHMZBOzUZA@jetpack">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i115" id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i56" id="flash@adobe.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i103" id="kdrgun@gmail.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i99" id="pfzPXmnzQRXX6@2iABkVe.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
-                        <versionRange  minVersion="1.1b1" maxVersion="1.1b1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i3" id="langpack-vi-VN@firefox.mozilla.org">
-                        <versionRange  minVersion="2.0" maxVersion="2.0">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i73" id="a1g0a9g219d@a1.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i96" id="youtubeee@youtuber3.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i106" os="WINNT" id="{97E22097-9A2F-45b1-8DAF-36AD648C7EF4}">
-                        <versionRange  minVersion="0" maxVersion="15.0.5" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i11" id="yslow@yahoo-inc.com">
-                        <versionRange  minVersion="2.0.5" maxVersion="2.0.5">
+      <emItem  blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">
+                        <versionRange  minVersion="0.1" maxVersion="1.3.328.4" severity="1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.5.7" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i52" id="ff-ext@youtube">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i45" id="{22119944-ED35-4ab1-910B-E619EA06A115}">
-                        <versionRange  minVersion="0.1" maxVersion="7.6.1">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="8.0a1" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i15" id="personas@christopher.beard">
-                        <versionRange  minVersion="1.6" maxVersion="1.6">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.6" maxVersion="3.6.*" />
+                              <versionRange  minVersion="3.7a1pre" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
       <emItem  blockID="i21" id="support@update-firefox.com">
                         </emItem>
     </emItems>
 
   <pluginItems>
+      <pluginItem  blockID="p32">
+                  <match name="filename" exp="npViewpoint.dll" />                      <versionRange >
+                      <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+              <versionRange  minVersion="3.0" maxVersion="*" />
+            </targetApplication>
+                  </versionRange>
+                  </pluginItem>
       <pluginItem  blockID="p26">
       <match name="name" exp="^Yahoo Application State Plugin$" />      <match name="description" exp="^Yahoo Application State Plugin$" />      <match name="filename" exp="npYState.dll" />                      <versionRange >
                       <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
               <versionRange  minVersion="3.0a1" maxVersion="3.*" />
             </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p27">
       <match name="name" exp="QuickTime Plug-in 7[.]1[.]" />            <match name="filename" exp="npqtplugin.?[.]dll" />                      <versionRange >
                       <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
               <versionRange  minVersion="3.0a1" maxVersion="3.*" />
             </targetApplication>
                   </versionRange>
                   </pluginItem>
-      <pluginItem  blockID="p28">
-                  <match name="filename" exp="NPFFAddOn.dll" />                        </pluginItem>
-      <pluginItem  blockID="p31">
-                  <match name="filename" exp="NPMySrch.dll" />                        </pluginItem>
-      <pluginItem  blockID="p32">
-                  <match name="filename" exp="npViewpoint.dll" />                      <versionRange >
-                      <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-              <versionRange  minVersion="3.0" maxVersion="*" />
-            </targetApplication>
-                  </versionRange>
-                  </pluginItem>
-      <pluginItem  blockID="p33">
-      <match name="name" exp="[0-6]\.0\.[01]\d{2}\.\d+" />            <match name="filename" exp="npdeploytk.dll" />                      <versionRange  severity="1"></versionRange>
-                  </pluginItem>
       <pluginItem  blockID="p34">
                   <match name="filename" exp="[Nn][Pp][Jj][Pp][Ii]1[56]0_[0-9]+\.[Dd][Ll][Ll]" />                      <versionRange >
                       <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
               <versionRange  minVersion="3.6a1pre" maxVersion="*" />
             </targetApplication>
                   </versionRange>
                   </pluginItem>
+      <pluginItem  blockID="p28">
+                  <match name="filename" exp="NPFFAddOn.dll" />                        </pluginItem>
+      <pluginItem  blockID="p31">
+                  <match name="filename" exp="NPMySrch.dll" />                        </pluginItem>
+      <pluginItem  blockID="p33">
+      <match name="name" exp="[0-6]\.0\.[01]\d{2}\.\d+" />            <match name="filename" exp="npdeploytk.dll" />                      <versionRange  severity="1"></versionRange>
+                  </pluginItem>
       <pluginItem  blockID="p80">
       <match name="name" exp="\(TM\)" />      <match name="description" exp="[^\d\._]((0(\.\d+(\.\d+([_\.]\d+)?)?)?)|(1\.(([0-5](\.\d+([_\.]\d+)?)?)|(6(\.0([_\.](0?\d|1\d|2\d|30))?)?)|(7(\.0([_\.][0-2])?)?))))([^\d\._]|$)" />      <match name="filename" exp="(npjp2\.dll)|(libnpjp2\.so)" />                      <versionRange  severity="1"></versionRange>
                   </pluginItem>
+      <pluginItem  blockID="p119">
+      <match name="name" exp="Java\(TM\) Plug-in 1\.(6\.0_(\d|[0-2]\d?|3[0-2])|7\.0(_0?([1-4]))?)([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                      <versionRange  severity="1"></versionRange>
+                  </pluginItem>
+      <pluginItem  blockID="p125">
+      <match name="name" exp="Java\(TM\) Platform SE ((6( U(\d|([0-2]\d)|3[0-2]))?)|(7(\sU[0-4])?))(\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                      <versionRange  severity="1"></versionRange>
+                  </pluginItem>
       <pluginItem  blockID="p85">
                   <match name="filename" exp="JavaPlugin2_NPAPI\.plugin" />                      <versionRange  minVersion="0" maxVersion="13.6.0" severity="1"></versionRange>
                   </pluginItem>
       <pluginItem  os="Darwin" blockID="p89">
                   <match name="filename" exp="AdobePDFViewerNPAPI\.plugin" />                      <versionRange  minVersion="0" maxVersion="10.1.3" severity="1"></versionRange>
                   </pluginItem>
       <pluginItem  blockID="p94">
                   <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" />                      <versionRange  minVersion="0" maxVersion="10.2.159.1" severity="0"></versionRange>
                   </pluginItem>
       <pluginItem  blockID="p102">
                   <match name="filename" exp="npmozax\.dll" />                      <versionRange  minVersion="0" maxVersion="*"></versionRange>
                   </pluginItem>
       <pluginItem  blockID="p113">
                   <match name="filename" exp="npuplaypc\.dll" />                      <versionRange  minVersion="0" maxVersion="1.0.0.0" severity="1"></versionRange>
                   </pluginItem>
+      <pluginItem  blockID="p123">
+                  <match name="filename" exp="JavaPlugin2_NPAPI\.plugin" />                      <versionRange  minVersion="0" maxVersion="14.2.0" severity="1"></versionRange>
+                  </pluginItem>
     </pluginItems>
 
   <gfxItems>
     <gfxBlacklistEntry  blockID="g35">      <os>WINNT 6.1</os>      <vendor>0x10de</vendor>              <devices>
                       <device>0x0a6c</device>
                   </devices>
             <feature>DIRECT2D</feature>      <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus>      <driverVersion>8.17.12.5896</driverVersion>      <driverVersionComparator>LESS_THAN_OR_EQUAL</driverVersionComparator>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g36">      <os>WINNT 6.1</os>      <vendor>0x10de</vendor>              <devices>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1123,16 +1123,22 @@ pref("browser.panorama.animate_zoom", tr
 // Defines the url to be used for new tabs.
 pref("browser.newtab.url", "about:newtab");
 // Activates preloading of the new tab url.
 pref("browser.newtab.preload", false);
 
 // Toggles the content of 'about:newtab'. Shows the grid when enabled.
 pref("browser.newtabpage.enabled", true);
 
+// number of rows of newtab grid
+pref("browser.newtabpage.rows", 3);
+
+// number of columns of newtab grid
+pref("browser.newtabpage.columns", 3);
+
 // Enable the DOM fullscreen API.
 pref("full-screen-api.enabled", true);
 
 // True if the fullscreen API requires approval upon a domain entering fullscreen.
 // Domains that have already had fullscreen permission granted won't re-request
 // approval.
 pref("full-screen-api.approval-required", true);
 
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -83,33 +83,36 @@ var FullZoom = {
       case "DOMMouseScroll":
         this._handleMouseScrolled(event);
         break;
     }
   },
 
   _handleMouseScrolled: function FullZoom__handleMouseScrolled(event) {
     // Construct the "mousewheel action" pref key corresponding to this event.
-    // Based on nsEventStateManager::GetBasePrefKeyForMouseWheel.
-    var pref = "mousewheel";
-    if (event.axis == event.HORIZONTAL_AXIS)
-      pref += ".horizscroll";
+    // Based on nsEventStateManager::WheelPrefs::GetBasePrefName().
+    var pref = "mousewheel.";
 
-    if (event.shiftKey)
-      pref += ".withshiftkey";
-    else if (event.ctrlKey)
-      pref += ".withcontrolkey";
-    else if (event.altKey)
-      pref += ".withaltkey";
-    else if (event.metaKey)
-      pref += ".withmetakey";
-    else
-      pref += ".withnokey";
+    var pressedModifierCount = event.shiftKey + event.ctrlKey + event.altKey +
+                                 event.metaKey + event.getModifierState("OS");
+    if (pressedModifierCount != 1) {
+      pref += "default.";
+    } else if (event.shiftKey) {
+      pref += "with_shift.";
+    } else if (event.ctrlKey) {
+      pref += "with_control.";
+    } else if (event.altKey) {
+      pref += "with_alt.";
+    } else if (event.metaKey) {
+      pref += "with_meta.";
+    } else {
+      pref += "with_win.";
+    }
 
-    pref += ".action";
+    pref += "action";
 
     // Don't do anything if this isn't a "zoom" scroll event.
     var isZoomEvent = false;
     try {
       isZoomEvent = (gPrefService.getIntPref(pref) == MOUSE_SCROLL_ZOOM);
     } catch (e) {}
     if (!isZoomEvent)
       return;
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -248,19 +248,16 @@ let SocialShareButton = {
   }
 };
 
 var SocialToolbar = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function SocialToolbar_init() {
     document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
 
-    let notifBrowser = document.getElementById("social-notification-browser");
-    notifBrowser.docShell.isAppTab = true;
-
     let removeItem = document.getElementById("social-remove-menuitem");
     let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
     let label = gNavigatorBundle.getFormattedString("social.remove.label",
                                                     [brandShortName]);
     let accesskey = gNavigatorBundle.getString("social.remove.accesskey");
     removeItem.setAttribute("label", label);
     removeItem.setAttribute("accesskey", accesskey);
 
@@ -277,16 +274,24 @@ var SocialToolbar = {
   },
 
   get button() {
     return document.getElementById("social-toolbar-button");
   },
 
   updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
     this.button.hidden = !Social.uiVisible;
+    if (!Social.provider.profile || !Social.provider.profile.userName) {
+      ["social-notification-box",
+       "social-status-iconbox"].forEach(function removeChildren(parentId) {
+        let parent = document.getElementById(parentId);
+        while(parent.hasChildNodes())
+          parent.removeChild(parent.firstChild);
+      });
+    }
   },
 
   updateProfile: function SocialToolbar_updateProfile() {
     // Profile may not have been initialized yet, since it depends on a worker
     // response. In that case we'll be called again when it's available, via
     // social:profile-changed
     let profile = Social.provider.profile || {};
     let userPortrait = profile.portrait || "chrome://browser/skin/social/social.png";
@@ -301,83 +306,120 @@ var SocialToolbar = {
     } else {
       notLoggedInLabel.hidden = false;
       userNameBtn.hidden = true;
     }
   },
 
   updateButton: function SocialToolbar_updateButton() {
     this.updateButtonHiddenState();
-
     let provider = Social.provider;
-    // if there are no ambient icons, we collapse them in the following loop
     let iconNames = Object.keys(provider.ambientNotificationIcons);
     let iconBox = document.getElementById("social-status-iconbox");
-    for (var i = 0; i < iconBox.childNodes.length; i++) {
-      let iconContainer = iconBox.childNodes[i];
-      if (i > iconNames.length - 1) {
-        iconContainer.collapsed = true;
-        continue;
+    let notifBox = document.getElementById("social-notification-box");
+    let notifBrowsers = document.createDocumentFragment();
+    let iconContainers = document.createDocumentFragment();
+
+    for each(let name in iconNames) {
+      let icon = provider.ambientNotificationIcons[name];
+
+      let notifBrowserId = "social-status-" + icon.name;
+      let notifBrowser = document.getElementById(notifBrowserId);
+      if (!notifBrowser) {
+        notifBrowser = document.createElement("iframe");
+        notifBrowser.setAttribute("type", "content");
+        notifBrowser.setAttribute("id", notifBrowserId);
+        notifBrowsers.appendChild(notifBrowser);
       }
-
-      iconContainer.collapsed = false;
-      let icon = provider.ambientNotificationIcons[iconNames[i]];
-      let iconImage = iconContainer.firstChild;
-      let iconCounter = iconImage.nextSibling;
+      notifBrowser.setAttribute("origin", provider.origin);
+      if (notifBrowser.getAttribute("src") != icon.contentPanel)
+        notifBrowser.setAttribute("src", icon.contentPanel);
 
-      iconImage.setAttribute("contentPanel", icon.contentPanel);
-      iconImage.setAttribute("src", icon.iconURL);
+      let iconId = "social-notification-icon-" + icon.name;
+      let iconContainer = document.getElementById(iconId);
+      let iconImage, iconCounter;
+      if (iconContainer) {
+        iconImage = iconContainer.getElementsByClassName("social-notification-icon-image")[0];
+        iconCounter = iconContainer.getElementsByClassName("social-notification-icon-counter")[0];
+      } else {
+        iconContainer = document.createElement("box");
+        iconContainer.setAttribute("id", iconId);
+        iconContainer.classList.add("social-notification-icon-container");
+        iconContainer.addEventListener("click", function (e) { SocialToolbar.showAmbientPopup(iconContainer); }, false);
 
-      if (iconCounter.firstChild)
-        iconCounter.removeChild(iconCounter.firstChild);
+        iconImage = document.createElement("image");
+        iconImage.classList.add("social-notification-icon-image");
+        iconImage = iconContainer.appendChild(iconImage);
 
-      if (icon.counter) {
-        iconCounter.appendChild(document.createTextNode(icon.counter));
-        iconCounter.collapsed = false;
-      } else {
-        iconCounter.collapsed = true;
+        iconCounter = document.createElement("box");
+        iconCounter.classList.add("social-notification-icon-counter");
+        iconCounter.appendChild(document.createTextNode(""));
+        iconCounter = iconContainer.appendChild(iconCounter);
+
+        iconContainers.appendChild(iconContainer);
       }
+      if (iconImage.getAttribute("src") != icon.iconURL)
+        iconImage.setAttribute("src", icon.iconURL);
+      iconImage.setAttribute("notifBrowserId", notifBrowserId);
+
+      iconCounter.collapsed = !icon.counter;
+      iconCounter.firstChild.textContent = icon.counter || "";
+    }
+    notifBox.appendChild(notifBrowsers);
+    iconBox.appendChild(iconContainers);
+
+    let browserIter = notifBox.firstElementChild;
+    while (browserIter) {
+      browserIter.docShell.isAppTab = true;
+      browserIter = browserIter.nextElementSibling;
     }
   },
 
   showAmbientPopup: function SocialToolbar_showAmbientPopup(iconContainer) {
     let iconImage = iconContainer.firstChild;
     let panel = document.getElementById("social-notification-panel");
-    let notifBrowser = document.getElementById("social-notification-browser");
+    let notifBox = document.getElementById("social-notification-box");
+    let notifBrowser = document.getElementById(iconImage.getAttribute("notifBrowserId"));
 
     panel.hidden = false;
 
     function sizePanelToContent() {
       // FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
       // Need to handle dynamic sizing
       let doc = notifBrowser.contentDocument;
+      if (!doc) {
+        return;
+      }
       // "notif" is an implementation detail that we should get rid of
       // eventually
-      let body = doc.getElementById("notif") || (doc.body && doc.body.firstChild);
-      if (!body)
+      let body = doc.getElementById("notif") || doc.body;
+      if (!body || !body.firstChild) {
         return;
-      let h = body.scrollHeight > 0 ? body.scrollHeight : 300;
-      notifBrowser.style.width = body.scrollWidth + "px";
-      notifBrowser.style.height = h + "px";
+      }
+
+      // Clear dimensions on all browsers so the panel size will
+      // only use the selected browser.
+      let browserIter = notifBox.firstElementChild;
+      while (browserIter) {
+        browserIter.hidden = (browserIter != notifBrowser);
+        browserIter = browserIter.nextElementSibling;
+      }
+
+      let [height, width] = [body.firstChild.offsetHeight || 300, 330];
+      notifBrowser.style.width = width + "px";
+      notifBrowser.style.height = height + "px";
     }
 
-    notifBrowser.addEventListener("DOMContentLoaded", function onload() {
-      notifBrowser.removeEventListener("DOMContentLoaded", onload);
-      sizePanelToContent();
-    });
+    sizePanelToContent();
 
     panel.addEventListener("popuphiding", function onpopuphiding() {
       panel.removeEventListener("popuphiding", onpopuphiding);
-      // unload the panel
       SocialToolbar.button.removeAttribute("open");
-      notifBrowser.setAttribute("src", "about:blank");
     });
 
-    notifBrowser.setAttribute("origin", Social.provider.origin);
-    notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel"));
     this.button.setAttribute("open", "true");
     panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
   }
 }
 
 var SocialSidebar = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function SocialSidebar_init() {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -264,17 +264,17 @@
                 label="&social.sharePopup.undo.label;"
                 accesskey="&social.sharePopup.undo.accesskey;"
                 command="Social:UnsharePage"/>
 #endif
       </hbox>
     </panel>
 
     <panel id="social-notification-panel" type="arrow" hidden="true" noautofocus="true">
-      <browser id="social-notification-browser" type="content" flex="1"/>
+      <box id="social-notification-box" flex="1"></box>
     </panel>
 
     <menupopup id="inspector-node-popup">
       <menuitem id="inspectorHTMLCopyInner"
                 label="&inspectorHTMLCopyInner.label;"
                 accesskey="&inspectorHTMLCopyInner.accesskey;"
                 command="Inspector:CopyInner"/>
       <menuitem id="inspectorHTMLCopyOuter"
@@ -680,31 +680,16 @@
                         type="checkbox"
                         autocheck="false"
                         command="Social:ToggleSidebar"
                         label="&social.toggleSidebar.label;"
                         accesskey="&social.toggleSidebar.accesskey;"/>
             </menupopup>
           </button>
           <hbox id="social-status-iconbox" flex="1">
-            <box class="social-notification-icon-container" collapsed="true"
-                     onclick="SocialToolbar.showAmbientPopup(this);">
-              <image class="social-notification-icon-image"/>
-              <box class="social-notification-icon-counter" collapsed="true"/>
-            </box>
-            <box class="social-notification-icon-container" collapsed="true"
-                     onclick="SocialToolbar.showAmbientPopup(this);">
-              <image class="social-notification-icon-image"/>
-              <box class="social-notification-icon-counter" collapsed="true"/>
-            </box>
-            <box class="social-notification-icon-container" collapsed="true"
-                     onclick="SocialToolbar.showAmbientPopup(this);">
-              <image class="social-notification-icon-image"/>
-              <box class="social-notification-icon-counter" collapsed="true"/>
-            </box>
           </hbox>
         </hbox>
       </toolbaritem>
 
       <toolbaritem id="bookmarks-menu-button-container"
                    class="chromeclass-toolbar-additional"
                    removable="true"
                    title="&bookmarksMenuButton.label;">
--- a/browser/base/content/newtab/grid.js
+++ b/browser/base/content/newtab/grid.js
@@ -17,41 +17,32 @@ let gGrid = {
   /**
    * The cached DOM fragment for sites.
    */
   _siteFragment: null,
 
   /**
    * All cells contained in the grid.
    */
-  get cells() {
-    let cells = [];
-    let children = this.node.querySelectorAll(".newtab-cell");
-    for (let i = 0; i < children.length; i++)
-      cells.push(new Cell(this, children[i]));
-
-    // Replace the getter with our cached value.
-    Object.defineProperty(this, "cells", {value: cells, enumerable: true});
-
-    return cells;
-  },
+  _cells: null,
+  get cells() this._cells,
 
   /**
    * All sites contained in the grid's cells. Sites may be empty.
    */
   get sites() [cell.site for each (cell in this.cells)],
 
   /**
    * Initializes the grid.
    * @param aSelector The query selector of the grid.
    */
   init: function Grid_init() {
     this._node = document.getElementById("newtab-grid");
     this._createSiteFragment();
-    this._draw();
+    this._render();
   },
 
   /**
    * Creates a new site in the grid.
    * @param aLink The new site's link.
    * @param aCell The cell that will contain the new site.
    * @return The newly created site.
    */
@@ -69,18 +60,18 @@ let gGrid = {
     this.cells.forEach(function (cell) {
       let node = cell.node;
       let child = node.firstElementChild;
 
       if (child)
         node.removeChild(child);
     }, this);
 
-    // Draw the grid again.
-    this._draw();
+    // Render the grid again.
+    this._render();
   },
 
   /**
    * Locks the grid to block all pointer events.
    */
   lock: function Grid_lock() {
     this.node.setAttribute("locked", "true");
   },
@@ -88,16 +79,42 @@ let gGrid = {
   /**
    * Unlocks the grid to allow all pointer events.
    */
   unlock: function Grid_unlock() {
     this.node.removeAttribute("locked");
   },
 
   /**
+   * Creates the newtab grid.
+   */
+  _renderGrid: function Grid_renderGrid() {
+    let row = document.createElementNS(HTML_NAMESPACE, "div");
+    let cell = document.createElementNS(HTML_NAMESPACE, "div");
+    row.classList.add("newtab-row");
+    cell.classList.add("newtab-cell");
+
+    // Clear the grid
+    this._node.innerHTML = "";
+
+    // Creates the structure of one row
+    for (let i = 0; i < gGridPrefs.gridColumns; i++) {
+      row.appendChild(cell.cloneNode(true));
+    }
+    // Creates the grid
+    for (let j = 0; j < gGridPrefs.gridRows; j++) {
+      this._node.appendChild(row.cloneNode(true));
+    }
+
+    // (Re-)initialize all cells.
+    let cellElements = this.node.querySelectorAll(".newtab-cell");
+    this._cells = [new Cell(this, cell) for (cell of cellElements)];
+  },
+
+  /**
    * Creates the DOM fragment that is re-used when creating sites.
    */
   _createSiteFragment: function Grid_createSiteFragment() {
     let site = document.createElementNS(HTML_NAMESPACE, "div");
     site.classList.add("newtab-site");
     site.setAttribute("draggable", "true");
 
     // Create the site's inner HTML code.
@@ -111,23 +128,41 @@ let gGrid = {
       '<input type="button" title="' + newTabString("block") + '"' +
       '       class="newtab-control newtab-control-block"/>';
 
     this._siteFragment = document.createDocumentFragment();
     this._siteFragment.appendChild(site);
   },
 
   /**
-   * Draws the grid, creates all sites and puts them into their cells.
+   * Renders the sites, creates all sites and puts them into their cells.
    */
-  _draw: function Grid_draw() {
+  _renderSites: function Grid_renderSites() {
     let cells = this.cells;
-
     // Put sites into the cells.
     let links = gLinks.getLinks();
     let length = Math.min(links.length, cells.length);
 
     for (let i = 0; i < length; i++) {
       if (links[i])
         this.createSite(links[i], cells[i]);
     }
+  },
+
+  /**
+   * Renders the grid.
+   */
+  _render: function Grid_render() {
+    if (this._shouldRenderGrid()) {
+      this._renderGrid();
+    }
+
+    this._renderSites();
+  },
+
+  _shouldRenderGrid : function Grid_shouldRenderGrid() {
+    let rowsLength = this._node.querySelectorAll(".newtab-row").length;
+    let cellsLength = this._node.querySelectorAll(".newtab-cell").length;
+
+    return (rowsLength != gGridPrefs.gridRows ||
+            cellsLength != (gGridPrefs.gridRows * gGridPrefs.gridColumns));
   }
 };
--- a/browser/base/content/newtab/newTab.js
+++ b/browser/base/content/newtab/newTab.js
@@ -15,17 +15,18 @@ Cu.import("resource:///modules/NewTabUti
 XPCOMUtils.defineLazyModuleGetter(this, "Rect",
   "resource://gre/modules/Geometry.jsm");
 
 let {
   links: gLinks,
   allPages: gAllPages,
   linkChecker: gLinkChecker,
   pinnedLinks: gPinnedLinks,
-  blockedLinks: gBlockedLinks
+  blockedLinks: gBlockedLinks,
+  gridPrefs: gGridPrefs
 } = NewTabUtils;
 
 XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
   return Services.strings.
     createBundle("chrome://browser/locale/newTab.properties");
 });
 
 function newTabString(name) gStringBundle.GetStringFromName('newtab.' + name);
--- a/browser/base/content/newtab/newTab.xul
+++ b/browser/base/content/newtab/newTab.xul
@@ -21,31 +21,16 @@
 
     <div id="newtab-vertical-margin">
       <div id="newtab-margin-top"/>
 
       <div id="newtab-horizontal-margin">
         <div class="newtab-side-margin"/>
 
         <div id="newtab-grid">
-          <div class="newtab-row">
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-          </div>
-          <div class="newtab-row">
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-          </div>
-          <div class="newtab-row">
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-          </div>
         </div>
 
         <div class="newtab-side-margin"/>
       </div>
 
       <div id="newtab-margin-bottom"/>
     </div>
     <input id="newtab-toggle" type="button"/>
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -59,16 +59,19 @@ endif
 # 480169)
 
 # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
 
 # browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
 
 # browser_pageInfo.js + feed_tab.html is disabled for leaking (bug 767896)
 
+# browser_social_shareButton.js is disabled for not properly
+#   tearing down the social providers (bug 780010).
+
 _BROWSER_FILES = \
                  head.js \
                  browser_typeAheadFind.js \
                  browser_keywordSearch.js \
                  browser_allTabsPanel.js \
                  browser_alltabslistener.js \
                  browser_bug304198.js \
                  title_test.svg \
@@ -151,17 +154,16 @@ endif
                  browser_bug710878.js \
                  browser_bug719271.js \
                  browser_bug724239.js \
                  browser_bug735471.js \
                  browser_bug743421.js \
                  browser_bug749738.js \
                  browser_bug763468.js \
                  browser_bug767836.js \
-                 browser_social_shareButton.js \
                  browser_canonizeURL.js \
                  browser_customize.js \
                  browser_findbarClose.js \
                  browser_homeDrop.js \
                  browser_keywordBookmarklets.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
--- a/browser/base/content/test/browser_social_mozSocial_API.js
+++ b/browser/base/content/test/browser_social_mozSocial_API.js
@@ -24,17 +24,17 @@ var tests = {
 
     function checkNext() {
       if (iconsReady && gotSidebarMessage)
         triggerIconPanel();
     }
 
     function triggerIconPanel() {
       let statusIcons = document.getElementById("social-status-iconbox");
-      ok(!statusIcons.firstChild.collapsed, "status icon is visible");
+      ok(!statusIcons.firstChild.hidden, "status icon is visible");
       // Click the button to trigger its contentPanel
       let panel = document.getElementById("social-notification-panel");
       EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});
     }
 
     let port = Social.provider.port;
     ok(port, "provider has a port");
     port.postMessage({topic: "test-init"});
--- a/browser/base/content/test/browser_social_toolbar.js
+++ b/browser/base/content/test/browser_social_toolbar.js
@@ -57,16 +57,16 @@ var tests = {
     Social.provider.updateUserProfile({});
     // check dom values
     let portrait = document.getElementById("social-statusarea-user-portrait").getAttribute("src");
     is(portrait, "chrome://browser/skin/social/social.png", "portrait is generic");
     let userButton = document.getElementById("social-statusarea-username");
     ok(userButton.hidden, "username is not visible");
     let ambience = document.getElementById("social-status-iconbox").firstChild;
     while (ambience) {
-      ok(ambience.collapsed, "ambient icon is collapsed");
+      ok(ambience.collapsed, "ambient icon (" + ambience.id + ") is collapsed");
       ambience = ambience.nextSibling;
     }
     
     next();
   }
 }
 
--- a/browser/base/content/test/newtab/Makefile.in
+++ b/browser/base/content/test/newtab/Makefile.in
@@ -23,14 +23,15 @@ include $(topsrcdir)/config/rules.mk
 	browser_newtab_unpin.js \
 	browser_newtab_bug721442.js \
 	browser_newtab_bug722273.js \
 	browser_newtab_bug723102.js \
 	browser_newtab_bug723121.js \
 	browser_newtab_bug725996.js \
 	browser_newtab_bug734043.js \
 	browser_newtab_bug735987.js \
+	browser_newtab_bug752841.js \
 	browser_newtab_bug765628.js \
 	head.js \
 	$(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/newtab/browser_newtab_bug752841.js
@@ -0,0 +1,53 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const PREF_NEWTAB_ROWS = "browser.newtabpage.rows";
+const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns";
+
+function runTests() {
+  let testValues = [
+    {row: 0, column: 0},
+    {row: -1, column: -1},
+    {row: -1, column: 0},
+    {row: 0, column: -1},
+    {row: 2, column: 4},
+    {row: 2, column: 5},
+  ];
+
+  // Expected length of grid
+  let expectedValues = [1, 1, 1, 1, 8, 10];
+
+   // Values before setting new pref values (9 is the default value -> 3 x 3)
+  let previousValues = [9, 1, 1, 1, 1, 8];
+
+  let existingTab, existingTabGridLength, newTab, newTabGridLength;
+  yield addNewTabPageTab();
+  existingTab = gBrowser.selectedTab;
+
+  for (let i = 0; i < expectedValues.length; i++) {
+    gBrowser.selectedTab = existingTab;
+    existingTabGridLength = getGrid().cells.length;
+    is(existingTabGridLength, previousValues[i],
+      "Grid length of existing page before update is correctly.");
+
+    Services.prefs.setIntPref(PREF_NEWTAB_ROWS, testValues[i].row);
+    Services.prefs.setIntPref(PREF_NEWTAB_COLUMNS, testValues[i].column);
+
+    existingTabGridLength = getGrid().cells.length;
+    is(existingTabGridLength, expectedValues[i],
+      "Existing page grid is updated correctly.");
+
+    yield addNewTabPageTab();
+    newTab = gBrowser.selectedTab;
+    newTabGridLength = getGrid().cells.length;
+    is(newTabGridLength, expectedValues[i],
+      "New page grid is updated correctly.");
+
+    gBrowser.removeTab(newTab);
+  }
+
+  gBrowser.removeTab(existingTab);
+
+  Services.prefs.clearUserPref(PREF_NEWTAB_ROWS);
+  Services.prefs.clearUserPref(PREF_NEWTAB_COLUMNS);
+}
--- a/browser/components/feeds/src/FeedConverter.js
+++ b/browser/components/feeds/src/FeedConverter.js
@@ -280,17 +280,17 @@ FeedConverter.prototype = {
     // Check for a header that tells us there was no sniffing
     // The value doesn't matter.
     try {
       var httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
       // Make sure to check requestSucceeded before the potentially-throwing
       // getResponseHeader.
       if (!httpChannel.requestSucceeded) {
         // Just give up, but don't forget to cancel the channel first!
-        request.cancel(0x804b0002); // NS_BINDING_ABORTED
+        request.cancel(Cr.NS_BINDING_ABORTED);
         return;
       }
       var noSniff = httpChannel.getResponseHeader("X-Moz-Is-Feed");
     }
     catch (ex) {
       this._sniffed = true;
     }
 
--- a/browser/components/sessionstore/test/Makefile.in
+++ b/browser/components/sessionstore/test/Makefile.in
@@ -55,21 +55,16 @@ MOCHITEST_BROWSER_FILES = \
 	browser_461743.js \
 	browser_461743_sample.html \
 	browser_463205.js \
 	browser_463205_helper.html \
 	browser_463205_sample.html \
 	browser_463206.js \
 	browser_463206_sample.html \
 	browser_464199.js \
-	browser_464620_a.js \
-	browser_464620_a.html \
-	browser_464620_b.js \
-	browser_464620_b.html \
-	browser_464620_xd.html \
 	browser_465215.js \
 	browser_465223.js \
 	browser_466937.js \
 	browser_466937_sample.html \
 	browser_467409-backslashplosion.js \
 	browser_477657.js \
 	browser_480148.js \
 	browser_480893.js \
@@ -131,16 +126,30 @@ MOCHITEST_BROWSER_FILES = \
 	browser_701377.js \
 	browser_705597.js \
 	browser_707862.js \
 	browser_739531.js \
 	browser_739531_sample.html \
 	browser_739805.js \
 	$(NULL)
 
+# Disabled on Windows for frequent intermittent failures
+ifneq ($(OS_ARCH), WINNT)
+MOCHITEST_FILES += \
+	browser_464620_a.js \
+	browser_464620_a.html \
+	browser_464620_b.js \
+	browser_464620_b.html \
+	browser_464620_xd.html \
+	$(NULL)
+else
+$(warning browser_464620_a.js is disabled on Windows for intermittent failures. Bug 552424)
+$(warning browser_464620_b.js is disabled on Windows for intermittent failures. Bug 552424)
+endif
+
 ifneq ($(OS_ARCH),Darwin)
 MOCHITEST_BROWSER_FILES += \
 	browser_597071.js \
 	browser_625016.js \
 	$(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/config/mozconfigs/win32/nightly
+++ b/browser/config/mozconfigs/win32/nightly
@@ -20,14 +20,8 @@ mk_add_options MOZ_MAKE_FLAGS=-j1
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
-
-# For known full-clobber builds on Windows (like nightlies/try), 
-# this speeds things up. IS_NIGHTLY is set by the build automation.
-if test "$IS_NIGHTLY" != ""; then 
-  ac_add_options --disable-auto-deps
-fi
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -18,15 +18,9 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
-# For known full-clobber builds on Windows (like nightlies/try), 
-# this speeds things up. IS_NIGHTLY is set by the build automation.
-if test "$IS_NIGHTLY" != ""; then 
-  ac_add_options --disable-auto-deps
-fi
-
 . $topsrcdir/build/win64/mozconfig.vs2010
--- a/browser/devtools/webconsole/WebConsoleUtils.jsm
+++ b/browser/devtools/webconsole/WebConsoleUtils.jsm
@@ -904,58 +904,73 @@ function JSPropertyProvider(aScope, aInp
 
   let completionPart = aInputValue.substring(beginning.startPos);
 
   // Don't complete on just an empty string.
   if (completionPart.trim() == "") {
     return null;
   }
 
-  let properties = completionPart.split(".");
-  let matchProp;
-  if (properties.length > 1) {
-    matchProp = properties.pop().trimLeft();
-    for (let i = 0; i < properties.length; i++) {
-      let prop = properties[i].trim();
-      if (!prop) {
-        return null;
-      }
+  let matches = null;
+  let matchProp = "";
+
+  let lastDot = completionPart.lastIndexOf(".");
+  if (lastDot > 0 &&
+      (completionPart[0] == "'" || completionPart[0] == '"') &&
+      completionPart[lastDot - 1] == completionPart[0]) {
+    // We are completing a string literal.
+    obj = obj.String.prototype;
+    matchProp = completionPart.slice(lastDot + 1);
+
+  }
+  else {
+    // We are completing a variable / a property lookup.
 
-      // If obj is undefined or null (which is what "== null" does),
-      // then there is no chance to run completion on it. Exit here.
-      if (obj == null) {
-        return null;
-      }
+    let properties = completionPart.split(".");
+    if (properties.length > 1) {
+      matchProp = properties.pop().trimLeft();
+      for (let i = 0; i < properties.length; i++) {
+        let prop = properties[i].trim();
+        if (!prop) {
+          return null;
+        }
 
-      // Check if prop is a getter function on obj. Functions can change other
-      // stuff so we can't execute them to get the next object. Stop here.
-      if (WCU.isNonNativeGetter(obj, prop)) {
-        return null;
-      }
-      try {
-        obj = obj[prop];
-      }
-      catch (ex) {
-        return null;
+        // If obj is undefined or null (which is what "== null" does),
+        // then there is no chance to run completion on it. Exit here.
+        if (obj == null) {
+          return null;
+        }
+
+        // Check if prop is a getter function on obj. Functions can change other
+        // stuff so we can't execute them to get the next object. Stop here.
+        if (WCU.isNonNativeGetter(obj, prop)) {
+          return null;
+        }
+        try {
+          obj = obj[prop];
+        }
+        catch (ex) {
+          return null;
+        }
       }
     }
-  }
-  else {
-    matchProp = properties[0].trimLeft();
-  }
+    else {
+      matchProp = properties[0].trimLeft();
+    }
 
-  // If obj is undefined or null (which is what "== null" does),
-  // then there is no chance to run completion on it. Exit here.
-  if (obj == null) {
-    return null;
-  }
+    // If obj is undefined or null (which is what "== null" does),
+    // then there is no chance to run completion on it. Exit here.
+    if (obj == null) {
+      return null;
+    }
 
-  // Skip Iterators and Generators.
-  if (WCU.isIteratorOrGenerator(obj)) {
-    return null;
+    // Skip Iterators and Generators.
+    if (WCU.isIteratorOrGenerator(obj)) {
+      return null;
+    }
   }
 
   let matches = Object.keys(getMatchedProps(obj, {matchProp:matchProp}));
 
   return {
     matchProp: matchProp,
     matches: matches.sort(),
   };
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
@@ -111,26 +111,26 @@ let TestObserver = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
 
   observe: function test_observe(aSubject)
   {
     if (testEnded || !(aSubject instanceof Ci.nsIScriptError)) {
       return;
     }
 
-    is(aSubject.category, TESTS[pos].category,
-      "test #" + pos + ": error category '" + TESTS[pos].category + "'");
+    var expectedCategory = TESTS[pos].category;
 
-    if (aSubject.category == TESTS[pos].category) {
+    info("test #" + pos + " console observer got " + aSubject.category + ", is expecting " + expectedCategory);
+
+    if (aSubject.category == expectedCategory) {
       foundCategory = true;
     }
     else {
-      ok(false, aSubject.sourceName + ':' + aSubject.lineNumber + '; ' +
+      info("unexpected message was: " + aSubject.sourceName + ':' + aSubject.lineNumber + '; ' +
                 aSubject.errorMessage);
-      testEnded = true;
     }
   }
 };
 
 function consoleOpened(hud) {
   output = hud.outputNode;
   output.addEventListener("DOMNodeInserted", onDOMNodeInserted, false);
   jsterm = hud.jsterm;
--- a/browser/devtools/webconsole/test/browser_webconsole_completion.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_completion.js
@@ -100,13 +100,20 @@ function testCompletion(hud) {
 
   // Test non-object autocompletion.
   input.value = "Object.name.sl";
   jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
   yield;
 
   is(jsterm.completeNode.value, "              ice", "non-object completion");
 
+  // Test string literal autocompletion.
+  input.value = "'Asimov'.sl";
+  jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
+  yield;
+
+  is(jsterm.completeNode.value, "           ice", "string literal completion");
+
   testDriver = jsterm = input = null;
   executeSoon(finishTest);
   yield;
 }
 
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -701,11 +701,12 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/webapprt/chrome/@AB_CD@@JAREXT@
 @BINPATH@/webapprt/chrome/@AB_CD@.manifest
 @BINPATH@/webapprt/components/CommandLineHandler.js
 @BINPATH@/webapprt/components/ContentPermission.js
 @BINPATH@/webapprt/components/ContentPolicy.js
 @BINPATH@/webapprt/components/DirectoryProvider.js
 @BINPATH@/webapprt/components/components.manifest
 @BINPATH@/webapprt/defaults/preferences/prefs.js
+@BINPATH@/webapprt/modules/Startup.jsm
 @BINPATH@/webapprt/modules/WebappRT.jsm
 @BINPATH@/webapprt/modules/WebappsHandler.jsm
 #endif
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -115,16 +115,17 @@ distribution/extensions/testpilot@labs.m
 #endif
 extensions/talkback@mozilla.org/
 extensions/talkback@mozilla.org/chrome.manifest
 extensions/talkback@mozilla.org/components/@DLL_PREFIX@qfaservices@DLL_SUFFIX@
 extensions/talkback@mozilla.org/components/qfaservices.xpt
 extensions/talkback@mozilla.org/install.rdf
 extensions/{641d8d09-7dda-4850-8228-ac0ab65e2ac9}/
 extensions/{641d8d09-7dda-4850-8228-ac0ab65e2ac9}/install.rdf
+extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/preview.png
 extensions/testpilot@labs.mozilla.com/chrome.manifest
 extensions/testpilot@labs.mozilla.com/components/TestPilot.js
 extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
 extensions/testpilot@labs.mozilla.com/content/all-studies-window.xul
 extensions/testpilot@labs.mozilla.com/content/browser.css
 extensions/testpilot@labs.mozilla.com/content/browser.js
 extensions/testpilot@labs.mozilla.com/content/debug.html
 extensions/testpilot@labs.mozilla.com/content/experiment-page.js
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -353,16 +353,19 @@ telemetryNoButtonLabel = No
 telemetryNoButtonAccessKey = N
 
 # Webapps notification popup
 webapps.install = Install
 webapps.install.accesskey = I
 #LOCALIZATION NOTE (webapps.requestInstall) %1$S is the web app name, %2$S is the site from which the web app is installed
 webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
 webapps.install.success = Application Installed
+# LOCALIZATION NOTE (webapps.uninstall.notification): %S will be replaced with the name of the uninstalled web app
+webapps.uninstall.notification = %S has been uninstalled from your computer.
+webapps.uninstall.label = Uninstall App
 
 # Telemetry opt-out prompt for Aurora and Nightly
 # LOCALIZATION NOTE (telemetryOptOutPrompt): %1$S and %3$S will be replaced by
 # brandFullName, and %2$S by the value of the toolkit.telemetry.server_owner preference.
 telemetryOptOutPrompt = %1$S sends information about performance, hardware, usage and customizations back to %2$S to help improve %3$S.
 
 # LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
 fullscreen.entered=%S is now fullscreen.
--- a/browser/modules/NewTabUtils.jsm
+++ b/browser/modules/NewTabUtils.jsm
@@ -19,16 +19,22 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyGetter(this, "gPrincipal", function () {
   let uri = Services.io.newURI("about:newtab", null, null);
   return Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
 });
 
 // The preference that tells whether this feature is enabled.
 const PREF_NEWTAB_ENABLED = "browser.newtabpage.enabled";
 
+// The preference that tells the number of rows of the newtab grid.
+const PREF_NEWTAB_ROWS = "browser.newtabpage.rows";
+
+// The preference that tells the number of columns of the newtab grid.
+const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns";
+
 // The maximum number of results we want to retrieve from history.
 const HISTORY_RESULTS_LIMIT = 100;
 
 // The gather telemetry topic.
 const TOPIC_GATHER_TELEMETRY = "gather-telemetry";
 
 /**
  * Singleton that provides storage functionality.
@@ -179,16 +185,70 @@ let AllPages = {
     this._addObserver = function () {};
   },
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference])
 };
 
 /**
+ * Singleton that keeps Grid preferences
+ */
+let GridPrefs = {
+  /**
+   * Cached value that tells the number of rows of newtab grid.
+   */
+  _gridRows: null,
+  get gridRows() {
+    if (!this._gridRows) {
+      this._gridRows = Math.max(1, Services.prefs.getIntPref(PREF_NEWTAB_ROWS));
+    }
+
+    return this._gridRows;
+  },
+
+  /**
+   * Cached value that tells the number of columns of newtab grid.
+   */
+  _gridColumns: null,
+  get gridColumns() {
+    if (!this._gridColumns) {
+      this._gridColumns = Math.max(1, Services.prefs.getIntPref(PREF_NEWTAB_COLUMNS));
+    }
+
+    return this._gridColumns;
+  },
+
+
+  /**
+   * Initializes object. Adds a preference observer
+   */
+  init: function GridPrefs_init() {
+    Services.prefs.addObserver(PREF_NEWTAB_ROWS, this, false);
+    Services.prefs.addObserver(PREF_NEWTAB_COLUMNS, this, false);
+  },
+
+  /**
+   * Implements the nsIObserver interface to get notified when the preference
+   * value changes.
+   */
+  observe: function GridPrefs_observe(aSubject, aTopic, aData) {
+    if (aData == PREF_NEWTAB_ROWS) {
+      this._gridRows = null;
+    } else {
+      this._gridColumns = null;
+    }
+
+    AllPages.update();
+  }
+};
+
+GridPrefs.init();
+
+/**
  * Singleton that keeps track of all pinned links and their positions in the
  * grid.
  */
 let PinnedLinks = {
   /**
    * The cached list of pinned links.
    */
   _links: null,
@@ -601,10 +661,11 @@ let NewTabUtils = {
       AllPages.update();
     }, true);
   },
 
   links: Links,
   allPages: AllPages,
   linkChecker: LinkChecker,
   pinnedLinks: PinnedLinks,
-  blockedLinks: BlockedLinks
+  blockedLinks: BlockedLinks,
+  gridPrefs: GridPrefs
 };
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -80,17 +80,21 @@ dnl A high level macro for selecting com
 AC_DEFUN([MOZ_COMPILER_OPTS],
 [
   MOZ_RTTI
 if test "$CLANG_CXX"; then
     ## We disable return-type-c-linkage because jsval is defined as a C++ type but is
     ## returned by C functions. This is possible because we use knowledge about the ABI
     ## to typedef it to a C type with the same layout when the headers are included
     ## from C.
-    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage"
+    ##
+    ## mismatched-tags is disabled (bug 780474) mostly because it's useless.
+    ## Worse, it's not supported by gcc, so it will cause tryserver bustage
+    ## without any easy way for non-Clang users to check for it.
+    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-mismatched-tags"
 fi
 
 if test "$GNU_CC"; then
     CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
     CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fno-exceptions"
 fi
 
 dnl ========================================================
--- a/build/autoconf/config.status.m4
+++ b/build/autoconf/config.status.m4
@@ -69,28 +69,30 @@ test "x$exec_prefix" = xNONE && exec_pre
 trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
 
 : ${CONFIG_STATUS=./config.status}
 
 dnl We're going to need [ ] for python syntax.
 changequote(<<<, >>>)dnl
 echo creating $CONFIG_STATUS
 
+extra_python_path=${COMM_BUILD:+"'mozilla', "}
+
 cat > $CONFIG_STATUS <<EOF
 #!${PYTHON}
 # coding=$encoding
 
 import os, sys
 dnl topsrcdir is the top source directory in native form, as opposed to a
 dnl form suitable for make.
 topsrcdir = '''${WIN_TOP_SRC:-$srcdir}'''
 if not os.path.isabs(topsrcdir):
     topsrcdir = os.path.normpath(os.path.join(os.path.dirname(<<<__file__>>>), topsrcdir))
 dnl Don't rely on virtualenv here. Standalone js doesn't use it.
-sys.path.append(os.path.join(topsrcdir, ${COMM_BUILD:+'mozilla',} 'build'))
+sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build'))
 from ConfigStatus import config_status
 
 args = {
     'topsrcdir': topsrcdir,
     'topobjdir': os.path.dirname(<<<__file__>>>),
 
 dnl All defines and substs are stored with an additional space at the beginning
 dnl and at the end of the string, to avoid any problem with values starting or
--- a/build/autoconf/mozconfig2client-mk
+++ b/build/autoconf/mozconfig2client-mk
@@ -5,21 +5,20 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # mozconfig2client-mk - Translates .mozconfig into options for client.mk.
 #    Prints defines to stdout.
 #
 # See mozconfig2configure for more details
 
 print_header() {
-  _mozconfig=${MOZCONFIG:-$HOME/.mozconfig}
   cat <<EOF
 # gmake
 # This file is automatically generated for client.mk.
-# Do not edit. Edit $_mozconfig instead.
+# Do not edit. Edit $FOUND_MOZCONFIG instead.
 
 EOF
 }
 
 ac_add_options() {
   echo "# $* is used by configure (not client.mk)"
 }
 
@@ -48,18 +47,16 @@ mk_echo_options() {
 
 # Main
 #--------------------------------------------------
 
 scriptdir=`dirname $0`
 topsrcdir=$1
 opts=""
 
-print_header
-
 # If the path changes, configure should be rerun
 echo "# PATH=$PATH"
 
 # If FOUND_MOZCONFIG isn't set, look for it and make sure the script doesn't error out
 isfoundset=${FOUND_MOZCONFIG+yes}
 if [ -z $isfoundset ]; then
   FOUND_MOZCONFIG=`$scriptdir/mozconfig-find $topsrcdir`
   if [ $? -ne 0 ]; then
@@ -67,16 +64,17 @@ if [ -z $isfoundset ]; then
   else
     isfoundset=yes
   fi
 fi
 
 if [ -n $isfoundset ]; then
   if [ "$FOUND_MOZCONFIG" ]
   then
+    print_header
     . "$FOUND_MOZCONFIG"
   fi
   echo "export FOUND_MOZCONFIG := $FOUND_MOZCONFIG"
 
   if [ "$opts" ]; then
     mk_echo_options
   fi
 fi
--- a/build/mobile/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -38,16 +38,18 @@ class B2GRemoteAutomation(Automation):
                  marionette=None, context_chrome=True):
         self._devicemanager = deviceManager
         self._appName = appName
         self._remoteProfile = None
         self._remoteLog = remoteLog
         self.marionette = marionette
         self.context_chrome = context_chrome
         self._is_emulator = False
+        self.test_script = None
+        self.test_script_args = None
 
         # Default our product to b2g
         self._product = "b2g"
         # Default log finish to mochitest standard
         self.logFinish = 'INFO SimpleTest FINISHED' 
         Automation.__init__(self)
 
     def setEmulator(self, is_emulator):
@@ -249,24 +251,24 @@ class B2GRemoteAutomation(Automation):
 
         # start the tests
         if hasattr(self, 'testURL'):
             # Start the tests by navigating to the mochitest url, by setting it
             # as the 'src' attribute to the homescreen mozbrowser element
             # provided by B2G's shell.js.
             self.marionette.execute_script("document.getElementById('homescreen').src='%s';" % self.testURL)
         # run the script that starts the tests
-        elif hasattr(self, 'testScript'):
-            if os.path.isfile(self.testScript):
-                script = open(self.testScript, 'r')
-                self.marionette.execute_script(script.read())
+        elif self.test_script:
+            if os.path.isfile(self.test_script):
+                script = open(self.test_script, 'r')
+                self.marionette.execute_script(script.read(), script_args=self.test_script_args)
                 script.close()
             else:
-                # assume testScript is a string
-                self.marionette.execute_script(self.testScript)
+                # assume test_script is a string
+                self.marionette.execute_script(self.test_script, script_args=self.test_script_args)
         else:
             # assumes the tests are started on startup automatically
             pass
 
         return instance
 
     # be careful here as this inner class doesn't have access to outer class members
     class B2GInstance(object):
--- a/build/mobile/devicemanager.py
+++ b/build/mobile/devicemanager.py
@@ -33,19 +33,22 @@ def abstractmethod(method):
     raise NotImplementedError('Abstract method %s at File "%s", line %s '
                               'should be implemented by a concrete class' %
                               (repr(method), filename,line))
   return not_implemented
 
 class DeviceManager:
 
   @abstractmethod
-  def shell(self, cmd, outputfile, env=None, cwd=None):
+  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
     """
     executes shell command on device
+
+    timeout is specified in seconds, and if no timeout is given, 
+    we will run until the script returns
     returns:
     success: Return code from command
     failure: None
     """
 
   @abstractmethod
   def pushFile(self, localname, destname):
     """
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -85,21 +85,23 @@ class DeviceManagerADB(DeviceManager):
       self.verifyZip()
     except DMError:
       pass
 
   def __del__(self):
     if self.host:
       self.disconnectRemoteADB()
 
-  # external function: executes shell command on device
+  # external function: executes shell command on device.
+  # timeout is specified in seconds, and if no timeout is given, 
+  # we will run until the script returns
   # returns:
   # success: <return code>
   # failure: None
-  def shell(self, cmd, outputfile, env=None, cwd=None):
+  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
     # FIXME: this function buffers all output of the command into memory,
     # always. :(
 
     # Getting the return code is more complex than you'd think because adb
     # doesn't actually return the return code from a process, so we have to
     # capture the output to get it
     cmdline = "%s; echo $?" % self._escapedCommandLine(cmd)
 
@@ -112,16 +114,26 @@ class DeviceManagerADB(DeviceManager):
 
     # all output should be in stdout
     args=[self.adbPath]
     if self.deviceSerial:
         args.extend(['-s', self.deviceSerial])
     args.extend(["shell", cmdline])
     proc = subprocess.Popen(args,
                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    if timeout:
+        timeout = int(timeout)
+        start_time = time.time()
+        ret_code = proc.poll()
+        while ((time.time() - start_time) <= timeout) and ret_code == None:
+            time.sleep(1)
+            ret_code = proc.poll()
+        if ret_code == None:
+            proc.kill()
+            raise DMError("Timeout exceeded for shell call")
     (stdout, stderr) = proc.communicate()
     outputfile.write(stdout.rstrip('\n'))
 
     lastline = _pop_last_line(outputfile)
     if lastline:
       m = re.search('([0-9]+)', lastline)
       if m:
         return_code = m.group(1)
@@ -707,33 +719,47 @@ class DeviceManagerADB(DeviceManager):
     return subprocess.Popen(finalArgs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
   def runCmdAs(self, args):
     if self.useRunAs:
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
     return self.runCmd(args)
 
-  def checkCmd(self, args):
+  # timeout is specified in seconds, and if no timeout is given, 
+  # we will run until the script returns
+  def checkCmd(self, args, timeout=None):
     # If we are not root but have run-as, and we're trying to execute
     # a shell command then using run-as is the best we can do
     finalArgs = [self.adbPath]
     if self.deviceSerial:
       finalArgs.extend(['-s', self.deviceSerial])
     if (not self.haveRoot and self.useRunAs and args[0] == "shell" and args[1] != "run-as"):
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
     finalArgs.extend(args)
+    if timeout:
+        timeout = int(timeout)
+        proc = subprocess.Popen(finalArgs)
+        start_time = time.time()
+        ret_code = proc.poll()
+        while ((time.time() - start_time) <= timeout) and ret_code == None:
+            time.sleep(1)
+            ret_code = proc.poll()
+        if ret_code == None:
+            proc.kill()
+            raise DMError("Timeout exceeded for checkCmd call")
+        return ret_code
     return subprocess.check_call(finalArgs)
 
-  def checkCmdAs(self, args):
+  def checkCmdAs(self, args, timeout=None):
     if (self.useRunAs):
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
-    return self.checkCmd(args)
+    return self.checkCmd(args, timeout)
 
   # external function
   # returns:
   #  success: True
   #  failure: False
   def chmodDir(self, remoteDir):
     if (self.isDir(remoteDir)):
       files = self.listFiles(remoteDir.strip())
--- a/build/mobile/devicemanagerSUT.py
+++ b/build/mobile/devicemanagerSUT.py
@@ -118,16 +118,18 @@ class DeviceManagerSUT(DeviceManager):
     '''
     a wrapper for _doCmds that loops up to self.retrylimit iterations.
     this allows us to move the retry logic outside of the _doCmds() to make it
     easier for debugging in the future.
     note that since cmdlist is a list of commands, they will all be retried if
     one fails.  this is necessary in particular for pushFile(), where we don't want
     to accidentally send extra data if a failure occurs during data transmission.
     '''
+    if timeout:
+      raise NotImplementedError("'timeout' parameter is not yet supported")
     while self.retries < self.retrylimit:
       try:
         self._doCmds(cmdlist, outputfile, timeout)
         return
       except AgentError, err:
         # re-raise error if it's fatal (i.e. the device got the command but
         # couldn't execute it). retry otherwise
         if err.fatal:
@@ -256,26 +258,26 @@ class DeviceManagerSUT(DeviceManager):
       except:
         self._sock = None
         raise AgentError("Error closing socket")
 
   # external function: executes shell command on device
   # returns:
   # success: <return code>
   # failure: None
-  def shell(self, cmd, outputfile, env=None, cwd=None):
+  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
     cmdline = self._escapedCommandLine(cmd)
     if env:
       cmdline = '%s %s' % (self.formatEnvString(env), cmdline)
 
     try:
       if cwd:
-        self.sendCmds([{ 'cmd': 'execcwd %s %s' % (cwd, cmdline) }], outputfile)
+        self.sendCmds([{ 'cmd': 'execcwd %s %s' % (cwd, cmdline) }], outputfile, timeout)
       else:
-        self.sendCmds([{ 'cmd': 'exec su -c "%s"' % cmdline }], outputfile)
+        self.sendCmds([{ 'cmd': 'exec su -c "%s"' % cmdline }], outputfile, timeout)
     except AgentError:
       return None
 
     # dig through the output to get the return code
     lastline = _pop_last_line(outputfile)
     if lastline:
       m = re.search('return code \[([0-9]+)\]', lastline)
       if m:
--- a/build/mobile/sutagent/android/CmdWorkerThread.java
+++ b/build/mobile/sutagent/android/CmdWorkerThread.java
@@ -93,17 +93,17 @@ public class CmdWorkerThread extends Thr
         try {
             OutputStream cmdOut = socket.getOutputStream();
             InputStream cmdIn = socket.getInputStream();
             PrintWriter out = new PrintWriter(cmdOut, true);
             BufferedInputStream in = new BufferedInputStream(cmdIn);
             String inputLine, outputLine;
             DoCommand dc = new DoCommand(theParent.svc);
 
-            SUTAgentAndroid.logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "CmdWorkerThread starts: "+getId());
+            SUTAgentAndroid.logToFile(dc, "CmdWorkerThread starts: "+getId());
 
             int nAvail = cmdIn.available();
             cmdIn.skip(nAvail);
 
             out.print(prompt);
             out.flush();
 
             while (bListening)
@@ -131,17 +131,17 @@ public class CmdWorkerThread extends Thr
                     }
                 else
                     inputLine = "";
 
                 if ((inputLine += readLine(in)) != null)
                     {
                     String message = String.format("%s : %s",
                                      socket.getInetAddress().getHostAddress(), inputLine);
-                    SUTAgentAndroid.logToFile(dc.GetTestRoot(), dc.GetSystemTime(), message);
+                    SUTAgentAndroid.logToFile(dc, message);
 
                     outputLine = dc.processCommand(inputLine, out, in, cmdOut);
                     if (outputLine.length() > 0)
                         {
                         out.print(outputLine + "\n" + prompt);
                         }
                     else
                         out.print(prompt);
@@ -161,17 +161,17 @@ public class CmdWorkerThread extends Thr
                 else
                     break;
                 }
             out.close();
             out = null;
             in.close();
             in = null;
             socket.close();
-            SUTAgentAndroid.logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "CmdWorkerThread ends: "+getId());
+            SUTAgentAndroid.logToFile(dc, "CmdWorkerThread ends: "+getId());
         }
     catch (IOException e)
         {
         // TODO Auto-generated catch block
         e.printStackTrace();
         }
     }
 }
--- a/build/mobile/sutagent/android/SUTAgentAndroid.java
+++ b/build/mobile/sutagent/android/SUTAgentAndroid.java
@@ -70,16 +70,17 @@ public class SUTAgentAndroid extends Act
     public PrintWriter dataOut = null;
 
     private static boolean bNetworkingStarted = false;
     private static String RegSvrIPAddr = "";
     private static String RegSvrIPPort = "";
     private static String HardwareID = "";
     private static String Pool = "";
     private static String sRegString = "";
+    private static boolean LogCommands = false;
 
     private WifiLock wl = null;
 
     private BroadcastReceiver battReceiver = null;
 
     private TextView  tv = null;
 
     public boolean onCreateOptionsMenu(Menu menu)
@@ -147,27 +148,30 @@ public class SUTAgentAndroid extends Act
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.main);
 
         fixScreenOrientation();
 
         DoCommand dc = new DoCommand(getApplication());
 
-        logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onCreate");
-
         // Get configuration settings from "ini" file
         File dir = getFilesDir();
         File iniFile = new File(dir, "SUTAgent.ini");
         String sIniFile = iniFile.getAbsolutePath();
 
+        String lc = dc.GetIniData("General", "LogCommands", sIniFile);
+        if (lc != "" && Integer.parseInt(lc) == 1) {
+            SUTAgentAndroid.LogCommands = true;
+        }
         SUTAgentAndroid.RegSvrIPAddr = dc.GetIniData("Registration Server", "IPAddr", sIniFile);
         SUTAgentAndroid.RegSvrIPPort = dc.GetIniData("Registration Server", "PORT", sIniFile);
         SUTAgentAndroid.HardwareID = dc.GetIniData("Registration Server", "HARDWARE", sIniFile);
         SUTAgentAndroid.Pool = dc.GetIniData("Registration Server", "POOL", sIniFile);
+        logToFile(dc, "onCreate");
 
         tv = (TextView) this.findViewById(R.id.Textview01);
 
         if (getLocalIpAddress() == null)
             setUpNetwork(sIniFile);
 
         String macAddress = "Unknown";
         if (android.os.Build.VERSION.SDK_INT > 8) {
@@ -349,61 +353,61 @@ public class SUTAgentAndroid extends Act
             {
                Toast.makeText(getApplication().getApplicationContext(), "SUTAgent startprg finished ...", Toast.LENGTH_LONG).show();
             }
         }
 
     @Override
     public void onDestroy()
         {
+        DoCommand dc = new DoCommand(getApplication());
         super.onDestroy();
-        DoCommand dc = new DoCommand(getApplication());
         if (isFinishing())
             {
-            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onDestroy - finishing");
+            logToFile(dc, "onDestroy - finishing");
             Intent listenerSvc = new Intent(this, ASMozStub.class);
             listenerSvc.setAction("com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE");
             stopService(listenerSvc);
             bNetworkingStarted = false;
 
             unregisterReceiver(battReceiver);
 
             if (wl != null)
                 wl.release();
 
             System.exit(0);
             }
         else
             {
-            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onDestroy - not finishing");
+            logToFile(dc, "onDestroy - not finishing");
             }
         }
 
     @Override
     public void onLowMemory()
         {
         System.gc();
         DoCommand dc = new DoCommand(getApplication());
         if (dc != null)
             {
-            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onLowMemory");
-            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), dc.GetMemoryInfo());
+            logToFile(dc, "onLowMemory");
+            logToFile(dc, dc.GetMemoryInfo());
             String procInfo = dc.GetProcessInfo();
             if (procInfo != null)
                 {
                 String lines[] = procInfo.split("\n");
                 for (String line : lines) 
                     {
                     if (line.contains("mozilla"))
                         {
-                        logToFile(dc.GetTestRoot(), dc.GetSystemTime(), line);
+                        logToFile(dc, line);
                         String words[] = line.split("\t");
                         if ((words != null) && (words.length > 1))
                             {
-                            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), dc.StatProcess(words[1]));
+                            logToFile(dc, dc.StatProcess(words[1]));
                             }
                         }
                     }
                 }
             }
         else
             {
             Log.e("SUTAgentAndroid", "onLowMemory: unable to log to file!");
@@ -753,27 +757,39 @@ public class SUTAgentAndroid extends Act
             }
         catch (SocketException ex)
             {
             Toast.makeText(getApplication().getApplicationContext(), ex.toString(), Toast.LENGTH_LONG).show();
             }
         return null;
         }
 
-    public static void logToFile(String testRoot, String datestamp, String message)
+    public static void logToFile(DoCommand dc, String message)
         {
-        if (testRoot == null ||
-            datestamp == null ||
-            message == null)
+        if (SUTAgentAndroid.LogCommands == false)
+            {
+            return;
+            }
+
+        if (message == null)
             {
             Log.e("SUTAgentAndroid", "bad arguments in logToFile()!");
             return;
             }
         Log.i("SUTAgentAndroid", message);
         String fileDateStr = "00";
+        String testRoot = dc.GetTestRoot();
+        String datestamp = dc.GetSystemTime();
+        if (testRoot == null || datestamp == null)
+            {
+            Log.e("SUTAgentAndroid", "Unable to get testRoot or datestamp in logToFile!");
+            return;
+            }
+
+
         try 
             {
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
             Date dateStr = sdf.parse(datestamp);
             SimpleDateFormat sdf_file = new SimpleDateFormat("yyyy-MM-dd");
             fileDateStr = sdf_file.format(dateStr);
             } 
         catch (ParseException pe) {}
--- a/caps/tests/mochitest/test_bug292789.html.in
+++ b/caps/tests/mochitest/test_bug292789.html.in
@@ -8,17 +8,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=292789">Mozilla Bug 292789</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   <script src="chrome://global/content/strres.js"></script>
-  <script src="chrome://mozapps/content/xpinstall/xpinstallConfirm.js"></script>
+  <script type="application/javascript;version=1.8" src="chrome://mozapps/content/xpinstall/xpinstallConfirm.js"></script>
+  <script id="resjs" type="application/javascript;version=1.8"></script>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 292789
  **
  ** Selectively allow access to whitelisted chrome packages
  ** even for ALLOW_CHROME mechanisms (<script>, <img> etc)
@@ -31,23 +32,23 @@ function testScriptSrc(aCallback) {
     is(typeof srGetStrBundle, "function",
        "content can still load <script> from chrome://global");
     is(typeof XPInstallConfirm, "undefined",
        "content should not be able to load <script> from chrome://mozapps");
     
     /** make sure the last one didn't pass because someone
      ** moved the resource
      **/
-    var resjs = document.createElement("script");
+    var resjs = document.getElementById("resjs");
+    resjs.onload = scriptOnload;
 #ifdef MOZ_CHROME_FILE_FORMAT_JAR
     resjs.src = "jar:resource://gre/chrome/toolkit.jar!/content/mozapps/xpinstall/xpinstallConfirm.js";
 #else
     resjs.src = "resource://gre/chrome/toolkit/content/mozapps/xpinstall/xpinstallConfirm.js";
 #endif
-    resjs.onload = scriptOnload;
     document.getElementById("content").appendChild(resjs);
 
     function scriptOnload() {
       is(typeof XPInstallConfirm, "object",
          "xpinstallConfirm.js has not moved unexpectedly");
   
       // trigger the callback
       if (aCallback)
--- a/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
+++ b/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
@@ -359,16 +359,17 @@ function checkIFrame(aFrame, data) {
             "childPrincipal and parent principal should have different appId");
     }
   }
 
   eoList.push(principal.extendedOrigin);
 
   checkedCount++;
   if (checkedCount == checksTodo) {
+    SpecialPowers.removePermission("browser", "http://example.org");
     SimpleTest.finish();
   } else {
     gTestRunner.next();
   }
 }
 
 is('appStatus' in document.nodePrincipal, true,
    'appStatus should be present in nsIPrincipal');
@@ -423,16 +424,16 @@ function runTest() {
     content.appendChild(iframe);
 
     yield;
   }
 }
 
 var gTestRunner = runTest();
 
-SpecialPowers.pushPrefEnv({'set': [["dom.mozBrowserFramesEnabled", true],
-                                   ["dom.mozBrowserFramesWhitelist", "http://example.org"]]},
+SpecialPowers.addPermission("browser", true, "http://example.org");
+SpecialPowers.pushPrefEnv({'set':[["dom.mozBrowserFramesEnabled", true]]},
                            function() { gTestRunner.next(); });
 
 </script>
 </pre>
 </body>
 </html>
--- a/client.mk
+++ b/client.mk
@@ -65,17 +65,17 @@ AUTOCONF=$(error Could not find autoconf
 endif
 
 SH := /bin/sh
 PERL ?= perl
 PYTHON ?= python
 
 CONFIG_GUESS_SCRIPT := $(wildcard $(TOPSRCDIR)/build/autoconf/config.guess)
 ifdef CONFIG_GUESS_SCRIPT
-  CONFIG_GUESS = $(shell $(CONFIG_GUESS_SCRIPT))
+  CONFIG_GUESS := $(shell $(CONFIG_GUESS_SCRIPT))
 endif
 
 
 ####################################
 # Sanity checks
 
 ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
 # check for CRLF line endings
@@ -87,18 +87,16 @@ endif
 endif
 
 ####################################
 # Load mozconfig Options
 
 # See build pages, http://www.mozilla.org/build/ for how to set up mozconfig.
 
 MOZCONFIG_LOADER := build/autoconf/mozconfig2client-mk
-MOZCONFIG_FINDER := build/autoconf/mozconfig-find 
-MOZCONFIG_MODULES := build/unix/uniq.pl
 
 define CR
 
 
 endef
 
 # As $(shell) doesn't preserve newlines, use sed to replace them with an
 # unlikely sequence (||), which is then replaced back to newlines by make
--- a/client.py
+++ b/client.py
@@ -81,16 +81,31 @@ def do_cvs_export(modules, tag, cvsroot,
 
         (parent, leaf) = os.path.split(module)
         print "CVS export begin: " + datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
         check_call_noisy([cvs, '-d', cvsroot,
                           'export', '-r', tag, '-d', leaf, cvs_module],
                          cwd=os.path.join(topsrcdir, parent))
         print "CVS export end: " + datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
 
+def toggle_trailing_blank_line(depname):
+  """If the trailing line is empty, then we'll delete it.
+  Otherwise we'll add a blank line."""
+  lines = open(depname, "r").readlines()
+  if not lines:
+      print >>sys.stderr, "unexpected short file"
+      return
+
+  if not lines[-1].strip():
+      # trailing line is blank, removing it
+      open(depname, "w").writelines(lines[:-1])
+  else:
+      # adding blank line
+      open(depname, "a").write("\n")
+
 o = OptionParser(usage="client.py [options] update_nspr tagname | update_nss tagname | update_libffi tagname | update_webidlparser tagname")
 o.add_option("--skip-mozilla", dest="skip_mozilla",
              action="store_true", default=False,
              help="Obsolete")
 
 o.add_option("--cvs", dest="cvs", default=os.environ.get('CVS', 'cvs'),
              help="The location of the cvs binary")
 o.add_option("--cvsroot", dest="cvsroot",
@@ -109,23 +124,25 @@ if action in ('checkout', 'co'):
     print >>sys.stderr, "Warning: client.py checkout is obsolete."
     pass
 elif action in ('update_nspr'):
     tag, = args[1:]
     if not options.cvsroot:
         options.cvsroot = os.environ.get('CVSROOT', CVSROOT_MOZILLA)
     do_cvs_export(NSPR_DIRS, tag, options.cvsroot, options.cvs)
     print >>file("nsprpub/TAG-INFO", "w"), tag
+    toggle_trailing_blank_line("nsprpub/config/prdepend.h")
 elif action in ('update_nss'):
     tag, = args[1:]
     if not options.cvsroot:
         options.cvsroot = os.environ.get('CVSROOT', CVSROOT_MOZILLA)
     do_cvs_export(NSS_DIRS, tag, options.cvsroot, options.cvs)
     print >>file("security/nss/TAG-INFO", "w"), tag
     print >>file("security/nss/TAG-INFO-CKBI", "w"), tag
+    toggle_trailing_blank_line("security/coreconf/coreconf.dep")
 elif action in ('update_nssckbi'):
     tag, = args[1:]
     if not options.cvsroot:
         options.cvsroot = os.environ.get('CVSROOT', CVSROOT_MOZILLA)
     do_cvs_export(NSSCKBI_DIRS, tag, options.cvsroot, options.cvs)
     print >>file("security/nss/TAG-INFO-CKBI", "w"), tag
 elif action in ('update_libffi'):
     tag, = args[1:]
--- a/configure.in
+++ b/configure.in
@@ -5268,18 +5268,23 @@ MOZ_ARG_DISABLE_BOOL(webm,
     MOZ_WEBM=1)
 
 if test -n "$MOZ_WEBM"; then
     AC_DEFINE(MOZ_WEBM)
     MOZ_VP8=1
 fi;
 
 dnl ========================================================
-dnl = Disable media plugin support
-dnl ========================================================
+dnl = Enable media plugin support
+dnl ========================================================
+if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
+  dnl Enable support on android by default
+  MOZ_MEDIA_PLUGINS=1
+fi
+
 MOZ_ARG_ENABLE_BOOL(media-plugins,
 [  --enable-media-plugins  Enable support for media plugins],
     MOZ_MEDIA_PLUGINS=1,
     MOZ_MEDIA_PLUGINS=)
 
 if test -n "$MOZ_MEDIA_PLUGINS"; then
   AC_DEFINE(MOZ_MEDIA_PLUGINS)
 fi
@@ -5294,16 +5299,21 @@ MOZ_ARG_ENABLE_BOOL(media-navigator,
 
 if test -n "$MOZ_MEDIA_NAVIGATOR"; then
   AC_DEFINE(MOZ_MEDIA_NAVIGATOR)
 fi
 
 dnl ========================================================
 dnl = Enable building OMX media plugin (B2G or Android)
 dnl ========================================================
+if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
+  dnl Enable support on android by default
+  MOZ_OMX_PLUGIN=1
+fi
+
 MOZ_ARG_ENABLE_BOOL(omx-plugin,
 [  --enable-omx-plugin      Enable building OMX plugin (B2G)],
     MOZ_OMX_PLUGIN=1,
     MOZ_OMX_PLUGIN=)
 
 if test -n "$MOZ_OMX_PLUGIN"; then
     if test "$OS_TARGET" = "Android"; then
         dnl Only allow building OMX plugin on Gonk (B2G) or Android
@@ -5791,26 +5801,26 @@ esac
 MOZ_ARG_DISABLE_BOOL(crashreporter,
 [  --disable-crashreporter Disable breakpad crash reporting],
     MOZ_CRASHREPORTER=,
     MOZ_CRASHREPORTER=1)
 
 if test -n "$MOZ_CRASHREPORTER"; then
    AC_DEFINE(MOZ_CRASHREPORTER)
 
-  if (test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS") && \
+  if test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS" && \
     test -z "$SKIP_LIBRARY_CHECKS"; then
     PKG_CHECK_MODULES(MOZ_GTHREAD, gthread-2.0)
     AC_SUBST(MOZ_GTHREAD_CFLAGS)
     AC_SUBST(MOZ_GTHREAD_LIBS)
 
     MOZ_CHECK_HEADERS([curl/curl.h], [], [AC_MSG_ERROR([Couldn't find curl/curl.h which is required for the crash reporter.  Use --disable-crashreporter to disable the crash reporter.])])
   fi
 
-  if (test "$OS_ARCH" != "$HOST_OS_ARCH"); then
+  if test "$OS_ARCH" != "$HOST_OS_ARCH"; then
     AC_MSG_ERROR([Breakpad tools do not support compiling on $HOST_OS_ARCH while targeting $OS_ARCH.  Use --disable-crashreporter.])
   fi
 
   if test "$OS_ARCH" = "WINNT" -a -z "$HAVE_64BIT_OS"; then
     MOZ_CRASHREPORTER_INJECTOR=1
     AC_DEFINE(MOZ_CRASHREPORTER_INJECTOR)
   fi
 fi
@@ -7676,17 +7686,17 @@ MOZ_ARG_DISABLE_BOOL(md,
      _cpp_md_flag=1
    fi
   dnl Default is to use -xM if using Sun Studio on Solaris
    if test "$SOLARIS_SUNPRO_CC"; then
      _cpp_md_flag=1
    fi])
 if test "$_cpp_md_flag"; then
   COMPILER_DEPEND=1
-  _DEPEND_CFLAGS='$(filter-out %/.pp,-MD -MF $(MDDEPDIR)/$(@F).pp)'
+  _DEPEND_CFLAGS='$(filter-out %/.pp,-MMD -MF $(MDDEPDIR)/$(@F).pp)'
   dnl Sun Studio on Solaris use -xM instead of -MD, see config/rules.mk
   if test "$SOLARIS_SUNPRO_CC"; then
     _DEPEND_CFLAGS=
   fi
 else
   COMPILER_DEPEND=
   dnl Don't override this for MSVC
   if test -z "$_WIN32_MSVC"; then
@@ -8636,20 +8646,18 @@ if test "$MOZ_GL_DEFAULT_PROVIDER" = "GL
 fi # MOZ_GL_DEFAULT_PROVIDER=GLX
 fi # COMPILE_ENVIRONMENT
 
 dnl Set various defines and substitutions
 dnl ========================================================
 
 if test "$OS_ARCH" = "Darwin"; then
   AC_DEFINE(XP_UNIX)
-  AC_DEFINE(UNIX_ASYNC_DNS)
 elif test "$OS_ARCH" != "WINNT" -a "$OS_ARCH" != "OS2"; then
   AC_DEFINE(XP_UNIX)
-  AC_DEFINE(UNIX_ASYNC_DNS)
 fi
 
 if test "$MOZ_DEBUG"; then
     AC_DEFINE(MOZ_REFLOW_PERF)
     AC_DEFINE(MOZ_REFLOW_PERF_DSP)
 fi
 
 if test "$ACCESSIBILITY" -a "$MOZ_ENABLE_GTK2" ; then
--- a/content/base/public/nsDeprecatedOperationList.h
+++ b/content/base/public/nsDeprecatedOperationList.h
@@ -40,11 +40,10 @@ DEPRECATED_OPERATION(IsEqualNode)
 DEPRECATED_OPERATION(TextContent)
 DEPRECATED_OPERATION(EnablePrivilege)
 DEPRECATED_OPERATION(Position)
 DEPRECATED_OPERATION(TotalSize)
 DEPRECATED_OPERATION(InputEncoding)
 DEPRECATED_OPERATION(MozBeforePaint)
 DEPRECATED_OPERATION(MozBlobBuilder)
 DEPRECATED_OPERATION(DOMExceptionCode)
-DEPRECATED_OPERATION(NoExposedProps)
 DEPRECATED_OPERATION(MutationEvent)
 DEPRECATED_OPERATION(MozSlice)
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -8,16 +8,17 @@
  * Overview
  * This contains a set of classes and utilities for CSP.  It is in this
  * separate file for testing purposes.
  */
 
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
 // Module stuff
 var EXPORTED_SYMBOLS = ["CSPRep", "CSPSourceList", "CSPSource", "CSPHost",
                         "CSPWarning", "CSPError", "CSPdebug",
                         "CSPViolationReportListener", "CSPLocalizer"];
@@ -26,16 +27,51 @@ var STRINGS_URI = "chrome://global/local
 
 // these are not exported
 var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
                  .getService(Components.interfaces.nsIIOService);
 
 var gETLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
                    .getService(Components.interfaces.nsIEffectiveTLDService);
 
+// These regexps represent the concrete syntax on the w3 spec as of 7-5-2012
+// scheme          = <scheme production from RFC 3986>
+const R_SCHEME     = new RegExp ("([a-zA-Z0-9\\-]+)", 'i');
+const R_GETSCHEME  = new RegExp ("^" + R_SCHEME.source + "(?=\\:)", 'i');
+
+// scheme-source   = scheme ":"
+const R_SCHEMESRC  = new RegExp ("^" + R_SCHEME.source + "\\:$", 'i');
+
+// host-char       = ALPHA / DIGIT / "-"
+const R_HOSTCHAR   = new RegExp ("[a-zA-Z0-9\\-]", 'i');
+
+// host            = "*" / [ "*." ] 1*host-char *( "." 1*host-char )
+const R_HOST       = new RegExp ("\\*|(((\\*\\.)?" + R_HOSTCHAR.source +
+                                      "+)(\\." + R_HOSTCHAR.source +"+)+)",'i');
+// port            = ":" ( 1*DIGIT / "*" )
+const R_PORT       = new RegExp ("(\\:([0-9]+|\\*))", 'i');
+
+// host-source     = [ scheme "://" ] host [ port ]
+const R_HOSTSRC    = new RegExp ("^((" + R_SCHEME.source + "\\:\\/\\/)?("
+                                       +   R_HOST.source + ")"
+                                       +   R_PORT.source + "?)$", 'i');
+
+// ext-host-source = host-source "/" *( <VCHAR except ";" and ","> )
+//                 ; ext-host-source is reserved for future use.
+const R_EXTHOSTSRC = new RegExp ("^" + R_HOSTSRC.source + "\\/[:print:]+$", 'i');
+
+// keyword-source  = "'self'" / "'unsafe-inline'" / "'unsafe-eval'"
+const R_KEYWORDSRC = new RegExp ("^('self'|'unsafe-inline'|'unsafe-eval')$", 'i');
+
+// source-exp      = scheme-source / host-source / keyword-source
+const R_SOURCEEXP  = new RegExp (R_SCHEMESRC.source + "|" +
+                                   R_HOSTSRC.source + "|" +
+                                R_KEYWORDSRC.source,  'i');
+
+
 var gPrefObserver = {
   get debugEnabled () {
     if (!this._branch)
       this._initialize();
     return this._debugEnabled;
   },
 
   _initialize: function() {
@@ -474,18 +510,20 @@ CSPRep.prototype = {
    *        a new CSPRep instance of the intersection
    */
   intersectWith:
   function cspsd_intersectWith(aCSPRep) {
     var newRep = new CSPRep();
 
     for (var dir in CSPRep.SRC_DIRECTIVES) {
       var dirv = CSPRep.SRC_DIRECTIVES[dir];
-      newRep._directives[dirv] = this._directives[dirv]
-               .intersectWith(aCSPRep._directives[dirv]);
+      if (this._directives.hasOwnProperty(dirv))
+        newRep._directives[dirv] = this._directives[dirv].intersectWith(aCSPRep._directives[dirv]);
+      else
+        newRep._directives[dirv] = aCSPRep._directives[dirv];
     }
 
     // REPORT_URI
     var reportURIDir = CSPRep.URI_DIRECTIVES.REPORT_URI;
     if (this._directives[reportURIDir] && aCSPRep._directives[reportURIDir]) {
       newRep._directives[reportURIDir] =
         this._directives[reportURIDir].concat(aCSPRep._directives[reportURIDir]);
     }
@@ -493,22 +531,16 @@ CSPRep.prototype = {
       // blank concat makes a copy of the string.
       newRep._directives[reportURIDir] = this._directives[reportURIDir].concat();
     }
     else if (aCSPRep._directives[reportURIDir]) {
       // blank concat makes a copy of the string.
       newRep._directives[reportURIDir] = aCSPRep._directives[reportURIDir].concat();
     }
 
-    for (var dir in CSPRep.SRC_DIRECTIVES) {
-      var dirv = CSPRep.SRC_DIRECTIVES[dir];
-      newRep._directives[dirv] = this._directives[dirv]
-               .intersectWith(aCSPRep._directives[dirv]);
-    }
-
     newRep._allowEval =          this.allowsEvalInScripts
                            && aCSPRep.allowsEvalInScripts;
 
     newRep._allowInlineScripts = this.allowsInlineScripts 
                            && aCSPRep.allowsInlineScripts;
 
     return newRep;
   },
@@ -583,46 +615,53 @@ function CSPSourceList() {
  *        URI or CSPSource representing the "self" source
  * @param enforceSelfChecks (optional)
  *        if present, and "true", will check to be sure "self" has the
  *        appropriate values to inherit when they are omitted from the source.
  * @returns
  *        an instance of CSPSourceList 
  */
 CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
-  // Source list is:
-  //    <host-dir-value> ::= <source-list>
-  //                       | "'none'"
-  //    <source-list>    ::= <source>
-  //                       | <source-list>" "<source>
+  // source-list = *WSP [ source-expression *( 1*WSP source-expression ) *WSP ]
+  //             / *WSP "'none'" *WSP
 
   /* If self parameter is passed, convert to CSPSource,
      unless it is already a CSPSource. */
   if(self && !(self instanceof CSPSource)) {
      self = CSPSource.create(self);
   }
 
   var slObj = new CSPSourceList();
-  if (aStr === "'none'")
-    return slObj;
-
-  if (aStr === "*") {
-    slObj._permitAllSources = true;
+  aStr = aStr.trim();
+  // w3 specifies case insensitive equality
+  if (aStr.toUpperCase() === "'NONE'"){
+    slObj._permitAllSources = false;
     return slObj;
   }
 
   var tokens = aStr.split(/\s+/);
   for (var i in tokens) {
-    if (tokens[i] === "") continue;
+    if (!R_SOURCEEXP.test(tokens[i])){
+      CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
+                                           [tokens[i]]));
+      continue;
+    }
     var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
     if (!src) {
-      CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource", [tokens[i]]));
+      CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
+                                           [tokens[i]]));
       continue;
     }
-    slObj._sources.push(src);
+    // if a source is a *, then we can permit all sources
+    if (src.permitAll){
+      slObj._permitAllSources = true;
+      return slObj;
+    } else {
+      slObj._sources.push(src);
+    }
   }
 
   return slObj;
 };
 
 CSPSourceList.prototype = {
   /**
    * Compares one CSPSourceList to another.
@@ -731,16 +770,18 @@ CSPSourceList.prototype = {
    * @returns
    *        a new instance of a CSPSourceList representing the intersection
    */
   intersectWith:
   function cspsd_intersectWith(that) {
 
     var newCSPSrcList = null;
 
+    if (!that) return this.clone();
+
     if (this.isNone() || that.isNone())
       newCSPSrcList = CSPSourceList.fromString("'none'");
 
     if (this.isAll()) newCSPSrcList = that.clone();
     if (that.isAll()) newCSPSrcList = this.clone();
 
     if (!newCSPSrcList) {
       // the shortcuts didn't apply, must do intersection the hard way.
@@ -782,16 +823,19 @@ CSPSourceList.prototype = {
 /**
  * Class to model a source (scheme, host, port)
  */
 function CSPSource() {
   this._scheme = undefined;
   this._port = undefined;
   this._host = undefined;
 
+  //when set to true, this allows all source
+  this._permitAll = false;
+
   // when set to true, this source represents 'self'
   this._isSelf = false;
 }
 
 /**
  * General factory method to create a new source from one of the following
  * types:
  *  - nsURI
@@ -919,157 +963,93 @@ CSPSource.fromString = function(aStr, se
   if (!aStr)
     return null;
 
   if (!(typeof aStr === 'string')) {
     CSPError(CSPLocalizer.getStr("argumentIsNotString"));
     return null;
   }
 
+  var sObj = new CSPSource();
+  sObj._self = self;
+
+  // if equal, return does match
+  if (aStr === "*"){
+    sObj._permitAll = true;
+    return sObj;
+  }
+
   if (!self && enforceSelfChecks) {
     CSPError(CSPLocalizer.getStr("selfDataNotProvided"));
     return null;
   }
 
   if (self && !(self instanceof CSPSource)) {
     self = CSPSource.create(self, undefined, false);
   }
 
-  var sObj = new CSPSource();
-  sObj._self = self;
+  // check for scheme-source match
+  if (R_SCHEMESRC.test(aStr)){
+    var schemeSrcMatch = R_GETSCHEME.exec(aStr);
+    sObj._scheme = schemeSrcMatch[0];
+    if (!sObj._host) sObj._host = CSPHost.fromString("*");
+    if (!sObj._port) sObj._port = "*";
+    return sObj;
+  }
+
+  // check for host-source or ext-host-source match
+  if (R_HOSTSRC.test(aStr) || R_EXTHOSTSRC.test(aStr)){
+    var schemeMatch = R_GETSCHEME.exec(aStr);
+    if (!schemeMatch)
+      sObj._scheme = self.scheme;
+    else {
+      sObj._scheme = schemeMatch[0];
+    }
 
-  // take care of 'self' keyword
-  if (aStr === "'self'") {
-    if (!self) {
+    var hostMatch = R_HOST.exec(aStr);
+    if (!hostMatch) {
+      CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
+      return null;
+    }
+    sObj._host = CSPHost.fromString(hostMatch[0]);
+    var portMatch = R_PORT.exec(aStr);
+    if (!portMatch) {
+      // gets the default port for the given scheme
+      defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
+      if (!defPort) {
+        CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
+        return null;
+      }
+      sObj._port = defPort;
+    }
+    else {
+      // strip the ':' from the port
+      sObj._port = portMatch[0].substr(1);
+    }
+    return sObj;
+  }
+
+  // check for 'self' (case insensitive)
+  if (aStr.toUpperCase() === "'SELF'"){
+    if (!self){
       CSPError(CSPLocalizer.getStr("selfKeywordNoSelfData"));
       return null;
     }
     sObj._self = self.clone();
     sObj._isSelf = true;
     return sObj;
   }
-
-  // We could just create a URI and then send this off to fromURI, but
-  // there's no way to leave out the scheme or wildcard the port in an nsURI.
-  // That has to be supported here.
-
-  // split it up
-  var chunks = aStr.split(":");
-
-  // If there is only one chunk, it's gotta be a host.
-  if (chunks.length == 1) {
-    sObj._host = CSPHost.fromString(chunks[0]);
-    if (!sObj._host) {
-      CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
-      return null;
-    }
-
-    // enforce 'self' inheritance
-    if (enforceSelfChecks) {
-      // note: the non _scheme accessor checks sObj._self
-      if (!sObj.scheme || !sObj.port) {
-        CSPError(CSPLocalizer.getFormatStr("hostSourceWithoutData",[aStr]));
-        return null;
-      }
-    }
-    return sObj;
-  }
-
-  // If there are two chunks, it's either scheme://host or host:port
-  //   ... but scheme://host can have an empty host.
-  //   ... and host:port can have an empty host
-  if (chunks.length == 2) {
-
-    // is the last bit a port?
-    if (chunks[1] === "*" || chunks[1].match(/^\d+$/)) {
-      sObj._port = chunks[1];
-      // then the previous chunk *must* be a host or empty.
-      if (chunks[0] !== "") {
-        sObj._host = CSPHost.fromString(chunks[0]);
-        if (!sObj._host) {
-          CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
-          return null;
-        }
-      }
-      // enforce 'self' inheritance 
-      // (scheme:host requires port, host:port does too.  Wildcard support is
-      // only available if the scheme and host are wildcarded)
-      if (enforceSelfChecks) {
-        // note: the non _scheme accessor checks sObj._self
-        if (!sObj.scheme || !sObj.host || !sObj.port) {
-          CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
-          return null;
-        }
-      }
-    }
-    // is the first bit a scheme?
-    else if (CSPSource.validSchemeName(chunks[0])) {
-      sObj._scheme = chunks[0];
-      // then the second bit *must* be a host or empty
-      if (chunks[1] === "") {
-        // Allow scheme-only sources!  These default to wildcard host/port,
-        // especially since host and port don't always matter.
-        // Example: "javascript:" and "data:" 
-        if (!sObj._host) sObj._host = CSPHost.fromString("*");
-        if (!sObj._port) sObj._port = "*";
-      } else {
-        // some host was defined.
-        // ... remove <= 3 leading slashes (from the scheme) and parse
-        var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
-        // ... and parse
-        sObj._host = CSPHost.fromString(cleanHost);
-        if (!sObj._host) {
-          CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidHost",[cleanHost]));
-          return null;
-        }
-      }
-
-      // enforce 'self' inheritance (scheme-only should be scheme:*:* now, and
-      // if there was a host provided it should be scheme:host:selfport
-      if (enforceSelfChecks) {
-        // note: the non _scheme accessor checks sObj._self
-        if (!sObj.scheme || !sObj.host || !sObj.port) {
-          CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
-          return null;
-        }
-      }
-    }
-    else  {
-      // AAAH!  Don't know what to do!  No valid scheme or port!
-      CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
-      return null;
-    }
-
-    return sObj;
-  }
-
-  // If there are three chunks, we got 'em all!
-  if (!CSPSource.validSchemeName(chunks[0])) {
-    CSPError(CSPLocalizer.getFormatStr("couldntParseScheme",[aStr]));
-    return null;
-  }
-  sObj._scheme = chunks[0];
-  if (!(chunks[2] === "*" || chunks[2].match(/^\d+$/))) {
-    CSPError(CSPLocalizer.getFormatStr("couldntParsePort",[aStr]));
-    return null;
-  }
-
-  sObj._port = chunks[2];
-
-  // ... remove <= 3 leading slashes (from the scheme) and parse
-  var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
-  sObj._host = CSPHost.fromString(cleanHost);
-
-  return sObj._host ? sObj : null;
+  CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
+  return null;
 };
 
 CSPSource.validSchemeName = function(aStr) {
   // <scheme-name>       ::= <alpha><scheme-suffix>
-  // <scheme-suffix>     ::= <scheme-chr> 
-  //                      | <scheme-suffix><scheme-chr> 
+  // <scheme-suffix>     ::= <scheme-chr>
+  //                      | <scheme-suffix><scheme-chr>
   // <scheme-chr>        ::= <letter> | <digit> | "+" | "." | "-"
   
   return aStr.match(/^[a-zA-Z][a-zA-Z0-9+.-]*$/);
 };
 
 CSPSource.prototype = {
 
   get scheme () {
@@ -1083,17 +1063,23 @@ CSPSource.prototype = {
   get host () {
     if (this._isSelf && this._self)
       return this._self.host;
     if (!this._host && this._self)
       return this._self.host;
     return this._host;
   },
 
-  /** 
+  get permitAll () {
+    if (this._isSelf && this._self)
+      return this._self.permitAll;
+    return this._permitAll;
+  },
+
+  /**
    * If this doesn't have a nonstandard port (hard-defined), use the default
    * port for this source's scheme. Should never inherit port from 'self'.
    */
   get port () {
     if (this._isSelf && this._self)
       return this._self.port;
     if (this._port) return this._port;
     // if no port, get the default port for the scheme
@@ -1194,64 +1180,64 @@ CSPSource.prototype = {
     // 'self' is not part of the intersection.  Intersect the raw values from
     // the source, self must be set by someone creating this source.
     // When intersecting, we take the more specific of the two: if one scheme,
     // host or port is undefined, the other is taken.  (This is contrary to
     // when "permits" is called -- there, the value of 'self' is looked at 
     // when a scheme, host or port is undefined.)
 
     // port
-    if (!this._port)
-      newSource._port = that._port;
-    else if (!that._port)
-      newSource._port = this._port;
-    else if (this._port === "*") 
-      newSource._port = that._port;
-    else if (that._port === "*")
-      newSource._port = this._port;
-    else if (that._port === this._port)
-      newSource._port = this._port;
+    if (!this.port)
+      newSource._port = that.port;
+    else if (!that.port)
+      newSource._port = this.port;
+    else if (this.port === "*")
+      newSource._port = that.port;
+    else if (that.port === "*")
+      newSource._port = this.port;
+    else if (that.port === this.port)
+      newSource._port = this.port;
     else {
       CSPError(CSPLocalizer.getFormatStr("notIntersectPort", [this.toString(), that.toString()]));
       return null;
     }
 
     // scheme
-    if (!this._scheme)
-      newSource._scheme = that._scheme;
-    else if (!that._scheme)
-      newSource._scheme = this._scheme;
-    if (this._scheme === "*")
-      newSource._scheme = that._scheme;
-    else if (that._scheme === "*")
-      newSource._scheme = this._scheme;
-    else if (that._scheme === this._scheme)
-      newSource._scheme = this._scheme;
+    if (!this.scheme)
+      newSource._scheme = that.scheme;
+    else if (!that.scheme)
+      newSource._scheme = this.scheme;
+    if (this.scheme === "*")
+      newSource._scheme = that.scheme;
+    else if (that.scheme === "*")
+      newSource._scheme = this.scheme;
+    else if (that.scheme === this.scheme)
+      newSource._scheme = this.scheme;
     else {
       CSPError(CSPLocalizer.getFormatStr("notIntersectScheme", [this.toString(), that.toString()]));
       return null;
     }
 
     // NOTE: Both sources must have a host, if they don't, something funny is
     // going on.  The fromString() factory method should have set the host to
     // * if there's no host specified in the input. Regardless, if a host is
     // not present either the scheme is hostless or any host should be allowed.
     // This means we can use the other source's host as the more restrictive
     // host expression, or if neither are present, we can use "*", but the
     // error should still be reported.
 
     // host
-    if (this._host && that._host) {
-      newSource._host = this._host.intersectWith(that._host);
-    } else if (this._host) {
+    if (this.host && that.host) {
+      newSource._host = this.host.intersectWith(that.host);
+    } else if (this.host) {
       CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [that.toString()]));
-      newSource._host = this._host.clone();
-    } else if (that._host) {
+      newSource._host = this.host.clone();
+    } else if (that.host) {
       CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [this.toString()]));
-      newSource._host = that._host.clone();
+      newSource._host = that.host.clone();
     } else {
       CSPError(CSPLocalizer.getFormatStr("intersectingSourcesWithUndefinedHosts", [this.toString(), that.toString()]));
       newSource._host = CSPHost.fromString("*");
     }
 
     return newSource;
   },
 
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -1305,17 +1305,17 @@ nsAttrValue::ParseEnumValue(const nsAStr
   return false;
 }
 
 bool
 nsAttrValue::ParseSpecialIntValue(const nsAString& aString)
 {
   ResetIfSet();
 
-  PRInt32 ec;
+  nsresult ec;
   bool strict;
   bool isPercent = false;
   nsAutoString tmp(aString);
   PRInt32 originalVal = StringToInteger(aString, &strict, &ec, true, &isPercent);
 
   if (NS_FAILED(ec)) {
     return false;
   }
@@ -1338,17 +1338,17 @@ nsAttrValue::ParseSpecialIntValue(const 
 bool
 nsAttrValue::ParseIntWithBounds(const nsAString& aString,
                                 PRInt32 aMin, PRInt32 aMax)
 {
   NS_PRECONDITION(aMin < aMax, "bad boundaries");
 
   ResetIfSet();
 
-  PRInt32 ec;
+  nsresult ec;
   bool strict;
   PRInt32 originalVal = StringToInteger(aString, &strict, &ec);
   if (NS_FAILED(ec)) {
     return false;
   }
 
   PRInt32 val = NS_MAX(originalVal, aMin);
   val = NS_MIN(val, aMax);
@@ -1358,34 +1358,34 @@ nsAttrValue::ParseIntWithBounds(const ns
   return true;
 }
 
 bool
 nsAttrValue::ParseNonNegativeIntValue(const nsAString& aString)
 {
   ResetIfSet();
 
-  PRInt32 ec;
+  nsresult ec;
   bool strict;
   PRInt32 originalVal = StringToInteger(aString, &strict, &ec);
   if (NS_FAILED(ec) || originalVal < 0) {
     return false;
   }
 
   SetIntValueAndType(originalVal, eInteger, strict ? nullptr : &aString);
 
   return true;
 }
 
 bool
 nsAttrValue::ParsePositiveIntValue(const nsAString& aString)
 {
   ResetIfSet();
 
-  PRInt32 ec;
+  nsresult ec;
   bool strict;
   PRInt32 originalVal = StringToInteger(aString, &strict, &ec);
   if (NS_FAILED(ec) || originalVal <= 0) {
     return false;
   }
 
   SetIntValueAndType(originalVal, eInteger, strict ? nullptr : &aString);
 
@@ -1656,17 +1656,17 @@ nsAttrValue::GetStringBuffer(const nsASt
   PRUnichar *data = static_cast<PRUnichar*>(buf->Data());
   CopyUnicodeTo(aValue, 0, data, len);
   data[len] = PRUnichar(0);
   return buf;
 }
 
 PRInt32
 nsAttrValue::StringToInteger(const nsAString& aValue, bool* aStrict,
-                             PRInt32* aErrorCode,
+                             nsresult* aErrorCode,
                              bool aCanBePercent,
                              bool* aIsPercent) const
 {
   *aStrict = true;
   *aErrorCode = NS_ERROR_ILLEGAL_VALUE;
   if (aCanBePercent) {
     *aIsPercent = false;
   }
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -413,17 +413,17 @@ private:
 
   bool EnsureEmptyMiscContainer();
   bool EnsureEmptyAtomArray();
   nsStringBuffer* GetStringBuffer(const nsAString& aValue) const;
   // aStrict is set true if stringifying the return value equals with
   // aValue.
   PRInt32 StringToInteger(const nsAString& aValue,
                           bool* aStrict,
-                          PRInt32* aErrorCode,
+                          nsresult* aErrorCode,
                           bool aCanBePercent = false,
                           bool* aIsPercent = nullptr) const;
   // Given an enum table and a particular entry in that table, return
   // the actual integer value we should store.
   PRInt32 EnumTableEntryToValue(const EnumTable* aEnumTable,
                                 const EnumTable* aTableEntry);  
 
   static nsTArray<const EnumTable*, nsTArrayDefaultAllocator>* sEnumTableArray;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -7,16 +7,17 @@
 /* A namespace class for static layout utilities. */
 
 #include "mozilla/Util.h"
 
 #include "jsapi.h"
 #include "jsdbgapi.h"
 #include "jsfriendapi.h"
 
+#include "Layers.h"
 #include "nsJSUtils.h"
 #include "nsCOMPtr.h"
 #include "nsAString.h"
 #include "nsPrintfCString.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsDOMCID.h"
 #include "nsContentUtils.h"
@@ -6550,16 +6551,28 @@ nsContentUtils::FindInternalContentViewe
         if (docFactory && aLoaderType) {
           *aLoaderType = TYPE_CONTENT;
         }
         return docFactory.forget();
       }
     }
   }
 #endif
+
+#ifdef MOZ_MEDIA_PLUGINS
+  if (nsHTMLMediaElement::IsMediaPluginsEnabled() &&
+      nsHTMLMediaElement::IsMediaPluginsType(nsDependentCString(aType))) {
+    docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
+    if (docFactory && aLoaderType) {
+      *aLoaderType = TYPE_CONTENT;
+    }
+    return docFactory.forget();
+  }
+#endif // MOZ_MEDIA_PLUGINS
+
 #endif // MOZ_MEDIA
 
   return NULL;
 }
 
 // static
 bool
 nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -12,17 +12,18 @@
 #include "nsError.h"
 #include "nsICharsetDetector.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIClassInfo.h"
 #include "nsIConverterInputStream.h"
 #include "nsIDocument.h"
 #include "nsIFileStreams.h"
 #include "nsIInputStream.h"
-#include "nsIIPCSerializable.h"
+#include "nsIIPCSerializableInputStream.h"
+#include "nsIIPCSerializableObsolete.h"
 #include "nsIMIMEService.h"
 #include "nsIPlatformCharset.h"
 #include "nsISeekableStream.h"
 #include "nsIUnicharInputStream.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsIUUIDGenerator.h"
@@ -42,63 +43,70 @@ using namespace mozilla::dom;
 
 // XXXkhuey the input stream that we pass out of a DOMFile
 // can outlive the actual DOMFile object.  Thus, we must
 // ensure that the buffer underlying the stream we get
 // from NS_NewByteInputStream is held alive as long as the
 // stream is.  We do that by passing back this class instead.
 class DataOwnerAdapter MOZ_FINAL : public nsIInputStream,
                                    public nsISeekableStream,
-                                   public nsIIPCSerializable,
-                                   public nsIClassInfo
+                                   public nsIIPCSerializableObsolete,
+                                   public nsIClassInfo,
+                                   public nsIIPCSerializableInputStream
 {
   typedef nsDOMMemoryFile::DataOwner DataOwner;
 public:
   static nsresult Create(DataOwner* aDataOwner,
                          PRUint32 aStart,
                          PRUint32 aLength,
                          nsIInputStream** _retval);
 
   NS_DECL_ISUPPORTS
 
   // These are mandatory.
   NS_FORWARD_NSIINPUTSTREAM(mStream->)
   NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
 
   // These are optional. We use a conditional QI to keep them from being called
   // if the underlying stream doesn't QI to either interface.
-  NS_FORWARD_NSIIPCSERIALIZABLE(mSerializable->)
+  NS_FORWARD_NSIIPCSERIALIZABLEOBSOLETE(mSerializableObsolete->)
   NS_FORWARD_NSICLASSINFO(mClassInfo->)
+  NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
 
 private:
   DataOwnerAdapter(DataOwner* aDataOwner,
                    nsIInputStream* aStream)
     : mDataOwner(aDataOwner), mStream(aStream),
       mSeekableStream(do_QueryInterface(aStream)),
-      mSerializable(do_QueryInterface(aStream)),
-      mClassInfo(do_QueryInterface(aStream))
+      mSerializableObsolete(do_QueryInterface(aStream)),
+      mClassInfo(do_QueryInterface(aStream)),
+      mSerializableInputStream(do_QueryInterface(aStream))
   {
     NS_ASSERTION(mSeekableStream, "Somebody gave us the wrong stream!");
   }
 
   nsRefPtr<DataOwner> mDataOwner;
   nsCOMPtr<nsIInputStream> mStream;
   nsCOMPtr<nsISeekableStream> mSeekableStream;
-  nsCOMPtr<nsIIPCSerializable> mSerializable;
+  nsCOMPtr<nsIIPCSerializableObsolete> mSerializableObsolete;
   nsCOMPtr<nsIClassInfo> mClassInfo;
+  nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
 };
 
 NS_IMPL_THREADSAFE_ADDREF(DataOwnerAdapter)
 NS_IMPL_THREADSAFE_RELEASE(DataOwnerAdapter)
 
 NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
   NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializable, mSerializable)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableObsolete,
+                                     mSerializableObsolete)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIClassInfo, mClassInfo)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
+                                     mSerializableInputStream)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
 NS_INTERFACE_MAP_END
 
 nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
                                   PRUint32 aStart,
                                   PRUint32 aLength,
                                   nsIInputStream** _retval)
 {
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8487,20 +8487,23 @@ DispatchFullScreenChange(nsIDocument* aT
                         true,
                         false);
   e->PostDOMEvent();
 }
 
 NS_IMETHODIMP
 nsDocument::MozCancelFullScreen()
 {
-  if (!nsContentUtils::IsRequestFullScreenAllowed()) {
-    return NS_OK;
-  }
-  RestorePreviousFullScreenState();
+  // Only perform fullscreen changes if we're running in a webapp
+  // same-origin to the web app, or if we're in a user generated event
+  // handler.
+  if (NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
+      nsContentUtils::IsRequestFullScreenAllowed()) {
+    RestorePreviousFullScreenState();
+  }
   return NS_OK;
 }
 
 // Runnable to set window full-screen mode. Used as a script runner
 // to ensure we only call nsGlobalWindow::SetFullScreen() when it's safe to
 // run script. nsGlobalWindow::SetFullScreen() dispatches a synchronous event
 // (handled in chome code) which is unsafe to run if this is called in
 // nsGenericElement::UnbindFromTree().
@@ -9119,16 +9122,17 @@ nsDocument::RequestFullScreen(Element* a
 
   // If this document hasn't already been approved in this session,
   // check to see if the user has granted the fullscreen access
   // to the document's principal's host, if it has one. Note that documents
   // in web apps which are the same origin as the web app are considered
   // trusted and so are automatically approved.
   if (!mIsApprovedForFullscreen) {
     mIsApprovedForFullscreen =
+      !Preferences::GetBool("full-screen-api.approval-required") ||
       NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
       nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen");
   }
 
   // If this document, or a document with the same principal has not
   // already been approved for fullscreen this fullscreen-session, dispatch
   // an event so that chrome knows to pop up a warning/approval UI.
   nsCOMPtr<nsIDocument> previousFullscreenDoc(do_QueryReferent(sFullScreenDoc));
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -1415,17 +1415,17 @@ nsHTMLCopyEncoder::SetSelection(nsISelec
   nsCOMPtr<nsIEnumerator> enumerator;
   rv = privSelection->GetEnumerator(getter_AddRefs(enumerator));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
 
   // loop thru the ranges in the selection
   enumerator->First(); 
   nsCOMPtr<nsISupports> currentItem;
-  while ((NS_ENUMERATOR_FALSE == enumerator->IsDone()))
+  while (static_cast<nsresult>(NS_ENUMERATOR_FALSE) == enumerator->IsDone())
   {
     rv = enumerator->CurrentItem(getter_AddRefs(currentItem));
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(currentItem, NS_ERROR_FAILURE);
     
     range = do_QueryInterface(currentItem);
     NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
     nsCOMPtr<nsIDOMRange> myRange;
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -283,16 +283,17 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrame
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsIContentViewManager)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFrameLoader)
 NS_INTERFACE_MAP_END
 
 nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
   : mOwnerContent(aOwner)
+  , mDetachedSubdocViews(nullptr)
   , mDepthTooGreat(false)
   , mIsTopLevelContent(false)
   , mDestroyCalled(false)
   , mNeedsAsyncDestroy(false)
   , mInSwap(false)
   , mInShow(false)
   , mHideCalled(false)
   , mNetworkCreated(aNetworkCreated)
@@ -2367,13 +2368,29 @@ nsFrameLoader::GetOwnerElement(nsIDOMEle
   return NS_OK;
 }
 
 void
 nsFrameLoader::SetRemoteBrowser(nsITabParent* aTabParent)
 {
   MOZ_ASSERT(!mRemoteBrowser);
   MOZ_ASSERT(!mCurrentRemoteFrame);
+  mRemoteFrame = true;
   mRemoteBrowser = static_cast<TabParent*>(aTabParent);
 
   ShowRemoteFrame(nsIntSize(0, 0));
 }
 
+void
+nsFrameLoader::SetDetachedSubdocView(nsIView* aDetachedViews,
+                                     nsIDocument* aContainerDoc)
+{
+  mDetachedSubdocViews = aDetachedViews;
+  mContainerDocWhileDetached = aContainerDoc;
+}
+
+nsIView*
+nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const
+{
+  NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached);
+  return mDetachedSubdocViews;
+}
+
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -263,16 +263,35 @@ public:
    *
    * This will assert if mRemoteBrowser or mCurrentRemoteFrame is non-null.  In
    * practice, this means you can't have successfully run TryRemoteBrowser() on
    * this object, which means you can't have called ShowRemoteFrame() or
    * ReallyStartLoading().
    */
   void SetRemoteBrowser(nsITabParent* aTabParent);
 
+  /**
+   * Stashes a detached view on the frame loader. We do this when we're
+   * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is
+   * being reframed we'll restore the detached view when it's recreated,
+   * otherwise we'll discard the old presentation and set the detached
+   * subdoc view to null. aContainerDoc is the document containing the
+   * the subdoc frame. This enables us to detect when the containing
+   * document has changed during reframe, so we can discard the presentation 
+   * in that case.
+   */
+  void SetDetachedSubdocView(nsIView* aDetachedView,
+                             nsIDocument* aContainerDoc);
+
+  /**
+   * Retrieves the detached view and the document containing the view,
+   * as set by SetDetachedSubdocView().
+   */
+  nsIView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const;
+
 private:
 
   void SetOwnerContent(mozilla::dom::Element* aContent);
 
   bool ShouldUseRemoteProcess();
 
   /**
    * Is this a frameloader for a bona fide <iframe mozbrowser> or
@@ -321,16 +340,26 @@ private:
   nsCOMPtr<nsIDocShell> mDocShell;
   nsCOMPtr<nsIURI> mURIToLoad;
   mozilla::dom::Element* mOwnerContent; // WEAK
 public:
   // public because a callback needs these.
   nsRefPtr<nsFrameMessageManager> mMessageManager;
   nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
 private:
+  // Stores the root view of the subdocument while the subdocument is being
+  // reframed. Used to restore the presentation after reframing.
+  nsIView* mDetachedSubdocViews;
+  // Stores the containing document of the frame corresponding to this
+  // frame loader. This is reference is kept valid while the subframe's
+  // presentation is detached and stored in mDetachedSubdocViews. This
+  // enables us to detect whether the frame has moved documents during
+  // a reframe, so that we know not to restore the presentation.
+  nsCOMPtr<nsIDocument> mContainerDocWhileDetached;
+
   bool mDepthTooGreat : 1;
   bool mIsTopLevelContent : 1;
   bool mDestroyCalled : 1;
   bool mNeedsAsyncDestroy : 1;
   bool mInSwap : 1;
   bool mInShow : 1;
   bool mHideCalled : 1;
   // True when the object is created for an element which the parser has
--- a/content/base/src/nsNodeInfo.cpp
+++ b/content/base/src/nsNodeInfo.cpp
@@ -77,17 +77,17 @@ nsNodeInfo::~nsNodeInfo()
   NS_RELEASE(mOwnerManager);
 }
 
 
 nsNodeInfo::nsNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
                        PRUint16 aNodeType, nsIAtom* aExtraName,
                        nsNodeInfoManager *aOwnerManager)
 {
-  CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
+  CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
   NS_ABORT_IF_FALSE(aOwnerManager, "Invalid aOwnerManager");
 
   // Initialize mInner
   NS_ADDREF(mInner.mName = aName);
   NS_IF_ADDREF(mInner.mPrefix = aPrefix);
   mInner.mNamespaceID = aNamespaceID;
   mInner.mNodeType = aNodeType;
   NS_ADDREF(mOwnerManager = aOwnerManager);
--- a/content/base/src/nsNodeInfo.h
+++ b/content/base/src/nsNodeInfo.h
@@ -12,16 +12,18 @@
 #ifndef nsNodeInfo_h___
 #define nsNodeInfo_h___
 
 #include "nsINodeInfo.h"
 #include "nsNodeInfoManager.h"
 #include "plhash.h"
 #include "nsIAtom.h"
 #include "nsCOMPtr.h"
+#include "nsIDOMNode.h"
+#include "nsGkAtoms.h"
 
 class nsFixedSizeAllocator;
 
 class nsNodeInfo : public nsINodeInfo
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeInfo)
@@ -58,50 +60,54 @@ public:
 private:
   static nsFixedSizeAllocator* sNodeInfoPool;
 
   /**
    * This method gets called by Release() when it's time to delete 
    * this object, instead of always deleting the object we'll put the
    * object in the cache unless the cache is already full.
    */
-   void LastRelease();
+  void LastRelease();
 };
 
-#define CHECK_VALID_NODEINFO(_nodeType, _name, _namespaceID, _extraName)    \
-NS_ABORT_IF_FALSE(_nodeType == nsIDOMNode::ELEMENT_NODE ||                  \
-                  _nodeType == nsIDOMNode::ATTRIBUTE_NODE ||                \
-                  _nodeType == nsIDOMNode::TEXT_NODE ||                     \
-                  _nodeType == nsIDOMNode::CDATA_SECTION_NODE ||            \
-                  _nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||   \
-                  _nodeType == nsIDOMNode::COMMENT_NODE ||                  \
-                  _nodeType == nsIDOMNode::DOCUMENT_NODE ||                 \
-                  _nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||            \
-                  _nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||        \
-                  _nodeType == PR_UINT16_MAX,                               \
-                  "Invalid nodeType");                                      \
-NS_ABORT_IF_FALSE((_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||  \
-                   _nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==          \
-                  (_extraName != nullptr),                                   \
-                  "Supply aExtraName for and only for PIs and doctypes");   \
-NS_ABORT_IF_FALSE(_nodeType == nsIDOMNode::ELEMENT_NODE ||                  \
-                  _nodeType == nsIDOMNode::ATTRIBUTE_NODE ||                \
-                  _nodeType == PR_UINT16_MAX ||                             \
-                  aNamespaceID == kNameSpaceID_None,                        \
-                  "Only attributes and elements can be in a namespace");    \
-NS_ABORT_IF_FALSE(_name && _name != nsGkAtoms::_empty, "Invalid localName");\
-NS_ABORT_IF_FALSE(((_nodeType == nsIDOMNode::TEXT_NODE) ==                  \
-                   (_name == nsGkAtoms::textTagName)) &&                    \
-                  ((_nodeType == nsIDOMNode::CDATA_SECTION_NODE) ==         \
-                   (_name == nsGkAtoms::cdataTagName)) &&                   \
-                  ((_nodeType == nsIDOMNode::COMMENT_NODE) ==               \
-                   (_name == nsGkAtoms::commentTagName)) &&                 \
-                  ((_nodeType == nsIDOMNode::DOCUMENT_NODE) ==              \
-                   (_name == nsGkAtoms::documentNodeName)) &&               \
-                  ((_nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==     \
-                   (_name == nsGkAtoms::documentFragmentNodeName)) &&       \
-                  ((_nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==         \
-                   (_name == nsGkAtoms::documentTypeNodeName)) &&           \
-                  ((_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==\
-                   (_name == nsGkAtoms::processingInstructionTagName)),     \
-                  "Wrong localName for nodeType");
+inline void
+CheckValidNodeInfo(PRUint16 aNodeType, nsIAtom *aName, PRInt32 aNamespaceID,
+                   nsIAtom* aExtraName)
+{
+  NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
+                    aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
+                    aNodeType == nsIDOMNode::TEXT_NODE ||
+                    aNodeType == nsIDOMNode::CDATA_SECTION_NODE ||
+                    aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
+                    aNodeType == nsIDOMNode::COMMENT_NODE ||
+                    aNodeType == nsIDOMNode::DOCUMENT_NODE ||
+                    aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
+                    aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||
+                    aNodeType == PR_UINT16_MAX,
+                    "Invalid nodeType");
+  NS_ABORT_IF_FALSE((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
+                     aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
+                    !!aExtraName,
+                    "Supply aExtraName for and only for PIs and doctypes");
+  NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
+                    aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
+                    aNodeType == PR_UINT16_MAX ||
+                    aNamespaceID == kNameSpaceID_None,
+                    "Only attributes and elements can be in a namespace");
+  NS_ABORT_IF_FALSE(aName && aName != nsGkAtoms::_empty, "Invalid localName");
+  NS_ABORT_IF_FALSE(((aNodeType == nsIDOMNode::TEXT_NODE) ==
+                     (aName == nsGkAtoms::textTagName)) &&
+                    ((aNodeType == nsIDOMNode::CDATA_SECTION_NODE) ==
+                     (aName == nsGkAtoms::cdataTagName)) &&
+                    ((aNodeType == nsIDOMNode::COMMENT_NODE) ==
+                     (aName == nsGkAtoms::commentTagName)) &&
+                    ((aNodeType == nsIDOMNode::DOCUMENT_NODE) ==
+                     (aName == nsGkAtoms::documentNodeName)) &&
+                    ((aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==
+                     (aName == nsGkAtoms::documentFragmentNodeName)) &&
+                    ((aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
+                     (aName == nsGkAtoms::documentTypeNodeName)) &&
+                    ((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==
+                     (aName == nsGkAtoms::processingInstructionTagName)),
+                    "Wrong localName for nodeType");
+}
 
 #endif /* nsNodeInfo_h___ */
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -205,17 +205,17 @@ nsNodeInfoManager::DropDocumentReference
 }
 
 
 already_AddRefed<nsINodeInfo>
 nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
                                PRInt32 aNamespaceID, PRUint16 aNodeType,
                                nsIAtom* aExtraName /* = nullptr */)
 {
-  CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
+  CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
 
   nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType,
                                       aExtraName);
 
   void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
 
   if (node) {
     nsINodeInfo* nodeInfo = static_cast<nsINodeInfo *>(node);
@@ -251,17 +251,17 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *
 nsresult
 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
                                PRInt32 aNamespaceID, PRUint16 aNodeType,
                                nsINodeInfo** aNodeInfo)
 {
 #ifdef DEBUG
   {
     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
-    CHECK_VALID_NODEINFO(aNodeType, nameAtom, aNamespaceID, nullptr);
+    CheckValidNodeInfo(aNodeType, nameAtom, aNamespaceID, nullptr);
   }
 #endif
 
   nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType);
 
   void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
 
   if (node) {
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -1064,98 +1064,102 @@ nsObjectLoadingContent::ObjectState() co
         case eFallbackVulnerableNoUpdate:
           return NS_EVENT_STATE_VULNERABLE_NO_UPDATE;
       }
   };
   NS_NOTREACHED("unknown type?");
   return NS_EVENT_STATE_LOADING;
 }
 
-// Helper to call CheckURILoad on URI -> BaseURI and BaseURI -> Origin
-bool nsObjectLoadingContent::CheckObjectURIs(PRInt16 *aContentPolicy,
-                                             PRInt32 aContentPolicyType)
+bool
+nsObjectLoadingContent::CheckLoadPolicy(PRInt16 *aContentPolicy)
 {
+  if (!aContentPolicy || !mURI) {
+    NS_NOTREACHED("Doing it wrong");
+    return false;
+  }
+
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   NS_ASSERTION(thisContent, "Must be an instance of content");
 
-  nsCOMPtr<nsIURI> docBaseURI = thisContent->GetBaseURI();
-
-  // Must have these to load
-  if (!aContentPolicy || !mBaseURI) {
-    return false;
-  }
+  nsIDocument* doc = thisContent->OwnerDoc();
 
-  bool ret;
-  if (!URIEquals(mBaseURI, docBaseURI)) {
-    // If our object sets a new baseURI, make sure that base URI could be
-    // loaded by the document
-    ret = CheckURILoad(mBaseURI, aContentPolicy, aContentPolicyType);
-    if (!ret) {
-      return false;
-    }
-  }
-
-  if (mURI) {
-    return CheckURILoad(mURI, aContentPolicy, aContentPolicyType);
+  *aContentPolicy = nsIContentPolicy::ACCEPT;
+  nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OBJECT,
+                                          mURI,
+                                          doc->NodePrincipal(),
+                                          thisContent,
+                                          mContentType,
+                                          nullptr, //extra
+                                          aContentPolicy,
+                                          nsContentUtils::GetContentPolicy(),
+                                          nsContentUtils::GetSecurityManager());
+  NS_ENSURE_SUCCESS(rv, false);
+  if (NS_CP_REJECTED(*aContentPolicy)) {
+    nsCAutoString uri;
+    nsCAutoString baseUri;
+    mURI->GetSpec(uri);
+    mURI->GetSpec(baseUri);
+    LOG(("OBJLC [%p]: Content policy denied load of %s (base %s)",
+         this, uri.get(), baseUri.get()));
+    return false;
   }
 
   return true;
 }
 
-bool nsObjectLoadingContent::CheckURILoad(nsIURI *aURI,
-                                          PRInt16 *aContentPolicy,
-                                          PRInt32 aContentPolicyType)
+bool
+nsObjectLoadingContent::CheckProcessPolicy(PRInt16 *aContentPolicy)
 {
-  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-  NS_ASSERTION(secMan, "No security manager!?");
+  if (!aContentPolicy) {
+    NS_NOTREACHED("Null out variable");
+    return false;
+  }
 
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   NS_ASSERTION(thisContent, "Must be an instance of content");
 
-  nsCOMPtr<nsIURI> docBaseURI = thisContent->GetBaseURI();
-
   nsIDocument* doc = thisContent->OwnerDoc();
-  nsresult rv =
-    secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(), aURI, 0);
   
-  if (NS_FAILED(rv)) {
-    nsCAutoString uri;
-    nsCAutoString baseUri;
-    aURI->GetSpec(uri);
-    aURI->GetSpec(baseUri);
-    LOG(("OBJLC [%p]: CheckLoadURIWithPrincipal denied load of %s (base %s)",
-         this, uri.get(), baseUri.get()));
-    return false;
+  PRInt32 objectType;
+  switch (mType) {
+    case eType_Image:
+      objectType = nsIContentPolicy::TYPE_IMAGE;
+      break;
+    case eType_Document:
+      objectType = nsIContentPolicy::TYPE_DOCUMENT;
+      break;
+    case eType_Plugin:
+      objectType = nsIContentPolicy::TYPE_OBJECT;
+      break;
+    default:
+      NS_NOTREACHED("Calling checkProcessPolicy with a unloadable type");
+      return false;
   }
 
-  PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; // default permit
-  rv = NS_CheckContentLoadPolicy(aContentPolicyType,
-                                 aURI,
+  *aContentPolicy = nsIContentPolicy::ACCEPT;
+  nsresult rv =
+    NS_CheckContentProcessPolicy(objectType,
+                                 mURI,
                                  doc->NodePrincipal(),
                                  static_cast<nsIImageLoadingContent*>(this),
                                  mContentType,
                                  nullptr, //extra
-                                 &shouldLoad,
+                                 aContentPolicy,
                                  nsContentUtils::GetContentPolicy(),
-                                 secMan);
+                                 nsContentUtils::GetSecurityManager());
   NS_ENSURE_SUCCESS(rv, false);
-  if (aContentPolicy) {
-    *aContentPolicy = shouldLoad;
-  }
-  if (NS_CP_REJECTED(shouldLoad)) {
-    nsCAutoString uri;
-    nsCAutoString baseUri;
-    aURI->GetSpec(uri);
-    aURI->GetSpec(baseUri);
-    LOG(("OBJLC [%p]: Content policy denied load of %s (base %s)",
-         this, uri.get(), baseUri.get()));
+
+  if (NS_CP_REJECTED(*aContentPolicy)) {
+    LOG(("OBJLC [%p]: CheckContentProcessPolicy rejected load", this));
     return false;
   }
+
   return true;
 }
 
 nsObjectLoadingContent::ParameterUpdateFlags
 nsObjectLoadingContent::UpdateObjectParameters()
 {
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
@@ -1164,16 +1168,17 @@ nsObjectLoadingContent::UpdateObjectPara
   PRUint32 caps = GetCapabilities();
   LOG(("OBJLC [%p]: Updating object parameters", this));
 
   nsresult rv;
   nsCAutoString newMime;
   nsCOMPtr<nsIURI> newURI;
   nsCOMPtr<nsIURI> newBaseURI;
   ObjectType newType;
+  bool isJava = false;
   // Set if this state can't be used to load anything, forces eType_Null
   bool stateInvalid = false;
   // Indicates what parameters changed.
   // eParamChannelChanged - means parameters that affect channel opening
   //                        decisions changed
   // eParamStateChanged -   means anything that affects what content we load
   //                        changed, even if the channel we'd open remains the
   //                        same.
@@ -1184,35 +1189,41 @@ nsObjectLoadingContent::UpdateObjectPara
   // that far.
   nsObjectLoadingContent::ParameterUpdateFlags retval = eParamNoChange;
 
   ///
   /// Initial MIME Type
   ///
   if (thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
     newMime.AssignLiteral("application/x-java-vm");
+    isJava = true;
   } else {
     nsAutoString typeAttr;
     thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, typeAttr);
     if (!typeAttr.IsEmpty()) {
       CopyUTF16toUTF8(typeAttr, newMime);
+      isJava = nsPluginHost::IsJavaMIMEType(newMime.get());
     }
   }
 
   ///
   /// classID
   ///
 
-  bool usingClassID = false;
   if (caps & eSupportClassID) {
     nsAutoString classIDAttr;
     thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::classid, classIDAttr);
     if (!classIDAttr.IsEmpty()) {
-      usingClassID = true;
-      if (NS_FAILED(TypeForClassID(classIDAttr, newMime))) {
+      // Our classid support is limited to 'java:' ids
+      rv = IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-java-vm"));
+      if (NS_SUCCEEDED(rv) &&
+          StringBeginsWith(classIDAttr, NS_LITERAL_STRING("java:"))) {
+        newMime.Assign("application/x-java-vm");
+        isJava = true;
+      } else {
         // XXX(johns): Our de-facto behavior since forever was to refuse to load
         // Objects who don't have a classid we support, regardless of other type
         // or uri info leads to a valid plugin.
         newMime.Assign("");
         stateInvalid = true;
       }
     }
   }
@@ -1256,23 +1267,26 @@ nsObjectLoadingContent::UpdateObjectPara
   }
 
   ///
   /// URI
   ///
 
   nsAutoString uriStr;
   // Different elements keep this in various locations
-  if (thisContent->NodeInfo()->Equals(nsGkAtoms::object)) {
+  if (isJava) {
+    // Applet tags and embed/object with explicit java MIMEs have
+    // src/data attributes that are not parsed as URIs, so we will
+    // act as if URI is null
+  } else if (thisContent->NodeInfo()->Equals(nsGkAtoms::object)) {
     thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, uriStr);
   } else if (thisContent->NodeInfo()->Equals(nsGkAtoms::embed)) {
     thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, uriStr);
-  } else if (thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
-    // Applet tags have no URI, and their 'code=' parameter is not parsed as one
   } else {
+    // Applet tags should always have a java MIME type at this point
     NS_NOTREACHED("Unrecognized plugin-loading tag");
   }
 
   // Note that the baseURI changing could affect the newURI, even if uriStr did
   // not change.
   if (!uriStr.IsEmpty()) {
     rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(newURI),
                                                    uriStr,
@@ -1364,69 +1378,65 @@ nsObjectLoadingContent::UpdateObjectPara
         if (!typeHint.IsEmpty()) {
           mChannel->SetContentType(typeHint);
         }
     } else if (binaryChannelType
                && IsPluginEnabledByExtension(newURI, newMime)) {
       mChannel->SetContentType(newMime);
     } else {
       newMime = channelType;
+      if (nsPluginHost::IsJavaMIMEType(newMime.get())) {
+        //   Java does not load with a channel, and being java retroactively changes
+        //   how we may have interpreted the codebase to construct this URI above.
+        //   Because the behavior here is more or less undefined, play it safe and
+        //   reject the load.
+        LOG(("OBJLC [%p]: Refusing to load with channel with java MIME",
+             this));
+        stateInvalid = true;
+      }
     }
   }
 
-  bool isJava = nsPluginHost::IsJavaMIMEType(newMime.get());
-  if (useChannel && (!mChannel || isJava)) {
-    // Sanity checks
-    // - Java does not load with a channel, and being java retroactively changes
-    //   how we may have interpreted the codebase to construct this URI above.
-    //   Because the behavior here is more or less undefined, play it safe and
-    //   reject the load.
-    //
-    // - (useChannel && !mChannel) is true if a channel was opened but was
-    //   subsequently invalidated
-    //   in that case.
+  if (useChannel && !mChannel) {
+    // - (useChannel && !mChannel) is true if a channel was opened but
+    //   is no longer around, in which case we can't load.
     stateInvalid = true;
   }
 
   ///
   /// Determine final type
   ///
   //  1) If we have attempted channel load, or set stateInvalid above, the type
   //     is always null (fallback)
   //  2) Otherwise, If we have a loaded channel, we grabbed its mimeType above,
   //     use that type.
   //  3) Otherwise, See if we can load this as a plugin without a channel
   //     (image/document types always need a channel).
-  //     - If we have indication this is a plugin (mime, extension, or classID)
+  //     - If we have indication this is a plugin (mime, extension)
   //       AND:
   //       - We have eAllowPluginSkipChannel OR
-  //       - We have no URI in the first place OR
-  //       - We're loading based on classID
-  //         XXX(johns): Legacy behavior is to skip channel loading if we have
-  //                     a classID. I don't know why.
+  //       - We have no URI in the first place (including java)
   //  3) Otherwise, if we have a URI, set type to loading to indicate
   //     we'd need a channel to proceed.
   //  4) Otherwise, type null to indicate unloadable content (fallback)
   //
   // XXX(johns): <embed> tags both support URIs and have
   //   eAllowPluginSkipChannel, meaning it is possible that we have a URI, but
   //   are not going to open a channel for it. The old objLC code did this (in a
   //   less obviously-intended way), so it's probably best not to change our
   //   behavior at this point.
-  //   We ALSO skip channel loading for objects whose type is found by ClassID
-  //   (We only support a tiny subset of classid: java and ActiveX, above)
   //
 
   if (stateInvalid) {
     newType = eType_Null;
   } else if (useChannel) {
       // If useChannel is set above, we considered it in setting newMime
       newType = GetTypeOfContent(newMime);
       LOG(("OBJLC [%p]: Using channel type", this));
-  } else if (((caps & eAllowPluginSkipChannel) || !newURI || usingClassID) &&
+  } else if (((caps & eAllowPluginSkipChannel) || !newURI) &&
              (GetTypeOfContent(newMime) == eType_Plugin)) {
     newType = eType_Plugin;
     LOG(("OBJLC [%p]: Skipping loading channel, type plugin", this));
   } else if (newURI) {
     // We could potentially load this if we opened a channel on mURI, indicate
     // This by leaving type as loading
     newType = eType_Loading;
   } else {
@@ -1557,73 +1567,71 @@ nsObjectLoadingContent::LoadObject(bool 
   // event loop. Note that we check for still-open channels below
   UnloadObject(false); // Don't reset state
   if (!mIsLoading) {
     // The event loop must've spun and re-entered into LoadObject, which
     // finished the load
     return NS_OK;
   }
 
+  // Determine what's going on with our channel
   if (stateChange & eParamChannelChanged) {
     // If the channel params changed, throw away the channel, but unset
     // mChannelLoaded so we'll still try to open a new one for this load if
     // necessary
     CloseChannel();
     mChannelLoaded = false;
   } else if (mType == eType_Null && mChannel) {
     // If we opened a channel but then failed to find a loadable state, throw it
     // away. mChannelLoaded will indicate that we tried to load a channel at one
     // point so we wont recurse
     CloseChannel();
+  } else if (mType == eType_Loading && mChannel) {
+    // We're still waiting on a channel load, already opened one, and
+    // channel parameters didn't change
+    return NS_OK;
   } else if (mChannelLoaded && mChannel != aLoadingChannel) {
     // The only time we should have a loaded channel with a changed state is
     // when the channel has just opened -- in which case this call should
     // have originated from OnStartRequest
     NS_NOTREACHED("Loading with a channel, but state doesn't make sense");
     return NS_OK;
   }
 
   //
   // Security checks
   //
 
-  // NOTE For eType_Loading we'll try all three types, as we want to go ahead
-  //      with the channel if it could be any acceptable type. This type is
-  //      passed to OpenChannel() as the LoadType. We pass through LoadObject
-  //      again once the channel is opened and we're actually loading, so if
-  //      the final URI doesn't pass the now-known type, we'll abort.
-  PRInt32 policyType;
   if (mType != eType_Null) {
-    bool allowLoad = false;
     PRInt16 contentPolicy = nsIContentPolicy::ACCEPT;
-    PRUint32 caps = GetCapabilities();
-    bool supportImage = caps & eSupportImages;
-    bool supportDoc = (caps & eSupportDocuments) || (caps & eSupportSVG);
-    bool supportPlugin = caps & eSupportPlugins;
-    if (mType == eType_Image || (mType == eType_Loading && supportImage)) {
-      policyType = nsIContentPolicy::TYPE_IMAGE;
-      allowLoad = CheckObjectURIs(&contentPolicy, policyType);
+    bool allowLoad = false;
+    // We check load policy before opening a channel, and process policy before
+    // going ahead with any final-type load
+    if (mType == eType_Loading) {
+      nsCOMPtr<nsIScriptSecurityManager> secMan =
+        nsContentUtils::GetSecurityManager();
+      if (!secMan) {
+        NS_NOTREACHED("No security manager?");
+      } else {
+        rv = secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(),
+                                               mURI, 0);
+        allowLoad = NS_SUCCEEDED(rv) && CheckLoadPolicy(&contentPolicy);
+      }
+    } else {
+      allowLoad = CheckProcessPolicy(&contentPolicy);
     }
-    if (!allowLoad &&
-        (mType == eType_Document || (mType == eType_Loading && supportDoc))) {
-      contentPolicy = nsIContentPolicy::ACCEPT;
-      policyType = nsIContentPolicy::TYPE_SUBDOCUMENT;
-      allowLoad = CheckObjectURIs(&contentPolicy, policyType);
-    }
-    if (!allowLoad &&
-        (mType == eType_Plugin || (mType == eType_Loading && supportPlugin))) {
-      contentPolicy = nsIContentPolicy::ACCEPT;
-      policyType = nsIContentPolicy::TYPE_OBJECT;
-      allowLoad = CheckObjectURIs(&contentPolicy, policyType);
-    }
-
+    
     // Load denied, switch to fallback and set disabled/suppressed if applicable
     if (!allowLoad) {
+      LOG(("OBJLC [%p]: Load denied by policy", this));
       mType = eType_Null;
       if (contentPolicy == nsIContentPolicy::REJECT_TYPE) {
+        // XXX(johns) This is assuming that we were rejected by
+        //            nsContentBlocker, which rejects by type if permissions
+        //            reject plugins
         fallbackType = eFallbackUserDisabled;
       } else {
         fallbackType = eFallbackSuppressed;
       }
     }
   }
 
   // If we're a plugin but shouldn't start yet, load fallback with
@@ -1712,31 +1720,25 @@ nsObjectLoadingContent::LoadObject(bool 
     {
       if (!mChannel) {
         // We could mFrameLoader->LoadURI(mURI), but UpdateObjectParameters
         // requires documents have a channel, so this is not a valid state.
         NS_NOTREACHED("Attempting to load a document without a channel");
         mType = eType_Null;
         break;
       }
+      
+      mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(),
+                                           mNetworkCreated);
       if (!mFrameLoader) {
-        // Force a sync state change, we need the frame created
-        NotifyStateChanged(oldType, oldState, true, aNotify);
-        oldType = mType;
-        oldState = ObjectState();
-
-        mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(),
-                                             mNetworkCreated);
-        if (!mFrameLoader) {
-          NS_NOTREACHED("nsFrameLoader::Create failed");
-          mType = eType_Null;
-          break;
-        }
+        NS_NOTREACHED("nsFrameLoader::Create failed");
+        mType = eType_Null;
+        break;
       }
-
+      
       rv = mFrameLoader->CheckForRecursiveLoad(mURI);
       if (NS_FAILED(rv)) {
         mType = eType_Null;
         break;
       }
 
       // We're loading a document, so we have to set LOAD_DOCUMENT_URI
       // (especially important for firing onload)
@@ -1771,17 +1773,17 @@ nsObjectLoadingContent::LoadObject(bool 
         mSrcStreamLoading = true;
         rv = mFinalListener->OnStartRequest(mChannel, nullptr);
         mSrcStreamLoading = false;
       }
     }
     break;
     case eType_Loading:
       // If our type remains Loading, we need a channel to proceed
-      rv = OpenChannel(policyType);
+      rv = OpenChannel();
       if (NS_FAILED(rv)) {
         LOG(("OBJLC [%p]: OpenChannel returned failure (%u)", this, rv));
       }
     break;
     case eType_Null:
       // Handled below, silence compiler warnings
     break;
   };
@@ -1807,20 +1809,21 @@ nsObjectLoadingContent::LoadObject(bool 
     // Don't notify or send events - we'll handle those ourselves
     // (so really this is just setting mFallbackType)
     LoadFallback(fallbackType, false);
   }
 
   // Notify of our final state if we haven't already
   NotifyStateChanged(oldType, oldState, false, aNotify);
 
-  if (mType == eType_Null && mFallbackType != eFallbackAlternate) {
-    // if we're not showing alternate content, fire a pluginerror to trigger
-    // (we stopped LoadFallback from doing so above, it doesn't know of our old
-    //  state)
+  if (mType == eType_Null && !mContentType.IsEmpty() &&
+      mFallbackType != eFallbackAlternate) {
+    // if we have a content type and are not showing alternate
+    // content, fire a pluginerror to trigger (we stopped LoadFallback
+    // from doing so above, it doesn't know of our old state)
     FirePluginError(mFallbackType);
   }
 
   return NS_OK;
 }
 
 nsresult
 nsObjectLoadingContent::CloseChannel()
@@ -1839,17 +1842,17 @@ nsObjectLoadingContent::CloseChannel()
       mFinalListener = nullptr;
     }
     mChannel = nullptr;
   }
   return NS_OK;
 }
 
 nsresult
-nsObjectLoadingContent::OpenChannel(PRInt32 aPolicyType)
+nsObjectLoadingContent::OpenChannel()
 {
   nsCOMPtr<nsIContent> thisContent = 
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   NS_ASSERTION(thisContent, "must be a content");
   nsIDocument* doc = thisContent->OwnerDoc();
   NS_ASSERTION(doc, "No owner document?");
   NS_ASSERTION(!mInstanceOwner && !mInstantiating,
                "opening a new channel with already loaded content");
@@ -1866,17 +1869,17 @@ nsObjectLoadingContent::OpenChannel(PRIn
   nsCOMPtr<nsIChannel> chan;
   nsCOMPtr<nsIChannelPolicy> channelPolicy;
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, rv);
   if (csp) {
     channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
     channelPolicy->SetContentSecurityPolicy(csp);
-    channelPolicy->SetLoadType(aPolicyType);
+    channelPolicy->SetLoadType(nsIContentPolicy::TYPE_OBJECT);
   }
   rv = NS_NewChannel(getter_AddRefs(chan), mURI, nullptr, group, this,
                      nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
                      nsIChannel::LOAD_CLASSIFY_URI,
                      channelPolicy);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Referrer
@@ -1940,17 +1943,21 @@ nsObjectLoadingContent::UnloadObject(boo
   CancelImageRequests(false);
   if (mFrameLoader) {
     mFrameLoader->Destroy();
     mFrameLoader = nullptr;
   }
 
   if (aResetState) {
     CloseChannel();
+    mChannelLoaded = false;
     mType = eType_Loading;
+    mURI = mOriginalURI = mBaseURI = nullptr;
+    mContentType.Truncate();
+    mOriginalContentType.Truncate();
   }
 
   // This call should be last as it may re-enter
   StopPluginInstance();
 }
 
 void
 nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
@@ -2049,44 +2056,16 @@ nsObjectLoadingContent::GetTypeOfContent
 
   if ((caps & eSupportPlugins) && NS_SUCCEEDED(IsPluginEnabledForType(aMIMEType))) {
     return eType_Plugin;
   }
 
   return eType_Null;
 }
 
-nsresult
-nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
-                                       nsACString& aType)
-{
-  if (StringBeginsWith(aClassID, NS_LITERAL_STRING("java:"))) {
-    // Supported if we have a java plugin
-    aType.AssignLiteral("application/x-java-vm");
-    nsresult rv = IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-java-vm"));
-    return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // If it starts with "clsid:", this is ActiveX content
-  if (StringBeginsWith(aClassID, NS_LITERAL_STRING("clsid:"), nsCaseInsensitiveStringComparator())) {
-    // Check if we have a plugin for that
-
-    if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-oleobject")))) {
-      aType.AssignLiteral("application/x-oleobject");
-      return NS_OK;
-    }
-    if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/oleobject")))) {
-      aType.AssignLiteral("application/oleobject");
-      return NS_OK;
-    }
-  }
-
-  return NS_ERROR_NOT_AVAILABLE;
-}
-
 nsObjectFrame*
 nsObjectLoadingContent::GetExistingFrame()
 {
   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   nsIFrame* frame = thisContent->GetPrimaryFrame();
   nsIObjectFrame* objFrame = do_QueryFrame(frame);
   return static_cast<nsObjectFrame*>(objFrame);
 }
@@ -2493,17 +2472,16 @@ nsObjectLoadingContent::ShouldPlay(Fallb
   }
   nsCOMPtr<nsIDOMWindow> topWindow;
   rv = window->GetTop(getter_AddRefs(topWindow));
   NS_ENSURE_SUCCESS(rv, false);
   nsCOMPtr<nsIDOMDocument> topDocument;
   rv = topWindow->GetDocument(getter_AddRefs(topDocument));
   NS_ENSURE_SUCCESS(rv, false);
   nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(topDocument);
-  nsIURI* topUri = topDoc->GetDocumentURI();
 
   nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, false);
 
   bool allowPerm = false;
   // For now we always say that the system principal uses click-to-play since
   // that maintains current behavior and we have tests that expect this.
   // What we really should do is disable plugins entirely in pages that use
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -262,63 +262,49 @@ class nsObjectLoadingContent : public ns
      * @return Returns a bitmask of ParameterUpdateFlags values
      */
     ParameterUpdateFlags UpdateObjectParameters();
 
     void NotifyContentObjectWrapper();
 
     /**
      * Opens the channel pointed to by mURI into mChannel.
-     *
-     * @param aPolicyType The value to be passed to channelPolicy->SetLoadType
      */
-    nsresult OpenChannel(PRInt32 aPolicyType);
+    nsresult OpenChannel();
 
     /**
      * Closes and releases references to mChannel and, if opened, mFinalListener
      */
     nsresult CloseChannel();
 
     /**
      * If this object is allowed to play plugin content, or if it would display
      * click-to-play instead.
      * NOTE that this does not actually check if the object is a loadable plugin
      */
     bool ShouldPlay(FallbackType &aReason);
 
     /**
-     * Checks if a URI passes security checks and content policy, relative to
-     * the current document's principal
+     * Helper to check if our current URI passes policy
+     *
+     * @param aContentPolicy [out] The result of the content policy decision
      *
-     * @param aURI                The URI to consider
-     * @param aContentPolicy      [in/out] A pointer to the initial content
-     *                            policy, that will be updated to contain the
-     *                            final determined policy
-     * @param aContentPolicyType  The 'contentType' parameter passed to
-     *                            NS_CheckContentLoadPolicy
-     *
-     * @return true if this URI is acceptable for loading
+     * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
      */
-    bool CheckURILoad(nsIURI *aURI,
-                      PRInt16 *aContentPolicy,
-                      PRInt32 aContentPolicyType);
+    bool CheckLoadPolicy(PRInt16 *aContentPolicy);
 
     /**
-     * Checks if the current mURI and mBaseURI pass content policy and security
-     * checks for loading
+     * Helper to check if the object passes process policy. Assumes we have a
+     * final determined type.
      *
-     * @param aContentPolicy     [in/out] A pointer to the initial content
-     *                           policy, that will be updated to contain the
-     *                           final determined policy if a URL is rejected
-     * @param aContentPolicyType The 'contentType' parameter passed to
-     *                           NS_CheckContentLoadPolicy
+     * @param aContentPolicy [out] The result of the content policy decision
      *
-     * @return true if the URIs are acceptable for loading
+     * @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
      */
-    bool CheckObjectURIs(PRInt16 *aContentPolicy, PRInt32 aContentPolicyType);
+    bool CheckProcessPolicy(PRInt16 *aContentPolicy);
 
     /**
      * Checks whether the given type is a supported document type
      *
      * NOTE Does not take content policy or capabilities into account
      */
     bool IsSupportedDocument(const nsCString& aType);
 
@@ -358,26 +344,16 @@ class nsObjectLoadingContent : public ns
      * into account
      * 
      * NOTE this does not consider whether the content would be suppressed by
      *      click-to-play or other content policy checks
      */
     ObjectType GetTypeOfContent(const nsCString& aMIMEType);
 
     /**
-     * For a classid, returns the MIME type that can be used to instantiate
-     * a plugin for this ID.
-     *
-     * @param aClassID The class ID in question
-     * @param aType    [out] The corresponding type, if the call is successful
-     * @return NS_ERROR_NOT_AVAILABLE Unsupported class ID.
-     */
-    nsresult TypeForClassID(const nsAString& aClassID, nsACString& aType);
-
-    /**
      * Gets the frame that's associated with this content node.
      * Does not flush.
      */
     nsObjectFrame* GetExistingFrame();
 
     // The final listener for mChannel (uriloader, pluginstreamlistener, etc.)
     nsCOMPtr<nsIStreamListener> mFinalListener;
 
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -71,16 +71,17 @@
 #include "nsIFileChannel.h"
 #include "mozilla/Telemetry.h"
 #include "jsfriendapi.h"
 #include "sampler.h"
 #include "mozilla/dom/XMLHttpRequestBinding.h"
 #include "nsIDOMFormData.h"
 #include "DictionaryHelpers.h"
 #include "mozilla/Attributes.h"
+#include "nsIPermissionManager.h"
 
 #include "nsWrapperCacheInlines.h"
 #include "nsStreamListenerWrapper.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define LOAD_STR "load"
@@ -567,19 +568,26 @@ nsXMLHttpRequest::InitParameters(bool aA
   // Chrome is always allowed access, so do the permission check only
   // for non-chrome pages.
   if (!nsContentUtils::IsCallerChrome()) {
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(window->GetExtantDocument());
     if (!doc) {
       return;
     }
 
-    nsCOMPtr<nsIURI> uri;
-    doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
-    if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.systemXHR.whitelist")) {
+    nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
+    nsCOMPtr<nsIPermissionManager> permMgr =
+      do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+    if (!permMgr)
+      return;
+
+    PRUint32 permission;
+    nsresult rv =
+      permMgr->TestPermissionFromPrincipal(principal, "systemXHR", &permission);
+    if (NS_FAILED(rv) || permission != nsIPermissionManager::ALLOW_ACTION) {
       return;
     }
   }
 
   mIsAnon = aAnon;
   mIsSystem = aSystem;
 }
 
--- a/content/base/test/test_XHR_anon.html
+++ b/content/base/test/test_XHR_anon.html
@@ -23,22 +23,21 @@ function runTests() {
 
     const {classes: Cc, interfaces: Ci} = SpecialPowers.wrap(Components);
 
     let authMgr = Cc["@mozilla.org/network/http-auth-manager;1"]
                     .getService(Components.interfaces.nsIHttpAuthManager)
     authMgr.setAuthIdentity("http", "example.com", 80, "basic", "testrealm",
                             "", "example.com", "user1", "password1");
 
-    SpecialPowers.setCharPref("dom.systemXHR.whitelist",
-                              "http://mochi.test:8888");
+    SpecialPowers.addPermission("systemXHR", true, document);
 
     return function tearDown() {
       authMgr.clearAll();
-      SpecialPowers.clearUserPref("dom.systemXHR.whitelist");
+      SpecialPowers.removePermission("systemXHR", document);
       SimpleTest.finish();
     }
   }());
 
   // An XHR with the anon flag set will not send cookie and auth information.
 
   const TEST_URL = "http://example.com/tests/content/base/test/file_XHR_anon.sjs";
 
--- a/content/base/test/test_XHR_parameters.html
+++ b/content/base/test/test_XHR_parameters.html
@@ -79,21 +79,21 @@ function runTests() {
   }
 
   // Run the tests once without API privileges...
   validParameters.forEach(testValidParameter);
   invalidParameters.forEach(testInvalidParameter);
 
   // ...and once with privileges.
   havePrivileges = true;
-  SpecialPowers.setCharPref("dom.systemXHR.whitelist",
-                            "http://mochi.test:8888");
+  SpecialPowers.addPermission("systemXHR", true, document);
+
   validParameters.forEach(testValidParameter);
   invalidParameters.forEach(testInvalidParameter);
-  SpecialPowers.clearUserPref("dom.systemXHR.whitelist");
+  SpecialPowers.removePermission("systemXHR", document);
 
   SimpleTest.finish();
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/base/test/test_XHR_system.html
+++ b/content/base/test/test_XHR_system.html
@@ -11,22 +11,22 @@
 </p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="application/javascript;version=1.8">
 
 function runTests() {
+  var comp = SpecialPowers.wrap(Components);
   SimpleTest.waitForExplicitFinish();
-  SpecialPowers.setCharPref("dom.systemXHR.whitelist",
-                            "http://mochi.test:8888");
+  SpecialPowers.addPermission("systemXHR", true, document);
 
   function tearDown() {
-    SpecialPowers.clearUserPref("dom.systemXHR.whitelist");
+    SpecialPowers.removePermission("systemXHR", document);
     SimpleTest.finish();
   }
 
   // An XHR with system privileges will be able to do cross-site calls.
 
   const TEST_URL = "http://example.com/tests/content/base/test/test_XHR_system.html";
   is(window.location.hostname, "mochi.test");
 
--- a/content/base/test/test_ipc_messagemanager_blob.html
+++ b/content/base/test/test_ipc_messagemanager_blob.html
@@ -68,16 +68,17 @@
         let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
         mm.addMessageListener("test:ipcClonedMessage", function(message) {
           // We need to wrap to access message.json, and unwrap to do the
           // identity check.
           is(SpecialPowers.unwrap(SpecialPowers.wrap(message).json),
              messages[receivedMessageIndex++],
              "Got correct round-tripped response");
           if (receivedMessageIndex == messages.length) {
+            SpecialPowers.removePermission("browser", document);
             SimpleTest.finish();
           }
         });
         mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
                            false);
 
         for each (let message in messages) {
           mm.sendAsyncMessage("test:ipcClonedMessage", message);
@@ -85,30 +86,20 @@
       });
 
       document.body.appendChild(iframe);
     }
 
     addEventListener("load", function() {
       info("Got load event.");
 
-      let whitelist;
-      try {
-        whitelist =
-          SpecialPowers.getCharPref("dom.mozBrowserFramesWhitelist") + ", ";
-      } catch (e) {
-        whitelist = "";
-      }
-
-      whitelist += window.location.protocol + "//" + window.location.host;
-
+      SpecialPowers.addPermission("browser", true, document);
       SpecialPowers.pushPrefEnv({
         "set": [
           ["dom.ipc.browser_frames.oop_by_default", true],
           ["dom.mozBrowserFramesEnabled", true],
-          ["dom.mozBrowserFramesWhitelist", whitelist],
           ["browser.pageThumbs.enabled", false]
         ]
       }, runTests);
     });
   </script>
 </body>
 </html>
--- a/content/base/test/unit/test_csputils.js
+++ b/content/base/test/unit/test_csputils.js
@@ -154,39 +154,45 @@ test(
     });
 
 ///////////////////// Test the Source object //////////////////////
 
 test(
     function test_CSPSource_fromString() {
     // can't do these tests because "self" is not defined.
       //"basic source should not be null.");
-      do_check_neq(null, CSPSource.fromString("a.com"));
+      do_check_neq(null, CSPSource.fromString("a.com", "http://abc.com"));
 
       //"ldh characters should all work for host.");
-      do_check_neq(null, CSPSource.fromString("a2-c.com"));
+      do_check_neq(null, CSPSource.fromString("a2-c.com", "https://a.com"));
 
       //"wildcard should work in first token for host.");
-      do_check_neq(null, CSPSource.fromString("*.a.com"));
+      do_check_neq(null, CSPSource.fromString("*.a.com", "http://abc.com"));
 
       //print(" --- Ignore the following two errors if they print ---");
       //"wildcard should not work in non-first token for host.");
-      do_check_eq(null, CSPSource.fromString("x.*.a.com"));
+      do_check_eq(null, CSPSource.fromString("x.*.a.com", "http://a.com"));
 
       //"funny characters (#) should not work for host.");
-      do_check_eq(null, CSPSource.fromString("a#2-c.com"));
+      do_check_eq(null, CSPSource.fromString("a#2-c.com", "http://a.com"));
 
       //print(" --- Stop ignoring errors that print ---\n");
 
       //"failed to parse host with port.");
-      do_check_neq(null, CSPSource.create("a.com:23"));
+      do_check_neq(null, CSPSource.create("a.com:23", "http://a.com"));
       //"failed to parse host with scheme.");
-      do_check_neq(null, CSPSource.create("https://a.com"));
+      do_check_neq(null, CSPSource.create("https://a.com", "http://a.com"));
       //"failed to parse host with scheme and port.");
-      do_check_neq(null, CSPSource.create("https://a.com:200"));
+      do_check_neq(null, CSPSource.create("https://a.com:200", "http://a.com"));
+
+      //Check to make sure we don't match multiple instances with regex
+      do_check_eq(null, CSPSource.create("http://foo.com:bar.com:23"));
+      //Port parsing should work for all schemes
+      do_check_neq(null, CSPSource.create("data:"));
+      do_check_neq(null, CSPSource.create("javascript:"));
     });
 
 test(
     function test_CSPSource_fromString_withSelf() {
       var src;
       src = CSPSource.create("a.com", "https://foobar.com:443");
       //"src should inherit port *
       do_check_true(src.permits("https://a.com:443"));
@@ -265,16 +271,17 @@ test(
 
 test(
     function test_CSPSourceList_permits() {
       var nullSourceList = CSPSourceList.fromString("'none'");
       var simpleSourceList = CSPSourceList.fromString("a.com", URI("http://self.com"));
       var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88",
                                                       URI("http://self.com:88"));
       var allSourceList = CSPSourceList.fromString("*");
+      var allAndMoreSourceList = CSPSourceList.fromString("* https://bar.com 'none'");
 
       //'none' should permit none."
       do_check_false( nullSourceList.permits("http://a.com"));
       //a.com should permit a.com"
       do_check_true( simpleSourceList.permits("http://a.com"));
       //wrong host"
       do_check_false( simpleSourceList.permits("http://b.com"));
       //double list permits http://bar.com:88"
@@ -288,25 +295,27 @@ test(
       //"double list does not permit foo.com on http"
       do_check_false( doubleSourceList.permits("http://foo.com"));
 
       //"* does not permit specific host"
       do_check_true( allSourceList.permits("http://x.com:23"));
       //"* does not permit a long host with no port"
       do_check_true( allSourceList.permits("http://a.b.c.d.e.f.g.h.i.j.k.l.x.com"));
 
+      //* short circuts parsing
+      do_check_true(allAndMoreSourceList.permits("http://a.com"));
     });
 
 test(
     function test_CSPSourceList_intersect() {
       // for this test, 'self' values are irrelevant
       // policy a /\ policy b intersects policies, not context (where 'self'
       // values come into play)
       var nullSourceList = CSPSourceList.fromString("'none'");
-      var simpleSourceList = CSPSourceList.fromString("a.com");
+      var simpleSourceList = CSPSourceList.fromString("http://a.com");
       var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88");
       var singleFooSourceList = CSPSourceList.fromString("https://foo.com");
       var allSourceList = CSPSourceList.fromString("*");
 
       //"Intersection of one source with 'none' source list should be none.");
       do_check_true(nullSourceList.intersectWith(simpleSourceList).isNone());
       //"Intersection of two sources with 'none' source list should be none.");
       do_check_true(nullSourceList.intersectWith(doubleSourceList).isNone());
@@ -621,16 +630,67 @@ test(
       do_check_false(p_all.equals(p_none));
       do_check_false(p_all.equals(p_one));
 
       do_check_true(p_all.permits("http://bar.com"));
       do_check_true(p_one.permits("http://bar.com"));
       do_check_false(p_none.permits("http://bar.com"));
     });
 
+test(
+    function test_bug783497_refinePolicyIssues() {
+
+      const firstPolicy = "allow 'self'; img-src 'self'; script-src 'self'; options 'bogus-option'";
+      const secondPolicy = "default-src 'none'; script-src 'self'";
+      var cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"]
+                     .createInstance(Ci.nsIContentSecurityPolicy);
+      var selfURI = URI("http://self.com/");
+
+      function testPermits(aUri, aContext) {
+        return cspObj.shouldLoad(aContext, aUri, null, null, null, null)
+               == Ci.nsIContentPolicy.ACCEPT;
+      };
+
+      // everything is allowed by the default policy
+      do_check_true(testPermits(URI("http://self.com/foo.js"),
+                    Ci.nsIContentPolicy.TYPE_SCRIPT));
+      do_check_true(testPermits(URI("http://other.com/foo.js"),
+                    Ci.nsIContentPolicy.TYPE_SCRIPT));
+      do_check_true(testPermits(URI("http://self.com/foo.png"),
+                    Ci.nsIContentPolicy.TYPE_IMAGE));
+      do_check_true(testPermits(URI("http://other.com/foo.png"),
+                    Ci.nsIContentPolicy.TYPE_IMAGE));
+
+      // fold in the first policy
+      cspObj.refinePolicy(firstPolicy, selfURI);
+
+      // script-src and img-src are limited to self after the first policy
+      do_check_true(testPermits(URI("http://self.com/foo.js"),
+                    Ci.nsIContentPolicy.TYPE_SCRIPT));
+      do_check_false(testPermits(URI("http://other.com/foo.js"),
+                     Ci.nsIContentPolicy.TYPE_SCRIPT));
+      do_check_true(testPermits(URI("http://self.com/foo.png"),
+                    Ci.nsIContentPolicy.TYPE_IMAGE));
+      do_check_false(testPermits(URI("http://other.com/foo.png"),
+                     Ci.nsIContentPolicy.TYPE_IMAGE));
+
+      // fold in the second policy
+      cspObj.refinePolicy(secondPolicy, selfURI);
+
+      // script-src is self and img-src is none after the merge
+      do_check_true(testPermits(URI("http://self.com/foo.js"),
+                    Ci.nsIContentPolicy.TYPE_SCRIPT));
+      do_check_false(testPermits(URI("http://other.com/foo.js"),
+                     Ci.nsIContentPolicy.TYPE_SCRIPT));
+      do_check_false(testPermits(URI("http://self.com/foo.png"),
+                     Ci.nsIContentPolicy.TYPE_IMAGE));
+      do_check_false(testPermits(URI("http://other.com/foo.png"),
+                     Ci.nsIContentPolicy.TYPE_IMAGE));
+    });
+
 
 /*
 
 test(function test_CSPRep_fromPolicyURI_failswhenmixed() {
         var cspr;
         var self = "http://localhost:" + POLICY_PORT;
         var closed_policy = CSPRep.fromString("allow 'none'");
         var my_uri_policy = "policy-uri " + POLICY_URI;
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -119,18 +119,17 @@ ok(ctx.canvas === canvas, "ctx.canvas ==
 <!-- [[[ test_2d.clearRect.basic.html ]]] -->
 
 <p>Canvas test: 2d.clearRect.basic</p>
 <canvas id="c3" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 function isPixel(ctx, x,y, r,g,b,a, d) {
 	var pos = x + "," + y;
 	var colour = r + "," + g + "," + b + "," + a;
-    var pixel = SpecialPowers.unwrap(SpecialPowers.wrap(ctx)
-                                                  .getImageData(x, y, 1, 1));
+    var pixel = ctx.getImageData(x, y, 1, 1);
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
     ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
--- a/content/canvas/test/webgl/conformance/attribs/gl-enable-vertex-attrib.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-enable-vertex-attrib.html
@@ -45,13 +45,13 @@ gl.vertexAttribPointer(0, 3, gl.FLOAT, f
 gl.enableVertexAttribArray(3);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 gl.drawArrays(gl.TRIANGLES, 0, 3);
 glErrorShouldBe(gl, gl.INVALID_OPERATION);
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib-zero-issues.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib-zero-issues.html
@@ -79,13 +79,13 @@ for (var ii = 0; ii < 5; ++ii) {
       gl, gl.NO_ERROR,
       "drawing using attrib 3 with 60000 verts");
 }
 
 wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be 0, 0, 0, 0");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib.html
@@ -83,12 +83,12 @@ if (!gl) {
   }
   glErrorShouldBe(gl, gl.NO_ERROR);
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/attribs/gl-vertexattribpointer-offsets.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-vertexattribpointer-offsets.html
@@ -182,12 +182,12 @@ There is supposed to be an example drawi
                 }
               }
             }
        }
 
        init();
        successfullyParsed = true;
     </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/attribs/gl-vertexattribpointer.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-vertexattribpointer.html
@@ -122,12 +122,12 @@ if (!gl) {
     }
   }
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/buffer-bind-test.html
+++ b/content/canvas/test/webgl/conformance/buffers/buffer-bind-test.html
@@ -51,13 +51,13 @@ if (!gl) {
   gl.bindBuffer(gl.ARRAY_BUFFER, buf);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
             "should get INVALID_OPERATION if attempting to bind buffer to different target");
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/buffers/buffer-data-array-buffer.html
+++ b/content/canvas/test/webgl/conformance/buffers/buffer-data-array-buffer.html
@@ -57,11 +57,11 @@ gl.bufferSubData(gl.ARRAY_BUFFER, 10, ar
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 gl.bufferSubData(gl.ARRAY_BUFFER, 10, null);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation-copies-indices.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation-copies-indices.html
@@ -66,11 +66,11 @@ indices[5] = 1;
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 2)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 4)");
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation-crash-with-buffer-sub-data.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation-crash-with-buffer-sub-data.html
@@ -25,11 +25,11 @@ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, e
 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 256, gl.STATIC_DRAW);
 var data = new Uint8Array(127);
 gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 63, data);
 testPassed("bufferSubData, when buffer object was initialized with null, did not crash");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation-verifies-too-many-indices.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation-verifies-too-many-indices.html
@@ -37,11 +37,11 @@ context.bufferData(context.ELEMENT_ARRAY
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 2)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 4)");
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation-with-resized-buffer.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation-with-resized-buffer.html
@@ -94,11 +94,11 @@ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, i
 glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
 gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_BYTE, 0);
 glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation.html
@@ -131,11 +131,11 @@ shouldBeUndefined('gl.drawElements(gl.TR
 debug("Pass large negative index to vertexAttribPointer");
 gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), -2000000000 * sizeInBytes(gl.FLOAT));
 glErrorShouldBe(gl, gl.INVALID_VALUE);
 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/canvas/canvas-zero-size.html
+++ b/content/canvas/test/webgl/conformance/canvas/canvas-zero-size.html
@@ -31,12 +31,12 @@ gl.bindTexture(gl.TEXTURE_2D, tex);
 var pixel = new Uint8Array([0, 255, 0, 255]);
 gl.texImage2D(
   gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
 wtu.drawQuad(gl);
 
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/canvas/drawingbuffer-static-canvas-test.html
+++ b/content/canvas/test/webgl/conformance/canvas/drawingbuffer-static-canvas-test.html
@@ -138,11 +138,11 @@ if (!gl) {
   shouldBeTrue('gl.drawingBufferHeight == 50');
   shouldBe('gl.getError()', 'gl.NO_ERROR');
   drawTriangleTest(gl);
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 }
 debug("")
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/canvas/drawingbuffer-test.html
+++ b/content/canvas/test/webgl/conformance/canvas/drawingbuffer-test.html
@@ -137,11 +137,11 @@ if (!gl) {
   shouldBeTrue('gl.drawingBufferHeight == 50');
   shouldBe('gl.getError()', 'gl.NO_ERROR');
   drawTriangleTest(gl);
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 }
 debug("")
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/canvas/viewport-unchanged-upon-resize.html
+++ b/content/canvas/test/webgl/conformance/canvas/viewport-unchanged-upon-resize.html
@@ -101,12 +101,12 @@ if (passed) {
     if (passed) {
       testPassed("Viewport correctly did not change size during canvas resize");
     }
   }
 }
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/context/constants.html
+++ b/content/canvas/test/webgl/conformance/context/constants.html
@@ -474,12 +474,12 @@ for (var i in gl) {
     }
     debug(i);
   }
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/context/context-type-test.html
+++ b/content/canvas/test/webgl/conformance/context/context-type-test.html
@@ -38,12 +38,12 @@ if (!gl) {
 
   debug("Checking context type");
   assertMsg(gl instanceof WebGLRenderingContext,
             "context type should be WebGLRenderingContext");
 }
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/context/incorrect-context-object-behaviour.html
+++ b/content/canvas/test/webgl/conformance/context/incorrect-context-object-behaviour.html
@@ -73,11 +73,11 @@ shouldGenerateGLError(contextA, contextA
 shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderInfoLog(shaderB, 0)");
 shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderSource(shaderB)");
 shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniform(programB, locationA)");
 shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniformLocation(programB, 'u_modelViewProjMatrix')");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/context/methods.html
+++ b/content/canvas/test/webgl/conformance/context/methods.html
@@ -189,12 +189,12 @@ for (var i in gl) {
     }
     debug(i);
   }
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/context/resource-sharing-test.html
+++ b/content/canvas/test/webgl/conformance/context/resource-sharing-test.html
@@ -30,12 +30,12 @@ assertMsg(gl1 && gl2,
 var vertexObject = gl1.createBuffer();
 gl2.bindBuffer(gl2.ARRAY_BUFFER, vertexObject);
 assertMsg(
   gl2.getError() == gl2.INVALID_OPERATION,
   "attempt to use a resource from the wrong context should fail with INVALID_OPERATION");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
+++ b/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
@@ -166,12 +166,12 @@ function runHintTestEnabled() {
     }
 
     gl.deleteTexture(texture);
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
@@ -363,12 +363,12 @@ function runReferenceCycleTest()
 
     // create a self-cycle on the extension object
     ext.ext = ext;
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
@@ -204,12 +204,12 @@ function runReferenceCycleTest()
 
     // create a self-cycle on the extension object
     ext.ext = ext;
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/oes-vertex-array-object.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-vertex-array-object.html
@@ -399,12 +399,12 @@ function runDrawTests() {
     ext.bindVertexArrayOES(null);
     ext.deleteVertexArrayOES(vao0);
     ext.deleteVertexArrayOES(vao1);
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/webgl-compressed-texture-s3tc.html
+++ b/content/canvas/test/webgl/conformance/extensions/webgl-compressed-texture-s3tc.html
@@ -603,12 +603,12 @@ function compareRect(
 
 function testPVRTCTextures() {
     testFailed("PVRTC test not yet implemented");
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/webgl-debug-renderer-info.html
+++ b/content/canvas/test/webgl/conformance/extensions/webgl-debug-renderer-info.html
@@ -93,12 +93,12 @@ function runTestEnabled() {
     shouldBe("ext.UNMASKED_RENDERER_WEBGL", "0x9246");
     gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
     glErrorShouldBe(gl, gl.NO_ERROR, "UNMASKED_RENDERER_WEBGL query should succeed if extension is enable");
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/webgl-debug-shaders.html
+++ b/content/canvas/test/webgl/conformance/extensions/webgl-debug-shaders.html
@@ -86,12 +86,12 @@ function runTestEnabled() {
         testPassed("Successfully called getTranslatedShaderSource()");
     else
         testFailed("Calling getTranslatedShaderSource() failed");
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/misc/attrib-location-length-limits.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/attrib-location-length-limits.html
@@ -72,11 +72,11 @@ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE
 
 debug("Attempt to fetch too-long attrib location should produce error");
 program = wtu.loadStandardProgram(gl);
 shouldBe('gl.getAttribLocation(program, "vPosition01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567")', '-1');
 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
 
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-2types-of-textures-on-same-unit.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-2types-of-textures-on-same-unit.html
@@ -125,13 +125,13 @@ function init()
     glErrorShouldBe(gl, gl.INVALID_OPERATION,
               "drawing with 2 different targets on the same texture unit should generate INVALID_VALUE");
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html
@@ -128,12 +128,12 @@ function init()
         else
             testPassed("Rendering results are the same");
     }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-long-variable-names.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-long-variable-names.html
@@ -239,11 +239,11 @@
                     return;
                 }
 
             pass();
         }
 
         successfullyParsed = true;
     </script>
-    <script src="../../../resources/js-test-post.js"></script>
+    <script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-vertex-branch.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-vertex-branch.html
@@ -119,12 +119,12 @@ function init()
         else
             testPassed("Rendering results are the same");
     }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/glsl/misc/re-compile-re-link.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/re-compile-re-link.html
@@ -138,14 +138,14 @@ for (var i = 0; i < 10; ++i) {
   gl.linkProgram(program);
   checkProgramStatus(program)
 }
 
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
 
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/glsl/misc/uniform-location-length-limits.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/uniform-location-length-limits.html
@@ -75,11 +75,11 @@ program = wtu.loadProgramFromScript(gl, 
 wtu.glErrorShouldBe(gl, gl.NONE);
 shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
 var uniformLoc = gl.getUniformLocation(program, "identifier128CharactersLong_0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.identifier64CharactersLong_0123456789012345678901234567890123456.identifier63CharactersLong_012345678901234567890123456789012345");
 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
 shouldBeNull('uniformLoc');
 
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2d-bias.html
+++ b/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2d-bias.html
@@ -89,14 +89,14 @@ for (var ii = 0; ii < colors.length; ++i
       "256x256 texture drawn to 256x256 dest with bias = " + ii +
       " should be " + color.name);
 }
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 
 successfullyParsed = true;
 
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2dlod.html
+++ b/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2dlod.html
@@ -89,14 +89,14 @@ for (var ii = 0; ii < colors.length; ++i
       "256x256 texture drawn to 256x256 dest with lod = " + ii +
       " should be " + color.name);
 }
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 
 successfullyParsed = true;
 
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2dproj.html
+++ b/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2dproj.html
@@ -104,14 +104,14 @@ for (var ss = 0; ss < 2; ++ss) {
 	}
   }
 }
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 
 successfullyParsed = true;
 
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/glsl/variables/gl-fragcoord.html
+++ b/content/canvas/test/webgl/conformance/glsl/variables/gl-fragcoord.html
@@ -76,12 +76,12 @@ found in the LICENSE file.
               gl, xx, yy, 1, 1, color, msg, 4);
         }
       }
     }
 
     init();
     successfullyParsed = true;
   </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/variables/gl-frontfacing.html
+++ b/content/canvas/test/webgl/conformance/glsl/variables/gl-frontfacing.html
@@ -77,12 +77,12 @@ found in the LICENSE file.
           }
         }
       }
     }
 
     init();
     successfullyParsed = true;
   </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/variables/gl-pointcoord.html
+++ b/content/canvas/test/webgl/conformance/glsl/variables/gl-pointcoord.html
@@ -130,12 +130,12 @@ found in the LICENSE file.
             wtu.checkCanvasRect(gl, xf, yf, 1, 1, color, msg, 4);
           }
         }
       }
     }
 
     successfullyParsed = true;
   </script>
-  <script src="../../../resources/js-test-post.js"></script>
+  <script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/limits/gl-max-texture-dimensions.html
+++ b/content/canvas/test/webgl/conformance/limits/gl-max-texture-dimensions.html
@@ -84,14 +84,14 @@ var program = wtu.setupProgram(
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 
 // NOTE: We can't easily test cube maps because they require width == height
 // and we might not have enough memory for maxSize by maxSize texture.
 
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/limits/gl-min-attribs.html
+++ b/content/canvas/test/webgl/conformance/limits/gl-min-attribs.html
@@ -72,14 +72,14 @@ for (var ii = 0; ii < 7; ++ii) {
 wtu.drawQuad(gl);
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, [255, 127, 64, 32], "Should render 255,127,64,32 (+/-1)", 1);
 
 successfullyParsed = true;
 
 </script>
 </body>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/limits/gl-min-textures.html
+++ b/content/canvas/test/webgl/conformance/limits/gl-min-textures.html
@@ -59,14 +59,14 @@ for (var ii = 0; ii < 8; ++ii) {
 wtu.drawQuad(gl);
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 wtu.checkCanvas(gl, [255, 128, 64, 252],
                 "Should render using all texture units", 1);
 
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/limits/gl-min-uniforms.html
+++ b/content/canvas/test/webgl/conformance/limits/gl-min-uniforms.html
@@ -91,14 +91,14 @@ for (var ii = 0; ii < 16; ++ii) {
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 wtu.drawQuad(gl);
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, [32, 64, 127, 255], "Should render 32,64,127,255 (+/-1)", 1);
 
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/misc/bad-arguments-test.html
+++ b/content/canvas/test/webgl/conformance/misc/bad-arguments-test.html
@@ -107,11 +107,11 @@ for (var i = 0; i < arguments.length; ++
   func3("context.getProgramInfoLog(argument)");
   func3("context.getShaderInfoLog(argument)");
   func3("context.getShaderSource(argument)");
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/error-reporting.html
+++ b/content/canvas/test/webgl/conformance/misc/error-reporting.html
@@ -90,11 +90,11 @@ shouldBeUndefined("context.framebufferTe
 // Synthetic OpenGL error
 glErrorShouldBe(context, context.INVALID_OPERATION);
 // Error state should be clear by this point
 glErrorShouldBe(context, context.NO_ERROR);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/functions-returning-strings.html
+++ b/content/canvas/test/webgl/conformance/misc/functions-returning-strings.html
@@ -92,12 +92,12 @@ if (!gl) {
   shouldReturnString("gl.getParameter(gl.VERSION)");
   shouldReturnString("gl.getParameter(gl.SHADING_LANGUAGE_VERSION)");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/instanceof-test.html
+++ b/content/canvas/test/webgl/conformance/misc/instanceof-test.html
@@ -76,14 +76,14 @@ shouldThrowWithNew(window.WebGLProgram, 
 shouldThrowWithNew(window.WebGLRenderbuffer, 'WebGLRenderbuffer');
 shouldThrowWithNew(window.WebGLShader, 'WebGLShader');
 shouldThrowWithNew(window.WebGLTexture, 'WebGLTexture');
 shouldThrowWithNew(window.WebGLUniformLocation, 'WebGLUniformLocation');
 shouldThrowWithNew(window.WebGLShaderPrecisionFormat, 'WebGLShaderPrecisionFormat');
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/misc/invalid-passed-params.html
+++ b/content/canvas/test/webgl/conformance/misc/invalid-passed-params.html
@@ -183,11 +183,11 @@ for (var i = 0; i < invalidSet.length; +
   context.getUniformLocation(program, invalidName);
   shouldBe("context.getError()", "context.INVALID_VALUE");
 }
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/is-object.html
+++ b/content/canvas/test/webgl/conformance/misc/is-object.html
@@ -63,11 +63,11 @@ debug("");
 shouldGenerateGLError(gl, gl.NO_ERROR, "shader = gl.createShader(gl.VERTEX_SHADER)");
 shouldBeTrue("gl.isShader(shader)");
 shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteShader(shader)");
 shouldBeFalse("gl.isShader(shader)");
 debug("");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/null-object-behaviour.html
+++ b/content/canvas/test/webgl/conformance/misc/null-object-behaviour.html
@@ -97,11 +97,11 @@ shouldGenerateGLError(context, context.I
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, 1, 1, 0, context.RGBA, context.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]))");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.NEAREST)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.getTexParameter(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER)");
 
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/object-deletion-behaviour.html
+++ b/content/canvas/test/webgl/conformance/misc/object-deletion-behaviour.html
@@ -418,11 +418,11 @@ if (gl.checkFramebufferStatus(gl.FRAMEBU
   shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
   // check again because many buggy implementations will have bound to the true backbuffer on deleteFramebuffer.
   shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green")');
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/type-conversion-test.html
+++ b/content/canvas/test/webgl/conformance/misc/type-conversion-test.html
@@ -159,12 +159,12 @@ for (var i = 0; i < args.length; ++i) {
   func1("context.uniform4f(loc, 0, argument, 0, 0)");
   func1("context.uniform4f(loc, 0, 0, argument, 0)");
   func1("context.uniform4f(loc, 0, 0, 0, argument)");
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/misc/uninitialized-test.html
+++ b/content/canvas/test/webgl/conformance/misc/uninitialized-test.html
@@ -159,12 +159,12 @@ glErrorShouldBe(gl, gl.NO_ERROR);
 //TODO: uninitialized vertex elements buffer
 //TODO: uninitialized framebuffer? (implementations would need to do a GL clear at first binding?)
 //TODO: uninitialized renderbuffer? (implementations would need to do a GL clear at first binding?)
 //TODO: uninitialized uniform arrays?
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/misc/webgl-specific.html
+++ b/content/canvas/test/webgl/conformance/misc/webgl-specific.html
@@ -94,11 +94,11 @@ glErrorShouldBe(gl, gl.NO_ERROR, "set/ge
 
 debug("");
 debug("Verify that drawingBufferWidth and drawingBufferHeights are implemented");
 shouldBeTrue("gl.drawingBufferWidth >= 0 && gl.drawingBufferHeight >= 0");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/get-active-test.html
+++ b/content/canvas/test/webgl/conformance/programs/get-active-test.html
@@ -125,11 +125,11 @@ context.deleteProgram(program);
 shouldBeNull("context.getActiveUniform(program, 0)");
 glErrorShouldBe(context, context.INVALID_VALUE);
 shouldBeNull("context.getActiveAttrib(program, 0)");
 glErrorShouldBe(context, context.INVALID_VALUE);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/gl-bind-attrib-location-test.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-bind-attrib-location-test.html
@@ -190,12 +190,12 @@ gl.vertexAttrib4f(0, 1, 0, 0, 1);
 checkDraw(0, 3, 255, 0, 0, 255);
 
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/gl-get-active-attribute.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-get-active-attribute.html
@@ -71,14 +71,14 @@ for (var tt = 0; tt < tests.length; ++tt
   }
   if (!found) {
     testFailed("attrib 'attr0' not found");
   }
 }
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/programs/gl-get-active-uniform.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-get-active-uniform.html
@@ -130,14 +130,14 @@ gl.useProgram(p2);
 gl.uniform1f(l2, 1);
 glErrorShouldBe(gl, gl.NO_ERROR, "no errors setting uniform 0");
 gl.uniform1f(l1, 2);
 glErrorShouldBe(gl, gl.INVALID_OPERATION,
                 "setting a uniform using a location from another program");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/programs/gl-getshadersource.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-getshadersource.html
@@ -25,14 +25,14 @@ var gl = wtu.create3DContext("example");
 var original = document.getElementById("vshader").text;
 var shader = gl.createShader(gl.VERTEX_SHADER);
 gl.shaderSource(shader, original);
 var source = gl.getShaderSource(shader);
 shouldBe("source", "original");
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/programs/gl-shader-test.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-shader-test.html
@@ -37,12 +37,12 @@ if (!gl) {
   assertMsg(shader == null,
             "should not be able to create GEOMETRY shader");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/invalid-UTF-16.html
+++ b/content/canvas/test/webgl/conformance/programs/invalid-UTF-16.html
@@ -40,11 +40,11 @@ var string = array.join('');
 
 var gl = create3DContext();
 var program = gl.createProgram();
 gl.bindAttribLocation(program, 0, string);
 testPassed("bindAttribLocation with invalid UTF-16 did not crash");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/program-test.html
+++ b/content/canvas/test/webgl/conformance/programs/program-test.html
@@ -316,12 +316,12 @@ function go() {
     glErrorShouldBe(gl, gl.INVALID_VALUE, "a delete-marked shader should be deleted once all its attachments are removed");
 }
 
 debug("");
 go();
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/reading/read-pixels-pack-alignment.html
+++ b/content/canvas/test/webgl/conformance/reading/read-pixels-pack-alignment.html
@@ -230,11 +230,11 @@ for (var i = 0; i < formats.length; ++i)
     runTestIteration(format, gl.UNSIGNED_BYTE, 1, -1, 1);
     runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, -1);
     runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, -1);
     runTestIteration(format, gl.UNSIGNED_BYTE, 8, -1, -1);
 }
     
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-object-attachment.html
+++ b/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-object-attachment.html
@@ -413,11 +413,11 @@ function testFramebufferIncompleteDimens
     checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
 
     glErrorShouldBe(gl, gl.NO_ERROR);
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-test.html
+++ b/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-test.html
@@ -162,12 +162,12 @@ if (!gl) {
   glErrorShouldBe(gl, gl.NO_ERROR,
             "binding default (null) framebuffer should succeed.");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/renderbuffers/renderbuffer-initialization.html
+++ b/content/canvas/test/webgl/conformance/renderbuffers/renderbuffer-initialization.html
@@ -88,11 +88,11 @@ function runTest(gl, width, height, orde
     gl.canvas.width += 1;
     gl.canvas.height += 1;
 
     debug('');
 }
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/draw-arrays-out-of-bounds.html
+++ b/content/canvas/test/webgl/conformance/rendering/draw-arrays-out-of-bounds.html
@@ -123,11 +123,11 @@ shouldGenerateGLError(context, context.I
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0, 0x7fffffff)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0x7fffffff, 1)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0x7fffffff, 0x7fffffff)");
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/draw-elements-out-of-bounds.html
+++ b/content/canvas/test/webgl/conformance/rendering/draw-elements-out-of-bounds.html
@@ -167,11 +167,11 @@ context.vertexAttribPointer(0, 3, contex
 context.disableVertexAttribArray(0);
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
 context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, null);
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/gl-clear.html
+++ b/content/canvas/test/webgl/conformance/rendering/gl-clear.html
@@ -55,12 +55,12 @@ gl.clearColor(1,1,1,1);
 gl.clear(gl.COLOR_BUFFER_BIT);
 wtu.checkCanvas(gl, [128,128,128,255], "should be 128,128,128,255");
 
 // TODO: Test depth and stencil clearing.
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/rendering/gl-drawelements.html
+++ b/content/canvas/test/webgl/conformance/rendering/gl-drawelements.html
@@ -87,12 +87,12 @@ found in the LICENSE file.
                 gl.TRIANGLES, 3, gl.UNSIGNED_INT,
                 gl.INVALID_ENUM, "gl.DrawElements should return INVALID_ENUM with UNSIGNED_INT");
 
        }
 
        init();
        successfullyParsed = true;
     </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/gl-scissor-test.html
+++ b/content/canvas/test/webgl/conformance/rendering/gl-scissor-test.html
@@ -62,12 +62,12 @@ if (!gl) {
   checkPixel(b, 0, 1, [0, 0, 0, 0]);
   checkPixel(b, 1, 1, [0, 0, 0, 0]);
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/line-loop-tri-fan.html
+++ b/content/canvas/test/webgl/conformance/rendering/line-loop-tri-fan.html
@@ -232,11 +232,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
         <canvas id="testbed" width="10px" height="10px" style="width:50px; height:50px"></canvas>
         <div id="description"></div>
         <div id="console"></div>
         <script>
             description('Verify that LINE_LOOP and TRIANGLE_FAN works correctly.');
             runTest();
             successfullyParsed = true;
         </script>
-        <script src="../../resources/js-test-post.js"></script>
+        <script>finishTest();</script>
     </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/more-than-65536-indices.html
+++ b/content/canvas/test/webgl/conformance/rendering/more-than-65536-indices.html
@@ -81,14 +81,14 @@ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, i
 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
 gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_BYTE, 0);
 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
 wtu.checkCanvas(gl, [0, 255, 0, 255], "Should be green.");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/rendering/point-size.html
+++ b/content/canvas/test/webgl/conformance/rendering/point-size.html
@@ -114,12 +114,12 @@ found in the LICENSE file.
                 index += 4;
             }
         }
     }
 
     successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/triangle.html
+++ b/content/canvas/test/webgl/conformance/rendering/triangle.html
@@ -112,12 +112,12 @@ There is supposed to be an example drawi
                 }
 
             pass();
        }
 
        init();
        successfullyParsed = true;
     </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/state/gl-enable-enum-test.html
+++ b/content/canvas/test/webgl/conformance/state/gl-enable-enum-test.html
@@ -122,12 +122,12 @@ if (!gl) {
   }
 
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/state/gl-enum-tests.html
+++ b/content/canvas/test/webgl/conformance/state/gl-enum-tests.html
@@ -75,13 +75,13 @@ if (!gl) {
               tests[ii] + " should return INVALID_ENUM.");
   }
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/state/gl-get-calls.html
+++ b/content/canvas/test/webgl/conformance/state/gl-get-calls.html
@@ -145,12 +145,12 @@ else {
     shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[0] >= window.screen.width');
     shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[1] >= window.screen.height');
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/state/gl-geterror.html
+++ b/content/canvas/test/webgl/conformance/state/gl-geterror.html
@@ -65,12 +65,12 @@ if (err2 == gl.NO_ERROR) {
                'err5 == gl.INVALID_VALUE || ' +
                'err6 == gl.INVALID_VALUE');
   shouldBeTrue('gl.getError() == gl.NO_ERROR');
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/state/gl-getstring.html
+++ b/content/canvas/test/webgl/conformance/state/gl-getstring.html
@@ -47,12 +47,12 @@ function checkPrefix(expected, enum_val)
     testFailed("getParameter(gl." + enum_val + ") did not start with " + expected);
   }
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/state/gl-object-get-calls.html
+++ b/content/canvas/test/webgl/conformance/state/gl-object-get-calls.html
@@ -266,11 +266,11 @@ gl.deleteRenderbuffer(renderbuffer);
 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE');
 gl.deleteBuffer(buffer);
 shouldBeNull('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)');
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/compressed-tex-image.html
+++ b/content/canvas/test/webgl/conformance/textures/compressed-tex-image.html
@@ -50,11 +50,11 @@ if (!gl) {
 
   shouldGenerateGLError(gl, gl.NO_ERROR, "formats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)");
   shouldBeNonNull("formats");
   shouldBe("formats.length", "0");
 }
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/gl-pixelstorei.html
+++ b/content/canvas/test/webgl/conformance/textures/gl-pixelstorei.html
@@ -113,12 +113,12 @@ function init() {
     assertMsg(gl.getParameter(gl.PACK_ALIGNMENT) == table[ii],
         "PACK_ALIGNMENT is " + table[ii]);
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html
@@ -183,11 +183,11 @@ gl.clearColor(0,0,0,1);
 gl.clearDepth(1);
 
 textureLoc = gl.getUniformLocation(program, "tex");
 
 runTest();
 glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-image-and-uniform-binding-bugs.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-image-and-uniform-binding-bugs.html
@@ -55,12 +55,12 @@ tmpcanvas.width = 2;
 tmpcanvas.height = 2;
 var texture = gl.createTexture();
 shouldBeUndefined("gl.bindTexture(gl.TEXTURE_2D, texture)");
 shouldBeUndefined("gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tmpcanvas)");
 
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-image-with-invalid-data.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-image-with-invalid-data.html
@@ -89,13 +89,13 @@ test("Passing texSubImage2D parameter da
      function () {
       gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
      },
      "exception");
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/tex-input-validation.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-input-validation.html
@@ -351,11 +351,11 @@ testCases =
      expectedError: gl.INVALID_OPERATION} ];
 
 for (var ii = 0; ii < testCases.length; ++ii)
     testCopyFromInternalFBO(testCases[ii]);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-sub-image-2d-bad-args.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-sub-image-2d-bad-args.html
@@ -56,11 +56,11 @@ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 
 glErrorShouldBe(gl, gl.NO_ERROR, "format same as original RGBA 4_4_4_4");
 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGB, gl.UNSIGNED_BYTE, c);
 glErrorShouldBe(gl, gl.INVALID_OPERATION, "format not same as original RGBA 4_4_4_4");
 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, c);
 glErrorShouldBe(gl, gl.INVALID_OPERATION, "type not same as original RGBA 4_4_4_4");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-sub-image-2d.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-sub-image-2d.html
@@ -90,11 +90,11 @@ for (var i = 0; i < textureWidth; i++) {
     }
 }
 
 if (passed)
     testPassed("");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/texparameter-test.html
+++ b/content/canvas/test/webgl/conformance/textures/texparameter-test.html
@@ -176,13 +176,13 @@ function init()
   if (passed) {
     testPassed("rendered as expected");
    }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-active-bind-2.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-active-bind-2.html
@@ -177,13 +177,13 @@ function init()
 
     testPassed(msg);
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-active-bind.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-active-bind.html
@@ -126,13 +126,13 @@ function init()
       testPassed(msg);
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-clear.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-clear.html
@@ -30,13 +30,13 @@ gl.bindTexture(gl.TEXTURE_2D, tex);
 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0,255,0,255]));
 wtu.drawQuad(gl);
 wtu.checkCanvas(
     gl, [0, 255, 0, 255], "should be green");
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-complete.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-complete.html
@@ -55,13 +55,13 @@ function init()
       "texture that is not -texture-complete- when " +
       "TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255");
 }
 
 init();
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-formats-test.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-formats-test.html
@@ -240,12 +240,12 @@ if (!gl) {
   }
   checkTypes();
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/texture-mips.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-mips.html
@@ -245,12 +245,12 @@ function init()
     return 'rgb(' + c[0] + ',' + c[1] + ',' + c[2] +')';
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-npot.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-npot.html
@@ -213,13 +213,13 @@ function fillCubeTexture(gl, tex, width,
     gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
   for (var tt = 0; tt < targets.length; ++tt) {
     gl.texImage2D(
         targets[tt], opt_level, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
   }
 };
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/typedarrays/array-buffer-crash.html
+++ b/content/canvas/test/webgl/conformance/typedarrays/array-buffer-crash.html
@@ -28,11 +28,11 @@ try {
   new ArrayBuffer().byteLength;
 } catch (e) {
 }
 
 testPassed("new ArrayBuffer().byteLength did not crash");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/typedarrays/array-buffer-view-crash.html
+++ b/content/canvas/test/webgl/conformance/typedarrays/array-buffer-view-crash.html
@@ -54,12 +54,12 @@ try {
   new Uint32Array().length;
 } catch (e) {
 }
 
 testPassed("new Uint32Array().length did not crash");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/typedarrays/array-unit-tests.html
+++ b/content/canvas/test/webgl/conformance/typedarrays/array-unit-tests.html
@@ -1061,12 +1061,12 @@ function runTests() {
 
   printSummary();
 }
 
 runTests();
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/gl-uniform-arrays.html
+++ b/content/canvas/test/webgl/conformance/uniforms/gl-uniform-arrays.html
@@ -291,12 +291,12 @@ for (var tt = 0; tt < typeInfos.length; 
   gl.useProgram(null);
   glErrorShouldBe(gl, gl.NO_ERROR,
                   "can call gl.useProgram(null)");
 }
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/gl-uniform-bool.html
+++ b/content/canvas/test/webgl/conformance/uniforms/gl-uniform-bool.html
@@ -45,12 +45,12 @@ var loc = gl.getUniformLocation(gl.progr
 gl.uniform1f(loc, 1);
 glErrorShouldBe(gl, gl.NO_ERROR,
                 "should be able to set bool with gl.uniform1f");
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/gl-uniformmatrix4fv.html
+++ b/content/canvas/test/webgl/conformance/uniforms/gl-uniformmatrix4fv.html
@@ -68,12 +68,12 @@ for (var ii = 2; ii <= 4; ++ii) {
   gl[name](loc, true, mat);
   glErrorShouldBe(gl, gl.INVALID_VALUE, name + " should return INVALID_VALUE with transpose = true");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/gl-unknown-uniform.html
+++ b/content/canvas/test/webgl/conformance/uniforms/gl-unknown-uniform.html
@@ -54,12 +54,12 @@ if (!gl) {
   glErrorShouldBe(gl, gl.NO_ERROR,
             "there should be no error from trying to set an unknown uniform");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/null-uniform-location.html
+++ b/content/canvas/test/webgl/conformance/uniforms/null-uniform-location.html
@@ -66,11 +66,11 @@ for (var i = 0; i < funcs.length; i++) {
   callString = "callUniformFunction('" + funcs[i] + "')";
   shouldBeUndefined(callString);
   glErrorShouldBe(gl, gl.NO_ERROR);
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/uniform-location.html
+++ b/content/canvas/test/webgl/conformance/uniforms/uniform-location.html
@@ -102,11 +102,11 @@ locationSx2 = contextA.getUniformLocatio
 shouldBeFalse("locationSx === locationSx2");
 locationSx.foo  = {};
 locationSx2.foo = {};
 shouldBeFalse("locationSx.foo === locationSx2.foo");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/uniform-samplers-test.html
+++ b/content/canvas/test/webgl/conformance/uniforms/uniform-samplers-test.html
@@ -49,12 +49,12 @@ function init()
   gl.uniform1fv(textureLoc, [1]);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
             "uniform1fv returns INVALID_OPERATION if attempting to set a sampler uniform");
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/ext-texture-filter-anisotropic.patch
+++ b/content/canvas/test/webgl/ext-texture-filter-anisotropic.patch
@@ -186,12 +186,12 @@ new file mode 100644
 +    }
 +
 +    gl.deleteTexture(texture);
 +}
 +
 +debug("");
 +successfullyParsed = true;
 +</script>
-+<script src="../../resources/js-test-post.js"></script>
++<script>finishTest();</script>
 +
 +</body>
 +</html>
--- a/content/canvas/test/webgl/extra/canvas-compositing-test.html
+++ b/content/canvas/test/webgl/extra/canvas-compositing-test.html
@@ -111,15 +111,15 @@ img tag<br/>
             gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
             gl.drawArrays(gl.TRIANGLES, 0, 3);
        }
 
        init();
        successfullyParsed = true;
     </script>
 </body>
-<script src="../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 <script>
 </script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/extra/out-of-memory.html
+++ b/content/canvas/test/webgl/extra/out-of-memory.html
@@ -78,15 +78,15 @@ if (!gl) {
 }
 
 function finish() {
   debug("");
   successfullyParsed = true;
 }
 
 </script>
-<!-- <script src="../resources/js-test-post.js"></script> -->
+<!-- <script>finishTest();</script> -->
 
 <script>
 </script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/failing_tests_android.txt
+++ b/content/canvas/test/webgl/failing_tests_android.txt
@@ -21,15 +21,14 @@ conformance/glsl/functions/glsl-function
 conformance/glsl/functions/glsl-function-mod-gentype.html
 conformance/glsl/functions/glsl-function-normalize.html
 conformance/glsl/functions/glsl-function-reflect.html
 conformance/glsl/functions/glsl-function-sign.html
 conformance/glsl/functions/glsl-function-smoothstep-float.html
 conformance/glsl/functions/glsl-function-smoothstep-gentype.html
 conformance/glsl/functions/glsl-function-step-float.html
 conformance/glsl/functions/glsl-function-step-gentype.html
-conformance/glsl/misc/glsl-function-nodes.html
 conformance/glsl/misc/shared.html
 conformance/misc/null-object-behaviour.html
 conformance/renderbuffers/framebuffer-object-attachment.html
 conformance/textures/texture-mips.html
 conformance/textures/texture-npot.html
 conformance/textures/texture-npot-video.html
--- a/content/canvas/test/webgl/reference-cycle-test.patch
+++ b/content/canvas/test/webgl/reference-cycle-test.patch
@@ -44,17 +44,17 @@ diff --git a/content/canvas/test/webgl/c
 +
 +    // create a self-cycle on the extension object
 +    ext.ext = ext;
 +}
  
  debug("");
  successfullyParsed = true;
  </script>
- <script src="../../resources/js-test-post.js"></script>
+ <script>finishTest();</script>
  
  </body>
  </html>
 diff --git a/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html b/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
 --- a/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
 +++ b/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
 @@ -81,16 +81,17 @@ if (!gl) {
  
@@ -96,12 +96,12 @@ diff --git a/content/canvas/test/webgl/c
 +
 +    // create a self-cycle on the extension object
 +    ext.ext = ext;
 +}
  
  debug("");
  successfullyParsed = true;
  </script>
- <script src="../../resources/js-test-post.js"></script>
+ <script>finishTest();</script>
  
  </body>
  </html>
deleted file mode 100644
--- a/content/canvas/test/webgl/resources/js-test-post.js
+++ /dev/null
@@ -1,3 +0,0 @@
-shouldBeTrue("successfullyParsed");
-debug('<br /><span class="pass">TEST COMPLETE</span>');
-notifyFinishedToHarness()
--- a/content/canvas/test/webgl/resources/js-test-pre.js
+++ b/content/canvas/test/webgl/resources/js-test-pre.js
@@ -464,35 +464,12 @@ function gc() {
         temp += "foo";
         gcRec(n-1);
     }
     for (var i = 0; i < 1000; i++)
         gcRec(10);
 }
 
 function finishTest() {
-  testPassed("beginning of finishTest: " + (new Date().getTime()));
-
-  successfullyParsed = true;
-  var epilogue = document.createElement("script");
-  epilogue.onload = function() {
-    testPassed("finishTest epilogue onload: " + (new Date().getTime()));
-    if (window.nonKhronosFrameworkNotifyDone) {
-      window.nonKhronosFrameworkNotifyDone();
-    }
-  };
-
-  var basePath = "";
-  var expectedBase = "js-test-pre.js";
-  var scripts = document.getElementsByTagName('script');
-  for (var script, i = 0; script = scripts[i]; i++) {
-    var src = script.src;
-    var l = src.length;
-    if (src.substr(l - expectedBase.length) == expectedBase) {
-      basePath = src.substr(0, l - expectedBase.length);
-      break;
-    }
-  }
-  epilogue.src = basePath + "js-test-post.js";
-  document.body.appendChild(epilogue);
-  testPassed("end of finishTest: " + (new Date().getTime()));
+    debug('<br /><span class="pass">TEST COMPLETE</span>');
+    notifyFinishedToHarness();
 }
 
--- a/content/events/public/nsEventNameList.h
+++ b/content/events/public/nsEventNameList.h
@@ -312,16 +312,20 @@ EVENT(timeupdate,
 EVENT(volumechange,
       NS_VOLUMECHANGE,
       EventNameType_HTML,
       NS_EVENT_NULL)
 EVENT(waiting,
       NS_WAITING,
       EventNameType_HTML,
       NS_EVENT_NULL)
+EVENT(wheel,
+      NS_WHEEL_WHEEL,
+      EventNameType_All,
+      NS_WHEEL_EVENT)
 // Gecko-specific extensions that apply to elements
 EVENT(copy,
       NS_COPY,
       EventNameType_HTMLXUL,
       NS_EVENT)
 EVENT(cut,
       NS_CUT,
       EventNameType_HTMLXUL,
@@ -595,20 +599,16 @@ NON_IDL_EVENT(draggesture,
 NON_IDL_EVENT(overflow,
               NS_SCROLLPORT_OVERFLOW,
               EventNameType_XUL,
               NS_EVENT_NULL)
 NON_IDL_EVENT(underflow,
               NS_SCROLLPORT_UNDERFLOW,
               EventNameType_XUL,
               NS_EVENT_NULL)
-NON_IDL_EVENT(wheel,
-              NS_WHEEL_WHEEL,
-              EventNameType_XUL,
-              NS_WHEEL_EVENT)
 
 // Various SVG events
 NON_IDL_EVENT(SVGLoad,
               NS_SVG_LOAD,
               EventNameType_None,
               NS_SVG_EVENT)
 NON_IDL_EVENT(SVGUnload,
               NS_SVG_UNLOAD,
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -137,18 +137,16 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aP
           ...
         }
      */
     mEvent = new nsEvent(false, 0);
     mEvent->time = PR_Now();
   }
 
   InitPresContextData(aPresContext);
-
-  NS_ASSERTION(mEvent->message != NS_PAINT, "Trying to create a DOM paint event!");
 }
 
 void
 nsDOMEvent::InitPresContextData(nsPresContext* aPresContext)
 {
   mPresContext = aPresContext;
   // Get the explicit original target (if it's anonymous make it null)
   {
@@ -596,44 +594,16 @@ nsDOMEvent::DuplicatePrivateData()
       break;
     }
     case NS_GUI_EVENT:
     {
       // Not copying widget, it is a weak reference.
       newEvent = new nsGUIEvent(false, msg, nullptr);
       break;
     }
-    case NS_SIZE_EVENT:
-    {
-      nsSizeEvent* sizeEvent = new nsSizeEvent(false, msg, nullptr);
-      NS_ENSURE_TRUE(sizeEvent, NS_ERROR_OUT_OF_MEMORY);
-      sizeEvent->mWinWidth = static_cast<nsSizeEvent*>(mEvent)->mWinWidth;
-      sizeEvent->mWinHeight = static_cast<nsSizeEvent*>(mEvent)->mWinHeight;
-      newEvent = sizeEvent;
-      break;
-    }
-    case NS_SIZEMODE_EVENT:
-    {
-      newEvent = new nsSizeModeEvent(false, msg, nullptr);
-      NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
-      static_cast<nsSizeModeEvent*>(newEvent)->mSizeMode =
-        static_cast<nsSizeModeEvent*>(mEvent)->mSizeMode;
-      break;
-    }
-    case NS_ZLEVEL_EVENT:
-    {
-      nsZLevelEvent* zLevelEvent = new nsZLevelEvent(false, msg, nullptr);
-      NS_ENSURE_TRUE(zLevelEvent, NS_ERROR_OUT_OF_MEMORY);
-      nsZLevelEvent* oldZLevelEvent = static_cast<nsZLevelEvent*>(mEvent);
-      zLevelEvent->mPlacement = oldZLevelEvent->mPlacement;
-      zLevelEvent->mImmediate = oldZLevelEvent->mImmediate;
-      zLevelEvent->mAdjusted = oldZLevelEvent->mAdjusted;
-      newEvent = zLevelEvent;
-      break;
-    }
     case NS_SCROLLBAR_EVENT:
     {
       newEvent = new nsScrollbarEvent(false, msg, nullptr);
       NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
       static_cast<nsScrollbarEvent*>(newEvent)->position =
         static_cast<nsScrollbarEvent*>(mEvent)->position;
       break;
     }
@@ -787,24 +757,16 @@ nsDOMEvent::DuplicatePrivateData()
       mutationEvent->mRelatedNode = oldMutationEvent->mRelatedNode;
       mutationEvent->mAttrName = oldMutationEvent->mAttrName;
       mutationEvent->mPrevAttrValue = oldMutationEvent->mPrevAttrValue;
       mutationEvent->mNewAttrValue = oldMutationEvent->mNewAttrValue;
       mutationEvent->mAttrChange = oldMutationEvent->mAttrChange;
       newEvent = mutationEvent;
       break;
     }
-#ifdef ACCESSIBILITY
-    case NS_ACCESSIBLE_EVENT:
-    {
-      newEvent = new nsAccessibleEvent(false, msg, nullptr);
-      isInputEvent = true;
-      break;
-    }
-#endif
     case NS_FORM_EVENT:
     {
       newEvent = new nsFormEvent(false, msg);
       break;
     }
     case NS_FOCUS_EVENT:
     {
       nsFocusEvent* newFocusEvent = new nsFocusEvent(false, msg);
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1113,16 +1113,21 @@ nsEventStateManager::PreHandleEvent(nsPr
 
       nsIContent* content = GetFocusedContent();
       if (content)
         mCurrentTargetContent = content;
 
       widget::WheelEvent* wheelEvent = static_cast<widget::WheelEvent*>(aEvent);
       WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(wheelEvent);
 
+      // If we won't dispatch a DOM event for this event, nothing to do anymore.
+      if (!NS_IsAllowedToDispatchDOMEvent(wheelEvent)) {
+        break;
+      }
+
       // Init lineOrPageDelta values for line scroll events for some devices
       // on some platforms which might dispatch wheel events which don't have
       // lineOrPageDelta values.  And also, if delta values are customized by
       // prefs, this recomputes them.
       DeltaAccumulator::GetInstance()->
         InitLineOrPageDelta(aTargetFrame, this, wheelEvent);
     }
     break;
@@ -2510,19 +2515,19 @@ nsEventStateManager::DispatchLegacyMouse
   nsIntSize scrollAmountInCSSPixels(
     nsPresContext::AppUnitsToIntCSSPixels(scrollAmount.width),
     nsPresContext::AppUnitsToIntCSSPixels(scrollAmount.height));
 
   // XXX We don't deal with fractional amount in legacy event, though the
   //     default action handler (DoScrollText()) deals with it.
   //     If we implemented such strict computation, we would need additional
   //     accumulated delta values. It would made the code more complicated.
-  //     And also it would compute different delta values from the older
-  //     version.  It doesn't make sense to implement such code for legacy
-  //     events and rare cases.
+  //     And also it would computes different delta values from older version.
+  //     It doesn't make sense to implement such code for legacy events and
+  //     rare cases.
   PRInt32 scrollDeltaX, scrollDeltaY, pixelDeltaX, pixelDeltaY;
   switch (aEvent->deltaMode) {
     case nsIDOMWheelEvent::DOM_DELTA_PAGE:
       scrollDeltaX =
         !aEvent->lineOrPageDeltaX ? 0 :
           (aEvent->lineOrPageDeltaX > 0  ? nsIDOMUIEvent::SCROLL_PAGE_DOWN :
                                            nsIDOMUIEvent::SCROLL_PAGE_UP);
       scrollDeltaY =
@@ -5081,34 +5086,45 @@ nsEventStateManager::DeltaAccumulator::I
     // If wheel event type is changed, reset the values.
     if (mHandlingDeltaMode != aEvent->deltaMode ||
         mHandlingPixelOnlyDevice != aEvent->isPixelOnlyDevice) {
       Reset();
     } else {
       // If the delta direction is changed, we should reset only the
       // accumulated values.
       if (mX && aEvent->deltaX && ((aEvent->deltaX > 0.0) != (mX > 0.0))) {
-        mX = 0.0;
+        mX = mPendingScrollAmountX = 0.0;
       }
       if (mY && aEvent->deltaY && ((aEvent->deltaY > 0.0) != (mY > 0.0))) {
-        mY = 0.0;
+        mY = mPendingScrollAmountY = 0.0;
       }
     }
   }
 
   mHandlingDeltaMode = aEvent->deltaMode;
   mHandlingPixelOnlyDevice = aEvent->isPixelOnlyDevice;
 
   // If it's handling neither pixel scroll mode for pixel only device nor
   // delta values multiplied by prefs, we must not modify lineOrPageDelta
   // values.
   if (!(mHandlingDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL &&
         mHandlingPixelOnlyDevice) &&
       !nsEventStateManager::WheelPrefs::GetInstance()->
         NeedToComputeLineOrPageDelta(aEvent)) {
+    // Set the delta values to mX and mY.  They would be used when above block
+    // resets mX/mY/mPendingScrollAmountX/mPendingScrollAmountY if the direction
+    // is changed.
+    // NOTE: We shouldn't accumulate the delta values, it might could cause
+    //       overflow even though it's not a realistic situation.
+    if (aEvent->deltaX) {
+      mX = aEvent->deltaX;
+    }
+    if (aEvent->deltaY) {
+      mY = aEvent->deltaY;
+    }
     mLastTime = TimeStamp::Now();
     return;
   }
 
   mX += aEvent->deltaX;
   mY += aEvent->deltaY;
 
   if (mHandlingDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) {
@@ -5310,35 +5326,26 @@ nsEventStateManager::WheelPrefs::Init(
 
   nsCAutoString basePrefName;
   GetBasePrefName(aIndex, basePrefName);
 
   nsCAutoString prefNameX(basePrefName);
   prefNameX.AppendLiteral("delta_multiplier_x");
   mMultiplierX[aIndex] =
     static_cast<double>(Preferences::GetInt(prefNameX.get(), 100)) / 100;
-  if (mMultiplierX[aIndex] < 1.0 && mMultiplierX[aIndex] > -1.0) {
-    mMultiplierX[aIndex] = mMultiplierX[aIndex] < 0.0 ? -1.0 : 1.0;
-  }
 
   nsCAutoString prefNameY(basePrefName);
   prefNameY.AppendLiteral("delta_multiplier_y");
   mMultiplierY[aIndex] =
     static_cast<double>(Preferences::GetInt(prefNameY.get(), 100)) / 100;
-  if (mMultiplierY[aIndex] < 1.0 && mMultiplierY[aIndex] > -1.0) {
-    mMultiplierY[aIndex] = mMultiplierY[aIndex] < 0.0 ? -1.0 : 1.0;
-  }
 
   nsCAutoString prefNameZ(basePrefName);
   prefNameZ.AppendLiteral("delta_multiplier_z");
   mMultiplierZ[aIndex] =
     static_cast<double>(Preferences::GetInt(prefNameZ.get(), 100)) / 100;
-  if (mMultiplierZ[aIndex] < 1.0 && mMultiplierZ[aIndex] > -1.0) {
-    mMultiplierZ[aIndex] = mMultiplierZ[aIndex] < 0.0 ? -1.0 : 1.0;
-  }
 
   nsCAutoString prefNameAction(basePrefName);
   prefNameAction.AppendLiteral("action");
   mActions[aIndex] =
     static_cast<Action>(Preferences::GetInt(prefNameAction.get(),
                                             ACTION_SCROLL));
   if (mActions[aIndex] < ACTION_NONE || mActions[aIndex] > ACTION_LAST) {
     NS_WARNING("Unsupported action pref value, replaced with 'Scroll'.");
@@ -5375,20 +5382,22 @@ nsEventStateManager::WheelPrefs::ApplyUs
 
 void
 nsEventStateManager::WheelPrefs::CancelApplyingUserPrefsFromOverflowDelta(
                                                    widget::WheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
 
-  NS_ASSERTION(mMultiplierX[index] && mMultiplierY[index],
-               "The absolute values of both multipliers must be 1 or larger");
-  aEvent->overflowDeltaX /= mMultiplierX[index];
-  aEvent->overflowDeltaY /= mMultiplierY[index];
+  if (mMultiplierX[index]) {
+    aEvent->overflowDeltaX /= mMultiplierX[index];
+  }
+  if (mMultiplierY[index]) {
+    aEvent->overflowDeltaY /= mMultiplierY[index];
+  }
 }
 
 nsEventStateManager::WheelPrefs::Action
 nsEventStateManager::WheelPrefs::ComputeActionFor(widget::WheelEvent* aEvent)
 {
   if (!aEvent->deltaX && !aEvent->deltaY) {
     return ACTION_NONE;
   }
--- a/content/events/test/test_bug422132.html
+++ b/content/events/test/test_bug422132.html
@@ -33,17 +33,19 @@ function hitEventLoop(aFunc, aTimes)
     setTimeout(hitEventLoop, 0, aFunc, aTimes);
   } else {
     setTimeout(aFunc, 20);
   }
 }
 
 function runTests()
 {
+  SpecialPowers.setBoolPref("general.smoothScroll", false);
   SpecialPowers.setIntPref("mousewheel.min_line_scroll_amount", 1);
+  SpecialPowers.setIntPref("mousewheel.transaction.timeout", 100000);
 
   var target = document.getElementById("target");
 
   var scrollLeft = target.scrollLeft;
   var scrollTop = target.scrollTop;
   synthesizeWheel(target, 10, 10,
     { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
       deltaX: 0.5, deltaY: 0.5, lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 });
@@ -73,17 +75,19 @@ function runTests()
         synthesizeWheel(target, 10, 10,
           { deltaMode: WheelEvent.DOM_DELTA_LINE,
             deltaX: 0.5, deltaY: 0.5, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 });
         hitEventLoop(function () {
           ok(target.scrollLeft > scrollLeft,
              "not scrolled to right by 0.5 line delta value with pending 0.5 line delta");
           ok(target.scrollTop > scrollTop,
              "not scrolled to bottom by 0.5 line delta value with pending 0.5 line delta");
+          SpecialPowers.clearUserPref("general.smoothScroll");
           SpecialPowers.clearUserPref("mousewheel.min_line_scroll_amount");
+          SpecialPowers.clearUserPref("mousewheel.transaction.timeout");
           SimpleTest.finish();
         }, 20);
       }, 20);
     }, 20);
   }, 20);
 }
 
 </script>
--- a/content/events/test/test_dom_wheel_event.html
+++ b/content/events/test/test_dom_wheel_event.html
@@ -296,42 +296,53 @@ function testDeltaMultiplierPrefs()
         modifierList += "Meta ";
       }
       if (currentEvent.osKey) {
         modifierList += "Win ";
       }
 
       for (var j = 0; j < kPrefValues.length; j++) {
         currentMultiplier = kPrefValues[j] / 100;
-        if (currentMultiplier > -1.0 && currentMultiplier < 1.0) {
-          currentMultiplier = currentMultiplier < 0 ? -1.0 : 1.0;
-        }
         for (var k = 0; k < kDeltaMultiplierPrefs.length; k++) {
           currentPref = "mousewheel." + currentTest.name + "." + kDeltaMultiplierPrefs[k];
 
           SpecialPowers.setIntPref(currentPref, kPrefValues[j]);
 
           gScrollableElement.scrollTop = gScrollableElement.scrollBottom = 1000;
 
           // trusted event's delta valuses should be reverted by the pref.
           testingExpected = aIsExpected;
 
           description = "testDeltaMultiplierPrefs, pref: " + currentPref + "=" + kPrefValues[j] +
             ", deltaMode: " + currentEvent.deltaMode + ", modifiers: \"" + modifierList + "\", (trusted event): ";
           synthesizeWheel(gScrollableElement, 10, 10, currentEvent);
 
-          ok(calledHandlers.wheel, description + "wheel event was not fired");
-          ok(calledHandlers.DOMMouseScroll.horizontal,
-             description + "Horizontal DOMMouseScroll event was not fired");
-          ok(calledHandlers.DOMMouseScroll.vertical,
-             description + "Vertical DOMMouseScroll event was not fired");
-          ok(calledHandlers.MozMousePixelScroll.horizontal,
-             description + "Horizontal MozMousePixelScroll event was not fired");
-          ok(calledHandlers.MozMousePixelScroll.vertical,
-             description + "Vertical MozMousePixelScroll event was not fired");
+          var expectedProps = {
+            deltaX: currentEvent.deltaX * currentMultiplier,
+            deltaY: currentEvent.deltaY * currentMultiplier,
+            dletaZ: currentEvent.deltaZ * currentMultiplier,
+            lineOrPageDeltaX: currentEvent.lineOrPageDeltaX * currentMultiplier,
+            lineOrPageDeltaY: currentEvent.lineOrPageDeltaY * currentMultiplier,
+          };
+
+          is(calledHandlers.wheel,
+             expectedProps.deltaX != 0 || expectedProps.deltaY != 0 || expectedProps.deltaZ != 0,
+             description + "wheel event was (not) fired");
+          is(calledHandlers.DOMMouseScroll.horizontal,
+             expectedProps.lineOrPageDeltaX >= 1 || expectedProps.lineOrPageDeltaX <= -1,
+             description + "Horizontal DOMMouseScroll event was (not) fired");
+          is(calledHandlers.DOMMouseScroll.vertical,
+             expectedProps.lineOrPageDeltaY >= 1 || expectedProps.lineOrPageDeltaY <= -1,
+             description + "Vertical DOMMouseScroll event was (not) fired");
+          is(calledHandlers.MozMousePixelScroll.horizontal,
+             expectedProps.deltaY >= 1 || expectedProps.deltaY <= -1,
+             description + "Horizontal MozMousePixelScroll event was (not) fired");
+          is(calledHandlers.MozMousePixelScroll.vertical,
+             expectedProps.deltaY >= 1 || expectedProps.deltaY <= -1,
+             description + "Vertical MozMousePixelScroll event was (not) fired");
 
           calledHandlers = { wheel: false,
                              DOMMouseScroll: { horizontal: false, vertical: false },
                              MozMousePixelScroll: { horizontal: false, vertical: false } };
 
           // untrusted event's delta values shouldn't be reverted by the pref.
           testingExpected = false;
           var props = {
@@ -647,16 +658,52 @@ function testEventOrder()
   window.removeEventListener("DOMMouseScroll", handler, true);
   window.removeEventListener("MozMousePixelScroll", handler, true);
 
   SpecialPowers.removeSystemEventListener(window, "wheel", systemHandler, true);
   SpecialPowers.removeSystemEventListener(window, "DOMMouseScroll", systemHandler, true);
   SpecialPowers.removeSystemEventListener(window, "MozMousePixelScroll", systemHandler, true);
 }
 
+var gOnWheelAttrHandled = new Array;
+
+function testOnWheelAttr()
+{
+  document.documentElement.setAttribute("onwheel", "gOnWheelAttrHandled['html'] = true;");
+  document.body.setAttribute("onwheel", "gOnWheelAttrHandled['body'] = true;");
+  gScrollableElement.setAttribute("onwheel", "gOnWheelAttrHandled['div'] = true;");
+  var target = document.getElementById("onwheel");
+  synthesizeWheel(gScrollableElement, 10, 10,
+                  { deltaMode: WheelEvent.DOM_DELTA_LINE,
+                    deltaX: 1.0, deltaY: 2.0 });
+  ok(gOnWheelAttrHandled['html'], "html element's onwheel attribute isn't performed");
+  ok(gOnWheelAttrHandled['body'], "body element's onwheel attribute isn't performed");
+  ok(gOnWheelAttrHandled['div'], "div element's onwheel attribute isn't performed");
+}
+
+var gOnWheelPropHandled = new Array;
+
+function testOnWheelProperty()
+{
+  window.onwheel = function (e) { gOnWheelPropHandled["window"] = true; }
+  document.onwheel = function (e) { gOnWheelPropHandled["document"] = true; }
+  document.documentElement.onwheel = function (e) { gOnWheelPropHandled["html"] = true; };
+  document.body.onwheel = function (e) { gOnWheelPropHandled["body"] = true; };
+  gScrollableElement.onwheel = function (e) { gOnWheelPropHandled["div"] = true; };
+  var target = document.getElementById("onwheel");
+  synthesizeWheel(gScrollableElement, 10, 10,
+                  { deltaMode: WheelEvent.DOM_DELTA_LINE,
+                    deltaX: 1.0, deltaY: 2.0 });
+  ok(gOnWheelPropHandled['window'], "window's onwheel property isn't performed");
+  ok(gOnWheelPropHandled['document'], "document's onwheel property isn't performed");
+  ok(gOnWheelPropHandled['html'], "html element's onwheel property isn't performed");
+  ok(gOnWheelPropHandled['body'], "body element's onwheel property isn't performed");
+  ok(gOnWheelPropHandled['div'], "div element's onwheel property isn't performed");
+}
+
 function runTests()
 {
   SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_x", 100);
   SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_y", 100);
   SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_z", 100);
   SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_x", 100);
   SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_y", 100);
   SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_z", 100);
@@ -673,16 +720,18 @@ function runTests()
   SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_y", 100);
   SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_z", 100);
 
   prepareScrollUnits();
   testMakingUntrustedEvent();
   testDeltaMultiplierPrefs();
   testDispatchingUntrustEvent();
   testEventOrder();
+  testOnWheelAttr();
+  testOnWheelProperty();
 
   SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_x");
   SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_y");
   SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_z");
   SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_x");
   SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_y");
   SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_z");
   SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_x");
--- a/content/events/test/window_bug659071.html
+++ b/content/events/test/window_bug659071.html
@@ -29,30 +29,30 @@ function hitEventLoop(aFunc, aTimes)
   } else {
     setTimeout(aFunc, 20);
   }
 }
 
 function runTests()
 {
   SpecialPowers.setIntPref("mousewheel.with_control.action", 3);
-  SpecialPowers.setFullZoom(window, 1.0);
+  synthesizeKey("0", { accelKey: true });
 
   var video = document.getElementById("v");
   hitEventLoop(function () {
     is(SpecialPowers.getFullZoom(window), 1.0,
        "failed to reset zoom");
     synthesizeWheel(video, 10, 10,
       { deltaMode: WheelEvent.DOM_DELTA_LINE, ctrlKey: true,
         deltaX: 0, deltaY: 1.0, lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 });
     hitEventLoop(function () {
       isnot(SpecialPowers.getFullZoom(window), 1.0,
              "failed to zoom by ctrl+wheel");
 
-      SpecialPowers.setFullZoom(window, 1.0);
+      synthesizeKey("0", { accelKey: true });
       SpecialPowers.clearUserPref("mousewheel.with_control.action");
 
       hitEventLoop(window.opener.finish, 20);
     }, 20);
   }, 20);
 }
 
 </script>
--- a/content/events/test/window_wheel_default_action.html
+++ b/content/events/test/window_wheel_default_action.html
@@ -777,29 +777,29 @@ function doTestZoom(aSettings, aCallback
           ok(SpecialPowers.getFullZoom(window) > 1.0,
              description + "not zoomed in, got " + SpecialPowers.getFullZoom(window));
         } else {
           ok(SpecialPowers.getFullZoom(window) < 1.0,
              description + "not zoomed out, got " + SpecialPowers.getFullZoom(window));
         }
       }
 
-      SpecialPowers.setFullZoom(window, 1.0);
+      synthesizeKey("0", { accelKey: true });
       hitEventLoop(doNextTest, 20);
     }, 20);
   }
   doNextTest();
 }
 
 function doTestZoomedScroll()
 {
   function testZoomedPixelScroll()
   {
     // Reset zoom and store the scroll amount into the data.
-    SpecialPowers.setFullZoom(window, 1.0);
+    synthesizeKey("0", { accelKey: true });
     gScrollableElement.scrollTop = 1000;
     gScrollableElement.scrollLeft = 1000;
     // Ensure not to be in reflow.
     hitEventLoop(function () {
       function handler(aEvent)
       {
         if (aEvent.axis == MouseScrollEvent.HORIZONTAL_AXIS) {
           is(aEvent.detail, 16,
@@ -838,28 +838,28 @@ function doTestZoomedScroll()
             ok(Math.abs(gScrollableElement.scrollLeft - (1000 + (scrolledX - 1000) / 2)) <= 1,
                "doTestZoomedScroll: zoomed horizontal scroll amount by pixel wheel event is different from normal, scrollLeft=" +
                  gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
             ok(Math.abs(gScrollableElement.scrollTop - (1000 + (scrolledY - 1000) / 2)) <= 1,
                "doTestZoomedScroll: zoomed vertical scroll amount by pixel wheel event is different from normal, scrollTop=" +
                  gScrollableElement.scrollTop + ", scrolledY=" + scrolledY);
             window.removeEventListener("MozMousePixelScroll", handler, true);
 
-            SpecialPowers.setFullZoom(window, 1.0);
+            synthesizeKey("0", { accelKey: true });
             testZoomedLineScroll();
           }, 20);
         }, 20);
       }, 20);
     }, 20);
   }
 
   function testZoomedLineScroll()
   {
     // Reset zoom and store the scroll amount into the data.
-    SpecialPowers.setFullZoom(window, 1.0);
+    synthesizeKey("0", { accelKey: true });
     gScrollableElement.scrollTop = 1000;
     gScrollableElement.scrollLeft = 1000;
     // Ensure not to be in reflow.
     hitEventLoop(function () {
       var lineHeightX, lineHeightY;
       function handler(aEvent)
       {
         if (aEvent.axis == MouseScrollEvent.HORIZONTAL_AXIS) {
@@ -910,17 +910,17 @@ function doTestZoomedScroll()
                "doTestZoomedScroll: zoomed horizontal scroll amount by line wheel event is different from normal, scrollLeft=" +
                  gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
             ok(Math.abs(gScrollableElement.scrollTop - scrolledY) <= 1,
                "doTestZoomedScroll: zoomed vertical scroll amount by line wheel event is different from normal, scrollTop=" +
                  gScrollableElement.scrollTop + ", scrolledY=" + scrolledY);
 
             window.removeEventListener("MozMousePixelScroll", handler, true);
 
-            SpecialPowers.setFullZoom(window, 1.0);
+            synthesizeKey("0", { accelKey: true });
           }, 20);
         }, 20);
       }, 20);
     }, 20);
   }
 
   // XXX It's too difficult to test page scroll because the page scroll amount
   //     is computed by complex logic.
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -7,16 +7,17 @@
 
 #include "nsGenericHTMLFrameElement.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "nsIAppsService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMApplicationRegistry.h"
+#include "nsIPermissionManager.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mFrameLoader, nsIFrameLoader)
@@ -285,28 +286,25 @@ nsGenericHTMLFrameElement::GetReallyIsBr
   // Fail if this frame doesn't have the mozbrowser attribute.
   bool isBrowser = false;
   GetMozbrowser(&isBrowser);
   if (!isBrowser) {
     return NS_OK;
   }
 
   // Fail if the node principal isn't trusted.
-  // TODO: check properly for mozApps rights when mozApps will be less hacky.
   nsIPrincipal *principal = NodePrincipal();
-  nsCOMPtr<nsIURI> principalURI;
-  principal->GetURI(getter_AddRefs(principalURI));
-  if (!nsContentUtils::IsSystemPrincipal(principal) &&
-      !nsContentUtils::URIIsChromeOrInPref(principalURI,
-                                           "dom.mozBrowserFramesWhitelist")) {
-    return NS_OK;
-  }
+  nsCOMPtr<nsIPermissionManager> permMgr =
+    do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+  NS_ENSURE_STATE(permMgr);
 
-  // Otherwise, succeed.
-  *aOut = true;
+  PRUint32 permission = nsIPermissionManager::DENY_ACTION;
+  nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission);
+  NS_ENSURE_SUCCESS(rv, NS_OK);
+  *aOut = permission == nsIPermissionManager::ALLOW_ACTION;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGenericHTMLFrameElement::GetReallyIsApp(bool *aOut)
 {
   nsAutoString manifestURL;
   GetAppManifestURL(manifestURL);
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -21,17 +21,16 @@
 #include "nsJSUtils.h"
 #include "nsMathUtils.h"
 #include "nsStreamUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsFrameManager.h"
 #include "nsDisplayList.h"
-#include "ImageLayers.h"
 #include "BasicLayers.h"
 #include "imgIEncoder.h"
 
 #include "nsIWritablePropertyBag2.h"
 
 #define DEFAULT_CANVAS_WIDTH 300
 #define DEFAULT_CANVAS_HEIGHT 150
 
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -62,17 +62,16 @@
 
 // input type=radio
 #include "nsIRadioGroupContainer.h"
 
 // input type=file
 #include "nsIFile.h"
 #include "nsNetUtil.h"
 #include "nsDOMFile.h"
-#include "nsIFilePicker.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIContentPrefService.h"
 #include "nsIMIMEService.h"
 #include "nsIObserverService.h"
 #include "nsIPopupWindowManager.h"
 #include "nsGlobalWindow.h"
 
 // input type=image
@@ -206,36 +205,109 @@ class nsHTMLInputElementState MOZ_FINAL 
     nsCOMArray<nsIDOMFile> mFiles;
     bool mChecked;
     bool mCheckedSet;
 };
 
 NS_IMPL_ISUPPORTS1(nsHTMLInputElementState, nsHTMLInputElementState)
 NS_DEFINE_STATIC_IID_ACCESSOR(nsHTMLInputElementState, NS_INPUT_ELEMENT_STATE_IID)
 
-class AsyncClickHandler : public nsRunnable {
-public:
-  AsyncClickHandler(nsHTMLInputElement* aInput)
-   : mInput(aInput) {
-    
-    nsPIDOMWindow* win = aInput->OwnerDoc()->GetWindow();
-    if (win) {
-      mPopupControlState = win->GetPopupControlState();
-    }
-  };
-
-  NS_IMETHOD Run();
-
-protected:
-  nsRefPtr<nsHTMLInputElement> mInput;
-  PopupControlState mPopupControlState;
-};
+nsHTMLInputElement::nsFilePickerShownCallback::nsFilePickerShownCallback(
+  nsHTMLInputElement* aInput, nsIFilePicker* aFilePicker, bool aMulti)
+  : mFilePicker(aFilePicker)
+  , mInput(aInput)
+  , mMulti(aMulti)
+{
+}
 
 NS_IMETHODIMP
-AsyncClickHandler::Run()
+nsHTMLInputElement::nsFilePickerShownCallback::Done(PRInt16 aResult)
+{
+  if (aResult == nsIFilePicker::returnCancel) {
+    return NS_OK;
+  }
+
+  // Collect new selected filenames
+  nsCOMArray<nsIDOMFile> newFiles;
+  if (mMulti) {
+    nsCOMPtr<nsISimpleEnumerator> iter;
+    nsresult rv = mFilePicker->GetFiles(getter_AddRefs(iter));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsISupports> tmp;
+    bool prefSaved = false;
+    bool loop = true;
+    while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
+      iter->GetNext(getter_AddRefs(tmp));
+      nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp);
+      if (!localFile) {
+        continue;
+      }
+      nsString path;
+      localFile->GetPath(path);
+      if (path.IsEmpty()) {
+        continue;
+      }
+      nsCOMPtr<nsIDOMFile> domFile =
+        do_QueryObject(new nsDOMFileFile(localFile));
+      newFiles.AppendObject(domFile);
+      if (!prefSaved) {
+        // Store the last used directory using the content pref service
+        nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
+          mInput->OwnerDoc()->GetDocumentURI(), localFile);
+        prefSaved = true;
+      }
+    }
+  }
+  else {
+    nsCOMPtr<nsIFile> localFile;
+    nsresult rv = mFilePicker->GetFile(getter_AddRefs(localFile));
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (localFile) {
+      nsString path;
+      rv = localFile->GetPath(path);
+      if (!path.IsEmpty()) {
+        nsCOMPtr<nsIDOMFile> domFile=
+          do_QueryObject(new nsDOMFileFile(localFile));
+        newFiles.AppendObject(domFile);
+        // Store the last used directory using the content pref service
+        nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
+          mInput->OwnerDoc()->GetDocumentURI(), localFile);
+      }
+    }
+  }
+
+  if (!newFiles.Count()) {
+    return NS_OK;
+  }
+
+  // The text control frame (if there is one) isn't going to send a change
+  // event because it will think this is done by a script.
+  // So, we can safely send one by ourself.
+  mInput->SetFiles(newFiles, true);
+  return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
+                                              static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
+                                              NS_LITERAL_STRING("change"), true,
+                                              false);
+}
+
+NS_IMPL_ISUPPORTS1(nsHTMLInputElement::nsFilePickerShownCallback,
+                   nsIFilePickerShownCallback);
+
+nsHTMLInputElement::AsyncClickHandler::AsyncClickHandler(nsHTMLInputElement* aInput)
+  : mInput(aInput)
+{
+  nsPIDOMWindow* win = aInput->OwnerDoc()->GetWindow();
+  if (win) {
+    mPopupControlState = win->GetPopupControlState();
+  }
+}
+
+NS_IMETHODIMP
+nsHTMLInputElement::AsyncClickHandler::Run()
 {
   // Get parent nsPIDOMWindow object.
   nsCOMPtr<nsIDocument> doc = mInput->OwnerDoc();
 
   nsPIDOMWindow* win = doc->GetWindow();
   if (!win) {
     return NS_ERROR_FAILURE;
   }
@@ -321,87 +393,19 @@ AsyncClickHandler::Run()
       // Default to "desktop" directory for each platform
       nsCOMPtr<nsIFile> homeDir;
       NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(homeDir));
       localFile = do_QueryInterface(homeDir);
     }
     filePicker->SetDisplayDirectory(localFile);
   }
 
-  // Open dialog
-  PRInt16 mode;
-  {
-    nsAutoSyncOperation sync(doc);
-    rv = filePicker->Show(&mode);
-  }
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (mode == nsIFilePicker::returnCancel) {
-    return NS_OK;
-  }
-
-  // Collect new selected filenames
-  nsCOMArray<nsIDOMFile> newFiles;
-  if (multi) {
-    nsCOMPtr<nsISimpleEnumerator> iter;
-    rv = filePicker->GetFiles(getter_AddRefs(iter));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsISupports> tmp;
-    bool prefSaved = false;
-    bool loop = true;
-    while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
-      iter->GetNext(getter_AddRefs(tmp));
-      nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp);
-      if (localFile) {
-        nsString unicodePath;
-        rv = localFile->GetPath(unicodePath);
-        if (!unicodePath.IsEmpty()) {
-          nsCOMPtr<nsIDOMFile> domFile =
-            do_QueryObject(new nsDOMFileFile(localFile));
-          newFiles.AppendObject(domFile);
-        }
-        if (!prefSaved) {
-          // Store the last used directory using the content pref service
-          nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(doc->GetDocumentURI(),
-                                                                     localFile);
-          prefSaved = true;
-        }
-      }
-    }
-  }
-  else {
-    nsCOMPtr<nsIFile> localFile;
-    rv = filePicker->GetFile(getter_AddRefs(localFile));
-    if (localFile) {
-      nsString unicodePath;
-      rv = localFile->GetPath(unicodePath);
-      if (!unicodePath.IsEmpty()) {
-        nsCOMPtr<nsIDOMFile> domFile=
-          do_QueryObject(new nsDOMFileFile(localFile));
-        newFiles.AppendObject(domFile);
-      }
-      // Store the last used directory using the content pref service
-      nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(doc->GetDocumentURI(),
-                                                                 localFile);
-    }
-  }
-
-  // Set new selected files
-  if (newFiles.Count()) {
-    // The text control frame (if there is one) isn't going to send a change
-    // event because it will think this is done by a script.
-    // So, we can safely send one by ourself.
-    mInput->SetFiles(newFiles, true);
-    nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
-                                         static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
-                                         NS_LITERAL_STRING("change"), true,
-                                         false);
-  }
-
-  return NS_OK;
+  nsCOMPtr<nsIFilePickerShownCallback> callback =
+    new nsHTMLInputElement::nsFilePickerShownCallback(mInput, filePicker, multi);
+  return filePicker->Open(callback);
 }
 
 #define CPS_PREF_NAME NS_LITERAL_STRING("browser.upload.lastDir")
 
 NS_IMPL_ISUPPORTS2(UploadLastDir, nsIObserver, nsISupportsWeakReference)
 
 void
 nsHTMLInputElement::InitUploadLastDir() {
--- a/content/html/content/src/nsHTMLInputElement.h
+++ b/content/html/content/src/nsHTMLInputElement.h
@@ -13,16 +13,17 @@
 #include "nsIPhonetic.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsTextEditorState.h"
 #include "nsCOMPtr.h"
 #include "nsIConstraintValidation.h"
 #include "nsDOMFile.h"
 #include "nsHTMLFormElement.h" // for ShouldShowInvalidUI()
 #include "nsIFile.h"
+#include "nsIFilePicker.h"
 
 class nsDOMFileList;
 class nsIFilePicker;
 class nsIRadioGroupContainer;
 class nsIRadioGroupVisitor;
 class nsIRadioVisitor;
 
 class UploadLastDir MOZ_FINAL : public nsIObserver, public nsSupportsWeakReference {
@@ -724,11 +725,43 @@ private:
     nsString mFilter;
     // mIsTrusted is true if mime type comes from a "trusted" source (e.g. our
     // hard-coded set).
     // false means it may come from an "untrusted" source (e.g. OS mime types
     // mapping, which can be different accross OS, user's personal configuration, ...)
     // For now, only mask filters are considered to be "trusted".
     bool mIsTrusted; 
   };
+
+  class AsyncClickHandler
+    : public nsRunnable
+  {
+  public:
+    AsyncClickHandler(nsHTMLInputElement* aInput);
+    NS_IMETHOD Run();
+
+  protected:
+    nsRefPtr<nsHTMLInputElement> mInput;
+    PopupControlState mPopupControlState;
+  };
+
+  class nsFilePickerShownCallback
+    : public nsIFilePickerShownCallback
+  {
+  public:
+    nsFilePickerShownCallback(nsHTMLInputElement* aInput,
+                              nsIFilePicker* aFilePicker,
+                              bool aMulti);
+    virtual ~nsFilePickerShownCallback()
+    { }
+
+    NS_DECL_ISUPPORTS
+
+    NS_IMETHOD Done(PRInt16 aResult);
+
+  private:
+    nsCOMPtr<nsIFilePicker> mFilePicker;
+    nsRefPtr<nsHTMLInputElement> mInput;
+    bool mMulti;
+  };
 };
 
 #endif
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -208,17 +208,17 @@ public:
     // Silently cancel if our load has been cancelled.
     if (IsCancelled())
       return NS_OK;
     LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching simple event source error", mElement.get()));
     return nsContentUtils::DispatchTrustedEvent(mElement->OwnerDoc(),
                                                 mSource,
                                                 NS_LITERAL_STRING("error"),
                                                 false,
-                                                true);
+                                                false);
   }
 };
 
 /**
  * There is a reference cycle involving this class: MediaLoadListener
  * holds a reference to the nsHTMLMediaElement, which holds a reference
  * to an nsIChannel, which holds a reference to this listener.
  * We break the reference cycle in OnStartRequest by clearing mElement.
@@ -2159,16 +2159,34 @@ nsHTMLMediaElement::IsH264Type(const nsA
 #endif
 
 #ifdef MOZ_MEDIA_PLUGINS
 bool
 nsHTMLMediaElement::IsMediaPluginsEnabled()
 {
   return Preferences::GetBool("media.plugins.enabled");
 }
+
+bool
+nsHTMLMediaElement::IsMediaPluginsType(const nsACString& aType)
+{
+  if (!IsMediaPluginsEnabled()) {
+    return false;
+  }
+
+  static const char* supportedTypes[] = {
+    "audio/mpeg", "audio/mp4", "video/mp4"
+  };
+  for (PRUint32 i = 0; i < ArrayLength(supportedTypes); ++i) {
+    if (aType.EqualsASCII(supportedTypes[i])) {
+      return true;
+    }
+  }
+  return false;
+}
 #endif
 
 /* static */
 nsHTMLMediaElement::CanPlayStatus 
 nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType,
                                        char const *const ** aCodecList)
 {
 #ifdef MOZ_RAW
@@ -3064,17 +3082,17 @@ nsresult nsHTMLMediaElement::DispatchAud
 
   nsCOMPtr<nsIDOMEvent> event;
   nsresult rv = domDoc->CreateEvent(NS_LITERAL_STRING("MozAudioAvailableEvent"),
                                     getter_AddRefs(event));
   nsCOMPtr<nsIDOMNotifyAudioAvailableEvent> audioavailableEvent(do_QueryInterface(event));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = audioavailableEvent->InitAudioAvailableEvent(NS_LITERAL_STRING("MozAudioAvailable"),
-                                                    true, true, frameBuffer.forget(), aFrameBufferLength,
+                                                    false, false, frameBuffer.forget(), aFrameBufferLength,
                                                     aTime, mAllowAudioData);
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool dummy;
   return target->DispatchEvent(event, &dummy);
 }
 
 nsresult nsHTMLMediaElement::DispatchEvent(const nsAString& aName)
@@ -3088,17 +3106,17 @@ nsresult nsHTMLMediaElement::DispatchEve
     mPendingEvents.AppendElement(aName);
     return NS_OK;
   }
 
   return nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
                                               static_cast<nsIContent*>(this),
                                               aName,
                                               false,
-                                              true);
+                                              false);
 }
 
 nsresult nsHTMLMediaElement::DispatchAsyncEvent(const nsAString& aName)
 {
   LOG_EVENT(PR_LOG_DEBUG, ("%p Queuing event %s", this,
             NS_ConvertUTF16toUTF8(aName).get()));
 
   nsCOMPtr<nsIRunnable> event = new nsAsyncEventRunner(aName, this);
--- a/content/media/MediaResource.cpp
+++ b/content/media/MediaResource.cpp
@@ -36,17 +36,18 @@ using namespace mozilla;
 
 ChannelMediaResource::ChannelMediaResource(nsMediaDecoder* aDecoder,
     nsIChannel* aChannel, nsIURI* aURI)
   : MediaResource(aDecoder, aChannel, aURI),
     mOffset(0), mSuspendCount(0),
     mReopenOnError(false), mIgnoreClose(false),
     mCacheStream(this),
     mLock("ChannelMediaResource.mLock"),
-    mIgnoreResume(false)
+    mIgnoreResume(false),
+    mSeekingForMetadata(false)
 {
 }
 
 ChannelMediaResource::~ChannelMediaResource()
 {
   if (mListener) {
     // Kill its reference to us since we're going away
     mListener->Revoke();
@@ -256,17 +257,22 @@ ChannelMediaResource::OnStartRequest(nsI
   }
 
   {
     MutexAutoLock lock(mLock);
     mChannelStatistics.Start(TimeStamp::Now());
   }
 
   mReopenOnError = false;
-  mIgnoreClose = false;
+  // If we are seeking to get metadata, because we are playing an OGG file,
+  // ignore if the channel gets closed without us suspending it explicitly. We
+  // don't want to tell the element that the download has finished whereas we
+  // just happended to have reached the end of the media while seeking.
+  mIgnoreClose = mSeekingForMetadata;
+
   if (mSuspendCount > 0) {
     // Re-suspend the channel if it needs to be suspended
     // No need to call PossiblySuspend here since the channel is
     // definitely in the right state for us in OnStartRequest.
     mChannel->Suspend();
     mIgnoreResume = false;
   }
 
@@ -585,16 +591,26 @@ nsresult ChannelMediaResource::Read(char
 
 nsresult ChannelMediaResource::Seek(PRInt32 aWhence, PRInt64 aOffset)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
 
   return mCacheStream.Seek(aWhence, aOffset);
 }
 
+void ChannelMediaResource::StartSeekingForMetadata()
+{
+  mSeekingForMetadata = true;
+}
+
+void ChannelMediaResource::EndSeekingForMetadata()
+{
+  mSeekingForMetadata = false;
+}
+
 PRInt64 ChannelMediaResource::Tell()
 {
   NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
 
   return mCacheStream.Tell();
 }
 
 nsresult ChannelMediaResource::GetCachedRanges(nsTArray<MediaByteRange>& aRanges)
@@ -921,16 +937,18 @@ public:
 
   // These methods are called off the main thread.
 
   // Other thread
   virtual void     SetReadMode(nsMediaCacheStream::ReadMode aMode) {}
   virtual void     SetPlaybackRate(PRUint32 aBytesPerSecond) {}
   virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
   virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
+  virtual void     StartSeekingForMetadata() {};
+  virtual void     EndSeekingForMetadata() {};
   virtual PRInt64  Tell();
 
   // Any thread
   virtual void    Pin() {}
   virtual void    Unpin() {}
   virtual double  GetDownloadRate(bool* aIsReliable)
   {
     // The data's all already here
--- a/content/media/MediaResource.h
+++ b/content/media/MediaResource.h
@@ -207,16 +207,18 @@ public:
   //
   // The default strategy does not do any seeking - the only issue is
   // a blocked read which it handles by causing the listener to close
   // the pipe, as per the http case.
   //
   // The file strategy doesn't block for any great length of time so
   // is fine for a no-op cancel.
   virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset) = 0;
+  virtual void StartSeekingForMetadata() = 0;
+  virtual void EndSeekingForMetadata() = 0;
   // Report the current offset in bytes from the start of the stream.
   virtual PRInt64 Tell() = 0;
   // Moves any existing channel loads into the background, so that they don't
   // block the load event. Any new loads initiated (for example to seek)
   // will also be in the background.
   void MoveLoadsToBackground();
   // Ensures that the value returned by IsSuspendedByCache below is up to date
   // (i.e. the cache has examined this stream at least once).
@@ -373,16 +375,18 @@ public:
   virtual nsresult ReadFromCache(char* aBuffer, PRInt64 aOffset, PRUint32 aCount);
   virtual void     EnsureCacheUpToDate();
 
   // Other thread
   virtual void     SetReadMode(nsMediaCacheStream::ReadMode aMode);
   virtual void     SetPlaybackRate(PRUint32 aBytesPerSecond);
   virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
   virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
+  virtual void     StartSeekingForMetadata();
+  virtual void     EndSeekingForMetadata();
   virtual PRInt64  Tell();
 
   // Any thread
   virtual void    Pin();
   virtual void    Unpin();
   virtual double  GetDownloadRate(bool* aIsReliable);
   virtual PRInt64 GetLength();
   virtual PRInt64 GetNextCachedData(PRInt64 aOffset);
@@ -468,13 +472,16 @@ protected:
   // This lock protects mChannelStatistics
   Mutex               mLock;
   MediaChannelStatistics mChannelStatistics;
 
   // True if we couldn't suspend the stream and we therefore don't want
   // to resume later. This is usually due to the channel not being in the
   // isPending state at the time of the suspend request.
   bool mIgnoreResume;
+
+  // True if we are seeking to get the real duration of the file.
+  bool mSeekingForMetadata;
 };
 
 }
 
 #endif
--- a/content/media/VideoFrameContainer.h
+++ b/content/media/VideoFrameContainer.h
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef VIDEOFRAMECONTAINER_H_
 #define VIDEOFRAMECONTAINER_H_
 
-#include "ImageLayers.h"
+#include "ImageContainer.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/TimeStamp.h"
 #include "nsISupportsImpl.h"
 #include "gfxPoint.h"
 
 class nsHTMLMediaElement;
 
 namespace mozilla {
--- a/content/media/VideoSegment.h
+++ b/content/media/VideoSegment.h
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_VIDEOSEGMENT_H_
 #define MOZILLA_VIDEOSEGMENT_H_
 
 #include "MediaSegment.h"
-#include "ImageLayers.h"
+#include "ImageContainer.h"
 
 namespace mozilla {
 
 class VideoFrame {
 public:
   typedef mozilla::layers::Image Image;
 
   VideoFrame(already_AddRefed<Image> aImage, const gfxIntSize& aIntrinsicSize)
--- a/content/media/nsAudioStream.cpp
+++ b/content/media/nsAudioStream.cpp
@@ -32,19 +32,19 @@ extern "C" {
 #endif
 
 using namespace mozilla;
 
 #if defined(XP_MACOSX)
 #define SA_PER_STREAM_VOLUME 1
 #endif
 
-// Android's audio backend is not available in content processes, so audio must
-// be remoted to the parent chrome process.
-#if defined(ANDROID)
+// Android's audio backend is not available in content processes, so
+// audio must be remoted to the parent chrome process.
+#if defined(MOZ_WIDGET_ANDROID)
 #define REMOTE_AUDIO 1
 #endif
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gAudioStreamLog = nullptr;
 #endif
 
 static const PRUint32 FAKE_BUFFER_SIZE = 176400;
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -190,21 +190,26 @@ destroying the nsBuiltinDecoder object.
 #include "nsSize.h"
 #include "prlog.h"
 #include "gfxContext.h"
 #include "gfxRect.h"
 #include "MediaResource.h"
 #include "nsMediaDecoder.h"
 #include "nsHTMLMediaElement.h"
 #include "mozilla/ReentrantMonitor.h"
-#include "ImageLayers.h"
-class nsAudioStream;
 
-typedef mozilla::layers::Image Image;
-typedef mozilla::layers::ImageContainer ImageContainer;
+namespace mozilla {
+namespace layers {
+class Image;
+} //namespace
+} //namespace
+
+typedef mozilla::layers::Image Image; 
+
+class nsAudioStream;
 
 static inline bool IsCurrentThread(nsIThread* aThread) {
   return NS_GetCurrentThread() == aThread;
 }
 
 // Decoder backends must implement this class to perform the codec
 // specific parts of decoding the video/audio format.
 class nsDecoderStateMachine : public nsRunnable
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -143,22 +143,22 @@ VideoData* VideoData::Create(nsVideoInfo
   nsAutoPtr<VideoData> v(new VideoData(aOffset,
                                        aTime,
                                        aEndTime,
                                        aKeyframe,
                                        aTimecode,
                                        aInfo.mDisplay));
   // Currently our decoder only knows how to output to PLANAR_YCBCR
   // format.
-  Image::Format format = Image::PLANAR_YCBCR;
+  ImageFormat format = PLANAR_YCBCR;
   v->mImage = aContainer->CreateImage(&format, 1);
   if (!v->mImage) {
     return nullptr;
   }
-  NS_ASSERTION(v->mImage->GetFormat() == Image::PLANAR_YCBCR,
+  NS_ASSERTION(v->mImage->GetFormat() == PLANAR_YCBCR,
                "Wrong format?");
   PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
 
   PlanarYCbCrImage::Data data;
   const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
   const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
   const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
 
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -14,17 +14,17 @@
 
 // Stores info relevant to presenting media frames.
 class nsVideoInfo {
 public:
   nsVideoInfo()
     : mAudioRate(44100),
       mAudioChannels(2),
       mDisplay(0,0),
-      mStereoMode(mozilla::layers::STEREO_MODE_MONO),
+      mStereoMode(mozilla::STEREO_MODE_MONO),
       mHasAudio(false),
       mHasVideo(false)
   {}
 
   // Returns true if it's safe to use aPicture as the picture to be
   // extracted inside a frame of size aFrame, and scaled up to and displayed
   // at a size of aDisplay. You should validate the frame, picture, and
   // display regions before using them to display video frames.
@@ -38,17 +38,17 @@ public:
   // Number of audio channels.
   PRUint32 mAudioChannels;
 
   // Size in pixels at which the video is rendered. This is after it has
   // been scaled by its aspect ratio.
   nsIntSize mDisplay;
 
   // Indicates the frame layout for single track stereo videos.
-  mozilla::layers::StereoMode mStereoMode;
+  mozilla::StereoMode mStereoMode;
 
   // True if we have an active audio bitstream.
   bool mHasAudio;
 
   // True if we have an active video bitstream.
   bool mHasVideo;
 };
 
@@ -457,17 +457,17 @@ public:
   public:
     VideoQueueMemoryFunctor() : mResult(0) {}
 
     virtual void* operator()(void* anObject) {
       const VideoData* v = static_cast<const VideoData*>(anObject);
       if (!v->mImage) {
         return nullptr;
       }
-      NS_ASSERTION(v->mImage->GetFormat() == mozilla::layers::Image::PLANAR_YCBCR,
+      NS_ASSERTION(v->mImage->GetFormat() == mozilla::PLANAR_YCBCR,
                    "Wrong format?");
       mozilla::layers::PlanarYCbCrImage* vi = static_cast<mozilla::layers::PlanarYCbCrImage*>(v->mImage.get());
 
       mResult += vi->GetDataSize();
       return nullptr;
     }
 
     PRInt64 mResult;
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -375,17 +375,16 @@ nsresult StateMachineTracker::RequestCre
   return NS_OK;
 }
 
 nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder,
                                                            nsBuiltinDecoderReader* aReader,
                                                            bool aRealTime) :
   mDecoder(aDecoder),
   mState(DECODER_STATE_DECODING_METADATA),
-  mCbCrSize(0),
   mPlayDuration(0),
   mStartTime(-1),
   mEndTime(-1),
   mSeekTime(0),
   mFragmentEndTime(-1),
   mReader(aReader),
   mCurrentFrameTime(0),
   mAudioStartTime(-1),
--- a/content/media/nsBuiltinDecoderStateMachine.h
+++ b/content/media/nsBuiltinDecoderStateMachine.h
@@ -463,23 +463,16 @@ protected:
   nsRefPtr<nsBuiltinDecoder> mDecoder;
 
   // The decoder monitor must be obtained before modifying this state.
   // NotifyAll on the monitor must be called when the state is changed so
   // that interested threads can wake up and alter behaviour if appropriate
   // Accessed on state machine, audio, main, and AV thread.
   State mState;
 
-  // The size of the decoded YCbCr frame.
-  // Accessed on state machine thread.
-  PRUint32 mCbCrSize;
-
-  // Accessed on state machine thread.
-  nsAutoArrayPtr<unsigned char> mCbCrBuffer;
-
   // Thread for pushing audio onto the audio hardware.
   // The "audio push thread".
   nsCOMPtr<nsIThread> mAudioThread;
 
   // Thread for decoding video in background. The "decode thread".
   nsCOMPtr<nsIThread> mDecodeThread;
 
   // Timer to call the state machine Run() method. Used by
@@ -561,16 +554,21 @@ protected:
   // Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written
   // from the state machine and main threads. Synchronised via decoder
   // monitor.
   double mVolume;
 
   // Time at which we started decoding. Synchronised via decoder monitor.
   TimeStamp mDecodeStartTime;
 
+  // The maximum number of second we spend buffering when we are short on
+  // unbuffered data.
+  PRUint32 mBufferingWait;
+  PRInt64  mLowDataThresholdUsecs;
+
   // True if we shouldn't play our audio (but still write it to any capturing
   // streams).
   bool mAudioCaptured;
 
   // True if the media resource can be seeked. Accessed from the state
   // machine and main threads. Synchronised via decoder monitor.
   bool mSeekable;
 
@@ -642,21 +640,16 @@ protected:
   // throttled to not-throttled we need to pump decoding.
   bool mDidThrottleAudioDecoding;
   bool mDidThrottleVideoDecoding;
 
   // True if we've requested a new decode thread, but it has not yet been
   // created. Synchronized by the decoder monitor.
   bool mRequestedNewDecodeThread;
   
-  // The maximum number of second we spend buffering when we are short on
-  // unbuffered data.
-  PRUint32 mBufferingWait;
-  PRInt64  mLowDataThresholdUsecs;
-
 private:
   // Manager for queuing and dispatching MozAudioAvailable events.  The
   // event manager is accessed from the state machine and audio threads,
   // and takes care of synchronizing access to its internal queue.
   nsAudioAvailableEventManager mEventManager;
 
   // Stores presentation info required for playback. The decoder monitor
   // must be held when accessing this.
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(nsMediaDecoder_h_)
 #define nsMediaDecoder_h_
 
 #include "mozilla/ReentrantMonitor.h"
 #include "VideoFrameContainer.h"
 #include "MediaStreamGraph.h"
+#include "nsIObserver.h"
 
 class nsHTMLMediaElement;
 class nsIStreamListener;
 class nsTimeRanges;
 class nsIMemoryReporter;
 class nsIPrincipal;
 class nsITimer;
 
--- a/content/media/ogg/Makefile.in
+++ b/content/media/ogg/Makefile.in
@@ -12,22 +12,20 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconogg_s
 LIBXUL_LIBRARY 	= 1
 
 
 EXPORTS		+= \
 		nsOggDecoder.h \
-		nsOggDecoderStateMachine.h \
 		nsOggCodecState.h \
 		$(NULL)
 
 CPPSRCS		= \
 		nsOggDecoder.cpp \
-		nsOggDecoderStateMachine.cpp \
 		nsOggCodecState.cpp \
 		nsOggReader.cpp \
 		$(NULL)
 
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
--- a/content/media/ogg/nsOggDecoder.cpp
+++ b/content/media/ogg/nsOggDecoder.cpp
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsOggDecoderStateMachine.h"
+#include "nsBuiltinDecoderStateMachine.h"
 #include "nsOggReader.h"
 #include "nsOggDecoder.h"
 
 nsDecoderStateMachine* nsOggDecoder::CreateStateMachine()
 {
-  return new nsOggDecoderStateMachine(this);
+  return new nsBuiltinDecoderStateMachine(this, new nsOggReader(this));
 }
deleted file mode 100644
--- a/content/media/ogg/nsOggDecoderStateMachine.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsOggDecoderStateMachine.h"
-#include "nsOggReader.h"
-#include "nsOggDecoder.h"
-
-nsOggDecoderStateMachine::nsOggDecoderStateMachine(nsBuiltinDecoder* aDecoder) :
-  nsBuiltinDecoderStateMachine(aDecoder, new nsOggReader(aDecoder))
-{
-}
deleted file mode 100644
--- a/content/media/ogg/nsOggDecoderStateMachine.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#if !defined(nsOggDecoderStateMachine_h_)
-#define nsOggDecoderStateMachine_h_
-
-#include "nsBuiltinDecoderStateMachine.h"
-
-class nsOggDecoderStateMachine : public nsBuiltinDecoderStateMachine
-{
-public:
-  nsOggDecoderStateMachine(nsBuiltinDecoder* aDecoder);
-};
-
-#endif
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -354,28 +354,31 @@ nsresult nsOggReader::ReadMetadata(nsVid
     MediaResource* resource = mDecoder->GetResource();
     if (mDecoder->GetStateMachine()->GetDuration() == -1 &&
         mDecoder->GetStateMachine()->GetState() != nsDecoderStateMachine::DECODER_STATE_SHUTDOWN &&
         resource->GetLength() >= 0 &&
         mDecoder->GetStateMachine()->IsSeekable())
     {
       // We didn't get a duration from the index or a Content-Duration header.
       // Seek to the end of file to find the end time.
+      mDecoder->GetResource()->StartSeekingForMetadata();
       PRInt6