merge again
authorBrad Lassey <blassey@mozilla.com>
Sat, 18 Feb 2012 18:17:10 -0500
changeset 92489 1705e50937fc9cb1344ed3272e14a00636b08730
parent 92488 9b757be291639d5baad2dd859a13db990278e8d4 (diff)
parent 92487 ed2f63d8e4b608364ef7bb788f20a2712313eaf6 (current diff)
child 92490 532171d0e792d4f5cbdc06465beb2065f76b5d53
push idunknown
push userunknown
push dateunknown
milestone13.0a1
merge again
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -1489,38 +1489,34 @@ nsHTMLTableAccessible::IsProbablyForLayo
   if (border.top && border.bottom && border.left && border.right) {
     RETURN_LAYOUT_ANSWER(false, "Has nonzero border-width on table cell");
   }
 
   /**
    * Rules for non-bordered tables with 2-4 columns and 2+ rows from here on forward
    */
 
-  // Check for styled background color across the row
-  // Alternating background color is a common way 
-  nsCOMPtr<nsIDOMNodeList> nodeList;
-  nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mContent));    
-  tableElt->GetElementsByTagName(NS_LITERAL_STRING("tr"), getter_AddRefs(nodeList));
-  NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
-  PRUint32 length;
-  nodeList->GetLength(&length);
-  nsAutoString color, lastRowColor;
-  for (PRUint32 rowCount = 0; rowCount < length; rowCount ++) {
-    nsCOMPtr<nsIDOMNode> rowNode;
-    nodeList->Item(rowCount, getter_AddRefs(rowNode));
-    nsCOMPtr<nsIContent> rowContent(do_QueryInterface(rowNode));
-
-    nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
-      nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), rowContent);
-    NS_ENSURE_TRUE(styleDecl, NS_ERROR_FAILURE);
-
-    lastRowColor = color;
-    styleDecl->GetPropertyValue(NS_LITERAL_STRING("background-color"), color);
-    if (rowCount > 0 && false == lastRowColor.Equals(color)) {
-      RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
+  // Check for styled background color across rows (alternating background
+  // color is a common feature for data tables).
+  PRUint32 childCount = GetChildCount();
+  nsAutoString rowColor, prevRowColor;
+  for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsAccessible* child = GetChildAt(childIdx);
+    if (child->Role() == roles::ROW) {
+      nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
+        nsCoreUtils::GetComputedStyleDeclaration(EmptyString(),
+                                                 child->GetContent());
+      if (styleDecl) {
+        prevRowColor = rowColor;
+        styleDecl->GetPropertyValue(NS_LITERAL_STRING("background-color"),
+                                    rowColor);
+        if (childIdx > 0 && !prevRowColor.Equals(rowColor)) {
+          RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
+        }
+      }
     }
   }
 
   // Check for many rows
   const PRInt32 kMaxLayoutRows = 20;
   if (rows > kMaxLayoutRows) { // A ton of rows, this is probably for data
     RETURN_LAYOUT_ANSWER(false, ">= kMaxLayoutRows (20) and non-bordered");
   }
--- a/accessible/tests/mochitest/treeupdate/Makefile.in
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -43,16 +43,17 @@ VPATH		= @srcdir@
 relativesrcdir  = accessible/treeupdate
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_ariadialog.html \
 		test_colorpicker.xul \
+		test_cssoverflow.html \
 		test_contextmenu.xul \
 		test_doc.html \
 		test_gencontent.html \
 		test_list_editabledoc.html \
 		test_list.html \
 		test_menu.xul \
 		test_menubutton.xul \
 		test_recreation.html \
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_cssoverflow.html
@@ -0,0 +1,141 @@
+<html>
+
+<head>
+  <title>Testing HTML scrollable frames (css overflow style)</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+    ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Change scroll range to not empty size and inserts a child into container
+     * to trigger tree update of the container. Prior to bug 677154 not empty
+     * size resulted to accessible creation for scroll area, container tree
+     * update picked up that accessible unattaching scroll area accessible
+     * subtree.
+     */
+    function changeScrollRange(aContainerID, aScrollAreaID)
+    {
+      this.containerNode = getNode(aContainerID);
+      this.container = getAccessible(this.containerNode);
+      this.scrollAreaNode = getNode(aScrollAreaID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, this.container)
+      ];
+
+      this.invoke = function changeScrollRange_invoke()
+      {
+        this.scrollAreaNode.style.width = "20px";
+        this.containerNode.appendChild(document.createElement("input"));
+      }
+
+      this.finalCheck = function changeScrollRange_finalCheck()
+      {
+        var accTree =
+          { SECTION: [ // container
+            { SECTION: [ // scroll area
+              { ENTRY: [] } // child content
+            ] },
+            { ENTRY: [] } // inserted input
+          ] };
+        testAccessibleTree(this.container, accTree);
+      }
+
+      this.getID = function changeScrollRange_getID()
+      {
+        return "change scroll range for " + prettyName(aScrollAreaID);
+      }
+    }
+
+    /**
+     * Change scrollbar styles from hidden to auto. That makes us to create an
+     * accessible for scroll area.
+     */
+    function changeScrollbarStyles(aContainerID, aScrollAreaID)
+    {
+      this.container = getAccessible(aContainerID);
+      this.scrollAreaNode = getNode(aScrollAreaID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, getAccessible, this.scrollAreaNode),
+        new invokerChecker(EVENT_REORDER, this.container)
+      ];
+
+      this.invoke = function changeScrollbarStyles_invoke()
+      {
+        var accTree =
+          { SECTION: [] };
+        testAccessibleTree(this.container, accTree);
+
+        this.scrollAreaNode.style.overflow = "auto";
+      }
+
+      this.finalCheck = function changeScrollbarStyles_finalCheck()
+      {
+        var accTree =
+          { SECTION: [ // container
+            { SECTION: [] } // scroll area
+          ] };
+        testAccessibleTree(this.container, accTree);
+      }
+
+      this.getID = function changeScrollbarStyles_getID()
+      {
+        return "change scrollbar styles " + prettyName(aScrollAreaID);
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Do tests
+    ////////////////////////////////////////////////////////////////////////////
+
+    var gQueue = null;
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
+
+    function doTests()
+    {
+      gQueue = new eventQueue();
+
+      gQueue.push(new changeScrollRange("container", "scrollarea"));
+      gQueue.push(new changeScrollbarStyles("container2", "scrollarea2"));
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  </script>
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=677154"
+     title="Detached document accessibility tree">
+    Mozilla Bug 677154</a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <div id="eventdump"></div>
+
+  <div id="container"><div id="scrollarea" style="overflow:auto;"><input></div></div>
+  <div id="container2"><div id="scrollarea2" style="overflow:hidden;"></div></div>
+</body>
+</html>
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -12,16 +12,17 @@ builtin(include, build/autoconf/codeset.
 builtin(include, build/autoconf/altoptions.m4)dnl
 builtin(include, build/autoconf/mozprog.m4)dnl
 builtin(include, build/autoconf/mozheader.m4)dnl
 builtin(include, build/autoconf/mozcommonheader.m4)dnl
 builtin(include, build/autoconf/acwinpaths.m4)dnl
 builtin(include, build/autoconf/lto.m4)dnl
 builtin(include, build/autoconf/gcc-pr49911.m4)dnl
 builtin(include, build/autoconf/frameptr.m4)dnl
+builtin(include, build/autoconf/compiler-opts.m4)dnl
 
 MOZ_PROG_CHECKMSYS()
 
 # Read the user's .mozconfig script.  We can't do this in
 # configure.in: autoconf puts the argument parsing code above anything
 # expanded from configure.in, and we need to get the configure options
 # from .mozconfig in place before that argument parsing code.
 MOZ_READ_MOZCONFIG(.)
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -421,12 +421,18 @@ pref("media.realtime_decoder.enabled", t
 // of talos regression.  This is a needed change for higher-framerate
 // CSS animations, and incidentally works around an apparent bug in
 // our handling of requestAnimationFrame() listeners, which are
 // supposed to enable this REPEATING_PRECISE_CAN_SKIP behavior.  The
 // secondary bug isn't really worth investigating since it's obseleted
 // by bug 710563.
 pref("layout.frame_rate.precise", true);
 
+// Temporary remote js console hack
+pref("b2g.remote-js.enabled", true);
+pref("b2g.remote-js.port", 9999);
+
 // Screen timeout in minutes
 pref("power.screen.timeout", 60);
 
 pref("full-screen-api.enabled", true);
+
+pref("media.volume.steps", 10);
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -3,16 +3,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/. */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const CC = Components.Constructor;
+const Cr = Components.results;
 
 const LocalFile = CC('@mozilla.org/file/local;1',
                      'nsILocalFile',
                      'initWithPath');
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 
@@ -20,21 +21,28 @@ XPCOMUtils.defineLazyGetter(Services, 'e
   return Cc['@mozilla.org/process/environment;1']
            .getService(Ci.nsIEnvironment);
 });
 
 XPCOMUtils.defineLazyGetter(Services, 'ss', function() {
   return Cc['@mozilla.org/content/style-sheet-service;1']
            .getService(Ci.nsIStyleSheetService);
 });
+
 XPCOMUtils.defineLazyGetter(Services, 'idle', function() {
   return Cc['@mozilla.org/widget/idleservice;1']
            .getService(Ci.nsIIdleService);
 });
 
+XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function(){
+  return Cc['@mozilla.org/focus-managr;1']
+           .getService(Ci.nsFocusManager);
+});
+
+
 // In order to use http:// scheme instead of file:// scheme
 // (that is much more restricted) the following code kick-off
 // a local http server listening on http://127.0.0.1:7777 and
 // http://localhost:7777.
 function startupHttpd(baseDir, port) {
   const httpdURL = 'chrome://browser/content/httpd.js';
   let httpd = {};
   Services.scriptloader.loadSubScript(httpdURL, httpd);
@@ -100,16 +108,17 @@ var shell = {
       let msg = 'Fatal error during startup: [No homescreen found]';
       return alert(msg);
     }
 
     window.controllers.appendController(this);
     window.addEventListener('keypress', this);
     window.addEventListener('MozApplicationManifest', this);
     window.addEventListener("AppCommand", this);
+    window.addEventListener('mozfullscreenchange', this);
     this.contentBrowser.addEventListener('load', this, true);
 
     try {
       Services.io.offline = false;
 
       let fileScheme = 'file://';
       if (homeURL.substring(0, fileScheme.length) == fileScheme) {
         homeURL = homeURL.replace(fileScheme, '');
@@ -181,16 +190,34 @@ var shell = {
     if (this.isDebug) {
       Services.prefs.setBoolPref("layers.acceleration.draw-fps", true);
       Services.prefs.setBoolPref("nglayout.debug.paint_flashing", true);
     } else {
       Services.prefs.setBoolPref("layers.acceleration.draw-fps", false);
       Services.prefs.setBoolPref("nglayout.debug.paint_flashing", false);
     }
   },
+ 
+  changeVolume: function shell_changeVolume(aDelta) {
+    let audioManager = Cc["@mozilla.org/telephony/audiomanager;1"].getService(Ci.nsIAudioManager);
+
+    let steps = 10;
+    try {
+      steps = Services.prefs.getIntPref("media.volume.steps");
+      if (steps <= 0)
+        steps = 1;
+    } catch(e) {}
+
+    let volume = audioManager.masterVolume + aDelta / steps;
+    if (volume > 1)
+      volume = 1;
+    if (volume < 0)
+      volume = 0;
+    audioManager.masterVolume = volume;
+  },
 
   handleEvent: function shell_handleEvent(evt) {
     switch (evt.type) {
       case 'keypress':
         switch (evt.keyCode) {
           case evt.DOM_VK_HOME:
             this.sendEvent(content, 'home');
             break;
@@ -212,18 +239,32 @@ var shell = {
       case 'AppCommand':
         switch (evt.command) {
           case 'Menu':
             this.sendEvent(content, 'menu');
             break;
           case 'Search':
             this.toggleDebug();
             break;
+          case 'VolumeUp':
+            this.changeVolume(1);
+            break;
+          case 'VolumeDown':
+            this.changeVolume(-1);
+            break;
         }
         break;
+
+      case 'mozfullscreenchange':
+        // When the screen goes fullscreen make sure to set the focus to the
+        // main window so noboby can prevent the ESC key to get out fullscreen
+        // mode
+        if (document.mozFullScreen)
+          Services.fm.focusedWindow = window;
+        break;
       case 'load':
         this.contentBrowser.removeEventListener('load', this, true);
         this.turnScreenOn();
 
         let chromeWindow = window.QueryInterface(Ci.nsIDOMChromeWindow);
         chromeWindow.browserDOMWindow = new nsBrowserAccess();
 
         this.sendEvent(window, 'ContentStart');
@@ -334,8 +375,55 @@ nsBrowserAccess.prototype = {
 // to logcat.
 Services.obs.addObserver(function onConsoleAPILogEvent(subject, topic, data) {
   let message = subject.wrappedJSObject;
   let prefix = "Content JS " + message.level.toUpperCase() +
                " at " + message.filename + ":" + message.lineNumber +
                " in " + (message.functionName || "anonymous") + ": ";
   Services.console.logStringMessage(prefix + Array.join(message.arguments, " "));
 }, "console-api-log-event", false);
+
+(function Repl() {
+  if (!Services.prefs.getBoolPref('b2g.remote-js.enabled')) {
+    return;
+  }
+  const prompt = 'JS> ';
+  let output;
+  let reader = {
+    onInputStreamReady : function repl_readInput(input) {
+      let sin = Cc['@mozilla.org/scriptableinputstream;1']
+                  .createInstance(Ci.nsIScriptableInputStream);
+      sin.init(input);
+      try {
+        let val = eval(sin.read(sin.available()));
+        let ret = (typeof val === 'undefined') ? 'undefined\n' : val + '\n';
+        output.write(ret, ret.length);
+        // TODO: check if socket has been closed
+      } catch (e) {
+        if (e.result === Cr.NS_BASE_STREAM_CLOSED ||
+            (typeof e === 'object' && e.result === Cr.NS_BASE_STREAM_CLOSED)) {
+          return;
+        }
+        let message = (typeof e === 'object') ? e.message + '\n' : e + '\n';
+        output.write(message, message.length);
+      }
+      output.write(prompt, prompt.length);
+      input.asyncWait(reader, 0, 0, Services.tm.mainThread);
+    }
+  }
+  let listener = {
+    onSocketAccepted: function repl_acceptConnection(serverSocket, clientSocket) {
+      dump('Accepted connection on ' + clientSocket.host + '\n');
+      let input = clientSocket.openInputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0)
+                              .QueryInterface(Ci.nsIAsyncInputStream);
+      output = clientSocket.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);
+      output.write(prompt, prompt.length);
+      input.asyncWait(reader, 0, 0, Services.tm.mainThread);
+    }
+  }
+  let serverPort = Services.prefs.getIntPref('b2g.remote-js.port');
+  let serverSocket = Cc['@mozilla.org/network/server-socket;1']
+                       .createInstance(Ci.nsIServerSocket);
+  serverSocket.init(serverPort, true, -1);
+  dump('Opened socket on ' + serverSocket.port + '\n');
+  serverSocket.asyncListen(listener);
+})();
+
--- a/b2g/chrome/content/webapi.js
+++ b/b2g/chrome/content/webapi.js
@@ -172,89 +172,82 @@ const ContentPanning = {
       case 'click':
         evt.stopPropagation();
         evt.preventDefault();
         evt.target.removeEventListener('click', this, true);
         break;
     }
   },
 
-  position: {
-    origin: new Point(0, 0),
-    current: new Point(0 , 0)
-  },
+  position: new Point(0 , 0),
 
   onTouchStart: function cp_onTouchStart(evt) {
     this.dragging = true;
-    KineticPanning.stop();
+
+    // If there is a pan animation running (from a previous pan gesture) and
+    // the user touch back the screen, stop this animation immediatly and
+    // prevent the possible click action.
+    if (KineticPanning.active) {
+      KineticPanning.stop();
+      this.preventNextClick = true;
+    }
 
     this.scrollCallback = this.getPannable(evt.originalTarget);
-    this.position.origin.set(evt.screenX, evt.screenY);
-    this.position.current.set(evt.screenX, evt.screenY);
-    KineticPanning.record(new Point(0, 0));
+    this.position.set(evt.screenX, evt.screenY);
+    KineticPanning.record(new Point(0, 0), evt.timeStamp);
   },
 
   onTouchEnd: function cp_onTouchEnd(evt) {
     if (!this.dragging)
       return;
     this.dragging = false;
 
-    if (this.isPan()) {
-      if (evt.detail) // The event will generate a click
-        evt.target.addEventListener('click', this, true);
+    this.onTouchMove(evt);
 
+    let pan = KineticPanning.isPan();
+    let click = evt.detail;
+    if (click && (pan || this.preventNextClick))
+      evt.target.addEventListener('click', this, true);
+
+    this.preventNextClick = false;
+
+    if (pan)
       KineticPanning.start(this);
-    }
   },
 
   onTouchMove: function cp_onTouchMove(evt) {
     if (!this.dragging || !this.scrollCallback)
       return;
 
-    let current = this.position.current;
+    let current = this.position;
     let delta = new Point(evt.screenX - current.x, evt.screenY - current.y);
     current.set(evt.screenX, evt.screenY);
 
-    if (this.isPan()) {
-      KineticPanning.record(delta);
-      this.scrollCallback(delta.scale(-1));
-    }
+    KineticPanning.record(delta, evt.timeStamp);
+    this.scrollCallback(delta.scale(-1));
   },
 
 
   onKineticBegin: function cp_onKineticBegin(evt) {
   },
 
   onKineticPan: function cp_onKineticPan(delta) {
     return !this.scrollCallback(delta);
   },
 
   onKineticEnd: function cp_onKineticEnd() {
     if (!this.dragging)
       this.scrollCallback = null;
   },
 
-  isPan: function cp_isPan() {
-    let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                     .getInterface(Ci.nsIDOMWindowUtils)
-                     .displayDPI;
-
-    let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi;
-
-    let deltaX = this.position.origin.x - this.position.current.x;
-    let deltaY = this.position.origin.y - this.position.current.y;
-    return (Math.abs(deltaX) > threshold || Math.abs(deltaY) > threshold);
-  },
-
   getPannable: function cp_getPannable(node) {
     if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML')
       return null;
 
     let content = node.ownerDocument.defaultView;
-
     while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
       let style = content.getComputedStyle(node, null);
 
       let overflow = [style.getPropertyValue('overflow'),
                       style.getPropertyValue('overflow-x'),
                       style.getPropertyValue('overflow-y')];
 
       let rect = node.getBoundingClientRect();
@@ -294,35 +287,43 @@ const ContentPanning = {
 ContentPanning.init();
 
 
 // Min/max velocity of kinetic panning. This is in pixels/millisecond.
 const kMinVelocity = 0.4;
 const kMaxVelocity = 6;
 
 // Constants that affect the "friction" of the scroll pane.
-const kExponentialC = 1400;
+const kExponentialC = 1000;
 const kPolynomialC = 100 / 1000000;
 
 // How often do we change the position of the scroll pane?
 // Too often and panning may jerk near the end.
 // Too little and panning will be choppy. In milliseconds.
 const kUpdateInterval = 16;
 
+// The numbers of momentums to use for calculating the velocity of the pan.
+// Those are taken from the end of the action
+const kSamples = 5;
+
 const KineticPanning = {
   _position: new Point(0, 0),
   _velocity: new Point(0, 0),
   _acceleration: new Point(0, 0),
 
+  get active() {
+    return this.target !== null;
+  },
+
   _target: null,
   start: function kp_start(target) {
     this.target = target;
 
     // Calculate the initial velocity of the movement based on user input
-    let momentums = this.momentums;
+    let momentums = this.momentums.slice(-kSamples);
 
     let distance = new Point(0, 0);
     momentums.forEach(function(momentum) {
       distance.add(momentum.dx, momentum.dy);
     });
 
     let elapsed = momentums[momentums.length - 1].time - momentums[0].time;
 
@@ -333,16 +334,17 @@ const KineticPanning = {
     }
 
     let velocityX = clampFromZero(distance.x / elapsed, 0, kMaxVelocity);
     let velocityY = clampFromZero(distance.y / elapsed, 0, kMaxVelocity);
 
     let velocity = this._velocity;
     velocity.set(Math.abs(velocityX) < kMinVelocity ? 0 : velocityX,
                  Math.abs(velocityY) < kMinVelocity ? 0 : velocityY);
+    this.momentums = [];
 
     // Set acceleration vector to opposite signs of velocity
     function sign(x) {
       return x ? (x > 0 ? 1 : -1) : 0;
     }
 
     this._acceleration.set(velocity.clone().map(sign).scale(-kPolynomialC));
 
@@ -353,30 +355,42 @@ const KineticPanning = {
 
     this.target.onKineticBegin();
   },
 
   stop: function kp_stop() {
     if (!this.target)
       return;
 
-    this.momentums.splice(0);
+    this.momentums = [];
 
     this.target.onKineticEnd();
     this.target = null;
   },
 
   momentums: [],
-  record: function kp_record(delta) {
-    // If the panning direction has changed, stop the current activity.
-    if (this.target && ((delta.x * this._velocity.x < 0) ||
-                        (delta.y * this._velocity.y < 0)))
-      this.stop();
+  record: function kp_record(delta, timestamp) {
+    this.momentums.push({ 'time': timestamp, 'dx' : delta.x, 'dy' : delta.y });
+  },
+
+  isPan: function cp_isPan() {
+    let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor)
+                     .getInterface(Ci.nsIDOMWindowUtils)
+                     .displayDPI;
 
-    this.momentums.push({ 'time': Date.now(), 'dx' : delta.x, 'dy' : delta.y });
+    let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi;
+
+    let deltaX = 0;
+    let deltaY = 0;
+    let start = this.momentums[0].time;
+    return this.momentums.slice(1).some(function(momentum) {
+      deltaX += momentum.dx;
+      deltaY += momentum.dy;
+      return (Math.abs(deltaX) > threshold) || (Math.abs(deltaY) > threshold);
+    });
   },
 
   _startAnimation: function kp_startAnimation() {
     let c = kExponentialC;
     function getNextPosition(position, v, a, t) {
       // Important traits for this function:
       //   p(t=0) is 0
       //   p'(t=0) is v0
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -146,19 +146,16 @@
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_base.xpt
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/dom_telephony.xpt
 @BINPATH@/components/dom_wifi.xpt
 @BINPATH@/components/dom_system_b2g.xpt
 #endif
 @BINPATH@/components/dom_battery.xpt
-#ifdef MOZ_B2G_BT
-@BINPATH@/components/dom_bluetooth.xpt
-#endif
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1328822681000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1329176667000">
   <emItems>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
                         <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>
@@ -22,18 +22,22 @@
                           </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="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
-                        <versionRange  minVersion="1.1b1" maxVersion="1.1b1">
+      <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">
@@ -117,18 +121,21 @@
                               <versionRange  minVersion="9.0a1" maxVersion="9.0" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
       <emItem  blockID="i60" id="youtb3@youtb3.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i56" id="flash@adobe.com">
-                        <versionRange  minVersion="0" maxVersion="*">
+      <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="i11" id="yslow@yahoo-inc.com">
                         <versionRange  minVersion="2.0.5" maxVersion="2.0.5">
@@ -173,30 +180,31 @@
       <emItem  blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
                         <versionRange  minVersion="2.2" maxVersion="2.2">
                     </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>
+      <emItem  blockID="i56" id="flash@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="8.0a1" maxVersion="*" />
                           </targetApplication>
                     </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="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
                         </emItem>
       <emItem  blockID="i52" id="ff-ext@youtube">
                         <versionRange  minVersion="0" maxVersion="*">
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -277,16 +277,17 @@ pref("browser.urlbar.clickSelectsAll", f
 pref("browser.urlbar.clickSelectsAll", true);
 #endif
 #ifdef UNIX_BUT_NOT_MAC
 pref("browser.urlbar.doubleClickSelectsAll", true);
 #else
 pref("browser.urlbar.doubleClickSelectsAll", false);
 #endif
 pref("browser.urlbar.autoFill", false);
+pref("browser.urlbar.autoFill.typed", true);
 // 0: Match anywhere (e.g., middle of words)
 // 1: Match on word boundaries and then try matching anywhere
 // 2: Match only on word boundaries (e.g., after / or .)
 // 3: Match at the beginning of the url or title
 pref("browser.urlbar.matchBehavior", 1);
 pref("browser.urlbar.filter.javascript", true);
 
 // the maximum number of results to show in autocomplete when doing richResults
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -9048,38 +9048,54 @@ var Scratchpad = {
 XPCOMUtils.defineLazyGetter(Scratchpad, "ScratchpadManager", function() {
   let tmp = {};
   Cu.import("resource:///modules/devtools/scratchpad-manager.jsm", tmp);
   return tmp.ScratchpadManager;
 });
 
 var StyleEditor = {
   prefEnabledName: "devtools.styleeditor.enabled",
-  openChrome: function SE_openChrome()
+  /**
+   * Opens the style editor. If the UI is already open, it will be focused.
+   *
+   * @param {CSSStyleSheet} [aSelectedStyleSheet] default Stylesheet.
+   * @param {Number} [aLine] Line to which the caret should be moved (one-indexed).
+   * @param {Number} [aCol] Column to which the caret should be moved (one-indexed).
+   */
+  openChrome: function SE_openChrome(aSelectedStyleSheet, aLine, aCol)
   {
     const CHROME_URL = "chrome://browser/content/styleeditor.xul";
     const CHROME_WINDOW_TYPE = "Tools:StyleEditor";
     const CHROME_WINDOW_FLAGS = "chrome,centerscreen,resizable,dialog=no";
 
     // focus currently open Style Editor window for this document, if any
     let contentWindow = gBrowser.selectedBrowser.contentWindow;
     let contentWindowID = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
       getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
     let enumerator = Services.wm.getEnumerator(CHROME_WINDOW_TYPE);
     while (enumerator.hasMoreElements()) {
       var win = enumerator.getNext();
       if (win.styleEditorChrome.contentWindowID == contentWindowID) {
+        if (aSelectedStyleSheet) {
+          win.styleEditorChrome.selectStyleSheet(aSelectedStyleSheet, aLine, aCol);
+        }
         win.focus();
         return win;
       }
     }
 
+    let args = {
+      contentWindow: contentWindow,
+      selectedStyleSheet: aSelectedStyleSheet,
+      line: aLine,
+      col: aCol
+    };
+    args.wrappedJSObject = args;
     let chromeWindow = Services.ww.openWindow(null, CHROME_URL, "_blank",
-                                              CHROME_WINDOW_FLAGS,
-                                              contentWindow);
+                                              CHROME_WINDOW_FLAGS, args);
     chromeWindow.focus();
     return chromeWindow;
   }
 };
 
 function onWebDeveloperMenuShowing() {
   document.getElementById("Tools:WebConsole").setAttribute("checked", HUDConsoleUI.getOpenHUD() != null);
 }
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -85,16 +85,17 @@
         titlemodifier="&mainWindow.titlemodifier;@PRE_RELEASE_SUFFIX@"
         titlemodifier_normal="&mainWindow.titlemodifier;@PRE_RELEASE_SUFFIX@"
         titlemodifier_privatebrowsing="&mainWindow.titlemodifier;@PRE_RELEASE_SUFFIX@ &mainWindow.titlePrivateBrowsingSuffix;"
 #endif
         titlemenuseparator="&mainWindow.titlemodifiermenuseparator;"
         lightweightthemes="true"
         lightweightthemesfooter="browser-bottombox"
         windowtype="navigator:browser"
+        macanimationtype="document"
         screenX="4" screenY="4"
         browsingmode="normal"
         persist="screenX screenY width height sizemode">
 
 # All JS files which are not content (only) dependent that browser.xul
 # wishes to include *must* go into the global-scripts.inc file
 # so that they can be shared by macBrowserOverlay.xul.
 #include global-scripts.inc
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1261,16 +1261,22 @@
               }, 0, this.tabContainer);
             } else {
               setTimeout(function (tabContainer) {
                 if (t.pinned)
                   tabContainer._handleNewTab(t);
                 else {
                   t._animStartTime = Date.now();
                   t.setAttribute("fadein", "true");
+
+                  // This call to adjustTabstrip is redundant but needed so that
+                  // when opening a second tab, the first tab's close buttons
+                  // appears immediately rather than when the transition ends.
+                  if (tabContainer.childNodes.length == 2)
+                    tabContainer.adjustTabstrip();
                 }
               }, 0, this.tabContainer);
             }
 
             this.tabContainer.appendChild(t);
 
             // invalidate cache, because tabContainer is about to change
             this._browsers = null;
@@ -1360,17 +1366,18 @@
             if (!blank) {
               // Stop the existing about:blank load.  Otherwise, if aURI
               // doesn't stop in-progress loads on its own, we'll get into
               // trouble with multiple parallel loads running at once.
               b.stop();
 
               // pretend the user typed this so it'll be available till
               // the document successfully loads
-              b.userTypedValue = aURI;
+              if (!isBlankPageURL(aURI))
+                b.userTypedValue = aURI;
 
               let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
               if (aAllowThirdPartyFixup)
                 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
               if (aFromExternal)
                 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL;
               if (aIsUTF8)
                 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_URI_IS_UTF8;
@@ -1552,25 +1559,36 @@
 
       <method name="_beginRemoveTab">
         <parameter name="aTab"/>
         <parameter name="aTabWillBeMoved"/>
         <parameter name="aCloseWindowWithLastTab"/>
         <parameter name="aCloseWindowFastpath"/>
         <body>
           <![CDATA[
-            if (aTab.closing || this._windowIsClosing)
+            if (aTab.closing ||
+                aTab._pendingPermitUnload ||
+                this._windowIsClosing)
               return false;
 
             var browser = this.getBrowserForTab(aTab);
 
             if (!aTabWillBeMoved) {
               let ds = browser.docShell;
-              if (ds && ds.contentViewer && !ds.contentViewer.permitUnload())
-                return false;
+              if (ds && ds.contentViewer) {
+                // We need to block while calling permitUnload() because it
+                // processes the event queue and may lead to another removeTab()
+                // call before permitUnload() even returned.
+                aTab._pendingPermitUnload = true;
+                let permitUnload = ds.contentViewer.permitUnload();
+                delete aTab._pendingPermitUnload;
+
+                if (!permitUnload)
+                  return false;
+              }
             }
 
             var closeWindow = false;
             var newTab = false;
             if (this.tabs.length - this._removingTabs.length == 1) {
               closeWindow = aCloseWindowWithLastTab != null ? aCloseWindowWithLastTab :
                             !window.toolbar.visible ||
                               this.tabContainer._closeWindowWithLastTab;
@@ -3528,22 +3546,24 @@
 
           this.tabbrowser.swapBrowsersAndCloseOther(newTab, draggedTab);
 
           // We need to select the tab after we've done
           // swapBrowsersAndCloseOther, so that the updateCurrentBrowser
           // it triggers will correctly update our URL bar.
           this.tabbrowser.selectedTab = newTab;
         } else {
-          let url = browserDragAndDrop.drop(event, { });
+          // Pass true to disallow dropping javascript: or data: urls
+          let url;
+          try {
+            url = browserDragAndDrop.drop(event, { }, true);
+          } catch (ex) {}
 
           // valid urls don't contain spaces ' '; if we have a space it isn't a valid url.
-          // Also disallow dropping javascript: or data: urls--bail out
-          if (!url || !url.length || url.indexOf(" ", 0) != -1 ||
-              /^\s*(javascript|data):/.test(url))
+          if (!url || url.indexOf(" ") != -1)
             return;
 
           let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
 
           if (event.shiftKey)
             bgLoad = !bgLoad;
 
           let tab = this._getDragTargetTab(event);
@@ -4050,17 +4070,17 @@
         ]]></body>
       </method>
 
       <method name="_calcMouseTargetRect">
         <body><![CDATA[
           let alignRight = false;
 
           if (getComputedStyle(document.documentElement).direction == "rtl")
-            alighRight = !alignRight;
+            alignRight = !alignRight;
 
           let rect = this.getBoundingClientRect();
           this._mouseTargetRect = {
             top:    rect.top,
             bottom: rect.bottom,
             left:   alignRight ? window.innerWidth - rect.width : 0,
             right:  alignRight ? window.innerWidth : rect.width
           };
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -263,16 +263,17 @@ endif
                  test_bug628179.html \
                  browser_wyciwyg_urlbarCopying.js \
                  test_wyciwyg_copying.html \
                  authenticate.sjs \
                  browser_minimize.js \
                  browser_aboutSyncProgress.js \
                  browser_middleMouse_inherit.js \
                  redirect_bug623155.sjs \
+                 browser_tabDrop.js \
                  $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_tabDrop.js
@@ -0,0 +1,71 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  let newTab = gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true});
+  registerCleanupFunction(function () {
+    gBrowser.removeTab(newTab);
+  });
+
+  let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
+                     getService(Ci.mozIJSSubScriptLoader);
+  let chromeUtils = {};
+  scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js", chromeUtils);
+
+  let tabContainer = gBrowser.tabContainer;
+  var receivedDropCount = 0;
+  function dropListener() {
+    receivedDropCount++;
+    if (receivedDropCount == triggeredDropCount) {
+      is(openedTabs, validDropCount, "correct number of tabs were opened");
+      executeSoon(finish);
+    }
+  }
+  tabContainer.addEventListener("drop", dropListener, false);
+  registerCleanupFunction(function () {
+    tabContainer.removeEventListener("drop", dropListener, false);
+  });
+
+  var openedTabs = 0;
+  function tabOpenListener(e) {
+    openedTabs++;
+    let tab = e.target;
+    executeSoon(function () {
+      gBrowser.removeTab(tab);
+    });
+  }
+
+  tabContainer.addEventListener("TabOpen", tabOpenListener, false);
+  registerCleanupFunction(function () {
+    tabContainer.removeEventListener("TabOpen", tabOpenListener, false);
+  });
+
+  var triggeredDropCount = 0;
+  var validDropCount = 0;
+  function drop(text, valid) {
+    triggeredDropCount++;
+    if (valid)
+      validDropCount++;
+    executeSoon(function () {
+      // A drop type of "link" onto an existing tab would normally trigger a
+      // load in that same tab, but tabbrowser code in _getDragTargetTab treats
+      // drops on the outer edges of a tab differently (loading a new tab
+      // instead). The events created by synthesizeDrop have all of their
+      // coordinates set to 0 (screenX/screenY), so they're treated as drops
+      // on the outer edge of the tab, thus they open new tabs.
+      chromeUtils.synthesizeDrop(newTab, newTab, [[{type: "text/plain", data: text}]], "link", window, EventUtils);
+    });
+  }
+
+  // Begin and end with valid drops to make sure we wait for all drops before
+  // ending the test
+  drop("mochi.test/first", true);
+  drop("javascript:'bad'");
+  drop("jAvascript:'bad'");
+  drop("space bad");
+  drop("mochi.test/second", true);
+  drop("data:text/html,bad");
+  drop("mochi.test/third", true);
+}
--- a/browser/branding/official/configure.sh
+++ b/browser/branding/official/configure.sh
@@ -1,2 +1,1 @@
 MOZ_APP_DISPLAYNAME=Firefox
-MOZ_UA_BUILDID=20100101
--- a/browser/components/sessionstore/src/nsSessionStartup.js
+++ b/browser/components/sessionstore/src/nsSessionStartup.js
@@ -67,16 +67,17 @@
 /* :::::::: Constants and Helpers ::::::::::::::: */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource:///modules/TelemetryStopwatch.jsm");
 
 const STATE_RUNNING_STR = "running";
 const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 megabytes
 
 function debug(aMsg) {
   aMsg = ("SessionStartup: " + aMsg).replace(/\S{80}/g, "$&\n");
   Services.console.logStringMessage(aMsg);
 }
@@ -122,45 +123,51 @@ SessionStartup.prototype = {
       return;
 
     // get string containing session state
     let iniString = this._readStateFile(sessionFile);
     if (!iniString)
       return;
 
     // parse the session state into a JS object
+    // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
+    if (iniString.charAt(0) == '(')
+      iniString = iniString.slice(1, -1);
+    let corruptFile = false;
     try {
-      // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
-      if (iniString.charAt(0) == '(')
-        iniString = iniString.slice(1, -1);
+      this._initialState = JSON.parse(iniString);
+    }
+    catch (ex) {
+      debug("The session file contained un-parse-able JSON: " + ex);
+      // Try to eval.
+      // evalInSandbox will throw if iniString is not parse-able.
       try {
-        this._initialState = JSON.parse(iniString);
-      }
-      catch (exJSON) {
         var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
         this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
+      } catch(ex) {
+        debug("The session file contained un-eval-able JSON: " + ex);
+        corruptFile = true;
       }
+    }
+    Services.telemetry.getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE").add(corruptFile);
 
-      // If this is a normal restore then throw away any previous session
-      if (!doResumeSessionOnce)
-        delete this._initialState.lastSessionState;
-    }
-    catch (ex) { debug("The session file is invalid: " + ex); }
+    // If this is a normal restore then throw away any previous session
+    if (!doResumeSessionOnce)
+      delete this._initialState.lastSessionState;
 
     let resumeFromCrash = prefBranch.getBoolPref("sessionstore.resume_from_crash");
     let lastSessionCrashed =
       this._initialState && this._initialState.session &&
       this._initialState.session.state &&
       this._initialState.session.state == STATE_RUNNING_STR;
 
     // Report shutdown success via telemetry. Shortcoming here are
     // being-killed-by-OS-shutdown-logic, shutdown freezing after
     // session restore was written, etc.
-    let Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
-    Telemetry.getHistogramById("SHUTDOWN_OK").add(!lastSessionCrashed);
+    Services.telemetry.getHistogramById("SHUTDOWN_OK").add(!lastSessionCrashed);
 
     // set the startup type
     if (lastSessionCrashed && resumeFromCrash)
       this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
     else if (!lastSessionCrashed && doResumeSession)
       this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
     else if (this._initialState)
       this._sessionType = Ci.nsISessionStartup.DEFER_SESSION;
@@ -291,19 +298,21 @@ SessionStartup.prototype = {
   /**
    * Reads a session state file into a string and lets
    * observers modify the state before it's being used
    *
    * @param aFile is any nsIFile
    * @returns a session state string
    */
   _readStateFile: function sss_readStateFile(aFile) {
+    TelemetryStopwatch.start("FX_SESSION_RESTORE_READ_FILE_MS");
     var stateString = Cc["@mozilla.org/supports-string;1"].
                         createInstance(Ci.nsISupportsString);
     stateString.data = this._readFile(aFile) || "";
+    TelemetryStopwatch.finish("FX_SESSION_RESTORE_READ_FILE_MS");
 
     Services.obs.notifyObservers(stateString, "sessionstore-state-read", "");
 
     return stateString.data;
   },
 
   /**
    * reads a file into a string
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -126,16 +126,17 @@ const TAB_EVENTS = ["TabOpen", "TabClose
 #endif
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 // debug.js adds NS_ASSERT. cf. bug 669196
 Cu.import("resource://gre/modules/debug.js");
 
 Cu.import("resource:///modules/TelemetryTimestamps.jsm");
+Cu.import("resource:///modules/TelemetryStopwatch.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
 XPCOMUtils.defineLazyGetter(this, "ScratchpadManager", function() {
   Cu.import("resource:///modules/devtools/scratchpad-manager.jsm");
@@ -3648,16 +3649,18 @@ SessionStoreService.prototype = {
     // if we're in private browsing mode, do nothing
     if (this._inPrivateBrowsing)
       return;
 
     // If crash recovery is disabled, we only want to resume with pinned tabs
     // if we crash.
     let pinnedOnly = this._loadState == STATE_RUNNING && !this._resume_from_crash;
 
+    TelemetryStopwatch.start("FX_SESSION_RESTORE_COLLECT_DATA_MS");
+
     var oState = this._getCurrentState(aUpdateAll, pinnedOnly);
     if (!oState)
       return;
 
 #ifndef XP_MACOSX
     // We want to restore closed windows that are marked with _shouldRestore.
     // We're doing this here because we want to control this only when saving
     // the file.
@@ -3686,26 +3689,30 @@ SessionStoreService.prototype = {
         Services.prefs.savePrefFile(null);
       }
     }
 
     // Persist the last session if we deferred restoring it
     if (this._lastSessionState)
       oState.lastSessionState = this._lastSessionState;
 
+    TelemetryStopwatch.finish("FX_SESSION_RESTORE_COLLECT_DATA_MS");
+
     this._saveStateObject(oState);
   },
 
   /**
    * write a state object to disk
    */
   _saveStateObject: function sss_saveStateObject(aStateObj) {
+    TelemetryStopwatch.start("FX_SESSION_RESTORE_SERIALIZE_DATA_MS");
     var stateString = Cc["@mozilla.org/supports-string;1"].
                         createInstance(Ci.nsISupportsString);
     stateString.data = this._toJSONString(aStateObj);
+    TelemetryStopwatch.finish("FX_SESSION_RESTORE_SERIALIZE_DATA_MS");
 
     Services.obs.notifyObservers(stateString, "sessionstore-state-write", "");
 
     // don't touch the file if an observer has deleted all state data
     if (stateString.data)
       this._writeFile(this._sessionFile, stateString.data);
 
     this._lastSaveTime = Date.now();
@@ -3804,17 +3811,17 @@ SessionStoreService.prototype = {
    *        Object containing session data
    */
   _openWindowWithState: function sss_openWindowWithState(aState) {
     var argString = Cc["@mozilla.org/supports-string;1"].
                     createInstance(Ci.nsISupportsString);
     argString.data = "";
 
     // Build feature string
-    let features = "chrome,dialog=no,all";
+    let features = "chrome,dialog=no,macsuppressanimation,all";
     let winState = aState.windows[0];
     WINDOW_ATTRIBUTES.forEach(function(aFeature) {
       // Use !isNaN as an easy way to ignore sizemode and check for numbers
       if (aFeature in winState && !isNaN(winState[aFeature]))
         features += "," + aFeature + "=" + winState[aFeature];
     });
 
     var window =
@@ -4422,31 +4429,33 @@ SessionStoreService.prototype = {
   /**
    * write file to disk
    * @param aFile
    *        nsIFile
    * @param aData
    *        String data
    */
   _writeFile: function sss_writeFile(aFile, aData) {
+    TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_MS");
     // Initialize the file output stream.
     var ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].
                   createInstance(Ci.nsIFileOutputStream);
     ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, ostream.DEFER_OPEN);
 
     // Obtain a converter to convert our data to a UTF-8 encoded input stream.
     var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
                     createInstance(Ci.nsIScriptableUnicodeConverter);
     converter.charset = "UTF-8";
 
     // Asynchronously copy the data to the file.
     var istream = converter.convertToInputStream(aData);
     var self = this;
     NetUtil.asyncCopy(istream, ostream, function(rc) {
       if (Components.isSuccessCode(rc)) {
+        TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_MS");
         Services.obs.notifyObservers(null,
                                      "sessionstore-state-write-complete",
                                      "");
       }
     });
   }
 };
 
copy from browser/config/mozconfigs/macosx-universal/nightly
copy to browser/config/mozconfigs/macosx-lion-universal/nightly
--- a/browser/config/mozconfigs/macosx-universal/nightly
+++ b/browser/config/mozconfigs/macosx-lion-universal/nightly
@@ -10,14 +10,15 @@ ac_add_options --disable-install-strip
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
-mk_add_options MOZ_MAKE_FLAGS="-j4"
+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
copy from browser/config/mozconfigs/macosx-universal/release
copy to browser/config/mozconfigs/macosx-lion-universal/release
--- a/browser/config/mozconfigs/macosx-universal/release
+++ b/browser/config/mozconfigs/macosx-lion-universal/release
@@ -12,8 +12,9 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
+ac_add_options --with-ccache
copy from browser/config/mozconfigs/macosx-universal/shark
copy to browser/config/mozconfigs/macosx-lion-universal/shark
--- a/browser/config/mozconfigs/macosx-universal/shark
+++ b/browser/config/mozconfigs/macosx-lion-universal/shark
@@ -7,19 +7,20 @@ ac_add_options --enable-application=brow
 
 ac_add_options --disable-tests
 ac_add_options --disable-install-strip
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 # Enable parallel compiling
-mk_add_options MOZ_MAKE_FLAGS="-j4"
+mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 # shark specific options
 ac_add_options --enable-shark
 ac_add_options --enable-dtrace
 
 # Need this to prevent name conflicts with the normal nightly build packages
 export MOZ_PKG_SPECIAL="shark"
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+ac_add_options --with-ccache
copy from browser/config/mozconfigs/macosx32/debug
copy to browser/config/mozconfigs/macosx32-lion/debug
--- a/browser/config/mozconfigs/macosx32/debug
+++ b/browser/config/mozconfigs/macosx32-lion/debug
@@ -1,11 +1,12 @@
 . $topsrcdir/build/macosx/mozconfig.leopard
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 
 # Enable parallel compiling
-mk_add_options MOZ_MAKE_FLAGS="-j4"
+mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
+ac_add_options --with-ccache
copy from browser/config/mozconfigs/macosx64/debug
copy to browser/config/mozconfigs/macosx64-lion/debug
--- a/browser/config/mozconfigs/macosx64/debug
+++ b/browser/config/mozconfigs/macosx64-lion/debug
@@ -1,16 +1,17 @@
 . $topsrcdir/build/macosx/common
 
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-accessibility
 
 # Enable parallel compiling
-mk_add_options MOZ_MAKE_FLAGS="-j4"
+mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 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
copy from browser/config/mozconfigs/macosx64/l10n-mozconfig
copy to browser/config/mozconfigs/macosx64-lion/l10n-mozconfig
--- a/browser/config/mozconfigs/macosx64/l10n-mozconfig
+++ b/browser/config/mozconfigs/macosx64-lion/l10n-mozconfig
@@ -1,4 +1,5 @@
 ac_add_options --with-l10n-base=../../l10n-central
 ac_add_options --enable-official-branding
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
+ac_add_options --with-ccache
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -67,16 +67,17 @@ include $(topsrcdir)/config/rules.mk
 	browser_dbg_stack-02.js \
 	browser_dbg_stack-03.js \
 	browser_dbg_stack-04.js \
 	browser_dbg_location-changes.js \
 	browser_dbg_script-switching.js \
 	browser_dbg_pause-resume.js \
 	browser_dbg_update-editor-mode.js \
 	browser_dbg_select-line.js \
+	browser_dbg_clean-exit.js \
 	head.js \
 	$(NULL)
 
 _BROWSER_TEST_PAGES = \
 	browser_dbg_tab1.html \
 	browser_dbg_tab2.html \
 	browser_dbg_debuggerstatement.html \
 	browser_dbg_stack.html \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_clean-exit.js
@@ -0,0 +1,42 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Test that closing a tab with the debugger in a paused state exits cleanly.
+
+var gPane = null;
+var gTab = null;
+var gDebuggee = null;
+var gDebugger = null;
+
+const DEBUGGER_TAB_URL = "http://example.com/browser/browser/devtools/" +
+                         "debugger/test/" +
+                         "browser_dbg_debuggerstatement.html";
+
+function test() {
+  debug_tab_pane(DEBUGGER_TAB_URL, function(aTab, aDebuggee, aPane) {
+    gTab = aTab;
+    gDebuggee = aDebuggee;
+    gPane = aPane;
+    gDebugger = gPane.debuggerWindow;
+
+    testCleanExit();
+  });
+}
+
+function testCleanExit() {
+  gPane.activeThread.addOneTimeListener("framesadded", function() {
+    Services.tm.currentThread.dispatch({ run: function() {
+      is(gDebugger.StackFrames.activeThread.paused, true,
+        "Should be paused after the debugger statement.");
+
+      gPane._client.addOneTimeListener("tabDetached", function () {
+        finish();
+      });
+      removeTab(gTab);
+    }}, 0);
+  });
+
+  gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
+}
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -758,16 +758,19 @@ InspectorUI.prototype = {
         this.store.setValue(winID, "ruleView", ruleViewStore);
       }
 
       this.ruleView = new CssRuleView(doc, ruleViewStore);
 
       this.boundRuleViewChanged = this.ruleViewChanged.bind(this);
       this.ruleView.element.addEventListener("CssRuleViewChanged",
                                              this.boundRuleViewChanged);
+      this.cssRuleViewBoundCSSLinkClicked = this.ruleViewCSSLinkClicked.bind(this);
+      this.ruleView.element.addEventListener("CssRuleViewCSSLinkClicked",
+                                             this.cssRuleViewBoundCSSLinkClicked);
 
       doc.documentElement.appendChild(this.ruleView.element);
       this.ruleView.highlight(this.selection);
       Services.obs.notifyObservers(null,
         INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, null);
     }.bind(this);
 
     iframe.addEventListener("load", boundLoadListener, true);
@@ -796,26 +799,52 @@ InspectorUI.prototype = {
 
   ruleViewChanged: function IUI_ruleViewChanged()
   {
     this.isDirty = true;
     this.nodeChanged(this.ruleViewObject);
   },
 
   /**
+   * When a css link is clicked this method is called in order to either:
+   *   1. Open the link in view source (for element style attributes)
+   *   2. Open the link in the style editor
+   *
+   * @param aEvent The event containing the style rule to act on
+   */
+  ruleViewCSSLinkClicked: function(aEvent)
+  {
+    if (!this.chromeWin) {
+      return;
+    }
+
+    let rule = aEvent.detail.rule;
+    let styleSheet = rule.sheet;
+
+    if (styleSheet) {
+      this.chromeWin.StyleEditor.openChrome(styleSheet, rule.ruleLine);
+    } else {
+      let href = rule.elementStyle.element.ownerDocument.location.href;
+      this.chromeWin.openUILinkIn("view-source:" + href, "window");
+    }
+  },
+
+  /**
    * Destroy the rule view.
    */
   destroyRuleView: function IUI_destroyRuleView()
   {
     let iframe = this.getToolIframe(this.ruleViewObject);
     iframe.parentNode.removeChild(iframe);
 
     if (this.ruleView) {
       this.ruleView.element.removeEventListener("CssRuleViewChanged",
                                                 this.boundRuleViewChanged);
+      this.ruleView.element.removeEventListener("CssRuleViewCSSLinkClicked",
+                                                this.cssRuleViewBoundCSSLinkClicked);
       delete boundRuleViewChanged;
       this.ruleView.clear();
       delete this.ruleView;
     }
   },
 
   /////////////////////////////////////////////////////////////////////////
   //// Utility Methods
--- a/browser/devtools/scratchpad/scratchpad.xul
+++ b/browser/devtools/scratchpad/scratchpad.xul
@@ -46,16 +46,17 @@
 <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/source-editor-overlay.xul"?>
 
 <window id="main-window"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         title="&window.title;"
         windowtype="devtools:scratchpad"
+        macanimationtype="document"
         screenX="4" screenY="4"
         width="640" height="480"
         persist="screenX screenY width height sizemode">
 
 <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
 <script type="application/javascript" src="chrome://browser/content/scratchpad.js"/>
 
 <commandset id="editMenuCommands"/>
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm
+++ b/browser/devtools/sourceeditor/source-editor-orion.jsm
@@ -73,16 +73,19 @@ const ORION_THEMES = {
  * to Orion events.
  */
 const ORION_EVENTS = {
   ContextMenu: "ContextMenu",
   TextChanged: "ModelChanged",
   Selection: "Selection",
   Focus: "Focus",
   Blur: "Blur",
+  MouseOver: "MouseOver",
+  MouseOut: "MouseOut",
+  MouseMove: "MouseMove",
 };
 
 /**
  * Known Orion annotation types.
  */
 const ORION_ANNOTATION_TYPES = {
   currentBracket: "orion.annotation.currentBracket",
   matchingBracket: "orion.annotation.matchingBracket",
--- a/browser/devtools/sourceeditor/source-editor.jsm
+++ b/browser/devtools/sourceeditor/source-editor.jsm
@@ -156,16 +156,40 @@ SourceEditor.EVENTS = {
    * The focus event is fired when the editor is focused.
    */
   FOCUS: "Focus",
 
   /**
    * The blur event is fired when the editor goes out of focus.
    */
   BLUR: "Blur",
+
+  /**
+   * The MouseMove event is sent when the user moves the mouse over a line
+   * annotation. The event object properties:
+   *   - event - the DOM mousemove event object.
+   *   - x and y - the mouse coordinates relative to the document being edited.
+   */
+  MOUSE_MOVE: "MouseMove",
+
+  /**
+   * The MouseOver event is sent when the mouse pointer enters a line
+   * annotation. The event object properties:
+   *   - event - the DOM mouseover event object.
+   *   - x and y - the mouse coordinates relative to the document being edited.
+   */
+  MOUSE_OVER: "MouseOver",
+
+  /**
+   * This MouseOut event is sent when the mouse pointer exits a line
+   * annotation. The event object properties:
+   *   - event - the DOM mouseout event object.
+   *   - x and y - the mouse coordinates relative to the document being edited.
+   */
+  MOUSE_OUT: "MouseOut",
 };
 
 /**
  * Extend a destination object with properties from a source object.
  *
  * @param object aDestination
  * @param object aSource
  */
--- a/browser/devtools/sourceeditor/test/Makefile.in
+++ b/browser/devtools/sourceeditor/test/Makefile.in
@@ -50,12 +50,13 @@ include $(topsrcdir)/config/rules.mk
 		browser_bug687573_vscroll.js \
 		browser_bug687568_pagescroll.js \
 		browser_bug687580_drag_and_drop.js \
 		browser_bug684546_reset_undo.js \
 		browser_bug695035_middle_click_paste.js \
 		browser_bug687160_line_api.js \
 		browser_bug650345_find.js \
 		browser_bug703692_focus_blur.js \
+		browser_bug725388_mouse_events.js \
 		head.js \
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/sourceeditor/test/browser_bug725388_mouse_events.js
@@ -0,0 +1,97 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+let tempScope = {};
+Cu.import("resource:///modules/source-editor.jsm", tempScope);
+let SourceEditor = tempScope.SourceEditor;
+
+let testWin;
+let editor;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
+    "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
+    " title='Test for bug 725388' width='600' height='500'><hbox flex='1'/></window>";
+  const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
+
+  testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
+  testWin.addEventListener("load", function onWindowLoad() {
+    testWin.removeEventListener("load", onWindowLoad, false);
+    waitForFocus(initEditor, testWin);
+  }, false);
+}
+
+function initEditor()
+{
+  let hbox = testWin.document.querySelector("hbox");
+
+  editor = new SourceEditor();
+  editor.init(hbox, {}, editorLoaded);
+}
+
+function editorLoaded()
+{
+  let text = "BrowserBug - 725388";
+  editor.setText(text);
+
+  let target = editor.editorElement;
+  let targetWin = target.ownerDocument.defaultView;
+
+  let mMoveHandler = function(aEvent) {
+    editor.removeEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
+
+    is(aEvent.event.type, "mousemove", "MouseMove event fired.");
+
+    editor.addEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
+    waitForFocus(function() {
+      EventUtils.synthesizeMouse(target, 10, 10, {type: "mouseover"},
+                                 targetWin);
+    });
+  };
+
+  let mOverHandler = function(aEvent) {
+    editor.removeEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
+
+    is(aEvent.event.type, "mouseover", "MouseOver event fired.");
+
+    editor.addEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
+    waitForFocus(function() {
+      EventUtils.synthesizeMouse(target, -10, -10, {type: "mouseout"},
+                                 targetWin);
+    }, targetWin);
+  };
+
+  let mOutHandler = function(aEvent) {
+    editor.removeEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
+
+    is(aEvent.event.type, "mouseout", "MouseOut event fired.");
+    executeSoon(testEnd);
+  };
+
+  editor.addEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
+
+  editor.focus();
+  waitForFocus(function() {
+  EventUtils.synthesizeMouse(target, 1, 1, {type: "mousemove"},
+                             targetWin);
+  }, targetWin);
+}
+
+function testEnd()
+{
+  if (editor) {
+    editor.destroy();
+  }
+  if (testWin) {
+    testWin.close();
+  }
+  testWin = editor = null;
+
+  waitForFocus(finish, window);
+}
--- a/browser/devtools/styleeditor/StyleEditor.jsm
+++ b/browser/devtools/styleeditor/StyleEditor.jsm
@@ -141,17 +141,17 @@ StyleEditor.prototype = {
 
   /**
    * Retrieve the stylesheet this editor is attached to.
    *
    * @return DOMStyleSheet
    */
   get styleSheet()
   {
-    assert(this._styleSheet, "StyleSheet must be loaded first.")
+    assert(this._styleSheet, "StyleSheet must be loaded first.");
     return this._styleSheet;
   },
 
   /**
    * Retrieve the index (order) of stylesheet in the document.
    *
    * @return number
    */
@@ -916,19 +916,21 @@ StyleEditor.prototype = {
   {
     // insert the origin editor instance as first argument
     if (!aArgs) {
       aArgs = [this];
     } else {
       aArgs.unshift(this);
     }
 
+    // copy the list of listeners to allow adding/removing listeners in handlers
+    let listeners = this._actionListeners.concat();
     // trigger all listeners that have this action handler
-    for (let i = 0; i < this._actionListeners.length; ++i) {
-      let listener = this._actionListeners[i];
+    for (let i = 0; i < listeners.length; ++i) {
+      let listener = listeners[i];
       let actionHandler = listener["on" + aName];
       if (actionHandler) {
         actionHandler.apply(listener, aArgs);
       }
     }
 
     // when a flag got changed, user-facing state need to be persisted
     if (aName == "FlagChange") {
--- a/browser/devtools/styleeditor/StyleEditorChrome.jsm
+++ b/browser/devtools/styleeditor/StyleEditorChrome.jsm
@@ -265,19 +265,21 @@ StyleEditorChrome.prototype = {
   {
     // insert the origin Chrome instance as first argument
     if (!aArgs) {
       aArgs = [this];
     } else {
       aArgs.unshift(this);
     }
 
-    // trigger all listeners that have this named handler
-    for (let i = 0; i < this._listeners.length; ++i) {
-      let listener = this._listeners[i];
+    // copy the list of listeners to allow adding/removing listeners in handlers
+    let listeners = this._listeners.concat();
+    // trigger all listeners that have this named handler.
+    for (let i = 0; i < listeners.length; i++) {
+      let listener = listeners[i];
       let handler = listener["on" + aName];
       if (handler) {
         handler.apply(listener, aArgs);
       }
     }
   },
 
   /**
@@ -324,20 +326,20 @@ StyleEditorChrome.prototype = {
    * Populate the chrome UI according to the content document.
    *
    * @see StyleEditor._setupShadowStyleSheet
    */
   _populateChrome: function SEC__populateChrome()
   {
     this._resetChrome();
 
+    let document = this.contentDocument;
     this._document.title = _("chromeWindowTitle",
-          this.contentDocument.title || this.contentDocument.location.href);
+      document.title || document.location.href);
 
-    let document = this.contentDocument;
     for (let i = 0; i < document.styleSheets.length; ++i) {
       let styleSheet = document.styleSheets[i];
 
       let editor = new StyleEditor(document, styleSheet);
       editor.addActionListener(this);
       this._editors.push(editor);
     }
 
@@ -348,16 +350,89 @@ StyleEditorChrome.prototype = {
     // NOT loaded/ready yet. This also helps responsivity during loading when
     // there are many heavy stylesheets.
     this._editors.forEach(function (aEditor) {
       this._window.setTimeout(aEditor.load.bind(aEditor), 0);
     }, this);
   },
 
   /**
+   * selects a stylesheet and optionally moves the cursor to a selected line
+   *
+   * @param {CSSStyleSheet} [aSheet]
+   *        Stylesheet that should be selected. If a stylesheet is not passed
+   *        and the editor is not initialized we focus the first stylesheet. If
+   *        a stylesheet is not passed and the editor is initialized we ignore
+   *        the call.
+   * @param {Number} [aLine]
+   *        Line to which the caret should be moved (one-indexed).
+   * @param {Number} [aCol]
+   *        Column to which the caret should be moved (one-indexed).
+   */
+  selectStyleSheet: function SEC_selectSheet(aSheet, aLine, aCol)
+  {
+    let select = function DEC_select(aEditor) {
+      let summary = aSheet ? this.getSummaryElementForEditor(aEditor)
+                           : this._view.getSummaryElementByOrdinal(0);
+      let setCaret = false;
+
+      if (aLine || aCol) {
+        aLine = aLine || 1;
+        aCol = aCol || 1;
+        setCaret = true;
+      }
+      if (!aEditor.sourceEditor) {
+        // If a line or column was specified we move the caret appropriately.
+        if (setCaret) {
+          aEditor.addActionListener({
+            onAttach: function SEC_selectSheet_onAttach()
+            {
+              aEditor.removeActionListener(this);
+              aEditor.sourceEditor.setCaretPosition(aLine - 1, aCol - 1);
+            }
+          });
+        }
+        this._view.activeSummary = summary;
+      } else {
+        this._view.activeSummary = summary;
+
+        // If a line or column was specified we move the caret appropriately.
+        if (setCaret) {
+          aEditor.sourceEditor.setCaretPosition(aLine - 1, aCol - 1);
+        }
+      }
+    }.bind(this);
+
+    if (!this.editors.length) {
+      // We are in the main initialization phase so we wait for the editor
+      // containing the target stylesheet to be added and select the target
+      // stylesheet, optionally moving the cursor to a selected line.
+      this.addChromeListener({
+        onEditorAdded: function SEC_selectSheet_onEditorAdded(aChrome, aEditor) {
+          if ((!aSheet && aEditor.styleSheetIndex == 0) ||
+              aEditor.styleSheet == aSheet) {
+            aChrome.removeChromeListener(this);
+            select(aEditor);
+          }
+        }
+      });
+    } else if (aSheet) {
+      // We are already initialized and a stylesheet has been specified. Here
+      // we iterate through the editors and select the one containing the target
+      // stylesheet, optionally moving the cursor to a selected line.
+      for each (let editor in this.editors) {
+        if (editor.styleSheet == aSheet) {
+          select(editor);
+          break;
+        }
+      }
+    }
+  },
+
+  /**
    * Disable all UI, effectively making editors read-only.
    * This is automatically called when no content window is attached.
    *
    * @see contentWindow
    */
   _disableChrome: function SEC__disableChrome()
   {
     let matches = this._root.querySelectorAll("button,toolbarbutton,textbox");
@@ -450,19 +525,18 @@ StyleEditorChrome.prototype = {
 
         aSummary.addEventListener("focus", function onSummaryFocus(aEvent) {
           if (aEvent.target == aSummary) {
             // autofocus the stylesheet name
             aSummary.querySelector(".stylesheet-name").focus();
           }
         }, false);
 
-        // autofocus the first or new stylesheet
-        if (editor.styleSheetIndex == 0 ||
-            editor.hasFlag(StyleEditorFlags.NEW)) {
+        // autofocus new stylesheets
+        if (editor.hasFlag(StyleEditorFlags.NEW)) {
           this._view.activeSummary = aSummary;
         }
 
         this._triggerChromeListeners("EditorAdded", [editor]);
       }.bind(this),
       onHide: function ASV_onItemShow(aSummary, aDetails, aData) {
         aData.editor.onHide();
       },
--- a/browser/devtools/styleeditor/styleeditor.xul
+++ b/browser/devtools/styleeditor/styleeditor.xul
@@ -127,13 +127,15 @@
                data-placeholder="&editorTextbox.placeholder;"/>
     </xul:box>
   </div> <!-- #splitview-templates -->
 </xul:box>   <!-- .splitview-root -->
 
 <xul:script type="application/javascript"><![CDATA[
 Components.utils.import("resource:///modules/devtools/StyleEditorChrome.jsm");
 let chromeRoot = document.getElementById("style-editor-chrome");
-let contentWindow = window.arguments[0];
+let args = window.arguments[0].wrappedJSObject;
+let contentWindow = args.contentWindow;
 let chrome = new StyleEditorChrome(chromeRoot, contentWindow);
+chrome.selectStyleSheet(args.selectedStyleSheet, args.line, args.col);
 window.styleEditorChrome = chrome;
 ]]></xul:script>
 </xul:window>
--- a/browser/devtools/styleeditor/test/Makefile.in
+++ b/browser/devtools/styleeditor/test/Makefile.in
@@ -46,16 +46,17 @@ include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
                  browser_styleeditor_enabled.js \
                  browser_styleeditor_filesave.js \
                  browser_styleeditor_import.js \
                  browser_styleeditor_init.js \
                  browser_styleeditor_loading.js \
                  browser_styleeditor_new.js \
+                 browser_styleeditor_passedinsheet.js \
                  browser_styleeditor_pretty.js \
                  browser_styleeditor_readonly.js \
                  browser_styleeditor_reopen.js \
                  browser_styleeditor_sv_keynav.js \
                  browser_styleeditor_sv_resize.js \
                  four.html \
                  head.js \
                  media.html \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_passedinsheet.js
@@ -0,0 +1,61 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TESTCASE_URI = TEST_BASE + "simple.html";
+const LINE = 6;
+const COL = 2;
+
+let editor = null;
+let sheet = null;
+
+function test()
+{
+  waitForExplicitFinish();
+  gBrowser.selectedBrowser.addEventListener("load", function () {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    run();
+  }, true);
+  content.location = TESTCASE_URI;
+}
+
+function run()
+{
+  sheet = content.document.styleSheets[1];
+  launchStyleEditorChrome(function attachListeners(aChrome) {
+    aChrome.addChromeListener({
+      onEditorAdded: checkSourceEditor
+    });
+  }, sheet, LINE, COL);
+}
+
+function checkSourceEditor(aChrome, aEditor)
+{
+  if (!aEditor.sourceEditor) {
+    aEditor.addActionListener({
+      onAttach: function (aEditor) {
+        aEditor.removeActionListener(this);
+        validate(aEditor);
+      }
+    });
+  } else {
+    validate(aEditor);
+  }
+}
+
+function validate(aEditor)
+{
+  info("validating style editor");
+  let sourceEditor = aEditor.sourceEditor;
+  let caretPosition = sourceEditor.getCaretPosition();
+  is(caretPosition.line, LINE - 1, "caret row is correct"); // index based
+  is(caretPosition.col, COL - 1, "caret column is correct");
+  is(aEditor.styleSheet, sheet, "loaded stylesheet matches document stylesheet");
+  finishUp();
+}
+
+function finishUp()
+{
+  editor = sheet = null;
+  finish();
+}
--- a/browser/devtools/styleeditor/test/head.js
+++ b/browser/devtools/styleeditor/test/head.js
@@ -14,33 +14,33 @@ function cleanup()
     gChromeWindow.close();
     gChromeWindow = null;
   }
   while (gBrowser.tabs.length > 1) {
     gBrowser.removeCurrentTab();
   }
 }
 
-function launchStyleEditorChrome(aCallback)
+function launchStyleEditorChrome(aCallback, aSheet, aLine, aCol)
 {
-  gChromeWindow = StyleEditor.openChrome();
+  gChromeWindow = StyleEditor.openChrome(aSheet, aLine, aCol);
   if (gChromeWindow.document.readyState != "complete") {
     gChromeWindow.addEventListener("load", function onChromeLoad() {
       gChromeWindow.removeEventListener("load", onChromeLoad, true);
       gChromeWindow.styleEditorChrome._alwaysDisableAnimations = true;
       aCallback(gChromeWindow.styleEditorChrome);
     }, true);
   } else {
     gChromeWindow.styleEditorChrome._alwaysDisableAnimations = true;
     aCallback(gChromeWindow.styleEditorChrome);
   }
 }
 
-function addTabAndLaunchStyleEditorChromeWhenLoaded(aCallback)
+function addTabAndLaunchStyleEditorChromeWhenLoaded(aCallback, aSheet, aLine, aCol)
 {
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
     gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
-    launchStyleEditorChrome(aCallback);
+    launchStyleEditorChrome(aCallback, aSheet, aLine, aCol);
   }, true);
 }
 
 registerCleanupFunction(cleanup);
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm
+++ b/browser/devtools/styleinspector/CssHtmlTree.jsm
@@ -268,24 +268,28 @@ CssHtmlTree.prototype = {
    */
   highlight: function CssHtmlTree_highlight(aElement)
   {
     this.viewedElement = aElement;
     this._unmatchedProperties = null;
     this._matchedProperties = null;
 
     if (this.htmlComplete) {
+      this.refreshSourceFilter();
       this.refreshPanel();
     } else {
       if (this._refreshProcess) {
         this._refreshProcess.cancel();
       }
 
       CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
 
+      // Refresh source filter ... this must be done after templateRoot has been
+      // processed.
+      this.refreshSourceFilter();
       this.numVisibleProperties = 0;
       let fragment = this.doc.createDocumentFragment();
       this._refreshProcess = new UpdateProcess(this.win, CssHtmlTree.propertyNames, {
         onItem: function(aPropertyName) {
           // Per-item callback.
           if (this.viewedElement != aElement || !this.styleInspector.isOpen()) {
             return false;
           }
@@ -357,31 +361,38 @@ CssHtmlTree.prototype = {
 
     this._filterChangedTimeout = win.setTimeout(function() {
       this.refreshPanel();
       this._filterChangeTimeout = null;
     }.bind(this), FILTER_CHANGED_TIMEOUT);
   },
 
   /**
-   * The change event handler for the onlyUserStyles checkbox. When
-   * onlyUserStyles.checked is true we do not display properties that have no
-   * matched selectors, and we do not display UA styles. If .checked is false we
-   * do display even properties with no matched selectors, and we include the UA
-   * styles.
+   * The change event handler for the onlyUserStyles checkbox.
    *
    * @param {Event} aEvent the DOM Event object.
    */
   onlyUserStylesChanged: function CssHtmltree_onlyUserStylesChanged(aEvent)
   {
+    this.refreshSourceFilter();
+    this.refreshPanel();
+  },
+
+  /**
+   * When onlyUserStyles.checked is true we only display properties that have
+   * matched selectors and have been included by the document or one of the
+   * document's stylesheets. If .checked is false we display all properties
+   * including those that come from UA stylesheets.
+   */
+  refreshSourceFilter: function CssHtmlTree_setSourceFilter()
+  {
     this._matchedProperties = null;
     this.cssLogic.sourceFilter = this.showOnlyUserStyles ?
                                  CssLogic.FILTER.ALL :
                                  CssLogic.FILTER.UA;
-    this.refreshPanel();
   },
 
   /**
    * The CSS as displayed by the UI.
    */
   createStyleViews: function CssHtmlTree_createStyleViews()
   {
     if (CssHtmlTree.propertyNames) {
@@ -969,9 +980,29 @@ SelectorView.prototype = {
           this.tree.styleInspector.selectFromPath(source);
           aEvent.preventDefault();
         }.bind(this), false);
       result += ".style";
     }
 
     return result;
   },
+
+  /**
+   * When a css link is clicked this method is called in order to either:
+   *   1. Open the link in view source (for element style attributes).
+   *   2. Open the link in the style editor.
+   *
+   * @param aEvent The click event
+   */
+  openStyleEditor: function(aEvent)
+  {
+    if (this.selectorInfo.selector._cssRule._cssSheet) {
+      let styleSheet = this.selectorInfo.selector._cssRule._cssSheet.domSheet;
+      let line = this.selectorInfo.ruleLine;
+
+      this.tree.win.StyleEditor.openChrome(styleSheet, line);
+    } else {
+      let href = this.selectorInfo.sourceElement.ownerDocument.location.href;
+      this.tree.win.openUILinkIn("view-source:" + href, "window");
+    }
+  },
 };
--- a/browser/devtools/styleinspector/CssLogic.jsm
+++ b/browser/devtools/styleinspector/CssLogic.jsm
@@ -227,17 +227,17 @@ CssLogic.prototype = {
     let oldValue = this._sourceFilter;
     this._sourceFilter = aValue;
 
     let ruleCount = 0;
 
     // Update the CssSheet objects.
     this.forEachSheet(function(aSheet) {
       aSheet._sheetAllowed = -1;
-      if (!aSheet.systemSheet && aSheet.sheetAllowed) {
+      if (aSheet.contentSheet && aSheet.sheetAllowed) {
         ruleCount += aSheet.ruleCount;
       }
     }, this);
 
     this._ruleCount = ruleCount;
 
     // Full update is needed because the this.processMatchedSelectors() method
     // skips UA stylesheets if the filter does not allow such sheets.
@@ -340,17 +340,17 @@ CssLogic.prototype = {
   get sheets()
   {
     if (!this._sheetsCached) {
       this._cacheSheets();
     }
 
     let sheets = [];
     this.forEachSheet(function (aSheet) {
-      if (!aSheet.systemSheet) {
+      if (aSheet.contentSheet) {
         sheets.push(aSheet);
       }
     }, this);
 
     return sheets;
   },
 
   /**
@@ -390,17 +390,17 @@ CssLogic.prototype = {
     }
 
     if (!sheetFound) {
       if (!(cacheId in this._sheets)) {
         this._sheets[cacheId] = [];
       }
 
       sheet = new CssSheet(this, aDomSheet, aIndex);
-      if (sheet.sheetAllowed && !sheet.systemSheet) {
+      if (sheet.sheetAllowed && sheet.contentSheet) {
         this._ruleCount += sheet.ruleCount;
       }
 
       this._sheets[cacheId].push(sheet);
     }
 
     return sheet;
   },
@@ -564,17 +564,17 @@ CssLogic.prototype = {
     if (!this._matchedSelectors) {
       this.processMatchedSelectors();
     }
 
     this._unmatchedSelectors = [];
 
     this.forEachSheet(function (aSheet) {
       // We do not show unmatched selectors from system stylesheets
-      if (aSheet.systemSheet || aSheet.disabled || !aSheet.mediaMatches) {
+      if (!aSheet.contentSheet || aSheet.disabled || !aSheet.mediaMatches) {
         return;
       }
 
       aSheet.forEachRule(function (aRule) {
         aRule.selectors.forEach(function (aSelector) {
           if (aSelector._matchId !== this._matchId) {
             this._unmatchedSelectors.push(aSelector);
             if (aCallback) {
@@ -659,17 +659,17 @@ CssLogic.prototype = {
         }
 
         let sheet = this.getSheet(domRule.parentStyleSheet, -1);
         if (sheet._passId !== this._passId) {
           sheet.index = sheetIndex++;
           sheet._passId = this._passId;
         }
 
-        if (filter !== CssLogic.FILTER.UA && sheet.systemSheet) {
+        if (filter === CssLogic.FILTER.ALL && !sheet.contentSheet) {
           continue;
         }
 
         let rule = sheet.getRule(domRule);
         if (rule._passId === this._passId) {
           continue;
         }
 
@@ -705,17 +705,17 @@ CssLogic.prototype = {
   {
     if (!this._matchedRules) {
       this._buildMatchedRules();
     }
 
     let result = {};
 
     this.forSomeSheets(function (aSheet) {
-      if (aSheet.systemSheet || aSheet.disabled || !aSheet.mediaMatches) {
+      if (!aSheet.contentSheet || aSheet.disabled || !aSheet.mediaMatches) {
         return false;
       }
 
       return aSheet.forSomeRules(function (aRule) {
         let unmatched = aRule._matchId !== this._matchId ||
                         this._ruleHasUnmatchedSelector(aRule);
         if (!unmatched) {
           return false;
@@ -860,39 +860,33 @@ CssLogic.getShortNamePath = function Css
  * @returns A localized version of the given key.
  */
 CssLogic.l10n = function(aName) CssLogic._strings.GetStringFromName(aName);
 
 XPCOMUtils.defineLazyGetter(CssLogic, "_strings", function() Services.strings
         .createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
 
 /**
- * Is the given property sheet a system (user agent) stylesheet?
+ * Is the given property sheet a content stylesheet?
  *
  * @param {CSSStyleSheet} aSheet a stylesheet
- * @return {boolean} true if the given stylesheet is a system stylesheet or
+ * @return {boolean} true if the given stylesheet is a content stylesheet,
  * false otherwise.
  */
-CssLogic.isSystemStyleSheet = function CssLogic_isSystemStyleSheet(aSheet)
+CssLogic.isContentStylesheet = function CssLogic_isContentStylesheet(aSheet)
 {
-  if (!aSheet) {
+  // All sheets with owner nodes have been included by content.
+  if (aSheet.ownerNode) {
     return true;
   }
 
-  let url = aSheet.href;
-
-  if (!url) return false;
-  if (url.length === 0) return true;
-
-  // Check for http[s]
-  if (url[0] === 'h') return false;
-  if (url.substr(0, 9) === "resource:") return true;
-  if (url.substr(0, 7) === "chrome:") return true;
-  if (url === "XPCSafeJSObjectWrapper.cpp") return true;
-  if (url.substr(0, 6) === "about:") return true;
+  // If the sheet has a CSSImportRule we need to check the parent stylesheet.
+  if (aSheet.ownerRule instanceof Ci.nsIDOMCSSImportRule) {
+    return CssLogic.isContentStylesheet(aSheet.parentStyleSheet);
+  }
 
   return false;
 };
 
 /**
  * Return a shortened version of a style sheet's source.
  *
  * @param {CSSStyleSheet} aSheet the DOM object for the style sheet.
@@ -937,17 +931,17 @@ CssLogic.shortSource = function CssLogic
  * @param {CSSStyleSheet} aDomSheet reference to a DOM CSSStyleSheet object.
  * @param {number} aIndex tells the index/position of the stylesheet within the
  * main document.
  */
 function CssSheet(aCssLogic, aDomSheet, aIndex)
 {
   this._cssLogic = aCssLogic;
   this.domSheet = aDomSheet;
-  this.index = this.systemSheet ? -100 * aIndex : aIndex;
+  this.index = this.contentSheet ? aIndex : -100 * aIndex;
 
   // Cache of the sheets href. Cached by the getter.
   this._href = null;
   // Short version of href for use in select boxes etc. Cached by getter.
   this._shortSource = null;
 
   // null for uncached.
   this._sheetAllowed = null;
@@ -955,31 +949,31 @@ function CssSheet(aCssLogic, aDomSheet, 
   // Cached CssRules from the given stylesheet.
   this._rules = {};
 
   this._ruleCount = -1;
 }
 
 CssSheet.prototype = {
   _passId: null,
-  _systemSheet: null,
+  _contentSheet: null,
   _mediaMatches: null,
 
   /**
    * Tells if the stylesheet is provided by the browser or not.
    *
-   * @return {boolean} true if this is a browser-provided stylesheet, or false
+   * @return {boolean} false if this is a browser-provided stylesheet, or true
    * otherwise.
    */
-  get systemSheet()
+  get contentSheet()
   {
-    if (this._systemSheet === null) {
-      this._systemSheet = CssLogic.isSystemStyleSheet(this.domSheet);
+    if (this._contentSheet === null) {
+      this._contentSheet = CssLogic.isContentStylesheet(this.domSheet);
     }
-    return this._systemSheet;
+    return this._contentSheet;
   },
 
   /**
    * Tells if the stylesheet is disabled or not.
    * @return {boolean} true if this stylesheet is disabled, or false otherwise.
    */
   get disabled()
   {
@@ -1043,17 +1037,17 @@ CssSheet.prototype = {
   {
     if (this._sheetAllowed !== null) {
       return this._sheetAllowed;
     }
 
     this._sheetAllowed = true;
 
     let filter = this._cssLogic.sourceFilter;
-    if (filter === CssLogic.FILTER.ALL && this.systemSheet) {
+    if (filter === CssLogic.FILTER.ALL && !this.contentSheet) {
       this._sheetAllowed = false;
     }
     if (filter !== CssLogic.FILTER.ALL && filter !== CssLogic.FILTER.UA) {
       this._sheetAllowed = (filter === this.href);
     }
 
     return this._sheetAllowed;
   },
@@ -1197,23 +1191,23 @@ function CssRule(aCssSheet, aDomRule, aE
   this._domRule = aDomRule;
 
   if (this._cssSheet) {
     // parse _domRule.selectorText on call to this.selectors
     this._selectors = null;
     this.line = this._cssSheet._cssLogic.domUtils.getRuleLine(this._domRule);
     this.source = this._cssSheet.shortSource + ":" + this.line;
     this.href = this._cssSheet.href;
-    this.systemRule = this._cssSheet.systemSheet;
+    this.contentRule = this._cssSheet.contentSheet;
   } else if (aElement) {
     this._selectors = [ new CssSelector(this, "@element.style") ];
     this.line = -1;
     this.source = CssLogic.l10n("rule.sourceElement");
     this.href = "#";
-    this.systemRule = false;
+    this.contentRule = true;
     this.sourceElement = aElement;
   }
 }
 
 CssRule.prototype = {
   _passId: null,
 
   /**
@@ -1391,22 +1385,22 @@ CssSelector.prototype = {
   get href()
   {
     return this._cssRule.href;
   },
 
   /**
    * Check if the selector comes from a browser-provided stylesheet.
    *
-   * @return {boolean} true if the selector comes from a browser-provided
+   * @return {boolean} true if the selector comes from a content-provided
    * stylesheet, or false otherwise.
    */
-  get systemRule()
+  get contentRule()
   {
-    return this._cssRule.systemRule;
+    return this._cssRule.contentRule;
   },
 
   /**
    * Check if the parent stylesheet is allowed by the CssLogic.sourceFilter.
    *
    * @return {boolean} true if the parent stylesheet is allowed by the current
    * sourceFilter, or false otherwise.
    */
@@ -1789,22 +1783,22 @@ function CssSelectorInfo(aSelector, aPro
   /* Score prefix:
   0 UA normal property
   1 UA important property
   2 normal property
   3 inline (element.style)
   4 important
   5 inline important
   */
-  let scorePrefix = this.systemRule ? 0 : 2;
+  let scorePrefix = this.contentRule ? 2 : 0;
   if (this.elementStyle) {
     scorePrefix++;
   }
   if (this.important) {
-    scorePrefix += this.systemRule ? 1 : 2;
+    scorePrefix += this.contentRule ? 2 : 1;
   }
 
   this.specificityScore = "" + scorePrefix + this.specificity.ids +
       this.specificity.classes + this.specificity.tags;
 }
 
 CssSelectorInfo.prototype = {
   /**
@@ -1897,32 +1891,32 @@ CssSelectorInfo.prototype = {
   },
 
   /**
    * Check if the selector comes from a browser-provided stylesheet.
    *
    * @return {boolean} true if the selector comes from a browser-provided
    * stylesheet, or false otherwise.
    */
-  get systemRule()
+  get contentRule()
   {
-    return this.selector.systemRule;
+    return this.selector.contentRule;
   },
 
   /**
    * Compare the current CssSelectorInfo instance to another instance, based on
    * specificity information.
    *
    * @param {CssSelectorInfo} aThat The instance to compare ourselves against.
    * @return number -1, 0, 1 depending on how aThat compares with this.
    */
   compareTo: function CssSelectorInfo_compareTo(aThat)
   {
-    if (this.systemRule && !aThat.systemRule) return 1;
-    if (!this.systemRule && aThat.systemRule) return -1;
+    if (!this.contentRule && aThat.contentRule) return 1;
+    if (this.contentRule && !aThat.contentRule) return -1;
 
     if (this.elementStyle && !aThat.elementStyle) {
       if (!this.important && aThat.important) return 1;
       else return -1;
     }
 
     if (!this.elementStyle && aThat.elementStyle) {
       if (this.important && !aThat.important) return -1;
--- a/browser/devtools/styleinspector/CssRuleView.jsm
+++ b/browser/devtools/styleinspector/CssRuleView.jsm
@@ -33,17 +33,17 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-"use strict"
+"use strict";
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
@@ -176,18 +176,18 @@ ElementStyle.prototype = {
     var domRules = this.domUtils.getCSSStyleRules(aElement);
 
     // getCSStyleRules returns ordered from least-specific to
     // most-specific.
     for (let i = domRules.Count() - 1; i >= 0; i--) {
       let domRule = domRules.GetElementAt(i);
 
       // XXX: Optionally provide access to system sheets.
-      let systemSheet = CssLogic.isSystemStyleSheet(domRule.parentStyleSheet);
-      if (systemSheet) {
+      let contentSheet = CssLogic.isContentStylesheet(domRule.parentStyleSheet);
+      if (!contentSheet) {
         continue;
       }
 
       if (domRule.type !== Ci.nsIDOMCSSRule.STYLE_RULE) {
         continue;
       }
 
       this._maybeAddRule({
@@ -319,17 +319,17 @@ ElementStyle.prototype = {
       dirty = computedProp._overriddenDirty || dirty;
       delete computedProp._overriddenDirty;
     }
 
     dirty = (!!aProp.overridden != overridden) || dirty;
     aProp.overridden = overridden;
     return dirty;
   }
-}
+};
 
 /**
  * A single style rule or declaration.
  *
  * @param {ElementStyle} aElementStyle
  *        The ElementStyle to which this rule belongs.
  * @param {object} aOptions
  *        The information used to construct this rule.  Properties include:
@@ -353,37 +353,55 @@ function Rule(aElementStyle, aOptions)
 }
 
 Rule.prototype = {
   get title()
   {
     if (this._title) {
       return this._title;
     }
-    let sheet = this.domRule ? this.domRule.parentStyleSheet : null;
-    this._title = CssLogic.shortSource(sheet);
+    this._title = CssLogic.shortSource(this.sheet);
     if (this.domRule) {
-      let line = this.elementStyle.domUtils.getRuleLine(this.domRule);
-      this._title += ":" + line;
+      this._title += ":" + this.ruleLine;
     }
 
     if (this.inherited) {
       let eltText = this.inherited.tagName.toLowerCase();
       if (this.inherited.id) {
         eltText += "#" + this.inherited.id;
       }
       let args = [eltText, this._title];
       this._title = CssLogic._strings.formatStringFromName("rule.inheritedSource",
                                                            args, args.length);
     }
 
     return this._title;
   },
 
   /**
+   * The rule's stylesheet.
+   */
+  get sheet()
+  {
+    return this.domRule ? this.domRule.parentStyleSheet : null;
+  },
+
+  /**
+   * The rule's line within a stylesheet
+   */
+  get ruleLine()
+  {
+    if (!this.sheet) {
+      // No stylesheet, no ruleLine
+      return null;
+    }
+    return this.elementStyle.domUtils.getRuleLine(this.domRule);
+  },
+
+  /**
    * Create a new TextProperty to include in the rule.
    *
    * @param {string} aName
    *        The text property name (such as "background" or "border-top").
    * @param {string} aValue
    *        The property's value (not including priority).
    * @param {string} aPriority
    *        The property's priority (either "important" or an empty string).
@@ -525,17 +543,17 @@ Rule.prototype = {
 
     for each (let prop in disabledProps) {
       let textProp = new TextProperty(this, prop.name,
                                       prop.value, prop.priority);
       textProp.enabled = false;
       this.textProps.push(textProp);
     }
   },
-}
+};
 
 /**
  * A single property in a rule's cssText.
  *
  * @param {Rule} aRule
  *        The rule this TextProperty came from.
  * @param {string} aName
  *        The text property name (such as "background" or "border-top").
@@ -613,17 +631,17 @@ TextProperty.prototype = {
     this.rule.setPropertyEnabled(this, aValue);
     this.updateEditor();
   },
 
   remove: function TextProperty_remove()
   {
     this.rule.removeProperty(this);
   }
-}
+};
 
 
 /**
  * View hierarchy mostly follows the model hierarchy.
  *
  * CssRuleView:
  *   Owns an ElementStyle and creates a list of RuleEditors for its
  *    Rules.
@@ -638,29 +656,28 @@ TextProperty.prototype = {
  *   Can mark a property disabled or enabled.
  */
 
 /**
  * CssRuleView is a view of the style rules and declarations that
  * apply to a given element.  After construction, the 'element'
  * property will be available with the user interface.
  *
- * @param Document aDocument
+ * @param Document aDoc
  *        The document that will contain the rule view.
  * @param object aStore
  *        The CSS rule view can use this object to store metadata
  *        that might outlast the rule view, particularly the current
  *        set of disabled properties.
  * @constructor
  */
 function CssRuleView(aDoc, aStore)
 {
   this.doc = aDoc;
   this.store = aStore;
-
   this.element = this.doc.createElementNS(XUL_NS, "vbox");
   this.element.setAttribute("tabindex", "0");
   this.element.classList.add("ruleview");
   this.element.flex = 1;
 }
 
 CssRuleView.prototype = {
   // The element that we're inspecting.
@@ -763,16 +780,24 @@ RuleEditor.prototype = {
     // span to be placed absolutely against.
     this.element.style.position = "relative";
 
     // Add the source link.
     let source = createChild(this.element, "div", {
       class: "ruleview-rule-source",
       textContent: this.rule.title
     });
+    source.addEventListener("click", function() {
+      let rule = this.rule;
+      let evt = this.doc.createEvent("CustomEvent");
+      evt.initCustomEvent("CssRuleViewCSSLinkClicked", true, false, {
+        rule: rule,
+      });
+      this.element.dispatchEvent(evt);
+    }.bind(this));
 
     let code = createChild(this.element, "div", {
       class: "ruleview-code"
     });
 
     let header = createChild(code, "div", {});
 
     let selectors = createChild(header, "span", {
@@ -1089,18 +1114,16 @@ TextPropertyEditor.prototype = {
    *
    * @param {string} aValue
    *        The value from the text editor.
    * @return an object with 'value' and 'priority' properties.
    */
   _parseValue: function TextPropertyEditor_parseValue(aValue)
   {
     let pieces = aValue.split("!", 2);
-    let value = pieces[0];
-    let priority = pieces.length > 1 ? pieces[1] : "";
     return {
       value: pieces[0].trim(),
       priority: (pieces.length > 1 ? pieces[1].trim() : "")
     };
   },
 
   /**
    * Called when a value editor closes.  If the user pressed escape,
--- a/browser/devtools/styleinspector/csshtmltree.xul
+++ b/browser/devtools/styleinspector/csshtmltree.xul
@@ -109,17 +109,17 @@ To visually debug the templates without 
   <div id="templateMatchedSelectors">
     <table>
       <loop foreach="selector in ${matchedSelectorViews}">
         <tr>
           <td dir="ltr" class="rule-text ${selector.statusClass}">
             ${selector.humanReadableText(__element)}
           </td>
           <td class="rule-link">
-            <a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
+            <a target="_blank" onclick="${selector.openStyleEditor}" class="link"
                title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
           </td>
         </tr>
       </loop>
     </table>
   </div>
 </div>
 
--- a/browser/devtools/styleinspector/test/Makefile.in
+++ b/browser/devtools/styleinspector/test/Makefile.in
@@ -54,20 +54,28 @@ include $(topsrcdir)/config/rules.mk
   browser_styleinspector_bug_689759_no_results_placeholder.js \
   browser_bug_692400_element_style.js \
   browser_csslogic_inherited.js \
   browser_ruleview_editor.js \
   browser_ruleview_inherit.js \
   browser_ruleview_manipulation.js \
   browser_ruleview_override.js \
   browser_ruleview_ui.js \
+  browser_bug705707_is_content_stylesheet.js \
   head.js \
   $(NULL)
 
 _BROWSER_TEST_PAGES = \
   browser_bug683672.html \
+  browser_bug705707_is_content_stylesheet.html \
+  browser_bug705707_is_content_stylesheet_imported.css \
+  browser_bug705707_is_content_stylesheet_imported2.css \
+  browser_bug705707_is_content_stylesheet_linked.css \
+  browser_bug705707_is_content_stylesheet_script.css \
+  browser_bug705707_is_content_stylesheet.xul \
+  browser_bug705707_is_content_stylesheet_xul.css \
   $(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
 
 libs:: $(_BROWSER_TEST_PAGES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet.html
@@ -0,0 +1,33 @@
+<html>
+<head>
+  <title>test</title>
+
+  <link href="./browser_bug705707_is_content_stylesheet_linked.css" rel="stylesheet" type="text/css">
+
+  <script>
+    // Load script.css
+    function loadCSS() {
+      var link = document.createElement('link');
+      link.rel = 'stylesheet';
+      link.type = 'text/css';
+      link.href = "./browser_bug705707_is_content_stylesheet_script.css";
+      document.getElementsByTagName('head')[0].appendChild(link);
+    }
+  </script>
+
+  <style>
+    table {
+      border: 1px solid #000;
+    }
+  </style>
+</head>
+<body onload="loadCSS();">
+  <table id="target">
+    <tr>
+      <td>
+        <h3>Simple test</h3>
+      </td>
+    </tr>
+  </table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet.js
@@ -0,0 +1,100 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that the correct stylesheets origins are identified in HTML & XUL
+// stylesheets
+
+let doc;
+
+const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/" +
+                 "test/browser_bug705707_is_content_stylesheet.html";
+const TEST_URI2 = "http://example.com/browser/browser/devtools/styleinspector/" +
+                 "test/browser_bug705707_is_content_stylesheet.xul";
+const XUL_URI = Cc["@mozilla.org/network/io-service;1"]
+                .getService(Ci.nsIIOService)
+                .newURI(TEST_URI2, null, null);
+
+let tempScope = {};
+Cu.import("resource:///modules/devtools/CssLogic.jsm", tempScope);
+let CssLogic = tempScope.CssLogic;
+
+function test()
+{
+  waitForExplicitFinish();
+  addTab(TEST_URI);
+  browser.addEventListener("load", htmlLoaded, true);
+}
+
+function htmlLoaded()
+{
+  browser.removeEventListener("load", htmlLoaded, true);
+  doc = content.document;
+  testFromHTML()
+}
+
+function testFromHTML()
+{
+  let target = doc.querySelector("#target");
+
+  executeSoon(function() {
+    checkSheets(target);
+    gBrowser.removeCurrentTab();
+    openXUL();
+  });
+}
+
+function openXUL()
+{
+  Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
+    .add(XUL_URI, 'allowXULXBL', Ci.nsIPermissionManager.ALLOW_ACTION);
+  addTab(TEST_URI2);
+  browser.addEventListener("load", xulLoaded, true);
+}
+
+function xulLoaded()
+{
+  browser.removeEventListener("load", xulLoaded, true);
+  doc = content.document;
+  testFromXUL()
+}
+
+function testFromXUL()
+{
+  let target = doc.querySelector("#target");
+
+  executeSoon(function() {
+    checkSheets(target);
+    finishUp();
+  });
+}
+
+function checkSheets(aTarget)
+{
+  let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
+      .getService(Ci.inIDOMUtils);
+  let domRules = domUtils.getCSSStyleRules(aTarget);
+
+  for (let i = 0, n = domRules.Count(); i < n; i++) {
+    let domRule = domRules.GetElementAt(i);
+    let sheet = domRule.parentStyleSheet;
+    let isContentSheet = CssLogic.isContentStylesheet(sheet);
+
+    if (!sheet.href ||
+        /browser_bug705707_is_content_stylesheet_/.test(sheet.href)) {
+      ok(isContentSheet, sheet.href + " identified as content stylesheet");
+    } else {
+      ok(!isContentSheet, sheet.href + " identified as non-content stylesheet");
+    }
+  }
+}
+
+function finishUp()
+{
+  info("finishing up");
+  Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
+    .add(XUL_URI, 'allowXULXBL', Ci.nsIPermissionManager.DENY_ACTION);
+  doc = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet.xul
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
+<?xml-stylesheet href="./browser_bug705707_is_content_stylesheet_xul.css"
+                 type="text/css"?>
+<!DOCTYPE window>
+<window id="testwindow" xmlns:html="http://www.w3.org/1999/xhtml"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <label id="target" value="Simple XUL document" />
+</window>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet_imported.css
@@ -0,0 +1,5 @@
+@import url("./browser_bug705707_is_content_stylesheet_imported2.css");
+
+#target {
+  text-decoration: underline;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet_imported2.css
@@ -0,0 +1,3 @@
+#target {
+  text-decoration: underline;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet_linked.css
@@ -0,0 +1,3 @@
+table  {
+  border-collapse: collapse;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet_script.css
@@ -0,0 +1,5 @@
+@import url("./browser_bug705707_is_content_stylesheet_imported.css");
+
+table  {
+  opacity: 1;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet_xul.css
@@ -0,0 +1,3 @@
+#target {
+  font-size: 200px;
+}
--- a/browser/devtools/webconsole/GcliCommands.jsm
+++ b/browser/devtools/webconsole/GcliCommands.jsm
@@ -121,16 +121,50 @@ gcli.addCommand({
     }
   ],
   exec: function Command_inspect(args, context) {
     let document = context.environment.chromeDocument;
     document.defaultView.InspectorUI.openInspectorUI(args.node);
   }
 });
 
+/**
+ * 'edit' command
+ */
+gcli.addCommand({
+  name: "edit",
+  description: gcli.lookup("editDesc"),
+  manual: gcli.lookup("editManual"),
+  params: [
+     {
+       name: 'resource',
+       type: {
+         name: 'resource',
+         include: 'text/css'
+       },
+       description: gcli.lookup("editResourceDesc")
+     },
+     {
+       name: "line",
+       defaultValue: 1,
+       type: {
+         name: "number",
+         min: 1,
+         step: 10
+       },
+       description: gcli.lookup("editLineToJumpToDesc")
+     }
+   ],
+   exec: function(args, context) {
+     let hud = HUDService.getHudReferenceById(context.environment.hudId);
+     let StyleEditor = hud.gcliterm.document.defaultView.StyleEditor;
+     StyleEditor.openChrome(args.resource.element, args.line);
+   }
+});
+
 let breakpoints = [];
 
 /**
  * 'break' command
  */
 gcli.addCommand({
   name: "break",
   description: gcli.lookup("breakDesc"),
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -145,19 +145,16 @@
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_base.xpt
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/dom_telephony.xpt
 @BINPATH@/components/dom_wifi.xpt
 @BINPATH@/components/dom_system_b2g.xpt
 #endif
 @BINPATH@/components/dom_battery.xpt
-#ifdef MOZ_B2G_BT
-@BINPATH@/components/dom_bluetooth.xpt
-#endif
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
--- a/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
@@ -124,8 +124,28 @@ breakdelBreakidDesc=Index of breakpoint
 # LOCALIZATION NOTE (breakdelRemoved) Used in the output of the 'break del'
 # command to explain that a breakpoint was removed.
 breakdelRemoved=Breakpoint removed
 
 # LOCALIZATION NOTE (consolecloseDesc) A very short description of the
 # 'console close' command. This string is designed to be shown in a menu
 # alongside the command name, which is why it should be as short as possible.
 consolecloseDesc=Close the console
+
+# LOCALIZATION NOTE (editDesc) A very short description of the 'edit'
+# command. See editManual for a fuller description of what it does. This
+# string is designed to be shown in a menu alongside the command name, which
+# is why it should be as short as possible.
+editDesc=Tweak a page resource
+
+# LOCALIZATION NOTE (editManual) A fuller description of the 'edit' command,
+# displayed when the user asks for help on what it does.
+editManual=Edit one of the resources that is part of this page (or maybe any generic web resource?)
+
+# LOCALIZATION NOTE (editResourceDesc) A very short string to describe the
+# 'resource' parameter to the 'edit' command, which is displayed in a dialog
+# when the user is using this command.
+editResourceDesc=URL to edit
+
+# LOCALIZATION NOTE (editLineToJumpToDesc) A very short string to describe the
+# 'line' parameter to the 'edit' command, which is displayed in a dialog
+# when the user is using this command.
+editLineToJumpToDesc=Line to jump to
--- a/browser/makefiles.sh
+++ b/browser/makefiles.sh
@@ -83,16 +83,22 @@ browser/fuel/public/Makefile
 browser/fuel/src/Makefile
 browser/installer/Makefile
 browser/locales/Makefile
 browser/modules/Makefile
 browser/themes/Makefile
 $MOZ_BRANDING_DIRECTORY/Makefile
 $MOZ_BRANDING_DIRECTORY/content/Makefile
 $MOZ_BRANDING_DIRECTORY/locales/Makefile
+toolkit/locales/Makefile
+extensions/spellcheck/locales/Makefile
+intl/locales/Makefile
+netwerk/locales/Makefile
+dom/locales/Makefile
+security/manager/locales/Makefile
 "
 
 if [ "$MOZ_SAFE_BROWSING" ]; then
   add_makefiles "
     browser/components/safebrowsing/Makefile
   "
 fi
 
--- a/browser/themes/gnomestripe/devtools/csshtmltree.css
+++ b/browser/themes/gnomestripe/devtools/csshtmltree.css
@@ -63,16 +63,19 @@
   color: #0091ff;
 }
 .link,
 .helplink,
 .link:visited,
 .helplink:visited {
   text-decoration: none;
 }
+.link:hover {
+  text-decoration: underline;
+}
 
 .helplink {
   display: block;
   height: 14px;
   width: 0;
   overflow: hidden;
   -moz-padding-start: 14px;
   background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
@@ -130,16 +133,17 @@
 .property-view-hidden,
 .property-content-hidden {
   display: none;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
+  cursor: pointer;
 }
 
 /* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
 .rule-text {
   direction: ltr;
   padding: 0;
   -moz-padding-start: 20px;
 }
@@ -195,17 +199,23 @@
  */
 
 .ruleview {
   background-color: #FFF;
 }
 
 .ruleview-rule-source {
   background-color: -moz-dialog;
+  color: #0091ff;
   padding: 2px 5px;
+  cursor: pointer;
+}
+
+.ruleview-rule-source:hover {
+  text-decoration: underline;
 }
 
 .ruleview-code {
   padding: 2px 5px;
 }
 
 .ruleview-ruleopen {
   -moz-padding-end: 5px;
--- a/browser/themes/pinstripe/devtools/csshtmltree.css
+++ b/browser/themes/pinstripe/devtools/csshtmltree.css
@@ -63,16 +63,19 @@
   color: #0091ff;
 }
 .link,
 .helplink,
 .link:visited,
 .helplink:visited {
   text-decoration: none;
 }
+.link:hover {
+  text-decoration: underline;
+}
 
 .helplink {
   display: block;
   height: 14px;
   width: 0;
   overflow: hidden;
   -moz-padding-start: 14px;
   background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
@@ -132,16 +135,17 @@
 .property-view-hidden,
 .property-content-hidden {
   display: none;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
+  cursor: pointer;
 }
 
 /* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
 .rule-text {
   direction: ltr;
   padding: 0;
   -moz-padding-start: 20px;
 }
@@ -197,17 +201,23 @@
  */
 
 .ruleview {
   background-color: #FFF;
 }
 
 .ruleview-rule-source {
   background-color: -moz-dialog;
+  color: #0091ff;
   padding: 2px 5px;
+  cursor: pointer;
+}
+
+.ruleview-rule-source:hover {
+  text-decoration: underline;
 }
 
 .ruleview-code {
   padding: 2px 5px;
 }
 
 .ruleview-ruleopen {
   -moz-padding-end: 5px;
--- a/browser/themes/winstripe/devtools/csshtmltree.css
+++ b/browser/themes/winstripe/devtools/csshtmltree.css
@@ -62,16 +62,19 @@
   color: #0091ff;
 }
 .link,
 .helplink,
 .link:visited,
 .helplink:visited {
   text-decoration: none;
 }
+.link:hover {
+  text-decoration: underline;
+}
 
 .helplink {
   display: block;
   height: 14px;
   width: 0;
   overflow: hidden;
   -moz-padding-start: 14px;
   background-image: url("chrome://browser/skin/devtools/goto-mdn.png");
@@ -130,16 +133,17 @@
 .property-view-hidden,
 .property-content-hidden {
   display: none;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
+  cursor: pointer;
 }
 
 /* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
 .rule-text {
   direction: ltr;
   padding: 0;
   -moz-padding-start: 20px;
 }
@@ -195,17 +199,23 @@
  */
 
 .ruleview {
   background-color: #FFF;
 }
 
 .ruleview-rule-source {
   background-color: -moz-dialog;
+  color: #0091ff;
   padding: 2px 5px;
+  cursor: pointer;
+}
+
+.ruleview-rule-source:hover {
+  text-decoration: underline;
 }
 
 .ruleview-code {
   padding: 2px 5px;
 }
 
 .ruleview-ruleopen {
   -moz-padding-end: 5px;
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -79,17 +79,17 @@ endif
 APP_BUILDID := $(shell cat $(DEPTH)/config/buildid)
 APP_INI_DEPS += $(DEPTH)/config/buildid
 
 DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DAPP_BUILDID=$(APP_BUILDID)
 
 DEFINES += -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)"
 APP_INI_DEPS += $(DEPTH)/config/autoconf.mk
 
-MOZ_SOURCE_STAMP ?= $(firstword $(shell hg -R $(topsrcdir)/$(MOZ_BUILD_APP)/.. parent --template="{node|short}\n" 2>/dev/null))
+MOZ_SOURCE_STAMP := $(firstword $(shell cd $(topsrcdir)/$(MOZ_BUILD_APP)/.. && hg parent --template="{node|short}\n" 2>/dev/null))
 ifdef MOZ_SOURCE_STAMP
 DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
 endif
 
 _dollar=$$
 SOURCE_REPO := $(shell cd $(topsrcdir)/$(MOZ_BUILD_APP)/.. && hg showconfig paths.default 2>/dev/null | head -n1 | sed -e "s/^ssh:/http:/" -e "s/\/$(_dollar)//" )
 ifdef SOURCE_REPO
 DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
new file mode 100644
--- /dev/null
+++ b/build/autoconf/compiler-opts.m4
@@ -0,0 +1,13 @@
+dnl Add compiler specific options
+
+AC_DEFUN([MOZ_COMPILER_OPTS],
+[
+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-return-type-c-linkage"
+fi
+])
+
--- a/build/unix/build-toolchain/build-gcc.py
+++ b/build/unix/build-toolchain/build-gcc.py
@@ -1,10 +1,23 @@
 #!/usr/bin/python
 
+# The directories end up in the debug info, so the easy way of getting
+# a reproducible build is to run it in a know absolute directory.
+# We use a directory in /builds/slave because the mozilla infrastructure
+# cleans it up automatically.
+base_dir = "/builds/slave/moz-toolschain"
+
+source_dir = base_dir + "/src"
+build_dir  = base_dir + "/build"
+aux_inst_dir = build_dir + '/aux_inst'
+old_make = aux_inst_dir + '/bin/make'
+
+##############################################
+
 import urllib
 import os
 import os.path
 import shutil
 import tarfile
 import subprocess
 
 def download_uri(uri):
@@ -28,27 +41,31 @@ def run_in(path, args):
     check_run(args)
     os.chdir(d)
 
 def patch(patch, plevel, srcdir):
     patch = os.path.realpath(patch)
     check_run(['patch', '-d', srcdir, '-p%s' % plevel, '-i', patch, '--fuzz=0',
                '-s'])
 
-def build_package(package_source_dir, package_build_dir, configure_args):
+def build_package(package_source_dir, package_build_dir, configure_args,
+                   make = old_make):
     os.mkdir(package_build_dir)
     run_in(package_build_dir,
            ["%s/configure" % package_source_dir] + configure_args)
-    run_in(package_build_dir, ["make", "-j8"])
-    run_in(package_build_dir, ["make", "install"])
+    run_in(package_build_dir, [make, "-j8"])
+    run_in(package_build_dir, [make, "install"])
 
-def build_tar(base_dir, tar_inst_dir):
+def build_aux_tools(base_dir):
+    make_build_dir = base_dir + '/make_build'
+    build_package(make_source_dir, make_build_dir,
+                  ["--prefix=%s" % aux_inst_dir], "make")
     tar_build_dir = base_dir + '/tar_build'
     build_package(tar_source_dir, tar_build_dir,
-                  ["--prefix=%s" % tar_inst_dir])
+                  ["--prefix=%s" % aux_inst_dir])
 
 def with_env(env, f):
     old_env = os.environ.copy()
     os.environ.update(env)
     f()
     os.environ.clear()
     os.environ.update(old_env)
 
@@ -128,94 +145,90 @@ def build_one_stage_aux(stage_dir, is_st
 
 def build_tar_package(tar, name, base, directory):
     name = os.path.realpath(name)
     run_in(base, [tar, "-cf", name, "--mtime=2012-01-01", "--owner=root",
                   directory])
 
 ##############################################
 
-# The directories end up in the debug info, so the easy way of getting
-# a reproducible build is to run it in a know absolute directory.
-# We use a directory in /builds/slave because the mozilla infrastructure
-# cleans it up automatically.
-base_dir = "/builds/slave/moz-toolschain"
-
-source_dir = base_dir + "/src"
-build_dir  = base_dir + "/build"
-
 def build_source_dir(prefix, version):
     return source_dir + '/' + prefix + version
 
 binutils_version = "2.21.1"
-glibc_version = "2.12.2" #FIXME: should probably use 2.5.1
+glibc_version = "2.5.1"
 tar_version = "1.26"
+make_version = "3.81"
 gcc_version = "4.5.2"
 mpfr_version = "2.4.2"
 gmp_version = "5.0.1"
 mpc_version = "0.8.1"
 
 binutils_source_uri = "http://ftp.gnu.org/gnu/binutils/binutils-%sa.tar.bz2" % \
     binutils_version
 glibc_source_uri = "http://ftp.gnu.org/gnu/glibc/glibc-%s.tar.bz2" % \
     glibc_version
 tar_source_uri = "http://ftp.gnu.org/gnu/tar/tar-%s.tar.bz2" % \
     tar_version
+make_source_uri = "http://ftp.gnu.org/gnu/make/make-%s.tar.bz2" % \
+    make_version
 gcc_source_uri = "http://ftp.gnu.org/gnu/gcc/gcc-%s/gcc-%s.tar.bz2" % \
     (gcc_version, gcc_version)
 mpfr_source_uri = "http://www.mpfr.org/mpfr-%s/mpfr-%s.tar.bz2" % \
     (mpfr_version, mpfr_version)
 gmp_source_uri = "http://ftp.gnu.org/gnu/gmp/gmp-%s.tar.bz2" % gmp_version
 mpc_source_uri = "http://www.multiprecision.org/mpc/download/mpc-%s.tar.gz" % \
     mpc_version
 
 binutils_source_tar = download_uri(binutils_source_uri)
 glibc_source_tar = download_uri(glibc_source_uri)
 tar_source_tar = download_uri(tar_source_uri)
+make_source_tar = download_uri(make_source_uri)
 mpc_source_tar = download_uri(mpc_source_uri)
 mpfr_source_tar = download_uri(mpfr_source_uri)
 gmp_source_tar = download_uri(gmp_source_uri)
 gcc_source_tar = download_uri(gcc_source_uri)
 
 binutils_source_dir  = build_source_dir('binutils-', binutils_version)
 glibc_source_dir  = build_source_dir('glibc-', glibc_version)
 tar_source_dir  = build_source_dir('tar-', tar_version)
+make_source_dir  = build_source_dir('make-', make_version)
 mpc_source_dir  = build_source_dir('mpc-', mpc_version)
 mpfr_source_dir = build_source_dir('mpfr-', mpfr_version)
 gmp_source_dir  = build_source_dir('gmp-', gmp_version)
 gcc_source_dir  = build_source_dir('gcc-', gcc_version)
 
 if not os.path.exists(source_dir):
     os.makedirs(source_dir)
     extract(binutils_source_tar, source_dir)
     patch('binutils-deterministic.patch', 1, binutils_source_dir)
     extract(glibc_source_tar, source_dir)
     patch('glibc-deterministic.patch', 1, glibc_source_dir)
     run_in(glibc_source_dir, ["autoconf"])
     extract(tar_source_tar, source_dir)
+    extract(make_source_tar, source_dir)
     extract(mpc_source_tar, source_dir)
     extract(mpfr_source_tar, source_dir)
     extract(gmp_source_tar, source_dir)
     extract(gcc_source_tar, source_dir)
     patch('plugin_finish_decl.diff', 0, gcc_source_dir)
     patch('pr49911.diff', 1, gcc_source_dir)
     patch('r159628-r163231-r171807.patch', 1, gcc_source_dir)
 
 if os.path.exists(build_dir):
     shutil.rmtree(build_dir)
 os.makedirs(build_dir)
 
-tar_inst_dir = build_dir + '/tar_inst'
-build_tar(build_dir, tar_inst_dir)
+build_aux_tools(build_dir)
 
 stage1_dir = build_dir + '/stage1'
 build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True)
 
 stage1_tool_inst_dir = stage1_dir + '/inst'
 stage2_dir = build_dir + '/stage2'
-build_one_stage({"CC"     : stage1_tool_inst_dir + "/bin/gcc",
+build_one_stage({"CC"     : stage1_tool_inst_dir + "/bin/gcc -fgnu89-inline",
                  "CXX"    : stage1_tool_inst_dir + "/bin/g++",
                  "AR"     : stage1_tool_inst_dir + "/bin/ar",
                  "RANLIB" : "true" },
                 stage2_dir, False)
 
-build_tar_package(tar_inst_dir + "/bin/tar",
+build_tar_package(aux_inst_dir + "/bin/tar",
                   "toolchain.tar", stage2_dir, "inst")
--- a/build/unix/build-toolchain/glibc-deterministic.patch
+++ b/build/unix/build-toolchain/glibc-deterministic.patch
@@ -1,36 +1,99 @@
 diff -ru a/configure.in b/configure.in
 --- a/configure.in	2011-01-17 23:34:07.000000000 -0500
 +++ b/configure.in	2012-01-25 20:40:27.919485606 -0500
-@@ -2230,6 +2230,7 @@
+@@ -841,14 +841,6 @@
+ LIBC_PROG_BINUTILS
+ AC_SUBST(MIG)dnl Needed by sysdeps/mach/configure.in
+ 
+-# Accept binutils 2.13 or newer.
+-AC_CHECK_PROG_VER(AS, $AS, --version,
+-		  [GNU assembler.* \([0-9]*\.[0-9.]*\)],
+-		  [2.1[3-9]*], AS=: critic_missing="$critic_missing as")
+-AC_CHECK_PROG_VER(LD, $LD, --version,
+-		  [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)],
+-		  [2.1[3-9]*], LD=: critic_missing="$critic_missing ld")
+-
+ # We need the physical current working directory.  We cannot use the
+ # "pwd -P" shell builtin since that's not portable.  Instead we try to
+ # find a pwd binary.  Note that assigning to the PWD environment
+@@ -2175,6 +2167,7 @@
  fi
  AC_SUBST(old_glibc_headers)
  
 +libc_cv_slibdir=${prefix}/lib64
  AC_SUBST(libc_cv_slibdir)
  AC_SUBST(libc_cv_localedir)
  AC_SUBST(libc_cv_sysconfdir)
 diff -ru a/csu/Makefile b/csu/Makefile
 --- a/csu/Makefile	2011-01-17 23:34:07.000000000 -0500
 +++ b/csu/Makefile	2012-01-23 13:58:28.957792633 -0500
-@@ -234,8 +234,7 @@
+@@ -223,8 +223,7 @@
  		   if [ -z "$$os" ]; then \
  		     os=Linux; \
  		   fi; \
 -		   printf '"Compiled on a %s %s system on %s.\\n"\n' \
 -			  "$$os" "$$version" "`date +%Y-%m-%d`";; \
 +                   ;; \
  	   *) ;; \
  	 esac; \
  	 files="$(all-Banner-files)";				\
+diff -ru a/elf/Makefile b/elf/Makefile
+--- a/elf/Makefile	2008-10-31 16:35:11.000000000 -0400
++++ b/elf/Makefile	2012-02-16 12:20:00.038593752 -0500
+@@ -295,18 +295,11 @@
+ z-now-yes = -Wl,-z,now
+ 
+ $(objpfx)ld.so: $(objpfx)librtld.os $(ld-map)
+-	@rm -f $@.lds
+-	$(LINK.o) -nostdlib -nostartfiles -shared $(z-now-$(bind-now))	\
+-		  $(LDFLAGS-rtld) -Wl,-z,defs -Wl,--verbose 2>&1 |	\
+-		  LC_ALL=C \
+-		  sed -e '/^=========/,/^=========/!d;/^=========/d'	\
+-		      -e 's/\. = 0 + SIZEOF_HEADERS;/& _begin = . - SIZEOF_HEADERS;/' \
+-		  > $@.lds
+ 	$(LINK.o) -nostdlib -nostartfiles -shared -o $@			\
+ 		  $(LDFLAGS-rtld) -Wl,-z,defs $(z-now-$(bind-now))	\
+ 		  $(filter-out $(map-file),$^) $(load-map-file)		\
+-		  -Wl,-soname=$(rtld-installed-name) -T $@.lds
+-	rm -f $@.lds
++		  -Wl,-soname=$(rtld-installed-name)			\
++		  -Wl,-defsym=_begin=0
+ 
+ # interp.c exists just to get this string into the libraries.
+ CFLAGS-interp.c = -D'RUNTIME_LINKER="$(slibdir)/$(rtld-installed-name)"' \
+diff -ru a/localedata/Makefile b/localedata/Makefile
+--- a/localedata/Makefile	2006-04-26 01:14:03.000000000 -0400
++++ b/localedata/Makefile	2012-02-17 10:31:24.592345047 -0500
+@@ -113,7 +113,7 @@
+ 	$(make-target-directory)
+ 	rm -f $(@:.gz=) $@
+ 	$(INSTALL_DATA) $< $(@:.gz=)
+-	gzip -9 $(@:.gz=)
++	gzip -9n $(@:.gz=)
+ 
+ # Install the locale source files in the appropriate directory.
+ $(inst_i18ndir)/locales/%: locales/% $(+force); $(do-install)
+diff -ru a/Makeconfig b/Makeconfig
+--- a/Makeconfig	2006-07-10 17:42:27.000000000 -0400
++++ b/Makeconfig	2012-02-17 08:28:31.859584817 -0500
+@@ -674,7 +674,7 @@
+ 	   $(foreach lib,$(libof-$(basename $(@F))) \
+ 		         $(libof-$(<F)) $(libof-$(@F)),$(CPPFLAGS-$(lib))) \
+ 	   $(CPPFLAGS-$(<F)) $(CPPFLAGS-$(@F)) $(CPPFLAGS-$(basename $(@F)))
+-override CFLAGS	= -std=gnu99 \
++override CFLAGS	= -std=gnu99 -fgnu89-inline \
+ 		  $(filter-out %frame-pointer,$(+cflags)) $(+gccwarn-c) \
+ 		  $(sysdep-CFLAGS) $(CFLAGS-$(suffix $@)) $(CFLAGS-$(<F)) \
+ 		  $(CFLAGS-$(@F))
 diff -ru a/Makerules b/Makerules
 --- a/Makerules	2011-01-17 23:34:07.000000000 -0500
 +++ b/Makerules	2012-01-30 08:47:56.565068903 -0500
-@@ -992,9 +992,9 @@
+@@ -977,9 +977,9 @@
  	 echo '   Use the shared library, but some functions are only in';\
  	 echo '   the static library, so try that secondarily.  */';\
  	 cat $<; \
 -	 echo 'GROUP ( $(slibdir)/libc.so$(libc.so-version)' \
 -	      '$(libdir)/$(patsubst %,$(libtype.oS),$(libprefix)$(libc-name))'\
 -	      ' AS_NEEDED (' $(slibdir)/$(rtld-installed-name) ') )' \
 +	 echo 'GROUP ( libc.so$(libc.so-version)' \
 +	      '$(patsubst %,$(libtype.oS),$(libprefix)$(libc-name))'\
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -52,17 +52,16 @@ MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNA
 MOZ_APP_BASENAME = @MOZ_APP_BASENAME@
 MOZ_APP_VENDOR = @MOZ_APP_VENDOR@
 MOZ_APP_PROFILE = @MOZ_APP_PROFILE@
 MOZ_APP_ID = @MOZ_APP_ID@
 MOZ_PROFILE_MIGRATOR = @MOZ_PROFILE_MIGRATOR@
 MOZ_EXTENSION_MANAGER = @MOZ_EXTENSION_MANAGER@
 MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
 MOZ_APP_VERSION = @MOZ_APP_VERSION@
-MOZ_UA_BUILDID = @MOZ_UA_BUILDID@
 MOZ_MACBUNDLE_NAME = @MOZ_MACBUNDLE_NAME@
 MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@
 
 MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@
 
 prefix		= @prefix@
 exec_prefix	= @exec_prefix@
 bindir		= @bindir@
@@ -176,16 +175,17 @@ VPX_AS_CONVERSION = @VPX_AS_CONVERSION@
 VPX_ASM_SUFFIX = @VPX_ASM_SUFFIX@
 VPX_X86_ASM = @VPX_X86_ASM@
 VPX_ARM_ASM = @VPX_ARM_ASM@
 VPX_NEED_OBJ_INT_EXTRACT = @VPX_NEED_OBJ_INT_EXTRACT@
 LIBJPEG_TURBO_AS = @LIBJPEG_TURBO_AS@
 LIBJPEG_TURBO_ASFLAGS = @LIBJPEG_TURBO_ASFLAGS@
 LIBJPEG_TURBO_X86_ASM = @LIBJPEG_TURBO_X86_ASM@
 LIBJPEG_TURBO_X64_ASM = @LIBJPEG_TURBO_X64_ASM@
+LIBJPEG_TURBO_ARM_ASM = @LIBJPEG_TURBO_ARM_ASM@
 NS_PRINTING = @NS_PRINTING@
 MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@
 MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
 MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@
 MOC = @MOC@
 RCC = @RCC@
 MOZ_NSS_PATCH = @MOZ_NSS_PATCH@
 MOZ_WEBGL = @MOZ_WEBGL@
@@ -288,17 +288,16 @@ MOZ_ENABLE_GNOME_COMPONENT = @MOZ_ENABLE
 MOZ_ENABLE_GIO = @MOZ_ENABLE_GIO@
 MOZ_GIO_CFLAGS = @MOZ_GIO_CFLAGS@
 MOZ_GIO_LIBS = @MOZ_GIO_LIBS@
 
 MOZ_NATIVE_NSPR = @MOZ_NATIVE_NSPR@
 MOZ_NATIVE_NSS = @MOZ_NATIVE_NSS@
 
 MOZ_B2G_RIL = @MOZ_B2G_RIL@
-MOZ_B2G_BT = @MOZ_B2G_BT@
 
 BUILD_CTYPES = @BUILD_CTYPES@
 
 COMPILE_ENVIRONMENT = @COMPILE_ENVIRONMENT@
 CROSS_COMPILE   = @CROSS_COMPILE@
 
 WCHAR_CFLAGS	= @WCHAR_CFLAGS@
 
--- a/config/optimizejars.py
+++ b/config/optimizejars.py
@@ -30,17 +30,17 @@
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
-import sys, os, subprocess, struct
+import sys, os, subprocess, struct, re
 
 local_file_header = [
     ("signature", "uint32"),
     ("min_version", "uint16"),
     ("general_flag", "uint16"),
     ("compression", "uint16"),
     ("lastmod_time", "uint16"),
     ("lastmod_date", "uint16"),
@@ -324,35 +324,37 @@ def optimizejar(jar, outjar, inlog = Non
                               reordered_count, len(central_directory), outjar)
     outfd.close()
     return outlog
         
 if len(sys.argv) != 5:
     print "Usage: --optimize|--deoptimize %s JAR_LOG_DIR IN_JAR_DIR OUT_JAR_DIR" % sys.argv[0]
     exit(1)
 
+jar_regex = re.compile("\\.jar?$")
+
 def optimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR):
     ls = os.listdir(IN_JAR_DIR)
     for jarfile in ls:
-        if not jarfile.endswith(".jar"):
+        if not re.search(jar_regex, jarfile):
             continue
         injarfile = os.path.join(IN_JAR_DIR, jarfile)
         outjarfile = os.path.join(OUT_JAR_DIR, jarfile) 
         logfile = os.path.join(JAR_LOG_DIR, jarfile + ".log")
         if not os.path.isfile(logfile):
             logfile = None
         optimizejar(injarfile, outjarfile, logfile)
 
 def deoptimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR):
     if not os.path.exists(JAR_LOG_DIR):
         os.makedirs(JAR_LOG_DIR)
 
     ls = os.listdir(IN_JAR_DIR)
     for jarfile in ls:
-        if not jarfile.endswith(".jar"):
+        if not re.search(jar_regex, jarfile):
             continue
         injarfile = os.path.join(IN_JAR_DIR, jarfile)
         outjarfile = os.path.join(OUT_JAR_DIR, jarfile) 
         logfile = os.path.join(JAR_LOG_DIR, jarfile + ".log")
         log = optimizejar(injarfile, outjarfile, None)
         open(logfile, "wb").write("\n".join(log))
 
 def main():        
--- a/configure.in
+++ b/configure.in
@@ -3338,16 +3338,17 @@ fi         # GNU_CC
 if test "$SOLARIS_SUNPRO_CC"; then
 VISIBILITY_FLAGS='-xldscope=hidden'
 fi         # Sun Studio on Solaris
 
 AC_SUBST(WRAP_SYSTEM_INCLUDES)
 AC_SUBST(VISIBILITY_FLAGS)
 
 MOZ_GCC_PR49911
+MOZ_COMPILER_OPTS
 
 dnl Check for __force_align_arg_pointer__ for SSE2 on gcc
 dnl ========================================================
 if test "$GNU_CC"; then
   CFLAGS_save="${CFLAGS}"
   CFLAGS="${CFLAGS} -Werror"
   AC_CACHE_CHECK(for __force_align_arg_pointer__ attribute,
                  ac_cv_force_align_arg_pointer,
@@ -4086,16 +4087,66 @@ if test "$ac_cv_thread_keyword" = yes -a
       :
       ;;
     *)
       AC_DEFINE(HAVE_THREAD_TLS_KEYWORD)
       ;;
   esac
 fi
 
+dnl Using the custom linker on ARMv6 requires 16k alignment of ELF segments.
+if test -n "$MOZ_LINKER"; then
+  if test "$CPU_ARCH" = arm; then
+    dnl Determine the target ARM architecture (5 for ARMv5, v5T, v5E, etc.; 6 for ARMv6, v6K, etc.)
+    ARM_ARCH=`${CC-cc} ${CFLAGS} -dM -E - < /dev/null | sed -n 's/.*__ARM_ARCH_\([[0-9]]*\).*/\1/p'`
+    dnl When building for < ARMv7, we need to ensure 16k alignment of ELF segments
+    if test -n "$ARM_ARCH" && test "$ARM_ARCH" -lt 7; then
+      LDFLAGS="$LDFLAGS -Wl,-z,max-page-size=0x4000"
+      _SUBDIR_LDFLAGS="$_SUBDIR_LDFLAGS -Wl,-z,max-page-size=0x4000"
+    fi
+  fi
+fi
+
+dnl The custom linker doesn't support text relocations, but NDK >= r6b
+dnl creates some (http://code.google.com/p/android/issues/detail?id=23203)
+dnl We however want to avoid these text relocations, and this can be done
+dnl by making gcc not link crtbegin and crtend. In the broken NDKs, crtend
+dnl doesn't contain anything at all, beside placeholders for some sections,
+dnl and crtbegin only contains a finalizer function that calls
+dnl __cxa_finalize. The custom linker actually takes care of calling
+dnl __cxa_finalize when the library doesn't call it itself, which makes it
+dnl safe not to link crtbegin. Besides, previous versions of the NDK didn't
+dnl link crtbegin and crtend at all.
+if test -n "$MOZ_LINKER" -a -z "$MOZ_OLD_LINKER" -a "$OS_TARGET" = "Android"; then
+  AC_CACHE_CHECK([whether the CRT objects have text relocations],
+    ac_cv_crt_has_text_relocations,
+    [echo 'int foo() { return 0; }' > conftest.cpp
+     if AC_TRY_COMMAND(${CXX-g++} -o conftest${DLL_SUFFIX} $CXXFLAGS $DSO_LDOPTS $LDFLAGS conftest.cpp $LIBS 1>&5) &&
+        test -s conftest${DLL_SUFFIX}; then
+       if readelf -d conftest${DLL_SUFFIX} | grep TEXTREL > /dev/null; then
+         ac_cv_crt_has_text_relocations=yes
+       else
+         ac_cv_crt_has_text_relocations=no
+       fi
+     else
+       AC_ERROR([couldn't compile a simple C file])
+     fi
+     rm -rf conftest*])
+  if test "$ac_cv_crt_has_text_relocations" = yes; then
+    dnl While we want libraries to skip the CRT files, we don't want
+    dnl executables to be treated the same way. We thus set the flag
+    dnl in DSO_LDOPTS and not LDFLAGS. However, to pass it to nspr,
+    dnl we need to use LDFLAGS because nspr doesn't inherit DSO_LDOPTS.
+    dnl Using LDFLAGS in nspr is safe, since we only really build
+    dnl libraries there.
+    DSO_LDOPTS="$DSO_LDOPTS -nostartfiles"
+    NSPR_LDFLAGS=-nostartfiles
+  fi
+fi
+
 dnl Check for the existence of various allocation headers/functions
 
 MALLOC_H=
 MOZ_CHECK_HEADER(malloc.h,        [MALLOC_H=malloc.h])
 if test "$MALLOC_H" = ""; then
   MOZ_CHECK_HEADER(malloc/malloc.h, [MALLOC_H=malloc/malloc.h])
   if test "$MALLOC_H" = ""; then
     MOZ_CHECK_HEADER(sys/malloc.h,    [MALLOC_H=sys/malloc.h])
@@ -4607,16 +4658,17 @@ VPX_AS_DASH_C_FLAG=
 VPX_AS_CONVERSION=
 VPX_ASM_SUFFIX=
 VPX_X86_ASM=
 VPX_ARM_ASM=
 LIBJPEG_TURBO_AS=
 LIBJPEG_TURBO_ASFLAGS=
 LIBJPEG_TURBO_X86_ASM=
 LIBJPEG_TURBO_X64_ASM=
+LIBJPEG_TURBO_ARM_ASM=
 MOZ_PANGO=1
 MOZ_PERMISSIONS=1
 MOZ_PLACES=1
 MOZ_PREF_EXTENSIONS=1
 MOZ_PROFILELOCKING=1
 MOZ_PSM=1
 MOZ_REFLOW_PERF=
 MOZ_SAFE_BROWSING=
@@ -4922,17 +4974,16 @@ cairo-gonk)
     AC_DEFINE(MOZ_TOUCH)
     MOZ_WIDGET_TOOLKIT=gonk
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS)'
     MOZ_WEBGL=1
     MOZ_PDF_PRINTING=1
     MOZ_B2G_RIL=1
     MOZ_TOUCH=1
-    MOZ_B2G_BT=1
     ;;
 
 esac
 
 AC_SUBST(MOZ_OLD_LINKER)
 AC_SUBST(MOZ_PDF_PRINTING)
 if test "$MOZ_PDF_PRINTING"; then
    PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
@@ -6166,48 +6217,61 @@ if test -n "$MOZ_LIBJPEG_TURBO"; then
   WINNT:x86|WINNT:i?86)
     LIBJPEG_TURBO_ASFLAGS="-f win32 -rnasm -pnasm -DPIC -DWIN32"
     LIBJPEG_TURBO_X86_ASM=1
   ;;
   WINNT:x86_64)
     LIBJPEG_TURBO_ASFLAGS="-f win64 -rnasm -pnasm -D__x86_64__ -DPIC -DWIN64 -DMSVC"
     LIBJPEG_TURBO_X64_ASM=1
   ;;
+  *:arm*)
+    LIBJPEG_TURBO_ASFLAGS="-march=armv7-a -mfpu=neon"
+    LIBJPEG_TURBO_ARM_ASM=1
+  ;;
   esac
 
 fi
 
-dnl If we're on a system which supports libjpeg-turbo's asm routines and
-dnl --disable-libjpeg-turbo wasn't passed, check for yasm, and error out if it
-dnl doesn't exist or we have too old of a version.
+dnl If we're on an x86 or x64 system which supports libjpeg-turbo's asm routines
+dnl and --disable-libjpeg-turbo wasn't passed, check for Yasm, and error out if
+dnl it doesn't exist or we have too old of a version.
 if test -n "$LIBJPEG_TURBO_X86_ASM" -o -n "$LIBJPEG_TURBO_X64_ASM" ; then
-    AC_MSG_CHECKING([for YASM assembler])
+    AC_MSG_CHECKING([for Yasm assembler])
     AC_CHECK_PROGS(LIBJPEG_TURBO_AS, yasm, "")
 
     if test -z "$LIBJPEG_TURBO_AS" ; then
-        AC_MSG_ERROR([yasm is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you do not appear to have yasm installed.  Either install it or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
+        AC_MSG_ERROR([Yasm is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you do not appear to have Yasm installed.  Either install it or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
     fi
 
     dnl Check that we have the right yasm version.  We require 1.0.1 or newer
     dnl on Linux and 1.1 or newer everywhere else.
     if test "$OS_ARCH" = "Linux" ; then
         if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -eq "0" -a "$_YASM_RELEASE" -lt "1" \) ; then
-            AC_MSG_ERROR([yasm 1.0.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.$_YASM_RELEASE.  Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
+            AC_MSG_ERROR([Yasm 1.0.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.$_YASM_RELEASE.  Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
         fi
     else
         if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -lt "1" \) ; then
-            AC_MSG_ERROR([yasm 1.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.  Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
+            AC_MSG_ERROR([Yasm 1.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.  Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
         fi
     fi
 fi
 
+dnl If we're on an ARM system which supports libjpeg-turbo's asm routines and
+dnl --disable-libjpeg-turbo wasn't passed, use the C compiler as the assembler.
+if test -n "$LIBJPEG_TURBO_ARM_ASM" ; then
+    echo "Using $AS as the assembler for ARM code."
+    LIBJPEG_TURBO_AS=$AS
+fi
+
 if test -n "$LIBJPEG_TURBO_X86_ASM"; then
     AC_DEFINE(LIBJPEG_TURBO_X86_ASM)
 elif test -n "$LIBJPEG_TURBO_X64_ASM"; then
     AC_DEFINE(LIBJPEG_TURBO_X64_ASM)
+elif test -n "$LIBJPEG_TURBO_ARM_ASM"; then
+    AC_DEFINE(LIBJPEG_TURBO_ARM_ASM)
 elif test -n "$MOZ_LIBJPEG_TURBO"; then
     dnl Warn if we're not building the optimized routines, even though the user
     dnl didn't specify --disable-libjpeg-turbo.
     AC_MSG_WARN([No assembler or assembly support for libjpeg-turbo.  Using unoptimized C routines.])
 fi
 
 dnl ========================================================
 dnl = Enable compilation of specific extension modules
@@ -7594,28 +7658,16 @@ MOZ_ARG_ENABLE_BOOL(b2g-ril,
     MOZ_B2G_RIL=1,
     MOZ_B2G_RIL= )
 if test -n "$MOZ_B2G_RIL"; then
    AC_DEFINE(MOZ_B2G_RIL)
 fi
 AC_SUBST(MOZ_B2G_RIL)
 
 dnl ========================================================
-dnl = Enable Bluetooth Interface for B2G (Gonk usually)
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(b2g-bt,
-[  --enable-b2g-bt      Set compile flags necessary for compiling Bluetooth API for B2G ],
-    MOZ_B2G_BT=1,
-    MOZ_B2G_BT= )
-if test -n "$MOZ_B2G_BT"; then
-   AC_DEFINE(MOZ_B2G_BT)
-fi
-AC_SUBST(MOZ_B2G_BT)
-
-dnl ========================================================
 dnl = Support for demangling undefined symbols
 dnl ========================================================
 if test -z "$SKIP_LIBRARY_CHECKS"; then
     AC_LANG_SAVE
     AC_LANG_CPLUSPLUS
     AC_CHECK_FUNCS(__cxa_demangle, HAVE_DEMANGLE=1, HAVE_DEMANGLE=)
     AC_LANG_RESTORE
 fi
@@ -8580,18 +8632,16 @@ AC_SUBST(MOZ_PROFILE_MIGRATOR)
 AC_SUBST(MOZ_EXTENSION_MANAGER)
 AC_DEFINE_UNQUOTED(MOZ_APP_UA_NAME, "$MOZ_APP_UA_NAME")
 AC_SUBST(MOZ_APP_UA_NAME)
 AC_DEFINE_UNQUOTED(MOZ_APP_UA_VERSION, "$MOZ_APP_VERSION")
 AC_SUBST(MOZ_APP_VERSION)
 AC_DEFINE_UNQUOTED(MOZ_UA_FIREFOX_VERSION, "$FIREFOX_VERSION")
 AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIREFOX_VERSION)
 AC_SUBST(FIREFOX_VERSION)
-AC_DEFINE_UNQUOTED(MOZ_UA_BUILDID, "$MOZ_UA_BUILDID")
-AC_SUBST(MOZ_UA_BUILDID)
 
 # We can't use the static application.ini data when building against
 # a libxul SDK.
 if test -n "$LIBXUL_SDK"; then
     MOZ_APP_STATIC_INI=
 fi
 AC_SUBST(MOZ_APP_STATIC_INI)
 
@@ -8751,16 +8801,17 @@ AC_SUBST(VPX_ASM_SUFFIX)
 AC_SUBST(VPX_X86_ASM)
 AC_SUBST(VPX_ARM_ASM)
 AC_SUBST(VPX_NEED_OBJ_INT_EXTRACT)
 AC_SUBST(MOZ_INSTRUMENT_EVENT_LOOP)
 AC_SUBST(LIBJPEG_TURBO_AS)
 AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
 AC_SUBST(LIBJPEG_TURBO_X86_ASM)
 AC_SUBST(LIBJPEG_TURBO_X64_ASM)
+AC_SUBST(LIBJPEG_TURBO_ARM_ASM)
 
 AC_MSG_CHECKING([for posix_fallocate])
 AC_TRY_LINK([#define _XOPEN_SOURCE 600
   #include <fcntl.h>],
                  [posix_fallocate(0, 0, 0);],
                  [ac_cv___posix_fallocate=true],
                  [ac_cv___posix_fallocate=false])
 
@@ -9085,17 +9136,21 @@ if test -z "$MOZ_NATIVE_NSPR"; then
         ac_configure_args="$ac_configure_args --with-arm-kuser"
     fi
     if test -n "$MOZ_LINKER" -a -z "$MOZ_OLD_LINKER" -a "$ac_cv_func_dladdr" = no ; then
       # dladdr is supported by the new linker, even when the system linker doesn't
       # support it. Trick nspr into using dladdr when it's not supported.
       _SAVE_CPPFLAGS="$CPPFLAGS"
       export CPPFLAGS="-include $_topsrcdir/mozglue/linker/dladdr.h $CPPFLAGS"
     fi
+    _SAVE_LDFLAGS="$LDFLAGS"
+    export LDFLAGS="$LDFLAGS $NSPR_LDFLAGS"
     AC_OUTPUT_SUBDIRS(nsprpub)
+    unset LDFLAGS
+    LDFLAGS="$_SAVE_LDFLAGS"
     if test -n "$MOZ_LINKER" -a -z "$MOZ_OLD_LINKER" -a "$ac_cv_func_dladdr" = no; then
       unset CPPFLAGS
       CPPFLAGS="$_SAVE_CFLAGS"
     fi
     ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 fi
 
 if test -z "$MOZ_NATIVE_NSPR"; then
--- a/content/base/crashtests/700512-worker.js
+++ b/content/base/crashtests/700512-worker.js
@@ -1,7 +1,7 @@
 onmessage = function(event) {
   var blob = event.data;
 
-  blob.mozSlice(1, 5);
+  blob.slice(1, 5);
 
   postMessage("done");
 }
--- a/content/base/public/nsIDOMFile.idl
+++ b/content/base/public/nsIDOMFile.idl
@@ -66,19 +66,19 @@ interface nsIDOMBlob : nsISupports
   readonly attribute unsigned long long size;
   readonly attribute DOMString type;
 
   [noscript] readonly attribute nsIInputStream internalStream;
   // The caller is responsible for releasing the internalUrl from the
   // blob: protocol handler
   [noscript] DOMString getInternalUrl(in nsIPrincipal principal);
 
-  [optional_argc] nsIDOMBlob mozSlice([optional] in long long start,
-                                      [optional] in long long end,
-                                      [optional] in DOMString contentType);
+  [optional_argc] nsIDOMBlob slice([optional] in long long start,
+                                   [optional] in long long end,
+                                   [optional] in DOMString contentType);
 
   // Get internal id of stored file. Returns -1 if it is not a stored file.
   // Intended only for testing. It can be called on any thread.
   [notxpcom] long long getFileId();
 
   // Called when the blob was successfully stored in a database or when
   // the blob is initialized from a database. It can be called on any thread.
   [notxpcom] void addFileInfo(in FileInfo aFileInfo);
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -43,16 +43,17 @@
 
 // Helper Classes
 #include "nsString.h"
 
 // Interfaces needed to be included
 #include "nsCopySupport.h"
 #include "nsIDOMUIEvent.h"
 #include "nsISelection.h"
+#include "nsISelectionController.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMDragEvent.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMRange.h"
@@ -65,71 +66,41 @@
 #include "nsISupportsPrimitives.h"
 #include "nsServiceManagerUtils.h"
 #include "nsNetUtil.h"
 #include "nsIFile.h"
 #include "nsIWebNavigation.h"
 #include "nsIDocShell.h"
 #include "nsIContent.h"
 #include "nsIImageLoadingContent.h"
+#include "nsITextControlElement.h"
 #include "nsUnicharUtils.h"
 #include "nsIURL.h"
 #include "nsIDocument.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIWebBrowserPersist.h"
 #include "nsEscape.h"
 #include "nsContentUtils.h"
 #include "nsIMIMEService.h"
 #include "imgIContainer.h"
 #include "imgIRequest.h"
 #include "nsDOMDataTransfer.h"
 
-// private clipboard data flavors for html copy, used by editor when pasting
-#define kHTMLContext   "text/_moz_htmlcontext"
-#define kHTMLInfo      "text/_moz_htmlinfo"
-
-// if aNode is null, use the selection from the window
-static nsresult
-GetTransferableForNodeOrSelection(nsIDOMWindow*     aWindow,
-                                  nsIContent*       aNode,
-                                  nsITransferable** aTransferable)
-{
-  NS_ENSURE_ARG_POINTER(aWindow);
-
-  nsCOMPtr<nsIDOMDocument> domDoc;
-  aWindow->GetDocument(getter_AddRefs(domDoc));
-  NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
-  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
-
-  nsresult rv;
-  if (aNode) {
-    rv = nsCopySupport::GetTransferableForNode(aNode, doc, aTransferable);
-  } else {
-    nsCOMPtr<nsISelection> selection;
-    aWindow->GetSelection(getter_AddRefs(selection));
-    rv = nsCopySupport::GetTransferableForSelection(selection, doc,
-                                                    aTransferable);
-  }
-
-  NS_ENSURE_SUCCESS(rv, rv);
-  return rv;
-}
-
 class NS_STACK_CLASS DragDataProducer
 {
 public:
   DragDataProducer(nsIDOMWindow* aWindow,
                    nsIContent* aTarget,
                    nsIContent* aSelectionTargetNode,
                    bool aIsAltKeyPressed);
   nsresult Produce(nsDOMDataTransfer* aDataTransfer,
                    bool* aCanDrag,
-                   bool* aDragSelection,
+                   nsISelection** aSelection,
                    nsIContent** aDragNode);
 
 private:
   void AddString(nsDOMDataTransfer* aDataTransfer,
                  const nsAString& aFlavor,
                  const nsAString& aData,
                  nsIPrincipal* aPrincipal);
   nsresult AddStringsToDataTransfer(nsIContent* aDragNode,
@@ -167,26 +138,26 @@ private:
 
 nsresult
 nsContentAreaDragDrop::GetDragData(nsIDOMWindow* aWindow,
                                    nsIContent* aTarget,
                                    nsIContent* aSelectionTargetNode,
                                    bool aIsAltKeyPressed,
                                    nsDOMDataTransfer* aDataTransfer,
                                    bool* aCanDrag,
-                                   bool* aDragSelection,
+                                   nsISelection** aSelection,
                                    nsIContent** aDragNode)
 {
   NS_ENSURE_TRUE(aSelectionTargetNode, NS_ERROR_INVALID_ARG);
 
   *aCanDrag = true;
 
   DragDataProducer
     provider(aWindow, aTarget, aSelectionTargetNode, aIsAltKeyPressed);
-  return provider.Produce(aDataTransfer, aCanDrag, aDragSelection, aDragNode);
+  return provider.Produce(aDataTransfer, aCanDrag, aSelection, aDragNode);
 }
 
 
 NS_IMPL_ISUPPORTS1(nsContentAreaDragDropDataProvider, nsIFlavorDataProvider)
 
 // SaveURIToFile
 // used on platforms where it's possible to drag items (e.g. images)
 // into the file system
@@ -407,55 +378,94 @@ DragDataProducer::GetNodeString(nsIConte
       range->ToString(outNodeString);
     }
   }
 }
 
 nsresult
 DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
                           bool* aCanDrag,
-                          bool* aDragSelection,
+                          nsISelection** aSelection,
                           nsIContent** aDragNode)
 {
-  NS_PRECONDITION(aCanDrag && aDragSelection && aDataTransfer && aDragNode,
+  NS_PRECONDITION(aCanDrag && aSelection && aDataTransfer && aDragNode,
                   "null pointer passed to Produce");
   NS_ASSERTION(mWindow, "window not set");
   NS_ASSERTION(mSelectionTargetNode, "selection target node should have been set");
 
   *aDragNode = nsnull;
 
   nsresult rv;
   nsIContent* dragNode = nsnull;
-
-  // find the selection to see what we could be dragging and if
-  // what we're dragging is in what is selected.
-  nsCOMPtr<nsISelection> selection;
-  mWindow->GetSelection(getter_AddRefs(selection));
-  if (!selection) {
-    return NS_OK;
-  }
+  *aSelection = nsnull;
 
-  // check if the node is inside a form control. If so, dragging will be
-  // handled in editor code (nsPlaintextDataTransfer::DoDrag). Don't set
-  // aCanDrag to false however, as we still want to allow the drag.
-  nsCOMPtr<nsIContent> findFormNode = mSelectionTargetNode;
-  nsIContent* findFormParent = findFormNode->GetParent();
-  while (findFormParent) {
-    nsCOMPtr<nsIFormControl> form(do_QueryInterface(findFormParent));
-    if (form && !form->AllowDraggableChildren()) {
+  // Find the selection to see what we could be dragging and if what we're
+  // dragging is in what is selected. If this is an editable textbox, use
+  // the textbox's selection, otherwise use the window's selection.
+  nsCOMPtr<nsISelection> selection;
+  nsIContent* editingElement = mSelectionTargetNode->IsEditable() ?
+                               mSelectionTargetNode->GetEditingHost() : nsnull;
+  nsCOMPtr<nsITextControlElement> textControl(do_QueryInterface(editingElement));
+  if (textControl) {
+    nsISelectionController* selcon = textControl->GetSelectionController();
+    if (selcon) {
+      selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
+      if (!selection)
+        return NS_OK;
+    }
+  }
+  else {
+    mWindow->GetSelection(getter_AddRefs(selection));
+    if (!selection)
       return NS_OK;
+
+    // Check if the node is inside a form control. Don't set aCanDrag to false
+    //however, as we still want to allow the drag.
+    nsCOMPtr<nsIContent> findFormNode = mSelectionTargetNode;
+    nsIContent* findFormParent = findFormNode->GetParent();
+    while (findFormParent) {
+      nsCOMPtr<nsIFormControl> form(do_QueryInterface(findFormParent));
+      if (form && !form->AllowDraggableChildren()) {
+        return NS_OK;
+      }
+      findFormParent = findFormParent->GetParent();
     }
-    findFormParent = findFormParent->GetParent();
   }
     
   // if set, serialize the content under this node
   nsCOMPtr<nsIContent> nodeToSerialize;
-  *aDragSelection = false;
+
+  bool isChromeShell = false;
+  nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(mWindow);
+  nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(webnav);
+  if (dsti) {
+    PRInt32 type = -1;
+    if (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
+        type == nsIDocShellTreeItem::typeChrome) {
+      isChromeShell = true;
+    }
+  }
 
-  {
+  // In chrome shells, only allow dragging inside editable areas.
+  if (isChromeShell && !editingElement)
+    return NS_OK;
+
+  if (isChromeShell && textControl) {
+    // Only use the selection if it isn't collapsed.
+    bool isCollapsed = false;
+    selection->GetIsCollapsed(&isCollapsed);
+    if (!isCollapsed)
+      selection.swap(*aSelection);
+  }
+  else {
+    // In content shells, a number of checks are made below to determine
+    // whether an image or a link is being dragged. If so, add additional
+    // data to the data transfer. This is also done for chrome shells, but
+    // only when in a non-textbox editor.
+
     bool haveSelectedContent = false;
 
     // possible parent link node
     nsCOMPtr<nsIContent> parentLink;
     nsCOMPtr<nsIContent> draggedNode;
 
     {
       // only drag form elements by using the alt key,
@@ -485,17 +495,17 @@ DragDataProducer::Produce(nsDOMDataTrans
     if (haveSelectedContent) {
       link = do_QueryInterface(selectedImageOrLinkNode);
       if (link && mIsAltKeyPressed) {
         // if alt is pressed, select the link text instead of drag the link
         *aCanDrag = false;
         return NS_OK;
       }
 
-      *aDragSelection = true;
+      selection.swap(*aSelection);
     } else if (selectedImageOrLinkNode) {
       // an image is selected
       image = do_QueryInterface(selectedImageOrLinkNode);
     } else {
       // nothing is selected -
       //
       // look for draggable elements under the mouse
       //
@@ -655,30 +665,38 @@ DragDataProducer::Produce(nsDOMDataTrans
       if (linkNode) {
         mIsAnchor = true;
         GetAnchorURL(linkNode, mUrlString);
         dragNode = linkNode;
       }
     }
   }
 
-  if (nodeToSerialize || *aDragSelection) {
-    // if we have selected text, use it in preference to the node
-    if (*aDragSelection) {
-      nodeToSerialize = nsnull;
-    }
-
+  if (nodeToSerialize || *aSelection) {
     mHtmlString.Truncate();
     mContextString.Truncate();
     mInfoString.Truncate();
     mTitleString.Truncate();
+
+    nsCOMPtr<nsIDOMDocument> domDoc;
+    mWindow->GetDocument(getter_AddRefs(domDoc));
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+    NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
+
+    // if we have selected text, use it in preference to the node
     nsCOMPtr<nsITransferable> transferable;
-    rv = ::GetTransferableForNodeOrSelection(mWindow, nodeToSerialize,
-                                             getter_AddRefs(transferable));
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (*aSelection) {
+      rv = nsCopySupport::GetTransferableForSelection(*aSelection, doc,
+                                                      getter_AddRefs(transferable));
+    }
+    else {
+      rv = nsCopySupport::GetTransferableForNode(nodeToSerialize, doc,
+                                                 getter_AddRefs(transferable));
+    }
+
     nsCOMPtr<nsISupportsString> data;
     PRUint32 dataSize;
     rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(data), &dataSize);
     if (NS_SUCCEEDED(rv)) {
       data->GetData(mHtmlString);
     }
     rv = transferable->GetTransferData(kHTMLContext, getter_AddRefs(data), &dataSize);
     if (NS_SUCCEEDED(rv)) {
@@ -742,25 +760,27 @@ DragDataProducer::AddStringsToDataTransf
     dragData += mTitleString;
 
     AddString(aDataTransfer, NS_LITERAL_STRING(kURLMime), dragData, principal);
     AddString(aDataTransfer, NS_LITERAL_STRING(kURLDataMime), mUrlString, principal);
     AddString(aDataTransfer, NS_LITERAL_STRING(kURLDescriptionMime), mTitleString, principal);
     AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
   }
 
-  // add a special flavor, even if we don't have html context data
-  AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), mContextString, principal);
+  // add a special flavor for the html context data
+  if (!mContextString.IsEmpty())
+    AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), mContextString, principal);
 
   // add a special flavor if we have html info data
   if (!mInfoString.IsEmpty())
     AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), mInfoString, principal);
 
   // add the full html
-  AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLMime), mHtmlString, principal);
+  if (!mHtmlString.IsEmpty())
+    AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLMime), mHtmlString, principal);
 
   // add the plain text. we use the url for text/plain data if an anchor is
   // being dragged, rather than the title text of the link or the alt text for
   // an anchor image.
   AddString(aDataTransfer, NS_LITERAL_STRING(kTextMime),
             mIsAnchor ? mUrlString : mTitleString, principal);
 
   // add image data, if present. For now, all we're going to do with
--- a/content/base/src/nsContentAreaDragDrop.h
+++ b/content/base/src/nsContentAreaDragDrop.h
@@ -73,28 +73,28 @@ public:
    * aSelectionTargetNode - the node where the drag event should be fired
    * aIsAltKeyPressed - true if the Alt key is pressed. In some cases, this
    *                    will prevent the drag from occuring. For example,
    *                    holding down Alt over a link should select the text,
    *                    not drag the link.
    * aDataTransfer - the dataTransfer for the drag event.
    * aCanDrag - [out] set to true if the drag may proceed, false to stop the
    *            drag entirely
-   * aDragSelection - [out] set to true to indicate that a selection is being
-   *                  dragged, rather than a specific node
+   * aSelection - [out] set to the selection being dragged, or null if no
+   *                    selection is being dragged.
    * aDragNode - [out] the link, image or area being dragged, or null if the
    *             drag occurred on another element.
    */
   static nsresult GetDragData(nsIDOMWindow* aWindow,
                               nsIContent* aTarget,
                               nsIContent* aSelectionTargetNode,
                               bool aIsAltKeyPressed,
                               nsDOMDataTransfer* aDataTransfer,
                               bool* aCanDrag,
-                              bool* aDragSelection,
+                              nsISelection** aSelection,
                               nsIContent** aDragNode);
 };
 
 // this is used to save images to disk lazily when the image data is asked for
 // during the drop instead of when it is added to the drag data transfer. This
 // ensures that the image data is only created when an image drop is allowed.
 class nsContentAreaDragDropDataProvider : public nsIFlavorDataProvider
 {
--- a/content/base/src/nsCopySupport.cpp
+++ b/content/base/src/nsCopySupport.cpp
@@ -86,20 +86,16 @@
 using namespace mozilla;
 
 nsresult NS_NewDomSelection(nsISelection **aDomSelection);
 
 static NS_DEFINE_CID(kCClipboardCID,           NS_CLIPBOARD_CID);
 static NS_DEFINE_CID(kCTransferableCID,        NS_TRANSFERABLE_CID);
 static NS_DEFINE_CID(kHTMLConverterCID,        NS_HTMLFORMATCONVERTER_CID);
 
-// private clipboard data flavors for html copy, used by editor when pasting
-#define kHTMLContext   "text/_moz_htmlcontext"
-#define kHTMLInfo      "text/_moz_htmlinfo"
-
 // copy string data onto the transferable
 static nsresult AppendString(nsITransferable *aTransferable,
                              const nsAString& aString,
                              const char* aFlavor);
 
 // copy HTML node data
 static nsresult AppendDOMNode(nsITransferable *aTransferable,
                               nsIDOMNode *aDOMNode);
--- a/content/base/src/nsDOMBlobBuilder.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -117,19 +117,19 @@ nsDOMMultipartFile::CreateSlice(PRUint64
     PRUint64 l;
     nsresult rv = blob->GetSize(&l);
     NS_ENSURE_SUCCESS(rv, nsnull);
 
     if (skipStart < l) {
       PRUint64 upperBound = NS_MIN<PRUint64>(l - skipStart, length);
 
       nsCOMPtr<nsIDOMBlob> firstBlob;
-      rv = blob->MozSlice(skipStart, skipStart + upperBound,
-                          aContentType, 3,
-                          getter_AddRefs(firstBlob));
+      rv = blob->Slice(skipStart, skipStart + upperBound,
+                       aContentType, 3,
+                       getter_AddRefs(firstBlob));
       NS_ENSURE_SUCCESS(rv, nsnull);
 
       // Avoid wrapping a single blob inside an nsDOMMultipartFile
       if (length == upperBound) {
         return firstBlob.forget();
       }
 
       blobs.AppendElement(firstBlob);
@@ -145,18 +145,18 @@ nsDOMMultipartFile::CreateSlice(PRUint64
     nsIDOMBlob* blob = mBlobs[i].get();
 
     PRUint64 l;
     nsresult rv = blob->GetSize(&l);
     NS_ENSURE_SUCCESS(rv, nsnull);
 
     if (length < l) {
       nsCOMPtr<nsIDOMBlob> lastBlob;
-      rv = blob->MozSlice(0, length, aContentType, 3,
-                          getter_AddRefs(lastBlob));
+      rv = blob->Slice(0, length, aContentType, 3,
+                       getter_AddRefs(lastBlob));
       NS_ENSURE_SUCCESS(rv, nsnull);
 
       blobs.AppendElement(lastBlob);
     } else {
       blobs.AppendElement(blob);
     }
     length -= NS_MIN<PRUint64>(l, length);
   }
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -233,19 +233,19 @@ ParseSize(PRInt64 aSize, PRInt64& aStart
   }
   else {
     aStart = newStartOffset.value();
     aEnd = newEndOffset.value();
   }
 }
 
 NS_IMETHODIMP
-nsDOMFileBase::MozSlice(PRInt64 aStart, PRInt64 aEnd,
-                        const nsAString& aContentType, PRUint8 optional_argc,
-                        nsIDOMBlob **aBlob)
+nsDOMFileBase::Slice(PRInt64 aStart, PRInt64 aEnd,
+                     const nsAString& aContentType, PRUint8 optional_argc,
+                     nsIDOMBlob **aBlob)
 {
   *aBlob = nsnull;
 
   // Truncate aStart and aEnd so that we stay within this file.
   PRUint64 thisLength;
   nsresult rv = GetSize(&thisLength);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1695,30 +1695,64 @@ nsINode::SetExplicitBaseURI(nsIURI* aURI
     SetHasExplicitBaseURI();
     NS_ADDREF(aURI);
   }
   return rv;
 }
 
 //----------------------------------------------------------------------
 
+static JSObject*
+GetJSObjectChild(nsWrapperCache* aCache)
+{
+  if (aCache->PreservingWrapper()) {
+    return aCache->GetWrapperPreserveColor();
+  }
+  return aCache->GetExpandoObjectPreserveColor();
+}
+
+static bool
+NeedsScriptTraverse(nsWrapperCache* aCache)
+{
+  JSObject* o = GetJSObjectChild(aCache);
+  return o && xpc_IsGrayGCThing(o);
+}
+
+//----------------------------------------------------------------------
+
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsChildContentList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsChildContentList)
 
+// If nsChildContentList is changed so that any additional fields are
+// traversed by the cycle collector, then CAN_SKIP must be updated.
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsChildContentList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsChildContentList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsChildContentList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsChildContentList)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
+// nsChildContentList only ever has a single child, its wrapper, so if
+// the wrapper is black, the list can't be part of a garbage cycle.
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsChildContentList)
+  return !NeedsScriptTraverse(tmp);
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
+
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsChildContentList)
+  return !NeedsScriptTraverse(tmp);
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
+
+// CanSkipThis returns false to avoid problems with incomplete unlinking.
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsChildContentList)
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
+
 NS_INTERFACE_TABLE_HEAD(nsChildContentList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsChildContentList)
     NS_INTERFACE_TABLE_ENTRY(nsChildContentList, nsINodeList)
     NS_INTERFACE_TABLE_ENTRY(nsChildContentList, nsIDOMNodeList)
   NS_OFFSET_AND_INTERFACE_TABLE_END
   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsChildContentList)
@@ -4400,32 +4434,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
     }
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericElement)
   nsINode::Trace(tmp, aCallback, aClosure);
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
-static JSObject*
-GetJSObjectChild(nsINode* aNode)
-{
-  if (aNode->PreservingWrapper()) {
-    return aNode->GetWrapperPreserveColor();
-  }
-  return aNode->GetExpandoObjectPreserveColor();
-}
-                                  
-static bool
-NeedsScriptTraverse(nsINode* aNode)
-{
-  JSObject* o = GetJSObjectChild(aNode);
-  return o && xpc_IsGrayGCThing(o);
-}
-
 void
 nsGenericElement::MarkUserData(void* aObject, nsIAtom* aKey, void* aChild,
                                void* aData)
 {
   PRUint32* gen = static_cast<PRUint32*>(aData);
   xpc_MarkInCCGeneration(static_cast<nsISupports*>(aChild), *gen);
 }
 
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -97,17 +97,17 @@ class nsChildContentList : public nsINod
 public:
   nsChildContentList(nsINode* aNode)
     : mNode(aNode)
   {
     SetIsProxy();
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsChildContentList)
+  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsChildContentList)
 
   // nsWrapperCache
   virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
                                bool *triedToWrap);
 
   // nsIDOMNodeList interface
   NS_DECL_NSIDOMNODELIST
 
--- a/content/base/test/fileutils.js
+++ b/content/base/test/fileutils.js
@@ -196,34 +196,34 @@ function checkMPSubmission(sub, expected
 }
 
 function testSlice(file, size, type, contents, fileType) {
   is(file.type, type, fileType + " file is correct type");
   is(file.size, size, fileType + " file is correct size");
   ok(file instanceof File, fileType + " file is a File");
   ok(file instanceof Blob, fileType + " file is also a Blob");
   
-  var slice = file.mozSlice(0, size);
+  var slice = file.slice(0, size);
   ok(slice instanceof Blob, fileType + " fullsize slice is a Blob");
   ok(!(slice instanceof File), fileType + " fullsize slice is not a File");
   
-  slice = file.mozSlice(0, 1234);
+  slice = file.slice(0, 1234);
   ok(slice instanceof Blob, fileType + " sized slice is a Blob");
   ok(!(slice instanceof File), fileType + " sized slice is not a File");
   
-  slice = file.mozSlice(0, size, "foo/bar");
+  slice = file.slice(0, size, "foo/bar");
   is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type");
 
-  slice = file.mozSlice(0, 5432, "foo/bar");
+  slice = file.slice(0, 5432, "foo/bar");
   is(slice.type, "foo/bar", fileType + " sized slice foo/bar type");
   
-  is(slice.mozSlice(0, 10).type, "", fileType + " slice-slice type");
-  is(slice.mozSlice(0, 10).size, 10, fileType + " slice-slice size");
-  is(slice.mozSlice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
-  is(slice.mozSlice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
+  is(slice.slice(0, 10).type, "", fileType + " slice-slice type");
+  is(slice.slice(0, 10).size, 10, fileType + " slice-slice size");
+  is(slice.slice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
+  is(slice.slice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
 
   // Start, end, expected size
   var indexes = [[0, size, size],
                  [0, 1234, 1234],
                  [size-500, size, 500],
                  [size-500, size+500, 500],
                  [size+500, size+1500, 0],
                  [0, 0, 0],
@@ -242,38 +242,38 @@ function testSlice(file, size, type, con
                  [0, 33000, 33000],
                  [1000, 34000, 33000],
                 ];
   
   for (var i = 0; i < indexes.length; ++i) {
     var sliceContents;
     var testName;
     if (indexes[i][0] == undefined) {
-      slice = file.mozSlice();
+      slice = file.slice();
       sliceContents = contents.slice();
       testName = fileType + " slice()";
     }
     else if (indexes[i][1] == undefined) {
-      slice = file.mozSlice(indexes[i][0]);
+      slice = file.slice(indexes[i][0]);
       sliceContents = contents.slice(indexes[i][0]);
       testName = fileType + " slice(" + indexes[i][0] + ")";
     }
     else {
-      slice = file.mozSlice(indexes[i][0], indexes[i][1]);
+      slice = file.slice(indexes[i][0], indexes[i][1]);
       sliceContents = contents.slice(indexes[i][0], indexes[i][1]);
       testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")";
     }
     is(slice.type, "", testName + " type");
     is(slice.size, indexes[i][2], testName + " size");
     is(sliceContents.length, indexes[i][2], testName + " data size");
     testFile(slice, sliceContents, testName);
   }
 
   // Slice of slice
-  var slice = file.mozSlice(0, 40000);
-  testFile(slice.mozSlice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
+  var slice = file.slice(0, 40000);
+  testFile(slice.slice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
   
   // ...of slice of slice
-  slice = slice.mozSlice(5000, 42000).mozSlice(400, 700);
+  slice = slice.slice(5000, 42000).slice(400, 700);
   SpecialPowers.gc();
   testFile(slice, contents.slice(5400, 5700), "file slice slice slice");
 }
 
--- a/content/base/test/test_blobbuilder.html
+++ b/content/base/test/test_blobbuilder.html
@@ -146,17 +146,17 @@ function doTest(data) {
 
     blobs.forEach(doAppend);
     ok(true, "Test " + testCounter + " appended all successfully");
     let blob = bb.getBlob();
     ok(blob, "Test " + testCounter + " got blob");
     ok(blob instanceof Blob, "Test " + testCounter + " blob is a Blob");
     ok(!(blob instanceof File), "Test " + testCounter + " blob is not a File");
 
-    let slice = blob.mozSlice(test.start, test.start + test.length);
+    let slice = blob.slice(test.start, test.start + test.length);
     ok(slice, "Test " + testCounter + " got slice");
     ok(slice instanceof Blob, "Test " + testCounter + " slice is a Blob");
     ok(!(slice instanceof File), "Test " + testCounter + " slice is not a File");
     is(slice.size, test.contents.length,
        "Test " + testCounter + " slice is correct size");
 
     testFile(slice, test.contents, "Test " + testCounter);
   }
--- a/content/base/test/test_fileapi_slice.html
+++ b/content/base/test/test_fileapi_slice.html
@@ -99,39 +99,39 @@ function imageLoadHandler(event) {
 
   testHasRun();
 }
 
 // image in the middle
 var imgfile = createFileWithData(testBinaryData + fileData + testBinaryData);
 is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
 var img = new Image;
-img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size));
+img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
 img.onload = imageLoadHandler;
 expectedTestCount++;
 
 // image at start
 var imgfile = createFileWithData(fileData + testBinaryData);
 is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
 var img = new Image;
-img.src = URL.createObjectURL(imgfile.mozSlice(0, size));
+img.src = URL.createObjectURL(imgfile.slice(0, size));
 img.onload = imageLoadHandler;
 expectedTestCount++;
 
 // image at end
 var imgfile = createFileWithData(testBinaryData + fileData);
 is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
 var img = new Image;
-img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size));
+img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
 img.onload = imageLoadHandler;
 expectedTestCount++;
 
 // image past end
 var imgfile = createFileWithData(testBinaryData + fileData);
 is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
 var img = new Image;
-img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size + 1000));
+img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size + 1000));
 img.onload = imageLoadHandler;
 expectedTestCount++;
 
 </script>
 </pre>
 </body> </html>
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -1019,17 +1019,17 @@ struct WebGLVertexAttribData {
     }
 
     GLuint actualStride() const {
         if (stride) return stride;
         return size * componentSize();
     }
 };
 
-class WebGLBuffer
+class WebGLBuffer MOZ_FINAL
     : public nsIWebGLBuffer
     , public WebGLRefCountedObject<WebGLBuffer>
     , public WebGLContextBoundObject
 {
 public:
     WebGLBuffer(WebGLContext *context)
         : WebGLContextBoundObject(context)
         , mHasEverBeenBound(false)
@@ -1153,17 +1153,17 @@ protected:
     PRUint8 mCachedMaxUbyteElement;
     bool mHasCachedMaxUbyteElement;
     PRUint16 mCachedMaxUshortElement;
     bool mHasCachedMaxUshortElement;
 
     void* mData; // in the case of an Element Array Buffer, we keep a copy.
 };
 
-class WebGLTexture
+class WebGLTexture MOZ_FINAL
     : public nsIWebGLTexture
     , public WebGLRefCountedObject<WebGLTexture>
     , public WebGLContextBoundObject
 {
 public:
     WebGLTexture(WebGLContext *context)
         : WebGLContextBoundObject(context)
         , mHasEverBeenBound(false)
@@ -1603,17 +1603,17 @@ public:
             if (mFakeBlackStatus == DontKnowIfNeedFakeBlack)
                 mFakeBlackStatus = DoNotNeedFakeBlack;
         }
 
         return mFakeBlackStatus == DoNeedFakeBlack;
     }
 };
 
-class WebGLShader
+class WebGLShader MOZ_FINAL
     : public nsIWebGLShader
     , public WebGLRefCountedObject<WebGLShader>
     , public WebGLContextBoundObject
 {
 public:
     WebGLShader(WebGLContext *context, WebGLenum stype)
         : WebGLContextBoundObject(context)
         , mType(stype)
@@ -1668,17 +1668,17 @@ protected:
     WebGLuint mGLName;
     WebGLenum mType;
     nsString mSource;
     nsCString mTranslationLog;
     bool mNeedsTranslation;
     WebGLMonotonicHandle mMonotonicHandle;
 };
 
-class WebGLProgram
+class WebGLProgram MOZ_FINAL
     : public nsIWebGLProgram
     , public WebGLRefCountedObject<WebGLProgram>
     , public WebGLContextBoundObject
 {
 public:
     WebGLProgram(WebGLContext *context)
         : WebGLContextBoundObject(context)
         , mLinkStatus(false)
@@ -1790,17 +1790,17 @@ protected:
     GLint mUniformMaxNameLength;
     GLint mAttribMaxNameLength;
     GLint mUniformCount;
     GLint mAttribCount;
     std::vector<bool> mAttribsInUse;
     WebGLMonotonicHandle mMonotonicHandle;
 };
 
-class WebGLRenderbuffer
+class WebGLRenderbuffer MOZ_FINAL
     : public nsIWebGLRenderbuffer
     , public WebGLRefCountedObject<WebGLRenderbuffer>
     , public WebGLRectangleObject
     , public WebGLContextBoundObject
 {
 public:
     WebGLRenderbuffer(WebGLContext *context)
         : WebGLContextBoundObject(context)
@@ -1996,17 +1996,17 @@ public:
             }
         }
 
         NS_ABORT(); // should never get there
         return false;
     }
 };
 
-class WebGLFramebuffer
+class WebGLFramebuffer MOZ_FINAL
     : public nsIWebGLFramebuffer
     , public WebGLRefCountedObject<WebGLFramebuffer>
     , public WebGLContextBoundObject
 {
 public:
     WebGLFramebuffer(WebGLContext *context)
         : WebGLContextBoundObject(context)
         , mHasEverBeenBound(false)
@@ -2291,17 +2291,17 @@ public:
     WebGLFramebufferAttachment mColorAttachment,
                                mDepthAttachment,
                                mStencilAttachment,
                                mDepthStencilAttachment;
 
     WebGLMonotonicHandle mMonotonicHandle;
 };
 
-class WebGLUniformLocation
+class WebGLUniformLocation MOZ_FINAL
     : public nsIWebGLUniformLocation
     , public WebGLContextBoundObject
     , public WebGLRefCountedObject<WebGLUniformLocation>
 {
 public:
     WebGLUniformLocation(WebGLContext *context, WebGLProgram *program, GLint location)
         : WebGLContextBoundObject(context)
         , mProgram(program)
@@ -2332,17 +2332,17 @@ protected:
     nsRefPtr<WebGLProgram> mProgram;
 
     PRUint32 mProgramGeneration;
     GLint mLocation;
     WebGLMonotonicHandle mMonotonicHandle;
     friend class WebGLProgram;
 };
 
-class WebGLActiveInfo
+class WebGLActiveInfo MOZ_FINAL
     : public nsIWebGLActiveInfo
 {
 public:
     WebGLActiveInfo(WebGLint size, WebGLenum type, const char *nameptr, PRUint32 namelength) :
         mSize(size),
         mType(type)
     {
         mName.AssignASCII(nameptr, namelength);
@@ -2351,17 +2351,17 @@ public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLACTIVEINFO
 protected:
     WebGLint mSize;
     WebGLenum mType;
     nsString mName;
 };
 
-class WebGLShaderPrecisionFormat
+class WebGLShaderPrecisionFormat MOZ_FINAL
     : public nsIWebGLShaderPrecisionFormat
 {
 public:
     WebGLShaderPrecisionFormat(WebGLint rangeMin, WebGLint rangeMax, WebGLint precision) :
         mRangeMin(rangeMin),
         mRangeMax(rangeMax),
         mPrecision(precision)
     {
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -4372,17 +4372,17 @@ WebGLContext::CompileShader(nsIWebGLShad
 
         // notice that on Android, we always use SH_GLSL_OUTPUT, we never use the ESSL backend.
         // see bug 709947, the reason is that 1) we dont really need a ESSL backend since the
         // source is already ESSL, and 2) we ran into massive Android crashes when we used the ESSL backend.
         // But if we wanted to use shader transformations on ES platforms, we would have to use the
         // ESSL backend
         compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
                                        SH_WEBGL_SPEC,
-#ifdef MOZ_WIDGET_ANDROID
+#ifdef ANDROID
                                        SH_GLSL_OUTPUT,
 #else
                                        gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT,
 #endif
                                        &resources);
 
         // We're storing an actual instance of StripComments because, if we don't, the 
         // cleanSource nsAString instance will be destroyed before the reference is
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -175,17 +175,17 @@ CopyContext(gfxContext* dest, gfxContext
     }
 }
 
 /**
  ** nsCanvasGradient
  **/
 #define NS_CANVASGRADIENT_PRIVATE_IID \
     { 0x491d39d8, 0x4058, 0x42bd, { 0xac, 0x76, 0x70, 0xd5, 0x62, 0x7f, 0x02, 0x10 } }
-class nsCanvasGradient : public nsIDOMCanvasGradient
+class nsCanvasGradient MOZ_FINAL : public nsIDOMCanvasGradient
 {
 public:
     NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENT_PRIVATE_IID)
 
     nsCanvasGradient(gfxPattern* pat)
         : mPattern(pat)
     {
     }
@@ -233,17 +233,17 @@ NS_INTERFACE_MAP_BEGIN(nsCanvasGradient)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 /**
  ** nsCanvasPattern
  **/
 #define NS_CANVASPATTERN_PRIVATE_IID \
     { 0xb85c6c8a, 0x0624, 0x4530, { 0xb8, 0xee, 0xff, 0xdf, 0x42, 0xe8, 0x21, 0x6d } }
-class nsCanvasPattern : public nsIDOMCanvasPattern
+class nsCanvasPattern MOZ_FINAL : public nsIDOMCanvasPattern
 {
 public:
     NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASPATTERN_PRIVATE_IID)
 
     nsCanvasPattern(gfxPattern* pat,
                     nsIPrincipal* principalForSecurityCheck,
                     bool forceWriteOnly,
                     bool CORSUsed)
--- a/content/canvas/test/webgl/failing_tests_mac.txt
+++ b/content/canvas/test/webgl/failing_tests_mac.txt
@@ -2,8 +2,10 @@ conformance/context/premultiplyalpha-tes
 conformance/glsl/misc/glsl-function-nodes.html
 conformance/glsl/misc/glsl-long-variable-names.html
 conformance/glsl/misc/shader-with-256-character-identifier.frag.html
 conformance/glsl/misc/shader-with-long-line.html
 conformance/more/conformance/quickCheckAPI-S_V.html
 conformance/glsl/misc/attrib-location-length-limits.html
 conformance/glsl/misc/uniform-location-length-limits.html
 conformance/programs/program-test.html
+conformance/textures/texture-mips.html
+conformance/textures/texture-npot.html
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -175,18 +175,17 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aP
 
 void
 nsDOMEvent::InitPresContextData(nsPresContext* aPresContext)
 {
   mPresContext = aPresContext;
   // Get the explicit original target (if it's anonymous make it null)
   {
     nsCOMPtr<nsIContent> content = GetTargetFromFrame();
-    mTmpRealOriginalTarget = do_QueryInterface(content);
-    mExplicitOriginalTarget = mTmpRealOriginalTarget;
+    mExplicitOriginalTarget = do_QueryInterface(content);
     if (content && content->IsInAnonymousSubtree()) {
       mExplicitOriginalTarget = nsnull;
     }
   }
 }
 
 nsDOMEvent::~nsDOMEvent() 
 {
@@ -232,20 +231,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
       case NS_MUTATION_EVENT:
         static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode = nsnull;
         break;
       default:
         break;
     }
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPresContext);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTmpRealOriginalTarget)
-  // Always set mExplicitOriginalTarget to null, when 
-  // mTmpRealOriginalTarget doesn't point to any object!
-  tmp->mExplicitOriginalTarget = nsnull;
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mExplicitOriginalTarget);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent)
   if (tmp->mEventIsInternal) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEvent->target)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEvent->currentTarget)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEvent->originalTarget)
     switch (tmp->mEvent->eventStructType) {
@@ -270,17 +266,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
         cb.NoteXPCOMChild(
           static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode);
         break;
       default:
         break;
     }
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mPresContext.get(), nsPresContext)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTmpRealOriginalTarget)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mExplicitOriginalTarget)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // nsIDOMEventInterface
 NS_METHOD nsDOMEvent::GetType(nsAString& aType)
 {
   if (!mCachedType.IsEmpty()) {
     aType = mCachedType;
     return NS_OK;
@@ -351,28 +347,16 @@ nsDOMEvent::GetExplicitOriginalTarget(ns
     NS_ADDREF(*aRealEventTarget);
     return NS_OK;
   }
 
   return GetTarget(aRealEventTarget);
 }
 
 NS_IMETHODIMP
-nsDOMEvent::GetTmpRealOriginalTarget(nsIDOMEventTarget** aRealEventTarget)
-{
-  if (mTmpRealOriginalTarget) {
-    *aRealEventTarget = mTmpRealOriginalTarget;
-    NS_ADDREF(*aRealEventTarget);
-    return NS_OK;
-  }
-
-  return GetOriginalTarget(aRealEventTarget);
-}
-
-NS_IMETHODIMP
 nsDOMEvent::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget)
 {
   if (mEvent->originalTarget) {
     return GetDOMEventTarget(mEvent->originalTarget, aOriginalTarget);
   }
 
   return GetTarget(aOriginalTarget);
 }
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -262,18 +262,17 @@ public:
 protected:
 
   // Internal helper functions
   nsresult SetEventType(const nsAString& aEventTypeArg);
   already_AddRefed<nsIContent> GetTargetFromFrame();
 
   nsEvent*                    mEvent;
   nsRefPtr<nsPresContext>     mPresContext;
-  nsCOMPtr<nsIDOMEventTarget> mTmpRealOriginalTarget;
-  nsIDOMEventTarget*          mExplicitOriginalTarget;
+  nsCOMPtr<nsIDOMEventTarget> mExplicitOriginalTarget;
   nsString                    mCachedType;
   bool                        mEventIsInternal;
   bool                        mPrivateDataDuplicated;
 };
 
 #define NS_FORWARD_TO_NSDOMEVENT \
   NS_FORWARD_NSIDOMEVENT(nsDOMEvent::)
 
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2076,24 +2076,22 @@ nsEventStateManager::GenerateDragGesture
         // it takes a long time
         KillClickHoldTimer();
       }
 
       nsRefPtr<nsDOMDataTransfer> dataTransfer = new nsDOMDataTransfer();
       if (!dataTransfer)
         return;
 
-      bool isInEditor = false;
-      bool isSelection = false;
+      nsCOMPtr<nsISelection> selection;
       nsCOMPtr<nsIContent> eventContent, targetContent;
       mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(eventContent));
       if (eventContent)
         DetermineDragTarget(aPresContext, eventContent, dataTransfer,
-                            &isSelection, &isInEditor,
-                            getter_AddRefs(targetContent));
+                            getter_AddRefs(selection), getter_AddRefs(targetContent));
 
       // Stop tracking the drag gesture now. This should stop us from
       // reentering GenerateDragGesture inside DOM event processing.
       StopTrackingDragGesture();
 
       if (!targetContent)
         return;
 
@@ -2124,36 +2122,35 @@ nsEventStateManager::GenerateDragGesture
 
       // Set the current target to the content for the mouse down
       mCurrentTargetContent = targetContent;
 
       // Dispatch both the dragstart and draggesture events to the DOM. For
       // elements in an editor, only fire the draggesture event so that the
       // editor code can handle it but content doesn't see a dragstart.
       nsEventStatus status = nsEventStatus_eIgnore;
-      if (!isInEditor)
-        nsEventDispatcher::Dispatch(targetContent, aPresContext, &startEvent, nsnull,
-                                    &status);
+      nsEventDispatcher::Dispatch(targetContent, aPresContext, &startEvent, nsnull,
+                                  &status);
 
       nsDragEvent* event = &startEvent;
       if (status != nsEventStatus_eConsumeNoDefault) {
         status = nsEventStatus_eIgnore;
         nsEventDispatcher::Dispatch(targetContent, aPresContext, &gestureEvent, nsnull,
                                     &status);
         event = &gestureEvent;
       }
 
       // now that the dataTransfer has been updated in the dragstart and
       // draggesture events, make it read only so that the data doesn't
       // change during the drag.
       dataTransfer->SetReadOnly();
 
       if (status != nsEventStatus_eConsumeNoDefault) {
         bool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer,
-                                                targetContent, isSelection);
+                                              targetContent, selection);
         if (dragStarted) {
           sActiveESM = nsnull;
           aEvent->flags |= NS_EVENT_FLAG_STOP_DISPATCH;
         }
       }
 
       // Note that frame event handling doesn't care about NS_DRAGDROP_GESTURE,
       // which is just as well since we don't really know which frame to
@@ -2168,64 +2165,54 @@ nsEventStateManager::GenerateDragGesture
     FlushPendingEvents(aPresContext);
   }
 } // GenerateDragGesture
 
 void
 nsEventStateManager::DetermineDragTarget(nsPresContext* aPresContext,
                                          nsIContent* aSelectionTarget,
                                          nsDOMDataTransfer* aDataTransfer,
-                                         bool* aIsSelection,
-                                         bool* aIsInEditor,
+                                         nsISelection** aSelection,
                                          nsIContent** aTargetNode)
 {
   *aTargetNode = nsnull;
-  *aIsInEditor = false;
 
   nsCOMPtr<nsISupports> container = aPresContext->GetContainer();
   nsCOMPtr<nsIDOMWindow> window = do_GetInterface(container);
 
   // GetDragData determines if a selection, link or image in the content
   // should be dragged, and places the data associated with the drag in the
-  // data transfer. Skip this check for chrome shells.
+  // data transfer.
+  // mGestureDownContent is the node where the mousedown event for the drag
+  // occurred, and aSelectionTarget is the node to use when a selection is used
   bool canDrag;
   nsCOMPtr<nsIContent> dragDataNode;
-  nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(container);
-  if (dsti) {
-    PRInt32 type = -1;
-    if (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
-        type != nsIDocShellTreeItem::typeChrome) {
-      // mGestureDownContent is the node where the mousedown event for the drag
-      // occurred, and aSelectionTarget is the node to use when a selection is used
-      nsresult rv =
-        nsContentAreaDragDrop::GetDragData(window, mGestureDownContent,
-                                           aSelectionTarget, mGestureDownAlt,
-                                           aDataTransfer, &canDrag, aIsSelection,
-                                           getter_AddRefs(dragDataNode));
-      if (NS_FAILED(rv) || !canDrag)
-        return;
-    }
-  }
+  nsresult rv = nsContentAreaDragDrop::GetDragData(window, mGestureDownContent,
+                                                   aSelectionTarget, mGestureDownAlt,
+                                                   aDataTransfer, &canDrag, aSelection,
+                                                   getter_AddRefs(dragDataNode));
+  if (NS_FAILED(rv) || !canDrag)
+    return;
 
   // if GetDragData returned a node, use that as the node being dragged.
   // Otherwise, if a selection is being dragged, use the node within the
   // selection that was dragged. Otherwise, just use the mousedown target.
   nsIContent* dragContent = mGestureDownContent;
   if (dragDataNode)
     dragContent = dragDataNode;
-  else if (*aIsSelection)
+  else if (*aSelection)
     dragContent = aSelectionTarget;
 
   nsIContent* originalDragContent = dragContent;
 
   // If a selection isn't being dragged, look for an ancestor with the
   // draggable property set. If one is found, use that as the target of the
   // drag instead of the node that was clicked on. If a draggable node wasn't
   // found, just use the clicked node.
-  if (!*aIsSelection) {
+  if (!*aSelection) {
     while (dragContent) {
       nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(dragContent);
       if (htmlElement) {
         bool draggable = false;
         htmlElement->GetDraggable(&draggable);
         if (draggable)
           break;
       }
@@ -2240,27 +2227,16 @@ nsEventStateManager::DetermineDragTarget
           // better way to specify whether something is draggable than just
           // on/off.
           dragContent = mGestureDownContent;
           break;
         }
         // otherwise, it's not an HTML or XUL element, so just keep looking
       }
       dragContent = dragContent->GetParent();
-
-      // if an editable parent is encountered, then we don't look at any
-      // ancestors. This is used because the editor attaches a draggesture
-      // listener to the editable element and we want to call it without
-      // making the editable element draggable. This should be removed once
-      // the editor is switched over to using the proper drag and drop api.
-      nsCOMPtr<nsIDOMNSEditableElement> editableElement = do_QueryInterface(dragContent);
-      if (editableElement) {
-        *aIsInEditor = true;
-        break;
-      }
     }
   }
 
   // if no node in the hierarchy was found to drag, but the GetDragData method
   // returned a node, use that returned node. Otherwise, nothing is draggable.
   if (!dragContent && dragDataNode)
     dragContent = dragDataNode;
 
@@ -2274,17 +2250,17 @@ nsEventStateManager::DetermineDragTarget
   }
 }
 
 bool
 nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
                                         nsDragEvent* aDragEvent,
                                         nsDOMDataTransfer* aDataTransfer,
                                         nsIContent* aDragTarget,
-                                        bool aIsSelection)
+                                        nsISelection* aSelection)
 {
   nsCOMPtr<nsIDragService> dragService =
     do_GetService("@mozilla.org/widget/dragservice;1");
   if (!dragService)
     return false;
 
   // Default handling for the draggesture/dragstart event.
   //
@@ -2328,48 +2304,37 @@ nsEventStateManager::DoDefaultDragStart(
     action = nsIDragService::DRAGDROP_ACTION_COPY |
              nsIDragService::DRAGDROP_ACTION_MOVE |
              nsIDragService::DRAGDROP_ACTION_LINK;
 
   // get any custom drag image that was set
   PRInt32 imageX, imageY;
   nsIDOMElement* dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
 
-  // If a selection is being dragged, and no custom drag image was
-  // set, get the selection so that the drag region can be created
-  // from the selection area. If a custom image was set, it doesn't
-  // matter what the selection is since the image will be used instead.
-  nsISelection* selection = nsnull;
-  if (aIsSelection && !dragImage) {
-    nsIDocument* doc = aDragTarget->GetCurrentDoc();
-    if (doc) {
-      nsIPresShell* presShell = doc->GetShell();
-      if (presShell) {
-        selection = presShell->GetCurrentSelection(
-                      nsISelectionController::SELECTION_NORMAL);
-      }
-    }
-  }
-
   nsCOMPtr<nsISupportsArray> transArray;
   aDataTransfer->GetTransferables(getter_AddRefs(transArray));
   if (!transArray)
     return false;
 
   // XXXndeakin don't really want to create a new drag DOM event
   // here, but we need something to pass to the InvokeDragSession
   // methods.
   nsCOMPtr<nsIDOMEvent> domEvent;
   NS_NewDOMDragEvent(getter_AddRefs(domEvent), aPresContext, aDragEvent);
 
   nsCOMPtr<nsIDOMDragEvent> domDragEvent = do_QueryInterface(domEvent);
   // if creating a drag event failed, starting a drag session will
   // just fail.
-  if (selection) {
-    dragService->InvokeDragSessionWithSelection(selection, transArray,
+
+  // Use InvokeDragSessionWithSelection if a selection is being dragged,
+  // such that the image can be generated from the selected text. However,
+  // use InvokeDragSessionWithImage if a custom image was set or something
+  // other than a selection is being dragged.
+  if (!dragImage && aSelection) {
+    dragService->InvokeDragSessionWithSelection(aSelection, transArray,
                                                 action, domDragEvent,
                                                 aDataTransfer);
   }
   else {
     // if dragging within a XUL tree and no custom drag image was
     // set, the region argument to InvokeDragSessionWithImage needs
     // to be set to the area encompassing the selected rows of the
     // tree to ensure that the drag feedback gets clipped to those
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -412,42 +412,40 @@ protected:
 
   /**
    * Determine which node the drag should be targeted at.
    * This is either the node clicked when there is a selection, or, for HTML,
    * the element with a draggable property set to true.
    *
    * aSelectionTarget - target to check for selection
    * aDataTransfer - data transfer object that will contain the data to drag
-   * aIsSelection - [out] set to true if a selection is being dragged
-   * aIsInEditor - [out] set to true if the content is in an editor field
+   * aSelection - [out] set to the selection to be dragged
    * aTargetNode - [out] the draggable node, or null if there isn't one
    */
   void DetermineDragTarget(nsPresContext* aPresContext,
                            nsIContent* aSelectionTarget,
                            nsDOMDataTransfer* aDataTransfer,
-                           bool* aIsSelection,
-                           bool* aIsInEditor,
+                           nsISelection** aSelection,
                            nsIContent** aTargetNode);
 
   /*
    * Perform the default handling for the dragstart/draggesture event and set up a
    * drag for aDataTransfer if it contains any data. Returns true if a drag has
    * started.
    *
    * aDragEvent - the dragstart/draggesture event
    * aDataTransfer - the data transfer that holds the data to be dragged
    * aDragTarget - the target of the drag
-   * aIsSelection - true if a selection is being dragged
+   * aSelection - the selection to be dragged
    */
   bool DoDefaultDragStart(nsPresContext* aPresContext,
                             nsDragEvent* aDragEvent,
                             nsDOMDataTransfer* aDataTransfer,
                             nsIContent* aDragTarget,
-                            bool aIsSelection);
+                            nsISelection* aSelection);
 
   bool IsTrackingDragGesture ( ) const { return mGestureDownContent != nsnull; }
   /**
    * Set the fields of aEvent to reflect the mouse position and modifier keys
    * that were set when the user first pressed the mouse button (stored by
    * BeginTrackingDragGesture). aEvent->widget must be
    * mCurrentTarget->GetNearestWidget().
    */
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -104,17 +104,16 @@ include $(topsrcdir)/config/rules.mk
 		test_bug448534.html \
 		test_bug463162.xhtml \
 		test_bug465498.html \
 		test_bug493187.html \
 		test_bug495145.html \
 		test_bug495300.html \
 		test_bug686942.html \
 		test_can_play_type.html \
-		test_closing_connections.html \
 		test_constants.html \
 		test_controls.html \
 		test_currentTime.html \
 		test_decode_error.html \
 		test_decoder_disable.html \
 		test_defaultMuted.html \
 		test_delay_load.html \
 		test_error_on_404.html \
@@ -171,16 +170,18 @@ endif
 # Bug 492821:
 #   test_videoDocumentTitle.html
 # Bug 493692:
 #   test_preload_suspend.html
 # Bug 567954 and Bug 574586:
 #   test_mixed_principals.html
 # Disabled since we don't play Wave files standalone, for now
 #		test_audioDocumentTitle.html
+# Bug 634564:
+#		test_closing_connections.html \
 
 # sample files
 _TEST_FILES += \
 		320x240.ogv \
 		448636.ogv \
 		audio-overhang.ogg \
 		audio-gaps.ogg \
 		beta-phrasebook.ogg \
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -1481,17 +1481,18 @@ nsSVGElement::GetCtx() const
     ancestor = ancestor->GetFlattenedTreeParent();
   }
 
   // we don't have an ancestor <svg> element...
   return nsnull;
 }
 
 /* virtual */ gfxMatrix
-nsSVGElement::PrependLocalTransformTo(const gfxMatrix &aMatrix) const
+nsSVGElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                                       TransformTypes aWhich) const
 {
   return aMatrix;
 }
 
 nsSVGElement::LengthAttributesInfo
 nsSVGElement::GetLengthInfo()
 {
   return LengthAttributesInfo(nsnull, nsnull, 0);
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -146,21 +146,46 @@ public:
   NS_IMETHOD GetOwnerSVGElement(nsIDOMSVGSVGElement** aOwnerSVGElement);
   NS_IMETHOD GetViewportElement(nsIDOMSVGElement** aViewportElement);
 
   // Gets the element that establishes the rectangular viewport against which
   // we should resolve percentage lengths (our "coordinate context"). Returns
   // nsnull for outer <svg> or SVG without an <svg> parent (invalid SVG).
   nsSVGSVGElement* GetCtx() const;
 
+  enum TransformTypes {
+     eAllTransforms
+    ,eUserSpaceToParent
+    ,eChildToUserSpace
+  };
   /**
-   * Returns aMatrix post-multiplied by the transform from the userspace
-   * established by this element to the userspace established by its parent.
+   * Returns aMatrix pre-multiplied by (explicit or implicit) transforms that
+   * are introduced by attributes on this element.
+   *
+   * If aWhich is eAllTransforms, then all the transforms from the coordinate
+   * space established by this element for its children to the coordinate
+   * space established by this element's parent element for this element, are
+   * included.
+   *
+   * If aWhich is eUserSpaceToParent, then only the transforms from this
+   * element's userspace to the coordinate space established by its parent is
+   * included. This includes any transforms introduced by the 'transform'
+   * attribute, transform animations and animateMotion, but not any offsets
+   * due to e.g. 'x'/'y' attributes, or any transform due to a 'viewBox'
+   * attribute. (SVG userspace is defined to be the coordinate space in which
+   * coordinates on an element apply.)
+   *
+   * If aWhich is eChildToUserSpace, then only the transforms from the
+   * coordinate space established by this element for its childre to this
+   * elements userspace are included. This includes any offsets due to e.g.
+   * 'x'/'y' attributes, and any transform due to a 'viewBox' attribute, but
+   * does not include any transforms due to the 'transform' attribute.
    */
-  virtual gfxMatrix PrependLocalTransformTo(const gfxMatrix &aMatrix) const;
+  virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                      TransformTypes aWhich = eAllTransforms) const;
 
   // Setter for to set the current <animateMotion> transformation
   // Only visible for nsSVGGraphicElement, so it's a no-op here, and that
   // subclass has the useful implementation.
   virtual void SetAnimateMotionTransform(const gfxMatrix* aMatrix) {/*no-op*/}
 
   bool IsStringAnimatable(PRUint8 aAttrEnum) {
     return GetStringInfo().mStringInfo[aAttrEnum].mIsAnimatable;
--- a/content/svg/content/src/nsSVGForeignObjectElement.cpp
+++ b/content/svg/content/src/nsSVGForeignObjectElement.cpp
@@ -107,26 +107,38 @@ NS_IMETHODIMP nsSVGForeignObjectElement:
 {
   return mLengthAttributes[HEIGHT].ToDOMAnimatedLength(aHeight, this);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 /* virtual */ gfxMatrix
-nsSVGForeignObjectElement::PrependLocalTransformTo(const gfxMatrix &aMatrix) const
+nsSVGForeignObjectElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                                                    TransformTypes aWhich) const
 {
+  NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
+                    "Skipping eUserSpaceToParent transforms makes no sense");
+
   // 'transform' attribute:
-  gfxMatrix matrix = nsSVGForeignObjectElementBase::PrependLocalTransformTo(aMatrix);
-  
-  // now translate by our 'x' and 'y':
+  gfxMatrix fromUserSpace =
+    nsSVGForeignObjectElementBase::PrependLocalTransformsTo(aMatrix, aWhich);
+  if (aWhich == eUserSpaceToParent) {
+    return fromUserSpace;
+  }
+  // our 'x' and 'y' attributes:
   float x, y;
   const_cast<nsSVGForeignObjectElement*>(this)->
     GetAnimatedLengthValues(&x, &y, nsnull);
-  return gfxMatrix().Translate(gfxPoint(x, y)) * matrix;
+  gfxMatrix toUserSpace = gfxMatrix().Translate(gfxPoint(x, y));
+  if (aWhich == eChildToUserSpace) {
+    return toUserSpace;
+  }
+  NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes");
+  return toUserSpace * fromUserSpace;
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(bool)
 nsSVGForeignObjectElement::IsAttributeMapped(const nsIAtom* name) const
 {
--- a/content/svg/content/src/nsSVGForeignObjectElement.h
+++ b/content/svg/content/src/nsSVGForeignObjectElement.h
@@ -64,17 +64,18 @@ public:
   NS_DECL_NSIDOMSVGFOREIGNOBJECTELEMENT
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGForeignObjectElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGForeignObjectElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGForeignObjectElementBase::)
 
   // nsSVGElement specializations:
-  virtual gfxMatrix PrependLocalTransformTo(const gfxMatrix &aMatrix) const;
+  virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                      TransformTypes aWhich = eAllTransforms) const;
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
--- a/content/svg/content/src/nsSVGGraphicElement.cpp
+++ b/content/svg/content/src/nsSVGGraphicElement.cpp
@@ -184,20 +184,35 @@ nsSVGGraphicElement::IsAttributeMapped(c
 
 bool
 nsSVGGraphicElement::IsEventName(nsIAtom* aName)
 {
   return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
 }
 
 gfxMatrix
-nsSVGGraphicElement::PrependLocalTransformTo(const gfxMatrix &aMatrix) const
+nsSVGGraphicElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                                              TransformTypes aWhich) const
 {
+  NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
+                    "Skipping eUserSpaceToParent transforms makes no sense");
+
   gfxMatrix result(aMatrix);
 
+  if (aWhich == eChildToUserSpace) {
+    // We don't have anything to prepend.
+    // eChildToUserSpace is not the common case, which is why we return
+    // 'result' to benefit from NRVO rather than returning aMatrix before
+    // creating 'result'.
+    return result;
+  }
+
+  NS_ABORT_IF_FALSE(aWhich == eAllTransforms || aWhich == eUserSpaceToParent,
+                    "Unknown TransformTypes");
+
   // animateMotion's resulting transform is supposed to apply *on top of*
   // any transformations from the |transform| attribute. So since we're
   // PRE-multiplying, we need to apply the animateMotion transform *first*.
   if (mAnimateMotionTransform) {
     result.PreMultiply(*mAnimateMotionTransform);
   }
 
   if (mTransforms) {
--- a/content/svg/content/src/nsSVGGraphicElement.h
+++ b/content/svg/content/src/nsSVGGraphicElement.h
@@ -57,17 +57,18 @@ public:
   // interfaces:  
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGLOCATABLE
   NS_DECL_NSIDOMSVGTRANSFORMABLE
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
-  virtual gfxMatrix PrependLocalTransformTo(const gfxMatrix &aMatrix) const;
+  virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                      TransformTypes aWhich = eAllTransforms) const;
   virtual void SetAnimateMotionTransform(const gfxMatrix* aMatrix);
 
   virtual mozilla::SVGAnimatedTransformList* GetAnimatedTransformList();
   virtual nsIAtom* GetTransformListAttrName() const {
     return nsGkAtoms::transform;
   }
 
 protected:
--- a/content/svg/content/src/nsSVGPathElement.cpp
+++ b/content/svg/content/src/nsSVGPathElement.cpp
@@ -435,17 +435,17 @@ nsSVGPathElement::GetPathLengthScale(Pat
   if (mPathLength.IsExplicitlySet()) {
     float authorsPathLengthEstimate = mPathLength.GetAnimValue();
     if (authorsPathLengthEstimate > 0) {
       gfxMatrix matrix;
       if (aFor == eForTextPath) {
         // For textPath, a transform on the referenced path affects the
         // textPath layout, so when calculating the actual path length
         // we need to take that into account.
-        matrix = PrependLocalTransformTo(matrix);
+        matrix = PrependLocalTransformsTo(matrix);
       }
       nsRefPtr<gfxFlattenedPath> path = GetFlattenedPath(matrix);
       if (path) {
         return path->GetLength() / authorsPathLengthEstimate;
       }
     }
   }
   return 1.0;
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -745,17 +745,26 @@ nsSVGSVGElement::GetCTM(nsIDOMSVGMatrix 
   NS_IF_ADDREF(*aCTM);
   return NS_OK;
 }
 
 /* nsIDOMSVGMatrix getScreenCTM (); */
 NS_IMETHODIMP
 nsSVGSVGElement::GetScreenCTM(nsIDOMSVGMatrix **aCTM)
 {
-  gfxMatrix m = nsSVGUtils::GetCTM(this, true);
+  gfxMatrix m;
+  if (IsRoot()) {
+    // Consistency with other elements would have us return only the
+    // eFromUserSpace transforms, but this is what we've been doing for
+    // a while, and it keeps us consistent with WebKit and Opera (if not
+    // really with the ambiguous spec).
+    m = PrependLocalTransformsTo(m);
+  } else {
+    m = nsSVGUtils::GetCTM(this, true);
+  }
   *aCTM = m.IsSingular() ? nsnull : new DOMSVGMatrix(m);
   NS_IF_ADDREF(*aCTM);
   return NS_OK;
 }
 
 /* nsIDOMSVGMatrix getTransformToElement (in nsIDOMSVGElement element); */
 NS_IMETHODIMP
 nsSVGSVGElement::GetTransformToElement(nsIDOMSVGElement *element,
@@ -1175,22 +1184,39 @@ nsSVGSVGElement::GetLength(PRUint8 aCtxT
   }
   return 0;
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 /* virtual */ gfxMatrix
-nsSVGSVGElement::PrependLocalTransformTo(const gfxMatrix &aMatrix) const
+nsSVGSVGElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                                          TransformTypes aWhich) const
 {
+  NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
+                    "Skipping eUserSpaceToParent transforms makes no sense");
+
   if (IsInner()) {
     float x, y;
     const_cast<nsSVGSVGElement*>(this)->GetAnimatedLengthValues(&x, &y, nsnull);
-    return GetViewBoxTransform() * gfxMatrix().Translate(gfxPoint(x, y)) * aMatrix;
+    if (aWhich == eAllTransforms) {
+      // the common case
+      return GetViewBoxTransform() * gfxMatrix().Translate(gfxPoint(x, y)) * aMatrix;
+    }
+    if (aWhich == eUserSpaceToParent) {
+      return gfxMatrix().Translate(gfxPoint(x, y)) * aMatrix;
+    }
+    NS_ABORT_IF_FALSE(aWhich == eChildToUserSpace, "Unknown TransformTypes");
+    return GetViewBoxTransform(); // no need to multiply identity aMatrix
+  }
+
+  if (aWhich == eUserSpaceToParent) {
+    // only inner-<svg> has eUserSpaceToParent transforms
+    return aMatrix;
   }
 
   if (IsRoot()) {
     gfxMatrix zoomPanTM;
     zoomPanTM.Translate(gfxPoint(mCurrentTranslate.GetX(), mCurrentTranslate.GetY()));
     zoomPanTM.Scale(mCurrentScale, mCurrentScale);
     return GetViewBoxTransform() * zoomPanTM * aMatrix;
   }
--- a/content/svg/content/src/nsSVGSVGElement.h
+++ b/content/svg/content/src/nsSVGSVGElement.h
@@ -181,18 +181,19 @@ public:
 
   nsSMILTimeContainer* GetTimedDocumentRoot();
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 
   // nsSVGElement specializations:
-  virtual gfxMatrix PrependLocalTransformTo(const gfxMatrix &aMatrix) const;
-  
+  virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                      TransformTypes aWhich = eAllTransforms) const;
+ 
   // nsSVGSVGElement methods:
   float GetLength(PRUint8 mCtxType);
 
   // public helpers:
   gfxMatrix GetViewBoxTransform() const;
   bool      HasValidViewbox() const { return mViewBox.IsValid(); }
 
   // This services any pending notifications for the transform on on this root
--- a/content/svg/content/src/nsSVGUseElement.cpp
+++ b/content/svg/content/src/nsSVGUseElement.cpp
@@ -483,25 +483,37 @@ nsSVGUseElement::UnlinkSource()
   }
   mSource.Unlink();
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 /* virtual */ gfxMatrix
-nsSVGUseElement::PrependLocalTransformTo(const gfxMatrix &aMatrix) const
+nsSVGUseElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                                          TransformTypes aWhich) const
 {
+  NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
+                    "Skipping eUserSpaceToParent transforms makes no sense");
+
   // 'transform' attribute:
-  gfxMatrix matrix = nsSVGUseElementBase::PrependLocalTransformTo(aMatrix);
-
-  // now translate by our 'x' and 'y':
+  gfxMatrix fromUserSpace =
+    nsSVGUseElementBase::PrependLocalTransformsTo(aMatrix, aWhich);
+  if (aWhich == eUserSpaceToParent) {
+    return fromUserSpace;
+  }
+  // our 'x' and 'y' attributes:
   float x, y;
   const_cast<nsSVGUseElement*>(this)->GetAnimatedLengthValues(&x, &y, nsnull);
-  return matrix.PreMultiply(gfxMatrix().Translate(gfxPoint(x, y)));
+  gfxMatrix toUserSpace = gfxMatrix().Translate(gfxPoint(x, y));
+  if (aWhich == eChildToUserSpace) {
+    return toUserSpace;
+  }
+  NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes");
+  return toUserSpace * fromUserSpace;
 }
 
 nsSVGElement::LengthAttributesInfo
 nsSVGUseElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
--- a/content/svg/content/src/nsSVGUseElement.h
+++ b/content/svg/content/src/nsSVGUseElement.h
@@ -98,17 +98,18 @@ public:
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGUseElementBase::)
 
   // for nsSVGUseFrame's nsIAnonymousContentCreator implementation.
   nsIContent* CreateAnonymousContent();
   nsIContent* GetAnonymousContent() const { return mClone; }
   void DestroyAnonymousContent();
 
   // nsSVGElement specializations:
-  virtual gfxMatrix PrependLocalTransformTo(const gfxMatrix &aMatrix) const;
+  virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+                      TransformTypes aWhich = eAllTransforms) const;
 
   // nsIContent interface
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   class SourceReference : public nsReferencedElement {
--- a/content/svg/content/test/bbox-helper.svg
+++ b/content/svg/content/test/bbox-helper.svg
@@ -1,12 +1,12 @@
 <?xml version="1.0"?>
 <svg xmlns="http://www.w3.org/2000/svg">
   <g transform="scale(0.5)">
-    <foreignObject id="f" width="100" height="100"/>
+    <foreignObject id="fO" x="10" y="10" width="100" height="100"/>
   </g>
   <text id="b" x="20" y="20">b</text>
   <text id="a" x="20" y="30">a</text>
   <text id="y" x="20" y="40">y</text>
   <g id="v">
     <circle cx="100" cy="50" r="5"/>
     <path d="M 100,100 L 100,200"/>
   </g>
--- a/content/svg/content/test/getCTM-helper.svg
+++ b/content/svg/content/test/getCTM-helper.svg
@@ -12,17 +12,17 @@
       <symbol id="sym" width="100" height="100">
         <rect id="symbolRect" width="0" height="0"
               transform="translate(70, 80)"/>
       </symbol>
     </defs>
     <svg id="inner" x="30" y="40" width="100" height="100">
       <g id="g1"/>
     </svg>
-    <foreignObject x="30" y="40" width="100" height="100" transform="translate(1, 1)">
+    <foreignObject id="fO" x="30" y="40" width="100" height="100" transform="translate(1, 1)">
       <!-- current layout implementation ignores x="50" and y="60".
            thus, I made getCTM and getScreenCTM do the same. -->
       <svg id="outer" x="50" y="60" width="100" height="100">
         <g id="g2" transform="translate(600, 700)"/>
       </svg>
     </foreignObject>
     <!-- something invalid -->
     <foreignObject>
--- a/content/svg/content/test/test_bbox.xhtml
+++ b/content/svg/content/test/test_bbox.xhtml
@@ -34,17 +34,17 @@ function run()
     is(bbox.height, height, id + ".getBBox().height");
   }
   function checkBBoxHeight(id1, id2) {
     var bbox1 = getBBox(id1);
     var bbox2 = getBBox(id2);
     is(bbox1.height, bbox2.height, id1 + ".getBBox().height");
   }
 
-  checkBBox("f", 0, 0, 100, 100);
+  checkBBox("fO", 10, 10, 100, 100);
   checkBBoxHeight("a", "b");
   checkBBoxHeight("a", "y");
   checkBBox("v", 95, 45, 10, 155);
   checkBBox("h", 195, 45, 105, 55);
   
   SimpleTest.finish();
 }
 
--- a/content/svg/content/test/test_getCTM.html
+++ b/content/svg/content/test/test_getCTM.html
@@ -32,16 +32,17 @@ function runTest()
   var inner = doc.getElementById("inner");
   var g1 = doc.getElementById("g1");
   var outer = doc.getElementById("outer");
   var g2 = doc.getElementById("g2");
   var g3 = doc.getElementById("g3");
   var g4 = doc.getElementById("g4");
   var sym = doc.getElementById("sym");
   var symbolRect = doc.getElementById("symbolRect");
+  var fO = doc.getElementById("fO");
   /* Tests the consistency with nearestViewportElement
      (code is from test_viewport.html) */
   // root.nearestViewportElement == null
   is((function(){try{return root.getCTM()}catch(e){return e}})(), null, "root.getCTM()");
   // inner.nearestViewportElement == root
   is((function(){try{return inner.getCTM().e}catch(e){return e}})(), 31, "inner.getCTM().e");
   is((function(){try{return inner.getCTM().f}catch(e){return e}})(), 42, "inner.getCTM().f");
   // g1.nearestViewportElement == inner
@@ -55,16 +56,19 @@ function runTest()
   // g3.nearestViewportElement == null
   is((function(){try{return g3.getCTM()}catch(e){return e}})(), null, "g3.getCTM()");
   // g4.nearestViewportElement == null
   is((function(){try{return g4.getCTM().e}catch(e){return e}})(), 1, "g4.getCTM().e");
   is((function(){try{return g4.getCTM().f}catch(e){return e}})(), 2, "g4.getCTM().f");
   // symbolRect.nearestViewportElement == sym
   is((function(){try{return symbolRect.getCTM().e}catch(e){return e}})(), 70, "symbolRect.getCTM().e");
   is((function(){try{return symbolRect.getCTM().f}catch(e){return e}})(), 80, "symbolRect.getCTM().f");
+  // fO.nearestViewportElement = <svg> with no 'id'
+  is((function(){try{return fO.getCTM().e}catch(e){return e}})(), 2, "fO.getCTM().e");
+  is((function(){try{return fO.getCTM().f}catch(e){return e}})(), 3, "fO.getCTM().f");
 
   /* Tests the consistency with farthestViewportElement
      (code is from test_viewport.html) */
   // root.farthestViewportElement == null (but actually == root)
   is((function(){try{return root.getScreenCTM().e}catch(e){return e}})(), 11, "root.getScreenCTM().e");
   is((function(){try{return root.getScreenCTM().f}catch(e){return e}})(), 22, "root.getScreenCTM().f");
   // inner.farthestViewportElement == root
   is((function(){try{return inner.getScreenCTM().e}catch(e){return e}})(), 45, "inner.getScreenCTM().e");
@@ -78,16 +82,19 @@ function runTest()
   // g2.farthestViewportElement == outer (but actually == root)
   is((function(){try{return g2.getScreenCTM().e}catch(e){return e}})(), 646, "g2.getScreenCTM().e");
   is((function(){try{return g2.getScreenCTM().f}catch(e){return e}})(), 769, "g2.getScreenCTM().f");
   // g3.farthestViewportElement == null (but actually == null)
   is((function(){try{return g3.getScreenCTM()}catch(e){return e}})(), null, "g3.getScreenCTM()");
   // symbolRect.farthestViewportElement == root
   is((function(){try{return symbolRect.getScreenCTM().e}catch(e){return e}})(), 85, "symbolRect.getScreenCTM().e");
   is((function(){try{return symbolRect.getScreenCTM().f}catch(e){return e}})(), 108, "symbolRect.getScreenCTM().f");
+  // fO.farthestViewportElement == root
+  is((function(){try{return fO.getScreenCTM().e}catch(e){return e}})(), 16, "symbolRect.getScreenCTM().e");
+  is((function(){try{return fO.getScreenCTM().f}catch(e){return e}})(), 29, "symbolRect.getScreenCTM().f");
 
   SimpleTest.finish();
 }
 
 window.addEventListener("load", runTest, false);
 </script>
 </pre>
 </body>
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -4114,19 +4114,17 @@ nsDocShell::DisplayLoadError(nsresult aE
             error.get(),
             strs, formatStrCount, getter_Copies(str));
         NS_ENSURE_SUCCESS(rv, rv);
         messageStr.Assign(str.get());
     }
 
     // Display the error as a page or an alert prompt
     NS_ENSURE_FALSE(messageStr.IsEmpty(), NS_ERROR_FAILURE);
-    // Note: For now, display an alert instead of an error page if we have no
-    // URI object. Missing URI objects are handled badly by session history.
-    if (mUseErrorPages && aURI) {
+    if (mUseErrorPages) {
         // Display an error page
         LoadErrorPage(aURI, aURL, errorPage.get(), error.get(),
                       messageStr.get(), cssClass.get(), aFailedChannel);
     } 
     else
     {
         // The prompter reqires that our private window has a document (or it
         // asserts). Satisfy that assertion now since GetDocument will force
@@ -4185,16 +4183,20 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, 
     if (aURI)
     {
         nsresult rv = aURI->GetSpec(url);
         rv |= aURI->GetOriginCharset(charset);
         NS_ENSURE_SUCCESS(rv, rv);
     }
     else if (aURL)
     {
+        // We need a URI object to store a session history entry, so make up a URI
+        nsresult rv = NS_NewURI(getter_AddRefs(mFailedURI), "about:blank");
+        NS_ENSURE_SUCCESS(rv, rv);
+
         CopyUTF16toUTF8(aURL, url);
     }
     else
     {
         return NS_ERROR_INVALID_POINTER;
     }
 
     // Create a URL to pass all the error information through to the page.
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -92,19 +92,14 @@ DIRS += \
 
 ifdef MOZ_B2G_RIL
 DIRS += \
   telephony \
   wifi \
   $(NULL)
 endif
 
-ifdef MOZ_B2G_BT
-DIRS += \
-  bluetooth \
-  $(NULL)
-endif
 TEST_DIRS += tests
 ifneq (,$(filter gtk2 cocoa windows android qt os2,$(MOZ_WIDGET_TOOLKIT)))
 TEST_DIRS += plugins/test
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -75,20 +75,16 @@
 #include "mozilla/Hal.h"
 #include "nsIWebNavigation.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "Connection.h"
 
 #ifdef MOZ_B2G_RIL
 #include "TelephonyFactory.h"
 #endif
-#ifdef MOZ_B2G_BT
-#include "nsIDOMBluetoothAdapter.h"
-#include "BluetoothAdapter.h"
-#endif
 
 // This should not be in the namespace.
 DOMCI_DATA(Navigator, mozilla::dom::Navigator)
 
 namespace mozilla {
 namespace dom {
 
 static const char sJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
@@ -132,19 +128,16 @@ NS_INTERFACE_MAP_BEGIN(Navigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorGeolocation)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorBattery)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorDesktopNotification)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorSms)
 #ifdef MOZ_B2G_RIL
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorTelephony)
 #endif
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorNetwork)
-#ifdef MOZ_B2G_BT
-  NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorBluetooth)
-#endif
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(Navigator)
 NS_IMPL_RELEASE(Navigator)
 
 void
 Navigator::Invalidate()
@@ -184,22 +177,16 @@ Navigator::Invalidate()
     mTelephony = nsnull;
   }
 #endif
 
   if (mConnection) {
     mConnection->Shutdown();
     mConnection = nsnull;
   }
-
-#ifdef MOZ_B2G_BT
-  if (mBluetooth) {
-    mBluetooth = nsnull;
-  }
-#endif
 }
 
 nsPIDOMWindow *
 Navigator::GetWindow()
 {
   nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
 
   return win;
@@ -1120,40 +1107,16 @@ Navigator::GetMozConnection(nsIDOMMozCon
     mConnection = new network::Connection();
     mConnection->Init(window, scx);
   }
 
   NS_ADDREF(*aConnection = mConnection);
   return NS_OK;
 }
 
-#ifdef MOZ_B2G_BT
-//*****************************************************************************
-//    nsNavigator::nsIDOMNavigatorBluetooth
-//*****************************************************************************
-
-NS_IMETHODIMP
-Navigator::GetMozBluetooth(nsIDOMBluetoothAdapter** aBluetooth)
-{
-  nsCOMPtr<nsIDOMBluetoothAdapter> bluetooth = mBluetooth;
-
-  if (!bluetooth) {
-    nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
-    NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-
-    mBluetooth = new bluetooth::BluetoothAdapter();
-
-    bluetooth = mBluetooth;
-  }
-
-  bluetooth.forget(aBluetooth);
-  return NS_OK;
-}
-#endif //MOZ_B2G_BT
-
 PRInt64
 Navigator::SizeOf() const
 {
   PRInt64 size = sizeof(*this);
 
   // TODO: add SizeOf() to nsMimeTypeArray, bug 674113.
   size += mMimeTypes ? sizeof(*mMimeTypes.get()) : 0;
   // TODO: add SizeOf() to nsPluginArray, bug 674114.
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -60,21 +60,16 @@ class nsDesktopNotificationCenter;
 class nsPIDOMWindow;
 class nsIDOMMozConnection;
 
 #ifdef MOZ_B2G_RIL
 #include "nsIDOMNavigatorTelephony.h"
 class nsIDOMTelephony;
 #endif
 
-#ifdef MOZ_B2G_BT
-#include "nsIDOMNavigatorBluetooth.h"
-#endif
-
-class nsIDOMAdapter;
 //*****************************************************************************
 // Navigator: Script "navigator" object
 //*****************************************************************************
 
 namespace mozilla {
 namespace dom {
 
 namespace battery {
@@ -98,19 +93,16 @@ class Navigator : public nsIDOMNavigator
                 , public nsIDOMNavigatorGeolocation
                 , public nsIDOMNavigatorDesktopNotification
                 , public nsIDOMMozNavigatorBattery
                 , public nsIDOMMozNavigatorSms
 #ifdef MOZ_B2G_RIL
                 , public nsIDOMNavigatorTelephony
 #endif
                 , public nsIDOMMozNavigatorNetwork
-#ifdef MOZ_B2G_BT
-                , public nsIDOMNavigatorBluetooth
-#endif
 {
 public:
   Navigator(nsPIDOMWindow *aInnerWindow);
   virtual ~Navigator();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMNAVIGATOR
   NS_DECL_NSIDOMCLIENTINFORMATION
@@ -118,20 +110,16 @@ public:
   NS_DECL_NSIDOMNAVIGATORDESKTOPNOTIFICATION
   NS_DECL_NSIDOMMOZNAVIGATORBATTERY
   NS_DECL_NSIDOMMOZNAVIGATORSMS
 #ifdef MOZ_B2G_RIL
   NS_DECL_NSIDOMNAVIGATORTELEPHONY
 #endif
   NS_DECL_NSIDOMMOZNAVIGATORNETWORK
 
-#ifdef MOZ_B2G_BT
-  NS_DECL_NSIDOMNAVIGATORBLUETOOTH
-#endif
-
   static void Init();
 
   void Invalidate();
   nsPIDOMWindow *GetWindow();
 
   void RefreshMIMEArray();
 
   static bool HasDesktopNotificationSupport();
@@ -153,19 +141,16 @@ private:
   nsRefPtr<nsDesktopNotificationCenter> mNotification;
   nsRefPtr<battery::BatteryManager> mBatteryManager;
   nsRefPtr<power::PowerManager> mPowerManager;
   nsRefPtr<sms::SmsManager> mSmsManager;
 #ifdef MOZ_B2G_RIL
   nsCOMPtr<nsIDOMTelephony> mTelephony;
 #endif
   nsRefPtr<network::Connection> mConnection;
-#ifdef MOZ_B2G_BT
-  nsCOMPtr<nsIDOMBluetoothAdapter> mBluetooth;
-#endif
   nsWeakPtr mWindow;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 nsresult NS_GetNavigatorUserAgent(nsAString& aUserAgent);
 nsresult NS_GetNavigatorPlatform(nsAString& aPlatform);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -527,20 +527,16 @@ using mozilla::dom::indexedDB::IDBWrappe
 #include "mozilla/dom/network/Utils.h"
 
 #ifdef MOZ_B2G_RIL
 #include "Telephony.h"
 #include "TelephonyCall.h"
 #include "CallEvent.h"
 #endif
 
-#ifdef MOZ_B2G_BT
-#include "BluetoothAdapter.h"
-#endif
-
 #include "DOMError.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
@@ -1626,21 +1622,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(Telephony, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(TelephonyCall, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CallEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
-#ifdef MOZ_B2G_BT
-  NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-#endif
-
   NS_DEFINE_CLASSINFO_DATA(DOMError, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 };
 
 // Objects that should be constructable through |new Name();|
 struct nsContractIDMapData
 {
   PRInt32 mDOMClassInfoID;
@@ -2427,19 +2418,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMMozNavigatorBattery,
                                         battery::BatteryManager::HasSupport())
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozNavigatorSms)
 #ifdef MOZ_B2G_RIL
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorTelephony)
 #endif
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMMozNavigatorNetwork,
                                         network::IsAPIEnabled())
-#ifdef MOZ_B2G_BT
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorBluetooth)
-#endif
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Plugin, nsIDOMPlugin)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPlugin)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(PluginArray, nsIDOMPluginArray)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPluginArray)
@@ -4372,22 +4360,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(CallEvent, nsIDOMCallEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCallEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
   DOM_CLASSINFO_MAP_END
 #endif
 
-#ifdef MOZ_B2G_BT
-  DOM_CLASSINFO_MAP_BEGIN(BluetoothAdapter, nsIDOMBluetoothAdapter)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothAdapter)
-  DOM_CLASSINFO_MAP_END
-#endif
-
   DOM_CLASSINFO_MAP_BEGIN(DOMError, nsIDOMDOMError)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMError)
   DOM_CLASSINFO_MAP_END
 
 #ifdef NS_DEBUG
   {
     PRUint32 i = ArrayLength(sClassInfoData);
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -535,13 +535,9 @@ DOMCI_CLASS(MediaQueryList)
 DOMCI_CLASS(CustomEvent)
 
 #ifdef MOZ_B2G_RIL
 DOMCI_CLASS(Telephony)
 DOMCI_CLASS(TelephonyCall)
 DOMCI_CLASS(CallEvent)
 #endif
 
-#ifdef MOZ_B2G_BT
-DOMCI_CLASS(BluetoothAdapter)
-#endif
-
 DOMCI_CLASS(DOMError)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2087,16 +2087,23 @@ nsDOMWindowUtils::GetFileReferences(cons
   }
 
   *aRefCnt = *aDBRefCnt = *aSliceRefCnt = -1;
   *aResult = false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMWindowUtils::IsIncrementalGCEnabled(JSContext* cx, bool* aResult)
+{
+  *aResult = js::IsIncrementalGCEnabled(JS_GetRuntime(cx));
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMWindowUtils::StartPCCountProfiling(JSContext* cx)
 {
   js::StartPCCountProfiling(cx);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::StopPCCountProfiling(JSContext* cx)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -130,16 +130,19 @@ static PRLogModuleInfo* gJSDiagnostics;
 #define NS_GC_DELAY                 4000 // ms
 
 #define NS_SHRINK_GC_BUFFERS_DELAY  4000 // ms
 
 // The amount of time we wait from the first request to GC to actually
 // doing the first GC.
 #define NS_FIRST_GC_DELAY           10000 // ms
 
+// Maximum amount of time that should elapse between incremental GC slices
+#define NS_INTERSLICE_GC_DELAY      100 // ms
+
 // The amount of time we wait between a request to CC (after GC ran)
 // and doing the actual CC.
 #define NS_CC_DELAY                 5000 // ms
 
 #define NS_CC_SKIPPABLE_DELAY       250 // ms
 
 #define NS_CC_FORCED                (5 * 60 * PR_USEC_PER_SEC) // 5 min
 
@@ -149,16 +152,19 @@ static PRLogModuleInfo* gJSDiagnostics;
 
 static nsITimer *sGCTimer;
 static nsITimer *sShrinkGCBuffersTimer;
 static nsITimer *sCCTimer;
 
 static PRTime sLastCCEndTime;
 
 static bool sGCHasRun;
+static bool sCCLockedOut;
+
+static js::GCSliceCallback sPrevGCSliceCallback;
 
 // The number of currently pending document loads. This count isn't
 // guaranteed to always reflect reality and can't easily as we don't
 // have an easy place to know when a load ends or is interrupted in
 // all cases. This counter also gets reset if we end up GC'ing while
 // we're waiting for a slow page to load. IOW, this count may be 0
 // even when there are pending loads.
 static PRUint32 sPendingLoadCount;
@@ -3269,16 +3275,21 @@ nsJSContext::ShrinkGCBuffersNow()
 void
 nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
                              PRInt32 aExtraForgetSkippableCalls)
 {
   if (!NS_IsMainThread()) {
     return;
   }
 
+  if (sCCLockedOut) {
+    // We're in the middle of an incremental GC; finish it first
+    nsJSContext::GarbageCollectNow(js::gcreason::CC_FORCED, nsGCNormal);
+  }
+
   SAMPLE_LABEL("GC", "CycleCollectNow");
   NS_TIME_FUNCTION_MIN(1.0);
 
   KillCCTimer();
 
   PRTime start = PR_Now();
 
   PRUint32 suspected = nsCycleCollector_suspectedCount();
@@ -3352,17 +3363,17 @@ nsJSContext::CycleCollectNow(nsICycleCol
 
 // static
 void
 GCTimerFired(nsITimer *aTimer, void *aClosure)
 {
   NS_RELEASE(sGCTimer);
 
   uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure);
-  nsJSContext::GarbageCollectNow(static_cast<js::gcreason::Reason>(reason), nsGCNormal);
+  nsJSContext::GarbageCollectNow(static_cast<js::gcreason::Reason>(reason), nsGCIncremental);
 }
 
 void
 ShrinkGCBuffersTimerFired(nsITimer *aTimer, void *aClosure)
 {
   NS_RELEASE(sShrinkGCBuffersTimer);
 
   nsJSContext::ShrinkGCBuffersNow();
@@ -3370,16 +3381,19 @@ ShrinkGCBuffersTimerFired(nsITimer *aTim
 
 // static
 void
 CCTimerFired(nsITimer *aTimer, void *aClosure)
 {
   if (sDidShutdown) {
     return;
   }
+  if (sCCLockedOut) {
+    return;
+  }
   ++sCCTimerFireCount;
   if (sCCTimerFireCount < (NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY)) {
     PRUint32 suspected = nsCycleCollector_suspectedCount();
     if ((sPreviousSuspectedCount + 100) > suspected) {
       // Just few new suspected objects, return early.
       return;
     }
     
@@ -3438,36 +3452,38 @@ nsJSContext::LoadEnd()
 
   // Its probably a good idea to GC soon since we have finished loading.
   sLoadingInProgress = false;
   PokeGC(js::gcreason::LOAD_END);
 }
 
 // static
 void
-nsJSContext::PokeGC(js::gcreason::Reason aReason)
+nsJSContext::PokeGC(js::gcreason::Reason aReason, int aDelay)
 {
   if (sGCTimer) {
     // There's already a timer for GC'ing, just return
     return;
   }
 
   CallCreateInstance("@mozilla.org/timer;1", &sGCTimer);
 
   if (!sGCTimer) {
     // Failed to create timer (probably because we're in XPCOM shutdown)
     return;
   }
 
   static bool first = true;
 
   sGCTimer->InitWithFuncCallback(GCTimerFired, reinterpret_cast<void *>(aReason),
-                                 first
-                                 ? NS_FIRST_GC_DELAY
-                                 : NS_GC_DELAY,
+                                 aDelay
+                                 ? aDelay
+                                 : (first
+                                    ? NS_FIRST_GC_DELAY
+                                    : NS_GC_DELAY),
                                  nsITimer::TYPE_ONE_SHOT);
 
   first = false;
 }
 
 // static
 void
 nsJSContext::PokeShrinkGCBuffers()
@@ -3544,71 +3560,92 @@ nsJSContext::KillCCTimer()
 
 void
 nsJSContext::GC(js::gcreason::Reason aReason)
 {
   PokeGC(aReason);
 }
 
 static void
-DOMGCFinishedCallback(JSRuntime *rt, JSCompartment *comp, const char *status)
+DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescription &aDesc)
 {
   NS_ASSERTION(NS_IsMainThread(), "GCs must run on the main thread");
 
-  if (sPostGCEventsToConsole) {
+  if (aDesc.logMessage && sPostGCEventsToConsole) {
     PRTime now = PR_Now();
     PRTime delta = 0;
     if (sFirstCollectionTime) {
       delta = now - sFirstCollectionTime;
     } else {
       sFirstCollectionTime = now;
     }
 
     NS_NAMED_LITERAL_STRING(kFmt, "GC(T+%.1f) %s");
     nsString msg;
     msg.Adopt(nsTextFormatter::smprintf(kFmt.get(),
-                                        double(delta) / PR_USEC_PER_SEC, status));
+                                        double(delta) / PR_USEC_PER_SEC,
+                                        aDesc.logMessage));
     nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     if (cs) {
       cs->LogStringMessage(msg.get());
     }
   }
 
-  sCCollectedWaitingForGC = 0;
-  sCleanupSinceLastGC = false;
-
-  if (sGCTimer) {
-    // If we were waiting for a GC to happen, kill the timer.
+  // Prevent cycle collections during incremental GC.
+  if (aProgress == js::GC_CYCLE_BEGIN) {
+    sCCLockedOut = true;
+  } else if (aProgress == js::GC_CYCLE_END) {
+    sCCLockedOut = false;
+  }
+
+  // The GC has more work to do, so schedule another GC slice.
+  if (aProgress == js::GC_SLICE_END) {
     nsJSContext::KillGCTimer();
-
-    // If this is a compartment GC, restart it. We still want
-    // a full GC to happen. Compartment GCs usually happen as a
-    // result of last-ditch or MaybeGC. In both cases its
-    // probably a time of heavy activity and we want to delay
-    // the full GC, but we do want it to happen eventually.
-    if (comp) {
-      nsJSContext::PokeGC(js::gcreason::POST_COMPARTMENT);
-
-      // We poked the GC, so we can kill any pending CC here.
-      nsJSContext::KillCCTimer();
+    nsJSContext::KillCCTimer();
+
+    nsJSContext::PokeGC(js::gcreason::INTER_SLICE_GC, NS_INTERSLICE_GC_DELAY);
+  }
+
+  if (aProgress == js::GC_CYCLE_END) {
+    sCCollectedWaitingForGC = 0;
+    sCleanupSinceLastGC = false;
+
+    if (sGCTimer) {
+      // If we were waiting for a GC to happen, kill the timer.
+      nsJSContext::KillGCTimer();
+
+      // If this is a compartment GC, restart it. We still want
+      // a full GC to happen. Compartment GCs usually happen as a
+      // result of last-ditch or MaybeGC. In both cases its
+      // probably a time of heavy activity and we want to delay
+      // the full GC, but we do want it to happen eventually.
+      if (aDesc.isCompartment) {
+        nsJSContext::PokeGC(js::gcreason::POST_COMPARTMENT);
+
+        // We poked the GC, so we can kill any pending CC here.
+        nsJSContext::KillCCTimer();
+      }
+    } else {
+      // If this was a full GC, poke the CC to run soon.
+      if (!aDesc.isCompartment) {
+        sGCHasRun = true;
+        nsJSContext::MaybePokeCC();
+      }
     }
-  } else {
-    // If this was a full GC, poke the CC to run soon.
-    if (!comp) {
-      sGCHasRun = true;
-      nsJSContext::MaybePokeCC();
+
+    // If we didn't end up scheduling a GC, make sure that we release GC buffers
+    // soon after canceling previous shrinking attempt.
+    nsJSContext::KillShrinkGCBuffersTimer();
+    if (!sGCTimer) {
+      nsJSContext::PokeShrinkGCBuffers();
     }
   }
 
-  // If we didn't end up scheduling a GC, make sure that we release GC buffers
-  // soon after canceling previous shrinking attempt 
-  nsJSContext::KillShrinkGCBuffersTimer();
-  if (!sGCTimer) {
-    nsJSContext::PokeShrinkGCBuffers();
-  }
+  if (sPrevGCSliceCallback)
+    (*sPrevGCSliceCallback)(aRt, aProgress, aDesc);
 }
 
 // Script object mananagement - note duplicate implementation
 // in nsJSRuntime below...
 nsresult
 nsJSContext::HoldScriptObject(void* aScriptObject)
 {
     NS_ASSERTION(sIsInitialized, "runtime not initialized");
@@ -3692,16 +3729,17 @@ nsJSRuntime::ParseVersion(const nsString
 
 //static
 void
 nsJSRuntime::Startup()
 {
   // initialize all our statics, so that we can restart XPCOM
   sGCTimer = sCCTimer = nsnull;
   sGCHasRun = false;
+  sCCLockedOut = false;
   sLastCCEndTime = 0;
   sPendingLoadCount = 0;
   sLoadingInProgress = false;
   sCCollectedWaitingForGC = 0;
   sPostGCEventsToConsole = false;
   gNameSpaceManager = nsnull;
   sRuntimeService = nsnull;
   sRuntime = nsnull;
@@ -3763,20 +3801,37 @@ SetMemoryMaxPrefChangedCallback(const ch
   PRUint32 max = (pref <= 0 || pref >= 0x1000) ? -1 : (PRUint32)pref * 1024 * 1024;
   JS_SetGCParameter(nsJSRuntime::sRuntime, JSGC_MAX_BYTES, max);
   return 0;
 }
 
 static int
 SetMemoryGCModePrefChangedCallback(const char* aPrefName, void* aClosure)
 {
-  bool enableCompartmentGC = Preferences::GetBool(aPrefName);
-  JS_SetGCParameter(nsJSRuntime::sRuntime, JSGC_MODE, enableCompartmentGC
-                                                      ? JSGC_MODE_COMPARTMENT
-                                                      : JSGC_MODE_GLOBAL);
+  PRBool enableCompartmentGC = Preferences::GetBool("javascript.options.mem.gc_per_compartment");
+  PRBool enableIncrementalGC = Preferences::GetBool("javascript.options.mem.gc_incremental");
+  JSGCMode mode;
+  if (enableIncrementalGC) {
+    mode = JSGC_MODE_INCREMENTAL;
+  } else if (enableCompartmentGC) {
+    mode = JSGC_MODE_COMPARTMENT;
+  } else {
+    mode = JSGC_MODE_GLOBAL;
+  }
+  JS_SetGCParameter(nsJSRuntime::sRuntime, JSGC_MODE, mode);
+  return 0;
+}
+
+static int
+SetMemoryGCSliceTimePrefChangedCallback(const char* aPrefName, void* aClosure)
+{
+  PRInt32 pref = Preferences::GetInt(aPrefName, -1);
+  // handle overflow and negative pref values
+  if (pref > 0 && pref < 100000)
+    JS_SetGCParameter(nsJSRuntime::sRuntime, JSGC_SLICE_TIME_BUDGET, pref);
   return 0;
 }
 
 static JSPrincipals *
 ObjectPrincipalFinder(JSContext *cx, JSObject *obj)
 {
   if (!sSecurityManager)
     return nsnull;
@@ -3853,17 +3908,17 @@ nsJSRuntime::Init()
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = sRuntimeService->GetRuntime(&sRuntime);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Let's make sure that our main thread is the same as the xpcom main thread.
   NS_ASSERTION(NS_IsMainThread(), "bad");
 
-  ::JS_SetGCFinishedCallback(sRuntime, DOMGCFinishedCallback);
+  sPrevGCSliceCallback = js::SetGCSliceCallback(sRuntime, DOMGCSliceCallback);
 
   JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime);
   NS_ASSERTION(callbacks, "SecMan should have set security callbacks!");
 
   callbacks->findObjectPrincipals = ObjectPrincipalFinder;
 
   // Set up the structured clone callbacks.
   static JSStructuredCloneCallbacks cloneCallbacks = {
@@ -3898,16 +3953,26 @@ nsJSRuntime::Init()
   SetMemoryMaxPrefChangedCallback("javascript.options.mem.max",
                                   nsnull);
 
   Preferences::RegisterCallback(SetMemoryGCModePrefChangedCallback,
                                 "javascript.options.mem.gc_per_compartment");
   SetMemoryGCModePrefChangedCallback("javascript.options.mem.gc_per_compartment",
                                      nsnull);
 
+  Preferences::RegisterCallback(SetMemoryGCModePrefChangedCallback,
+                                "javascript.options.mem.gc_incremental");
+  SetMemoryGCModePrefChangedCallback("javascript.options.mem.gc_incremental",
+                                     nsnull);
+
+  Preferences::RegisterCallback(SetMemoryGCSliceTimePrefChangedCallback,
+                                "javascript.options.mem.gc_incremental_slice_ms");
+  SetMemoryGCSliceTimePrefChangedCallback("javascript.options.mem.gc_incremental_slice_ms",
+                                          nsnull);
+
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (!obs)
     return NS_ERROR_FAILURE;
 
   Preferences::AddBoolVarCache(&sGCOnMemoryPressure,
                                "javascript.options.gc_on_memory_pressure",
                                true);
 
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -183,17 +183,17 @@ public:
 
   static void GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind = nsGCNormal);
   static void ShrinkGCBuffersNow();
   // If aExtraForgetSkippableCalls is -1, forgetSkippable won't be
   // called even if the previous collection was GC.
   static void CycleCollectNow(nsICycleCollectorListener *aListener = nsnull,
                               PRInt32 aExtraForgetSkippableCalls = 0);
 
-  static void PokeGC(js::gcreason::Reason aReason);
+  static void PokeGC(js::gcreason::Reason aReason, int aDelay = 0);
   static void KillGCTimer();
 
   static void PokeShrinkGCBuffers();
   static void KillShrinkGCBuffersTimer();
 
   static void MaybePokeCC();
   static void KillCCTimer();
 
deleted file mode 100644
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* 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 "BluetoothAdapter.h"
-#include "nsDOMClassInfo.h"
-
-USING_BLUETOOTH_NAMESPACE
-
-BluetoothAdapter::BluetoothAdapter() : mPower(false)
-{
-}
-
-NS_INTERFACE_MAP_BEGIN(BluetoothAdapter)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
-NS_INTERFACE_MAP_END
-  
-NS_IMPL_ADDREF(BluetoothAdapter)
-NS_IMPL_RELEASE(BluetoothAdapter)
-
-DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
-  
-NS_IMETHODIMP
-BluetoothAdapter::GetPower(bool* aPower)
-{
-  *aPower = mPower;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BluetoothAdapter::SetPower(bool aPower)
-{
-  mPower = aPower;
-  return NS_OK;
-}
deleted file mode 100644
--- a/dom/bluetooth/BluetoothAdapter.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* 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_dom_bluetooth_bluetoothadapter_h__
-#define mozilla_dom_bluetooth_bluetoothadapter_h__
-
-#include "BluetoothCommon.h"
-#include "nsIDOMBluetoothAdapter.h"
-
-BEGIN_BLUETOOTH_NAMESPACE
-
-class BluetoothAdapter : public nsIDOMBluetoothAdapter
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMBLUETOOTHADAPTER
-
-  BluetoothAdapter();
-
-protected:
-  bool mPower;
-};
-
-END_BLUETOOTH_NAMESPACE
-#endif
deleted file mode 100644
--- a/dom/bluetooth/BluetoothCommon.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* 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_dom_bluetooth_bluetoothcommon_h__
-#define mozilla_dom_bluetooth_bluetoothcommon_h__
-
-#define BEGIN_BLUETOOTH_NAMESPACE \
-  namespace mozilla { namespace dom { namespace bluetooth {
-#define END_BLUETOOTH_NAMESPACE \
-  } /* namespace bluetooth */ } /* namespace dom */ } /* namespace mozilla */
-#define USING_BLUETOOTH_NAMESPACE \
-  using namespace mozilla::dom::bluetooth;
-
-class nsIDOMBluetooth;
-
-#endif // mozilla_dom_bluetooth_bluetoothcommon_h__
deleted file mode 100644
--- a/dom/bluetooth/Makefile.in
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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/.
-
-DEPTH            = ../..
-topsrcdir        = @top_srcdir@
-srcdir           = @srcdir@
-VPATH            = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MODULE           = dom
-LIBRARY_NAME     = dombluetooth_s
-XPIDL_MODULE     = dom_bluetooth
-LIBXUL_LIBRARY   = 1
-FORCE_STATIC_LIB = 1
-
-include $(topsrcdir)/dom/dom-config.mk
-
-CPPSRCS = \
-  BluetoothAdapter.cpp \
-  $(NULL)
-
-XPIDLSRCS = \
-  nsIDOMNavigatorBluetooth.idl \
-  nsIDOMBluetoothAdapter.idl \
-  $(NULL)
-
-include $(topsrcdir)/config/rules.mk
-
deleted file mode 100644
--- a/dom/bluetooth/nsIDOMBluetoothAdapter.idl
+++ /dev/null
@@ -1,13 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* 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 "nsISupports.idl"
-
-[scriptable, builtinclass, uuid(29689a22-45ff-4ccf-b552-5364ce3a3642)]
-interface nsIDOMBluetoothAdapter : nsISupports
-{
-  attribute boolean power;
-};
deleted file mode 100644
--- a/dom/bluetooth/nsIDOMNavigatorBluetooth.idl
+++ /dev/null
@@ -1,15 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* 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 "nsISupports.idl"
-
-interface nsIDOMBluetoothAdapter;
-
-[scriptable, uuid(677f2c2d-c4d1-41ea-addc-21d30d0d3858)]
-interface nsIDOMNavigatorBluetooth : nsISupports
-{
-  readonly attribute nsIDOMBluetoothAdapter mozBluetooth;
-};
--- a/dom/dom-config.mk
+++ b/dom/dom-config.mk
@@ -26,14 +26,10 @@ DOM_SRCDIRS = \
 ifdef MOZ_B2G_RIL
 DOM_SRCDIRS += \
   dom/system/b2g \
   dom/telephony \
   dom/wifi \
   $(NULL)
 endif
 
-ifdef MOZ_B2G_BT
-DOM_SRCDIRS += dom/bluetooth
-endif
-
 LOCAL_INCLUDES += $(DOM_SRCDIRS:%=-I$(topsrcdir)/%)
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -65,17 +65,17 @@ interface nsIDOMEvent;
 interface nsITransferable;
 interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMTouch;
 
-[scriptable, uuid(ab6e9c71-8aa1-40bb-8bf9-65e16429055f)]
+[scriptable, uuid(73b48170-55d5-11e1-b86c-0800200c9a66)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -988,16 +988,22 @@ interface nsIDOMWindowUtils : nsISupport
    *
    */
   boolean getFileReferences(in AString aDatabaseName, in long long aId,
                             [optional] out long aRefCnt,
                             [optional] out long aDBRefCnt,
                             [optional] out long aSliceRefCnt);
 
   /**
+   * Return whether incremental GC has been disabled due to a binary add-on.
+   */
+  [implicit_jscontext]
+  boolean isIncrementalGCEnabled();
+
+  /**
    * Begin opcode-level profiling of all JavaScript execution in the window's
    * runtime.
    */
   [implicit_jscontext]
   void startPCCountProfiling();
 
   /**
    * Stop opcode-level profiling of JavaScript execution in the runtime, and
--- a/dom/interfaces/css/nsIDOMCSSStyleDeclaration.idl
+++ b/dom/interfaces/css/nsIDOMCSSStyleDeclaration.idl
@@ -55,14 +55,14 @@ interface nsIDOMCSSStyleDeclaration : ns
 
   DOMString          getPropertyValue(in DOMString propertyName);
   nsIDOMCSSValue     getPropertyCSSValue(in DOMString propertyName);
   DOMString          removeProperty(in DOMString propertyName)
                                         raises(DOMException);
   DOMString          getPropertyPriority(in DOMString propertyName);
   void               setProperty(in DOMString propertyName, 
                                  in DOMString value, 
-                                 in DOMString priority)
+                                 [optional] in DOMString priority)
                                         raises(DOMException);
   readonly attribute unsigned long    length;
   DOMString          item(in unsigned long index);
   readonly attribute nsIDOMCSSRule    parentRule;
 };
--- a/dom/interfaces/events/nsIDOMNSEvent.idl
+++ b/dom/interfaces/events/nsIDOMNSEvent.idl
@@ -39,17 +39,17 @@
 #include "domstubs.idl"
 
 %{C++
 #ifdef ERROR
 #undef ERROR
 #endif
 %}
 
-[scriptable, uuid(9be8096b-f795-4045-9664-0c275f36fe5b)]
+[scriptable, uuid(07F905C1-9170-4103-86CA-766374DA149A)]
 interface nsIDOMNSEvent : nsISupports
 {
   const long MOUSEDOWN    = 0x00000001;
   const long MOUSEUP      = 0x00000002;
   const long MOUSEOVER    = 0x00000004;
   const long MOUSEOUT     = 0x00000008;
   const long MOUSEMOVE    = 0x00000010;
   const long MOUSEDRAG    = 0x00000020;
@@ -92,22 +92,16 @@ interface nsIDOMNSEvent : nsISupports
    * to the target before the retargeting occurs.  For example, mouse events
    * are retargeted to their parent node when they happen over text nodes (bug
    * 185889), and in that case .target will show the parent and
    * .explicitOriginalTarget will show the text node.
    * .explicitOriginalTarget differs from .originalTarget in that it will never
    * contain anonymous content.
    */
   readonly attribute nsIDOMEventTarget  explicitOriginalTarget;
-  /* XXX This is TEMPORARY.  
-   * The original target, without any retargeting (like textnode retargeting).
-   * This really needs to be in .originalTarget, but this is a less risky way of
-   * fixing it.
-   */
-  [noscript] readonly attribute nsIDOMEventTarget  tmpRealOriginalTarget;
 
   /**
    * @deprecated Use nsIDOMEvent::stopPropagation.
    */
   void                      preventBubble();
 
   /**
    * @deprecated Use nsIDOMEvent::stopPropagation.
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -174,17 +174,17 @@ NPObjWrapper_Construct(JSContext *cx, ui
 
 static JSBool
 CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject *npobj,
                      jsid id, NPVariant* getPropertyResult, jsval *vp);
 
 static JSClass sNPObjectJSWrapperClass =
   {
     NPRUNTIME_JSCLASS_NAME,
-    JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
+    JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
     NPObjWrapper_AddProperty, NPObjWrapper_DelProperty,
     NPObjWrapper_GetProperty, NPObjWrapper_SetProperty,
     (JSEnumerateOp)NPObjWrapper_newEnumerate,
     (JSResolveOp)NPObjWrapper_NewResolve, NPObjWrapper_Convert,
     NPObjWrapper_Finalize, nsnull, nsnull, NPObjWrapper_Call,
     NPObjWrapper_Construct, nsnull, nsnull
   };
 
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -3110,18 +3110,23 @@ nsresult nsPluginHost::NewPluginURLStrea
       // Plug-ins seem to depend on javascript: URIs running synchronously
       scriptChannel->SetExecuteAsync(false);
     }
   }
 
   // deal with headers and post data
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
-    rv = httpChannel->SetReferrer(doc->GetDocumentURI());  
-    NS_ENSURE_SUCCESS(rv,rv);
+    if (!aPostStream) {
+      // Only set the Referer header for GET requests because IIS throws
+      // errors about malformed requests if we include it in POSTs. See
+      // bug 724465.
+      rv = httpChannel->SetReferrer(doc->GetDocumentURI());  
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
       
     if (aPostStream) {
       // XXX it's a bit of a hack to rewind the postdata stream
       // here but it has to be done in case the post data is
       // being reused multiple times.
       nsCOMPtr<nsISeekableStream>
       postDataSeekable(do_QueryInterface(aPostStream));
       if (postDataSeekable)
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1385,75 +1385,74 @@ void nsPluginInstanceOwner::CARefresh(ns
     r.left = 0;
     r.top = 0;
     r.right = window->width;
     r.bottom = window->height; 
     instanceOwner->InvalidateRect(&r);
   }
 }
 
-void nsPluginInstanceOwner::AddToCARefreshTimer(nsPluginInstanceOwner *aPluginInstance) {
+void nsPluginInstanceOwner::AddToCARefreshTimer() {
+  if (!mInstance) {
+    return;
+  }
+
+  // Flash invokes InvalidateRect for us.
+  const char* mime = nsnull;
+  if (NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime) {
+    if (strcmp(mime, "application/x-shockwave-flash") == 0) {
+      return;
+    }
+  }
+
   if (!sCARefreshListeners) {
     sCARefreshListeners = new nsTArray<nsPluginInstanceOwner*>();
     if (!sCARefreshListeners) {
       return;
     }
   }
 
-  NS_ASSERTION(!sCARefreshListeners->Contains(aPluginInstance), 
-      "pluginInstanceOwner already registered as a listener");
-  sCARefreshListeners->AppendElement(aPluginInstance);
+  if (sCARefreshListeners->Contains(this)) {
+    return;
+  }
+
+  sCARefreshListeners->AppendElement(this);
 
   if (!sCATimer) {
     sCATimer = new nsCOMPtr<nsITimer>();
     if (!sCATimer) {
       return;
     }
   }
 
   if (sCARefreshListeners->Length() == 1) {
     *sCATimer = do_CreateInstance("@mozilla.org/timer;1");
     (*sCATimer)->InitWithFuncCallback(CARefresh, NULL, 
                    DEFAULT_REFRESH_RATE, nsITimer::TYPE_REPEATING_SLACK);
   }
 }
 
-void nsPluginInstanceOwner::RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPluginInstance) {
-  if (!sCARefreshListeners || sCARefreshListeners->Contains(aPluginInstance) == false) {
+void nsPluginInstanceOwner::RemoveFromCARefreshTimer() {
+  if (!sCARefreshListeners || sCARefreshListeners->Contains(this) == false) {
     return;
   }
 
-  sCARefreshListeners->RemoveElement(aPluginInstance);
+  sCARefreshListeners->RemoveElement(this);
 
   if (sCARefreshListeners->Length() == 0) {
     if (sCATimer) {
       (*sCATimer)->Cancel();
       delete sCATimer;
       sCATimer = NULL;
     }
     delete sCARefreshListeners;
     sCARefreshListeners = NULL;
   }
 }
 
-void nsPluginInstanceOwner::SetupCARefresh()
-{
-  if (!mInstance) {
-    return;
-  }
-
-  const char* mime = nsnull;
-  if (NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime) {
-    // Flash invokes InvalidateRect for us.
-    if (strcmp(mime, "application/x-shockwave-flash") != 0) {
-    AddToCARefreshTimer(this);
-  }
-}
-}
-
 void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext,
                                                 int aWidth, int aHeight)
 {
   if (aWidth == 0 || aHeight == 0)
     return;
 
   if (!mIOSurface ||
       (mIOSurface->GetWidth() != (size_t)aWidth ||
@@ -2694,17 +2693,17 @@ nsPluginInstanceOwner::Destroy()
   if (mObjectFrame)
     mObjectFrame->SetInstanceOwner(nsnull);
 
 #ifdef MAC_CARBON_PLUGINS
   // stop the timer explicitly to reduce reference count.
   CancelTimer();
 #endif
 #ifdef XP_MACOSX
-  RemoveFromCARefreshTimer(this);
+  RemoveFromCARefreshTimer();
   if (mColorProfile)
     ::CGColorSpaceRelease(mColorProfile);  
 #endif
 
   // unregister context menu listener
   if (mCXMenuListener) {
     mCXMenuListener->Destroy(mContent);
     mCXMenuListener = nsnull;
@@ -3272,17 +3271,17 @@ void nsPluginInstanceOwner::ReleasePlugi
   }
 #endif
 }
 
 NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
 {
   NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
 
-    nsresult rv = NS_ERROR_FAILURE;
+  nsresult rv = NS_ERROR_FAILURE;
   
   // Can't call this twice!
   if (mWidget) {
     NS_WARNING("Trying to create a plugin widget twice!");
     return NS_ERROR_FAILURE;
   }
   
   bool windowless = false;
@@ -3313,16 +3312,31 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
       mWidget->Destroy();
       mWidget = nsnull;
       return rv;
     }
 
     mWidget->EnableDragDrop(true);
     mWidget->Show(false);
     mWidget->Enable(false);
+
+#ifdef XP_MACOSX
+    // Now that we have a widget we want to set the event model before
+    // any events are processed.
+    nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
+    if (!pluginWidget) {
+      return NS_ERROR_FAILURE;
+    }
+    pluginWidget->SetPluginEventModel(GetEventModel());
+    pluginWidget->SetPluginDrawingModel(GetDrawingModel());
+
+    if (GetDrawingModel() == NPDrawingModelCoreAnimation) {
+      AddToCARefreshTimer();
+    }
+#endif
   }
 
   if (mObjectFrame) {
     // NULL widget is fine, will result in windowless setup.
     mObjectFrame->PrepForDrawing(mWidget);
   }
 
   if (windowless) {
@@ -3664,42 +3678,52 @@ void nsPluginInstanceOwner::SetFrame(nsO
         // called, so OnDestroyImage() can't yet have been called.  So we need
         // to do ourselves what OnDestroyImage() would have done.
         NS_RELEASE_THIS();
       }
 #endif
       container->SetCurrentImage(nsnull);
     }
 
-    // If we had an old frame and we're not going to have a new one then
-    // we should unregister for some things.
+#if defined(XP_MACOSX) && !defined(NP_NO_QUICKDRAW)
     if (!aFrame) {
-      // Unregister scroll position listeners
+      // At this point we had a frame but it is going away and we're not getting a new one.
+      // Unregister for a scroll position listening, which is only required for Carbon
+      // event model plugins on Mac OS X. It's OK to unregister when we didn't register,
+      // so don't be strict about unregistering. Better to unregister when we didn't have to
+      // than to not unregister when we should.
       for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
         nsIScrollableFrame* sf = do_QueryFrame(f);
         if (sf) {
           sf->RemoveScrollPositionListener(this);
         }
       }
     }
+#endif
 
     // Make sure the old frame isn't holding a reference to us.
     mObjectFrame->SetInstanceOwner(nsnull);
   } else {
+    // Scroll position listening is only required for Carbon event model plugins on Mac OS X.
+    // Note that we probably have a crash bug in the way we register/unregister, bug 723190.
+    // Bug 723190 is mitigated by limiting registration to Carbon event model plugins.
+#if defined(XP_MACOSX) && !defined(NP_NO_QUICKDRAW)
     if (aFrame) {
-      // We didn't have an object frame before but we do now!
-      // We need to register a scroll position listener on every scrollable
-      // frame up to the top
-      for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
-        nsIScrollableFrame* sf = do_QueryFrame(f);
-        if (sf) {
-          sf->AddScrollPositionListener(this);
+      // We didn't have an object frame before but we do now. We need to register a scroll
+      // position listener on every scrollable frame up to the top.
+      if (GetEventModel() == NPEventModelCarbon) {
+        for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
+          nsIScrollableFrame* sf = do_QueryFrame(f);
+          if (sf) {
+            sf->AddScrollPositionListener(this);
+          }
         }
       }
     }
+#endif
   }
 
   // Swap in the new frame (or no frame)
   mObjectFrame = aFrame;
 
   // Set up a new frame
   if (mObjectFrame) {
     mObjectFrame->SetInstanceOwner(this);
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -177,19 +177,18 @@ public:
   
 #ifdef XP_MACOSX
   enum { ePluginPaintEnable, ePluginPaintDisable };
   
   NPDrawingModel GetDrawingModel();
   bool IsRemoteDrawingCoreAnimation();
   NPEventModel GetEventModel();
   static void CARefresh(nsITimer *aTimer, void *aClosure);
-  static void AddToCARefreshTimer(nsPluginInstanceOwner *aPluginInstance);
-  static void RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPluginInstance);
-  void SetupCARefresh();
+  void AddToCARefreshTimer();
+  void RemoveFromCARefreshTimer();
   // This calls into the plugin (NPP_SetWindow) and can run script.
   void* FixUpPluginWindow(PRInt32 inPaintState);
   void HidePluginWindow();
   // Set a flag that (if true) indicates the plugin port info has changed and
   // SetWindow() needs to be called.
   void SetPluginPortChanged(bool aState) { mPluginPortChanged = aState; }
   // Return a pointer to the internal nsPluginPort structure that's used to
   // store a copy of plugin port info and to detect when it's been changed.
--- a/dom/plugins/test/mochitest/Makefile.in
+++ b/dom/plugins/test/mochitest/Makefile.in
@@ -104,16 +104,18 @@ include $(topsrcdir)/config/rules.mk
   test_zero_opacity.html \
   test_NPPVpluginWantsAllNetworkStreams.html \
   test_npruntime_npnsetexception.html \
   test_NPNVdocumentOrigin.html \
   test_instance_re-parent.html \
   test_instance_unparent1.html \
   test_instance_unparent2.html \
   test_instance_unparent3.html \
+  test_pluginstream_referer.html \
+  plugin-stream-referer.sjs \
   $(NULL)
 
 #  test_plugin_scroll_painting.html \ bug 596491
 
 ifeq ($(OS_ARCH),WINNT)
 _MOCHITEST_FILES += \
   test_windowed_invalidate.html \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/plugin-stream-referer.sjs
@@ -0,0 +1,10 @@
+function handleRequest(request, response)
+{
+  response.setHeader('Content-Type', 'text/plain', false);
+  if (request.hasHeader('Referer')) {
+    response.write('Referer found: ' + request.getHeader('Referer'));
+  }
+  else {
+    response.write('No Referer found');
+  }
+}
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_pluginstream_referer.html
@@ -0,0 +1,42 @@
+<head>
+  <title>Do plugin stream requests send the Referer header correctly?</title>
+  <script type="application/javascript"
+	  src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" 
+        href="/tests/SimpleTest/test.css" />
+
+<body onload="runTests()">
+  <p id="display"></p>
+
+  <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+
+  <script class="testbody" type="application/javascript">
+  SimpleTest.waitForExplicitFinish();
+
+  var pending = 2;
+  function testDone() {
+    --pending;
+    if (0 == pending)
+      SimpleTest.finish()
+  }
+
+  function runTests() {
+    var p = document.getElementById('plugin1');
+
+    ok(p.streamTest('plugin-stream-referer.sjs', false, null, null,
+                    function(r, t) {
+                      is(r, 0, "GET plugin-stream-referer.sjs");
+                      is(t, "Referer found: " + window.location,
+                         "GET Referer correct");
+                      testDone();
+                    }, null, true), "referer GET");
+
+    ok(p.streamTest('plugin-stream-referer.sjs', true, "Dummy Data", null,
+                    function(r, t) {
+                      is(r, 0, "POST plugin-stream-referer.sjs");
+                      is(t, "No Referer found", "POST Referer absent");
+                      testDone();
+                    }, null, true), "referer POST");
+  }
+  </script>
+
--- a/dom/src/events/nsJSEventListener.cpp
+++ b/dom/src/events/nsJSEventListener.cpp
@@ -228,16 +228,18 @@ nsJSEventListener::HandleEvent(nsIDOMEve
   JSContext* cx = nsnull;
   nsCOMPtr<nsIJSContextStack> stack =
     do_GetService("@mozilla.org/js/xpc/ContextStack;1");
   NS_ASSERTION(stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx &&
                GetScriptContextFromJSContext(cx) == mContext,
                "JSEventListener has wrong script context?");
 #endif
   nsCOMPtr<nsIVariant> vrv;
+  xpc_UnmarkGrayObject(mScopeObject);
+  xpc_UnmarkGrayObject(mHandler);
   rv = mContext->CallEventHandler(mTarget, mScopeObject, mHandler, iargv,
                                   getter_AddRefs(vrv));
 
   if (NS_SUCCEEDED(rv)) {
     PRUint16 dataType = nsIDataType::VTYPE_VOID;
     if (vrv)
       vrv->GetDataType(&dataType);
 
--- a/dom/wifi/nsIWifi.idl
+++ b/dom/wifi/nsIWifi.idl
@@ -14,17 +14,17 @@
  * The Original Code is Telephony.
  *
  * The Initial Developer of the Original Code is
  * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *  Philipp von Weitershausen <philipp@weitershausen.de>
+ *  Blake Kaplan <mrbkap@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -32,11 +32,19 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
+[scriptable, uuid(14c815f0-e9db-41d4-a15e-f3e69140f83b)]
+interface nsIWifiNetwork : nsISupports {
+    readonly attribute DOMString ssid; // can be null
+    readonly attribute DOMString bssid; // can be null
+    readonly attribute DOMString flags; // TODO make this be real flags instead of a string
+    readonly attribute long signal;
+};
+
 [scriptable, uuid(9DCE05BF-659C-4427-A050-0EAC3BB6C1C0)]
 interface nsIWifi : nsISupports {
 };
--- a/dom/wifi/nsWifiWorker.js
+++ b/dom/wifi/nsWifiWorker.js
@@ -790,82 +790,110 @@ var WifiManager = (function() {
   manager.disableNetwork = function(netId, callback) {
     disableNetworkCommand(netId, callback);
   }
   manager.getMacAddress = getMacAddressCommand;
   manager.getScanResults = scanResultsCommand;
   return manager;
 })();
 
+function WifiNetwork(ssid, bssid, flags, signal) {
+  this.ssid = ssid;
+  this.bssid = bssid;
+  this.flags = flags;
+  this.signal = Number(signal);
+}
+
+WifiNetwork.prototype.QueryInterface = XPCOMUtils.generateQI([Ci.nsIWifiNetwork]);
+
 function nsWifiWorker() {
   WifiManager.onsupplicantconnection = function() {
     debug("Connected to supplicant");
     WifiManager.getMacAddress(function (mac) {
       debug("Got mac: " + mac);
     });
   }
   WifiManager.onsupplicantlost = function() {
     debug("Couldn't connect to supplicant");
   }
 
-  var state;
+  var self = this;
+
+  this.state = null;
+  this.networks = Object.create(null);
   WifiManager.onstatechange = function() {
-    debug("State change: " + state + " -> " + this.state);
-    if (state === "SCANNING" && this.state === "INACTIVE") {
-      // We're not trying to connect so try to find an open Mozilla network.
-      // TODO Remove me in favor of UI and a way to select a network.
+    debug("State change: " + self.state + " -> " + this.state);
+    self.state = this.state;
+
+    // TODO Worth adding a more generic API for this?
+    if (self.state === "INACTIVE" && connectToMozilla.waiting)
+      connectToMozilla();
+  }
+
+  function connectToMozilla() {
+    if (self.state !== "INACTIVE") {
+      connectToMozilla.waiting = true;
+      return;
+    }
+
+    // We're not trying to connect so try to find an open Mozilla network.
+    // TODO Remove me in favor of UI and a way to select a network.
 
-      debug("Haven't connected to a network, trying a default (for now)");
-      var name = "Mozilla";
-      var net = networks[name];
-      if (net && (net[1] && net[1] !== "[IBSS]")) {
-        debug("Network Mozilla exists, but is encrypted");
-        net = null;
+    debug("Haven't connected to a network, trying a default (for now)");
+    var name = "Mozilla";
+    var net = self.networks[name];
+    if (net && (net.flags && net.flags !== "[IBSS]")) {
+      debug("Network Mozilla exists, but is encrypted");
+      net = null;
+    }
+
+    var config = Object.create(null);
+    if (!net) {
+      name = "Mozilla Guest";
+      net = self.networks[name];
+      if (!net || (net.flags && net.flags !== "[IBSS]")) {
+        debug("Can't find either network, trying to force 'Mozilla Guest'");
+        config.scan_ssid = 1;
       }
-      if (!net) {
-        name = "Mozilla Guest";
-        net = networks[name];
-        if (!net || (net[1] && net[1] !== "[IBSS]")) {
-          debug("Network Mozilla Guest doesn't exist or is encrypted");
-          return;
-        }
+    }
+
+    config.ssid = '"' + name + '"';
+    config.key_mgmt = "NONE";
+    WifiManager.addNetwork(config, function(ok) {
+      if (!ok) {
+        debug("Unable to add the network!");
+        return;
       }
 
-      var config = Object.create(null);
-      config["ssid"] = '"' + name + '"';
-      config["key_mgmt"] = "NONE";
-      WifiManager.addNetwork(config, function(ok) {
-        if (!ok) {
-          debug("Unable to add the network!");
-          return;
-        }
+      WifiManager.enableNetwork(config.netId, false, function(ok) {
+        debug((ok ? "Successfully enabled " : "Didn't enable ") + name);
+      });
+    });
+  }
+  this.waitForScan(connectToMozilla);
 
-        WifiManager.enableNetwork(config.netId, false, function(ok) {
-          debug((ok ? "Successfully enabled " : "Didn't enable ") + name);
-        });
-      });
-    }
-
-    state = this.state;
-  }
-
-  var networks = Object.create(null);
   WifiManager.onscanresultsavailable = function() {
     debug("Scan results are available! Asking for them.");
     WifiManager.getScanResults(function(r) {
       let lines = r.split("\n");
       // NB: Skip the header line.
       for (let i = 1; i < lines.length; ++i) {
         // bssid / frequency / signal level / flags / ssid
-        var match = /([\S]+)\s+([\S]+)\s+([\S]+)\s+(\[[\S]+\])?\s+(.*)/.exec(lines[i])
-        if (match)
-          networks[match[5]] = [match[1], match[4]];
-        else
+        var match = /([\S]+)\s+([\S]+)\s+([\S]+)\s+(\[[\S]+\])?\s+(.*)/.exec(lines[i]);
+
+        // TODO Choose bssid based on strength?
+        if (match && match[5])
+          self.networks[match[5]] = new WifiNetwork(match[5], match[1], match[4], match[3]);
+        else if (!match)
           debug("Match didn't find anything for: " + lines[i]);
       }
+
+      if (self.wantScanResults) {
+        self.wantScanResults();
+      }
     });
   }
 
   WifiManager.setWifiEnabled(true, function (ok) {
       if (ok === 0)
         WifiManager.start();
       else
         debug("Couldn't start Wifi");
@@ -880,16 +908,28 @@ nsWifiWorker.prototype = {
                                     contractID: WIFIWORKER_CONTRACTID,
                                     classDescription: "WifiWorker",
                                     interfaces: [Ci.nsIWorkerHolder,
                                                  Ci.nsIWifi]}),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder,
                                          Ci.nsIWifi]),
 
+  // Internal methods.
+  waitForScan: function(callback) {
+    if (this.wantScanResults) {
+      var older = this.wantScanResults;
+      this.wantScanResults = function() { callback(); older(); };
+    } else {
+      this.wantScanResults = callback;
+    }
+  },
+
+  // nsIWifi
+
   setWifiEnabled: function(enable) {
     WifiManager.setWifiEnabled(enable, function (ok) {
       debug(ok);
     });
   },
 
   // This is a bit ugly, but works. In particular, this depends on the fact
   // that RadioManager never actually tries to get the worker from us.
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -166,24 +166,24 @@ private:
     }
 
     *aVp = STRING_TO_JSVAL(jsType);
 
     return true;
   }
 
   static JSBool
-  MozSlice(JSContext* aCx, uintN aArgc, jsval* aVp)
+  Slice(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     if (!obj) {
       return false;
     }
 
-    nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "mozSlice");
+    nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "slice");
     if (!blob) {
       return false;
     }
 
     jsdouble start = 0, end = 0;
     JSString* jsContentType = JS_GetEmptyString(JS_GetRuntime(aCx));
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "/IIS", &start,
                              &end, &jsContentType)) {
@@ -192,20 +192,20 @@ private:
 
     nsDependentJSString contentType;
     if (!contentType.init(aCx, jsContentType)) {
       return false;
     }
 
     PRUint8 optionalArgc = aArgc;
     nsCOMPtr<nsIDOMBlob> rtnBlob;
-    if (NS_FAILED(blob->MozSlice(static_cast<PRUint64>(start),
-                                 static_cast<PRUint64>(end),
-                                 contentType, optionalArgc,
-                                 getter_AddRefs(rtnBlob)))) {
+    if (NS_FAILED(blob->Slice(static_cast<PRUint64>(start),
+                              static_cast<PRUint64>(end),
+                              contentType, optionalArgc,
+                              getter_AddRefs(rtnBlob)))) {
       ThrowFileExceptionForCode(aCx, FILE_NOT_READABLE_ERR);
       return false;
     }
 
     JSObject* rtnObj = file::CreateBlob(aCx, rtnBlob);
     if (!rtnObj) {
       return false;
     }
@@ -225,17 +225,17 @@ JSClass Blob::sClass = {
 
 JSPropertySpec Blob::sProperties[] = {
   { "size", 0, PROPERTY_FLAGS, GetSize, js_GetterOnlyPropertyStub },
   { "type", 0, PROPERTY_FLAGS, GetType, js_GetterOnlyPropertyStub },
   { 0, 0, 0, NULL, NULL }
 };
 
 JSFunctionSpec Blob::sFunctions[] = {
-  JS_FN("mozSlice", MozSlice, 1, JSPROP_ENUMERATE),
+  JS_FN("slice", Slice, 1, JSPROP_ENUMERATE),
   JS_FS_END
 };
 
 class File : public Blob
 {
   // File should never be instantiated.
   File();
   ~File();
--- a/dom/workers/ListenerManager.cpp
+++ b/dom/workers/ListenerManager.cpp
@@ -102,16 +102,19 @@ struct Listener : PRCList
     listener->mPhase = aPhase;
     listener->mWantsUntrusted = aWantsUntrusted;
     return listener;
   }
 
   static void
   Remove(JSContext* aCx, Listener* aListener)
   {
+    if (js::IsIncrementalBarrierNeeded(aCx))
+      js::IncrementalValueBarrier(aListener->mListenerVal);
+
     PR_REMOVE_LINK(aListener);
     JS_free(aCx, aListener);
   }
 
   jsval mListenerVal;
   ListenerManager::Phase mPhase;
   bool mWantsUntrusted;
 };
--- a/dom/workers/Worker.cpp
+++ b/dom/workers/Worker.cpp
@@ -295,17 +295,17 @@ private:
     }
 
     return worker->PostMessage(aCx, message);
   }
 };
 
 JSClass Worker::sClass = {
   "Worker",
-  JSCLASS_HAS_PRIVATE,
+  JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize, NULL, NULL, NULL,
   NULL, NULL, NULL, Trace, NULL
 };
 
 JSPropertySpec Worker::sProperties[] = {
   { sEventStrings[STRING_onerror], STRING_onerror, PROPERTY_FLAGS,
     GetEventListener, SetEventListener },
@@ -410,17 +410,17 @@ private:
     if (worker) {
       worker->TraceInstance(aTrc);
     }
   }
 };
 
 JSClass ChromeWorker::sClass = {
   "ChromeWorker",
-  JSCLASS_HAS_PRIVATE,
+  JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize, NULL, NULL, NULL,
   NULL, NULL, NULL, Trace, NULL
 };
 
 WorkerPrivate*
 Worker::GetInstancePrivate(JSContext* aCx, JSObject* aObj,
                            const char* aFunctionName)
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -794,17 +794,17 @@ private:
     }
 
     return scope->mWorker->PostMessageToParent(aCx, message);
   }
 };
 
 JSClass DedicatedWorkerGlobalScope::sClass = {
   "DedicatedWorkerGlobalScope",
-  JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
+  JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_NEW_RESOLVE,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, reinterpret_cast<JSResolveOp>(Resolve), JS_ConvertStub,
   Finalize, NULL, NULL, NULL, NULL, NULL, NULL, Trace, NULL
 };
 
 JSPropertySpec DedicatedWorkerGlobalScope::sProperties[] = {
   { sEventStrings[STRING_onmessage], STRING_onmessage, PROPERTY_FLAGS,
     GetEventListener, SetEventListener },
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -215,17 +215,17 @@ private:
     }
 
     return priv->SetEventListenerOnEventTarget(aCx, name + 2, aVp);
   }
 };
 
 JSClass XMLHttpRequestUpload::sClass = {
   "XMLHttpRequestUpload",
-  JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
+  JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
   NULL, NULL, NULL, NULL, NULL, NULL, Trace, NULL
 };
 
 JSPropertySpec XMLHttpRequestUpload::sProperties[] = {
   { sEventStrings[STRING_onabort], STRING_onabort, PROPERTY_FLAGS,
     GetEventListener, SetEventListener },
@@ -764,17 +764,17 @@ private:
     }
 
     return priv->OverrideMimeType(aCx, mimeType);
   }
 };
 
 JSClass XMLHttpRequest::sClass = {
   "XMLHttpRequest",
-  JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
+  JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
   NULL, NULL, NULL, NULL, NULL, NULL, Trace, NULL
 };
 
 JSPropertySpec XMLHttpRequest::sProperties[] = {
 
 #define GENERIC_READONLY_PROPERTY(_name) \
--- a/dom/workers/test/Makefile.in
+++ b/dom/workers/test/Makefile.in
@@ -131,31 +131,31 @@ include $(topsrcdir)/config/rules.mk
   $(NULL)
 
 _CHROME_TEST_FILES = \
   test_chromeWorker.xul \
   test_chromeWorkerJSM.xul \
   test_extension.xul \
   test_extensionBootstrap.xul \
   test_file.xul \
-  test_fileMozSlice.xul \
+  test_fileSlice.xul \
   test_fileBlobPosting.xul \
   test_filePosting.xul \
   test_fileReaderSync.xul \
   test_fileReaderSyncErrors.xul \
-  test_fileReadMozSlice.xul \
+  test_fileReadSlice.xul \
   test_fileSubWorker.xul \
   test_fileBlobSubWorker.xul \
   file_worker.js \
   fileBlob_worker.js \
-  fileMozSlice_worker.js \
+  fileSlice_worker.js \
   filePosting_worker.js \
   fileReaderSync_worker.js \
   fileReaderSyncErrors_worker.js \
-  fileReadMozSlice_worker.js \
+  fileReadSlice_worker.js \
   fileSubWorker_worker.js \
   fileBlobSubWorker_worker.js \
   WorkerTest.jsm \
   WorkerTest_worker.js \
   WorkerTest_subworker.js \
   chromeWorker_worker.js \
   chromeWorker_subworker.js \
   test_workersDisabled.xul \
rename from dom/workers/test/fileReadMozSlice_worker.js
rename to dom/workers/test/fileReadSlice_worker.js
--- a/dom/workers/test/fileReadMozSlice_worker.js
+++ b/dom/workers/test/fileReadSlice_worker.js
@@ -2,15 +2,15 @@
  * Expects an object containing a blob, a start index and an end index
  * for slicing. Returns the contents of the blob read as text.
  */
 onmessage = function(event) {
   var blob = event.data.blob;
   var start = event.data.start;
   var end = event.data.end;
 
-  var slicedBlob = blob.mozSlice(start, end);
+  var slicedBlob = blob.slice(start, end);
 
   var fileReader = new FileReaderSync();
   var text = fileReader.readAsText(slicedBlob);
 
   postMessage(text);
 };
rename from dom/workers/test/fileMozSlice_worker.js
rename to dom/workers/test/fileSlice_worker.js
--- a/dom/workers/test/fileMozSlice_worker.js
+++ b/dom/workers/test/fileSlice_worker.js
@@ -6,21 +6,21 @@
 onmessage = function(event) {
   var blob = event.data.blob;
   var start = event.data.start;
   var end = event.data.end;
   var contentType = event.data.contentType;
 
   var slicedBlob;
   if (contentType == undefined && end == undefined) {
-    slicedBlob = blob.mozSlice(start);
+    slicedBlob = blob.slice(start);
   } else if (contentType == undefined) {
-    slicedBlob = blob.mozSlice(start, end);
+    slicedBlob = blob.slice(start, end);
   } else {
-    slicedBlob = blob.mozSlice(start, end, contentType);
+    slicedBlob = blob.slice(start, end, contentType);
   }
 
   var rtnObj = new Object();
 
   rtnObj.size = slicedBlob.size;
   rtnObj.type = slicedBlob.type;
 
   postMessage(rtnObj);
--- a/dom/workers/test/test_fileBlobPosting.xul
+++ b/dom/workers/test/test_fileBlobPosting.xul
@@ -65,17 +65,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     };
 
     worker.onmessage = function(event) {
       console.log(event.data);
       is(event.data.size, file.size, "size of file posted from worker does not match file posted to worker.");
       finish();
     };
 
-    var blob = file.mozSlice();
+    var blob = file.slice();
     worker.postMessage(blob);
     waitForWorkerFinish();
   }
 
   // Empty file.
   postBlob(createFileWithData(""));
 
   // Typical use case.
--- a/dom/workers/test/test_fileBlobSubWorker.xul
+++ b/dom/workers/test/test_fileBlobSubWorker.xul
@@ -67,17 +67,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       if (event.data == undefined) {
         ok(false, "Worker had an error.");
       } else {
         is(event.data.size, expectedSize, "size proproperty accessed from worker is not the same as on main thread.");
       }
       finish();
     };
 
-    var blob = file.mozSlice();
+    var blob = file.slice();
     worker.postMessage(blob);
     waitForWorkerFinish();
   }
 
   // Empty file.
   accessFileProperties(createFileWithData(""), 0);
 
   // Typical use case.
rename from dom/workers/test/test_fileReadMozSlice.xul
rename to dom/workers/test/test_fileReadSlice.xul
--- a/dom/workers/test/test_fileReadMozSlice.xul
+++ b/dom/workers/test/test_fileReadSlice.xul
@@ -31,17 +31,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   /**
    * Create a file which contains the given data.
    */
   function createFileWithData(fileData) {
     var testFile = Components.classes["@mozilla.org/file/directory_service;1"]
                        .getService(Components.interfaces.nsIProperties)
                        .get("ProfD", Components.interfaces.nsIFile);
-    testFile.append("workerReadMozSlice" + fileNum++);
+    testFile.append("workerReadSlice" + fileNum++);
 
     var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                         .createInstance(Components.interfaces.nsIFileOutputStream);
     outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
                    0666, 0);
     outStream.write(fileData, fileData.length);
     outStream.close();
 
@@ -50,18 +50,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     return fileList.files[0];
   }
 
   /**
    * Creates a worker which slices a blob to the given start and end offset and
    * reads the content as text.
    */
-  function readMozSlice(blob, start, end, expectedText) {
-    var worker = new Worker("fileReadMozSlice_worker.js");
+  function readSlice(blob, start, end, expectedText) {
+    var worker = new Worker("fileReadSlice_worker.js");
 
     worker.onerror = function(event) {
       ok(false, "Worker had an error: " + event.data);
       finish();
     };
 
     worker.onmessage = function(event) {
       is(event.data, expectedText, "Text from sliced blob in worker is incorrect.");
@@ -69,22 +69,22 @@ https://bugzilla.mozilla.org/show_bug.cg
     };
 
     var params = {blob: blob, start: start, end: end};
     worker.postMessage(params);
     waitForWorkerFinish();
   }
 
   // Empty file.
-  readMozSlice(createFileWithData(""), 0, 0, "");
+  readSlice(createFileWithData(""), 0, 0, "");
 
   // Typical use case.
-  readMozSlice(createFileWithData("HelloBye"), 5, 8, "Bye");
+  readSlice(createFileWithData("HelloBye"), 5, 8, "Bye");
 
   // End offset too large.
-  readMozSlice(createFileWithData("HelloBye"), 5, 9, "Bye");
+  readSlice(createFileWithData("HelloBye"), 5, 9, "Bye");
 
   // Start of file.
-  readMozSlice(createFileWithData("HelloBye"), 0, 5, "Hello");
+  readSlice(createFileWithData("HelloBye"), 0, 5, "Hello");
 
   ]]>
   </script>
 </window>
rename from dom/workers/test/test_fileMozSlice.xul
rename to dom/workers/test/test_fileSlice.xul
--- a/dom/workers/test/test_fileMozSlice.xul
+++ b/dom/workers/test/test_fileSlice.xul
@@ -32,17 +32,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   /**
    * Create a file which contains the given data and optionally adds the specified file extension.
    */
   function createFileWithData(fileData, /** optional */ extension) {
     var testFile = Components.classes["@mozilla.org/file/directory_service;1"]
                        .getService(Components.interfaces.nsIProperties)
                        .get("ProfD", Components.interfaces.nsIFile);
     var fileExtension = (extension == undefined) ? "" : "." + extension;
-    testFile.append("workerMozSlice" + fileNum++ + fileExtension);
+    testFile.append("workerSlice" + fileNum++ + fileExtension);
 
     var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                         .createInstance(Components.interfaces.nsIFileOutputStream);
     outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
                    0666, 0);
     outStream.write(fileData, fileData.length);
     outStream.close();
 
@@ -51,18 +51,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     return fileList.files[0];
   }
 
   /**
    * Starts a worker which slices the blob to the given start offset and optional end offset and
    * content type. It then verifies that the size and type of the sliced blob is correct.
    */
-  function createMozSlice(blob, start, expectedLength, /** optional */ end, /** optional */ contentType) {
-    var worker = new Worker("fileMozSlice_worker.js");
+  function createSlice(blob, start, expectedLength, /** optional */ end, /** optional */ contentType) {
+    var worker = new Worker("fileSlice_worker.js");
 
     worker.onerror = function(event) {
       ok(false, "Worker had an error: " + event.data);
       finish();
     };
 
     worker.onmessage = function(event) {
       is(event.data.size, expectedLength, "size property of slice is incorrect.");
@@ -71,36 +71,36 @@ https://bugzilla.mozilla.org/show_bug.cg
     };
 
     var params = {blob: blob, start: start, end: end, contentType: contentType};
     worker.postMessage(params);
     waitForWorkerFinish();
   }
 
   // Empty file.
-  createMozSlice(createFileWithData(""), 0, 0, 0);
+  createSlice(createFileWithData(""), 0, 0, 0);
 
   // Typical use case.
-  createMozSlice(createFileWithData("Hello"), 1, 1, 2);
+  createSlice(createFileWithData("Hello"), 1, 1, 2);
 
   // Longish file.
   var text = "";
   for (var i = 0; i < 10000; ++i) {
     text += "long";
   }
-  createMozSlice(createFileWithData(text), 2000, 2000, 4000);
+  createSlice(createFileWithData(text), 2000, 2000, 4000);
 
   // Slice to different type.
-  createMozSlice(createFileWithData("text", "txt"), 0, 2, 2, "image/png");
+  createSlice(createFileWithData("text", "txt"), 0, 2, 2, "image/png");
 
   // Length longer than blob.
-  createMozSlice(createFileWithData("text"), 0, 4, 20);
+  createSlice(createFileWithData("text"), 0, 4, 20);
 
   // Start longer than blob.
-  createMozSlice(createFileWithData("text"), 20, 0, 4);
+  createSlice(createFileWithData("text"), 20, 0, 4);
 
   // No optional arguments
-  createMozSlice(createFileWithData("text"), 0, 4);
-  createMozSlice(createFileWithData("text"), 2, 2);
+  createSlice(createFileWithData("text"), 0, 4);
+  createSlice(createFileWithData("text"), 2, 2);
 
   ]]>
   </script>
 </window>
--- a/editor/composer/src/nsEditorSpellCheck.cpp
+++ b/editor/composer/src/nsEditorSpellCheck.cpp
@@ -78,17 +78,17 @@ class UpdateDictionnaryHolder {
       if (mSpellCheck) {
         mSpellCheck->EndUpdateDictionary();
       }
     }
 };
 
 #define CPS_PREF_NAME NS_LITERAL_STRING("spellcheck.lang")
 
-class LastDictionary {
+class LastDictionary MOZ_FINAL {
 public:
   /**
    * Store current dictionary for editor document url. Use content pref
    * service.
    */
   NS_IMETHOD StoreCurrentDictionary(nsIEditor* aEditor, const nsAString& aDictionary);
 
   /**
--- a/editor/idl/nsIEditor.idl
+++ b/editor/idl/nsIEditor.idl
@@ -50,17 +50,17 @@ interface nsIDocumentStateListener;
 interface nsIOutputStream;
 interface nsITransactionManager;
 interface nsITransaction;
 interface nsIEditorObserver;
 interface nsIEditActionListener;
 interface nsIInlineSpellChecker;
 interface nsITransferable;
 
-[scriptable, uuid(20ee0b70-c528-11e0-9572-0800200c9a66)]
+[scriptable, uuid(94479B76-7FD7-47D3-BB1E-5B77846339D2)]
 
 interface nsIEditor  : nsISupports
 {
 %{C++
   typedef short EDirection;
 %}
   const short eNone = 0;
   const short eNext = 1;
@@ -355,36 +355,16 @@ interface nsIEditor  : nsISupports
   void selectAll();
 
   /** sets the document selection to the beginning of the document */
   void beginningOfDocument();
 
   /** sets the document selection to the end of the document */
   void endOfDocument();
 
-   /* ------------ Drag/Drop methods -------------- */
-  
-   /** 
-    * canDrag decides if a drag should be started
-    * (for example, based on the current selection and mousepoint).
-    */
-  boolean canDrag(in nsIDOMEvent aEvent);
- 
-   /** 
-    * doDrag transfers the relevant data (as appropriate)
-    * to a transferable so it can later be dropped.
-    */
-  void doDrag(in nsIDOMEvent aEvent);
- 
-   /** 
-    * insertFromDrop looks for a dragsession and inserts the
-    * relevant data in response to a drop.
-    */
-  void insertFromDrop(in nsIDOMEvent aEvent);
-
   /* ------------ Node manipulation methods -------------- */
 
   /**
    * setAttribute() sets the attribute of aElement.
    * No checking is done to see if aAttribute is a legal attribute of the node,
    * or if aValue is a legal value of aAttribute.
    *
    * @param aElement    the content element to operate on
--- a/editor/idl/nsIHTMLEditor.idl
+++ b/editor/idl/nsIHTMLEditor.idl
@@ -47,17 +47,17 @@ interface nsISupportsArray;
 interface nsISelection;
 interface nsIContentFilter;
 
 %{C++
 #define NS_EDITOR_ELEMENT_NOT_FOUND \
   NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_EDITOR, 1)
 
 %}
-[scriptable, uuid(d58f35a7-c269-4292-b9aa-a79e200a7c99)]
+[scriptable, uuid(FF67AD39-ED58-4CD1-A1A3-DCD988390A97)]
 
 interface nsIHTMLEditor : nsISupports
 {
 %{C++
   typedef short EAlignment;
 %}
 
   // used by GetAlignment()
@@ -194,36 +194,16 @@ interface nsIHTMLEditor : nsISupports
 
   /**
    *  Decrease font size for text in selection by 1 HTML unit
    *  All existing text is scanned for existing <FONT SIZE> attributes
    *  so they will be decreased instead of inserting new <FONT> tag
    */
   void decreaseFontSize();
 
-  /* ------------ Drag/Drop methods -------------- */
-
-  /** 
-   * canDrag decides if a drag should be started
-   * (for example, based on the current selection and mousepoint).
-   */
-  boolean canDrag(in nsIDOMEvent aEvent);
-
-  /** 
-   * doDrag transfers the relevant data (as appropriate)
-   * to a transferable so it can later be dropped.
-   */
-  void doDrag(in nsIDOMEvent aEvent);
-
-  /** 
-   * insertFromDrop looks for a dragsession and inserts the
-   * relevant data in response to a drop.
-   */
-  void insertFromDrop(in nsIDOMEvent aEvent);
-
   /* ------------ HTML content methods -------------- */
 
   /**
    * Tests if a node is a BLOCK element according the the HTML 4.0 DTD.
    *   This does NOT consider CSS effect on display type
    *
    * @param aNode      the node to test
    */
@@ -529,22 +509,16 @@ interface nsIHTMLEditor : nsISupports
    *
    * 8/31/00 THIS ISN'T BEING USED? SHOULD WE DROP IT?
    *
    * @param aAttr   The attribute to be set
    * @param aValue  The value of the attribute
    */
   void setBodyAttribute(in AString aAttr, in AString aValue);
   
-  /** 
-   * XXX Used to suppress spurious drag/drop events to workaround bug 50703
-   * Don't use this method! It will go away after first release!
-   */
-  void ignoreSpuriousDragEvent(in boolean aIgnoreSpuriousDragEvent);
-
   /**
    * Find all the nodes in the document which contain references
    * to outside URIs (e.g. a href, img src, script src, etc.)
    * The objects in the array will be type nsIURIRefObject.
    *
    * @return aNodeList    the linked nodes found
    */
   nsISupportsArray getLinkedObjects();
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -1186,35 +1186,16 @@ nsEditor::CanPaste(PRInt32 aSelectionTyp
 }
 
 NS_IMETHODIMP
 nsEditor::CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste)
 {
   return NS_ERROR_NOT_IMPLEMENTED; 
 }
 
-NS_IMETHODIMP
-nsEditor::CanDrag(nsIDOMEvent *aEvent, bool *aCanDrag)
-{
-  return NS_ERROR_NOT_IMPLEMENTED; 
-}
-
-NS_IMETHODIMP
-nsEditor::DoDrag(nsIDOMEvent *aEvent)
-{
-  return NS_ERROR_NOT_IMPLEMENTED; 
-}
-
-NS_IMETHODIMP
-nsEditor::InsertFromDrop(nsIDOMEvent *aEvent)
-{
-  return NS_ERROR_NOT_IMPLEMENTED; 
-}
-
-
 NS_IMETHODIMP 
 nsEditor::SetAttribute(nsIDOMElement *aElement, const nsAString & aAttribute, const nsAString & aValue)
 {
   nsRefPtr<ChangeAttributeTxn> txn;
   nsresult result = CreateTxnForSetAttribute(aElement, aAttribute, aValue,
                                              getter_AddRefs(txn));
   if (NS_SUCCEEDED(result))  {
     result = DoTransaction(txn);  
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -752,16 +752,30 @@ public:
   // nothing.
   nsresult InitializeSelection(nsIDOMEventTarget* aFocusEventTarget);
 
   // This method has to be called by nsEditorEventListener::Focus.
   // All actions that have to be done when the editor is focused needs to be
   // added here.
   void OnFocus(nsIDOMEventTarget* aFocusEventTarget);
 
+  // Used to insert content from a data transfer into the editable area.
+  // This is called for each item in the data transfer, with the index of
+  // each item passed as aIndex.
+  virtual nsresult InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
+                                          PRInt32 aIndex,
+                                          nsIDOMDocument *aSourceDoc,
+                                          nsIDOMNode *aDestinationNode,
+                                          PRInt32 aDestOffset,
+                                          bool aDoDeleteSelection) = 0;
+
+  virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent) = 0;
+
+  virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode) { return nsnull; }
+
 protected:
 
   PRUint32        mModCount;     // number of modifications (for undo/redo stack)
   PRUint32        mFlags;        // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
 
   nsWeakPtr       mSelConWeak;   // weak reference to the nsISelectionController
   PRInt32         mUpdateCount;
 
--- a/editor/libeditor/base/nsEditorEventListener.cpp
+++ b/editor/libeditor/base/nsEditorEventListener.cpp
@@ -56,18 +56,16 @@
 #include "nsFocusManager.h"
 #include "nsEventListenerManager.h"
 #include "nsIMEStateManager.h"
 #include "mozilla/Preferences.h"
 
 // Drag & Drop, Clipboard
 #include "nsIServiceManager.h"
 #include "nsIClipboard.h"
-#include "nsIDragService.h"
-#include "nsIDragSession.h"
 #include "nsIContent.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIDOMRange.h"
 #include "nsEditorUtils.h"
 #include "nsISelectionPrivate.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIFocusManager.h"
 #include "nsIDOMWindow.h"
@@ -153,21 +151,16 @@ nsEditorEventListener::InstallToEditor()
                                NS_LITERAL_STRING("keyup"),
                                NS_EVENT_FLAG_BUBBLE |
                                NS_EVENT_FLAG_SYSTEM_EVENT);
 #endif
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("keypress"),
                                NS_EVENT_FLAG_BUBBLE |
                                NS_EVENT_FLAG_SYSTEM_EVENT);
-  // See bug 455215, we cannot use the standard dragstart event yet
-  elmP->AddEventListenerByType(this,
-                               NS_LITERAL_STRING("draggesture"),
-                               NS_EVENT_FLAG_BUBBLE |
-                               NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("dragenter"),
                                NS_EVENT_FLAG_BUBBLE |
                                NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("dragover"),
                                NS_EVENT_FLAG_BUBBLE |
                                NS_EVENT_FLAG_SYSTEM_EVENT);
@@ -251,20 +244,16 @@ nsEditorEventListener::UninstallFromEdit
                                   NS_EVENT_FLAG_BUBBLE |
                                   NS_EVENT_FLAG_SYSTEM_EVENT);
 #endif
   elmP->RemoveEventListenerByType(this,
                                   NS_LITERAL_STRING("keypress"),
                                   NS_EVENT_FLAG_BUBBLE |
                                   NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->RemoveEventListenerByType(this,
-                                  NS_LITERAL_STRING("draggesture"),
-                                  NS_EVENT_FLAG_BUBBLE |
-                                  NS_EVENT_FLAG_SYSTEM_EVENT);
-  elmP->RemoveEventListenerByType(this,
                                   NS_LITERAL_STRING("dragenter"),
                                   NS_EVENT_FLAG_BUBBLE |
                                   NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->RemoveEventListenerByType(this,
                                   NS_LITERAL_STRING("dragover"),
                                   NS_EVENT_FLAG_BUBBLE |
                                   NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->RemoveEventListenerByType(this,
@@ -327,18 +316,16 @@ nsEditorEventListener::HandleEvent(nsIDO
 {
   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
 
   nsAutoString eventType;
   aEvent->GetType(eventType);
 
   nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
   if (dragEvent) {
-    if (eventType.EqualsLiteral("draggesture"))
-      return DragGesture(dragEvent);
     if (eventType.EqualsLiteral("dragenter"))
       return DragEnter(dragEvent);
     if (eventType.EqualsLiteral("dragover"))
       return DragOver(dragEvent);
     if (eventType.EqualsLiteral("dragexit"))
       return DragExit(dragEvent);
     if (eventType.EqualsLiteral("drop"))
       return Drop(dragEvent);
@@ -654,28 +641,16 @@ nsEditorEventListener::HandleText(nsIDOM
   return mEditor->UpdateIMEComposition(composedText, textRangeList);
 }
 
 /**
  * Drag event implementation
  */
 
 nsresult
-nsEditorEventListener::DragGesture(nsIDOMDragEvent* aDragEvent)
-{
-  // ...figure out if a drag should be started...
-  bool canDrag;
-  nsresult rv = mEditor->CanDrag(aDragEvent, &canDrag);
-  if ( NS_SUCCEEDED(rv) && canDrag )
-    rv = mEditor->DoDrag(aDragEvent);
-
-  return rv;
-}
-
-nsresult
 nsEditorEventListener::DragEnter(nsIDOMDragEvent* aDragEvent)
 {
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_OK);
 
   if (!mCaret) {
     mCaret = new nsCaret();
     mCaret->Init(presShell);
@@ -718,16 +693,20 @@ nsEditorEventListener::DragOver(nsIDOMDr
         mCaret->EraseCaret();
       
       //mCaret->SetCaretVisible(true);   // make sure it's visible
       mCaret->DrawAtPosition(parent, offset);
     }
   }
   else
   {
+    // This is needed when dropping on an input, to prevent the editor for
+    // the editable parent from receiving the event.
+    aDragEvent->StopPropagation();
+
     if (mCaret)
     {
       mCaret->EraseCaret();
     }
   }
 
   return NS_OK;
 }
@@ -789,18 +768,16 @@ nsEditorEventListener::Drop(nsIDOMDragEv
       // editfields if that is what is desired.
       return aMouseEvent->StopPropagation();
     }
     return NS_OK;
   }
 
   aMouseEvent->StopPropagation();
   aMouseEvent->PreventDefault();
-  // Beware! This may flush notifications via synchronous
-  // ScrollSelectionIntoView.
   return mEditor->InsertFromDrop(aMouseEvent);
 }
 
 bool
 nsEditorEventListener::CanDrop(nsIDOMDragEvent* aEvent)
 {
   // if the target doc is read-only, we can't drop
   if (mEditor->IsReadonly() || mEditor->IsDisabled()) {
--- a/editor/libeditor/base/nsEditorUtils.h
+++ b/editor/libeditor/base/nsEditorUtils.h
@@ -252,17 +252,16 @@ struct NS_STACK_CLASS DOMPoint
 class nsEditorUtils
 {
   public:
     static bool IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 *aOffset = 0);
     static bool IsLeafNode(nsIDOMNode *aNode);
 };
 
 
-class nsIDragSession;
 class nsITransferable;
 class nsIDOMEvent;
 class nsISimpleEnumerator;
 
 class nsEditorHookUtils
 {
   public:
     static bool     DoInsertionHook(nsIDOMDocument *aDoc, nsIDOMEvent *aEvent,
--- a/editor/libeditor/base/tests/Makefile.in
+++ b/editor/libeditor/base/tests/Makefile.in
@@ -51,16 +51,17 @@ include $(topsrcdir)/config/rules.mk
 		file_bug586662.html \
 		test_bug586662.html \
 		$(NULL)
 
 _CHROME_TEST_FILES = \
 		test_selection_move_commands.xul \
                 test_bug46555.html \
 		test_bug646194.xul \
+		test_dragdrop.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
 
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/base/tests/test_dragdrop.html
@@ -0,0 +1,163 @@
+<html>
+
+<head>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
+</head>
+
+<body>
+  <span id="text" style="font-size: 40px;">Some Text</span>
+
+  <input id="input" value="Drag Me">
+  <textarea id="textarea">Some Text To Drag</textarea>
+  <p id="contenteditable" contenteditable="true">This is some <b id="bold">editable</b> text.</p>
+
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// This listener allows us to clear the default data for the selection added for the drag.
+var shouldClear = false;
+window.addEventListener("dragstart", function (event) { if (shouldClear) event.dataTransfer.clearData() }, true);
+
+function doTest()
+{
+  const htmlContextData = { type: 'text/_moz_htmlcontext',
+                            data: '<html><body></body></html>' };
+  const htmlInfoData = { type: 'text/_moz_htmlinfo', data: '0,0' };
+  const htmlData = { type: 'text/html', data: '<span id="text" style="font-size: 40px;">Some Text</span>' };
+
+  const htmlContextDataEditable = { type: 'text/_moz_htmlcontext',
+                                    data: '<html><body><p id="contenteditable" contenteditable="true"></p></body></html>' };
+
+  var text = document.getElementById("text");
+  var input = document.getElementById("input");
+  var contenteditable = document.getElementById("contenteditable");
+
+  var selection = window.getSelection();
+
+  // -------- Test dragging regular text
+  selection.selectAllChildren(text);
+  var result = synthesizeDragStart(text, [[htmlContextData, htmlInfoData, htmlData,
+                                           {type: "text/plain", data: "Some Text"}]], window, 40, 10);
+  ok(!result, "Test dragging regular text");
+
+  // -------- Test dragging text from an <input>
+  input.setSelectionRange(1, 4);
+  result = synthesizeDragStart(input, [[{type: "text/plain", data: "rag"}]], window, 25, 6);
+  ok(!result, "Test dragging input");
+
+  // -------- Test dragging text from a <textarea>
+  textarea.setSelectionRange(1, 7);
+  result = synthesizeDragStart(textarea, [[{type: "text/plain", data: "ome Te"}]], window, 25, 6);
+  ok(!result, "Test dragging textarea");
+  textarea.blur();
+
+  // -------- Test dragging text from a contenteditable
+  selection.selectAllChildren(contenteditable.childNodes[1]);
+  result = synthesizeDragStart(contenteditable.childNodes[1],
+                               [[htmlContextDataEditable, htmlInfoData,
+                                {type: 'text/html', data: '<b id="bold">editable</b>' },
+                                {type: "text/plain", data: "editable"}]], window, 5, 6);
+  ok(!result, "Test dragging contenteditable");
+  contenteditable.blur();
+
+  // -------- Test dragging regular text of text/html to <input>
+
+  selection.selectAllChildren(text);
+  input.value = "";
+  synthesizeDrop(text, input, [], "copy");
+  is(input.value, "Some Text", "Drag text/html onto input");
+
+  // -------- Test dragging regular text of text/html to disabled <input>
+
+  selection.selectAllChildren(text);
+  input.value = "";
+  input.disabled = true;
+  synthesizeDrop(text, input, [], "copy");
+  is(input.value, "", "Drag text/html onto disabled input");
+  input.disabled = false;
+
+  // -------- Test dragging regular text of text/html to readonly <input>
+
+  selection.selectAllChildren(text);
+  input.readOnly = true;
+  synthesizeDrop(text, input, [], "copy");
+  is(input.value, "", "Drag text/html onto readonly input");
+  input.readOnly = false;
+
+  // -------- Test dragging regular text of text/html to <input>. This sets
+  //          shouldClear to true so that the default drag data is not present
+  //          and we can use the data passed to synthesizeDrop. This allows
+  //          testing of a drop with just text/html.
+  shouldClear = true;
+  selection.selectAllChildren(text);
+  input.value = "";
+  synthesizeDrop(text, input, [[{type: "text/html", data: "Some <b>Bold<b> Text"}]], "copy");
+  is(input.value, "", "Drag text/html onto input");
+
+  // -------- Test dragging regular text of text/plain and text/html to <input>
+
+  selection.selectAllChildren(text);
+  input.value = "";
+  synthesizeDrop(text, input, [[{type: "text/html", data: "Some <b>Bold<b> Text"},
+                                {type: "text/plain", data: "Some Plain Text"}]], "copy");
+  is(input.value, "Some Plain Text", "Drag text/html and text/plain onto input");
+
+  // -------- Test dragging regular text of text/plain to <textarea>
+
+// XXXndeakin Can't test textareas due to some event handling issue
+//  selection.selectAllChildren(text);
+//  synthesizeDrop(text, textarea, [[{type: "text/plain", data: "Somewhat Longer Text"}]], "copy");
+//  is(textarea.value, "Somewhat Longer Text", "Drag text/plain onto textarea");
+
+  // -------- Test dragging regular text of text/plain to contenteditable
+
+  selection.selectAllChildren(text);
+  synthesizeDrop(text, contenteditable, [[{type: "text/plain", data: "Sample Text"}]], "copy");
+  is(contenteditable.childNodes.length, 3, "Drag text/plain onto contenteditable child nodes");
+  is(contenteditable.textContent, "This is some editable text.Sample Text",
+                                  "Drag text/plain onto contenteditable text");
+
+  // -------- Test dragging regular text of text/html to contenteditable
+
+  selection.selectAllChildren(text);
+  synthesizeDrop(text, contenteditable, [[{type: "text/html", data: "Sample <i>Italic</i> Text"}]], "copy");
+  is(contenteditable.childNodes.length, 6, "Drag text/html onto contenteditable child nodes");
+  is(contenteditable.childNodes[4].tagName, "I", "Drag text/html onto contenteditable italic");
+  is(contenteditable.childNodes[4].textContent, "Italic", "Drag text/html onto contenteditable italic text");
+
+  // -------- Test dragging contenteditable to <input>
+
+  selection.selectAllChildren(document.getElementById("bold"));
+  synthesizeDrop(bold, input, [[{type: "text/html", data: "<b>editable</b>"},
+                                {type: "text/plain", data: "editable"}]], "copy");
+  is(input.value, "Some Plain Texteditable", "Move text/html and text/plain from contenteditable onto input");
+
+  // -------- Test dragging contenteditable to contenteditable
+
+  shouldClear = false;
+
+  selection.selectAllChildren(contenteditable.childNodes[4]);
+  synthesizeDrop(contenteditable.childNodes[4], contenteditable, [], "copy");
+  is(contenteditable.childNodes.length, 7, "Move text/html and text/plain from contenteditable onto itself child nodes");
+  is(contenteditable.childNodes[6].tagName, "I", "Move text/html and text/plain from contenteditable onto itself italic");
+  is(contenteditable.childNodes[6].textContent, "Italic", "Move text/html and text/plain from contenteditable onto itself text");
+
+  // We'd test 'move' here as well as 'copy', but that requires knowledge of
+  // the source of the drag which drag simulation doesn't provide.
+
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForFocus(doTest);
+
+</script>
+</body>
+</html>
--- a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
+++ b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
@@ -97,17 +97,17 @@ static PRInt32 GetCSSFloatValue(nsIDOMCS
         f = 5;
       break;
     }
   }
 
   return (PRInt32) f;
 }
 
-class nsElementDeletionObserver : public nsIMutationObserver
+class nsElementDeletionObserver MOZ_FINAL : public nsIMutationObserver
 {
 public:
   nsElementDeletionObserver(nsINode* aNativeAnonNode, nsINode* aObservedNode)
   : mNativeAnonNode(aNativeAnonNode), mObservedNode(aObservedNode) {}
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMUTATIONOBSERVER
 protected:
   nsINode* mNativeAnonNode;
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -59,16 +59,18 @@
 
 #include "nsIDocumentObserver.h"
 #include "nsIDocumentStateListener.h"
 
 #include "nsIEnumerator.h"
 #include "nsIContent.h"
 #include "nsIContentIterator.h"
 #include "nsIDOMRange.h"
+#include "nsIDOMDOMStringList.h"
+#include "nsIDOMDragEvent.h"
 #include "nsCOMArray.h"
 #include "nsIFile.h"
 #include "nsIURL.h"
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIPresShell.h"
@@ -126,19 +128,16 @@
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 const PRUnichar nbsp = 160;
 
 static NS_DEFINE_CID(kCParserCID,     NS_PARSER_CID);
 
-// private clipboard data flavors for html copy/paste
-#define kHTMLContext   "text/_moz_htmlcontext"
-#define kHTMLInfo      "text/_moz_htmlinfo"
 #define kInsertCookie  "_moz_Insert Here_moz_"
 
 #define NS_FOUND_TARGET NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR, 3)
 
 // some little helpers
 static bool FindIntegerAfterString(const char *aLeadingString, 
                                      nsCString &aCStr, PRInt32 &foundNumber);
 static nsresult RemoveFragComments(nsCString &theStr);
@@ -1199,16 +1198,126 @@ nsHTMLEditor::ParseCFHTML(nsCString & aC
                                                            nsLinebreakConverter::eLinebreakContent, 
                                                            oldLengthInChars, &newLengthInChars);
   // it's ok for context to be empty.  frag might be whole doc and contain all its context.
   
   // we're done!  
   return NS_OK;
 }
 
+bool nsHTMLEditor::IsSafeToInsertData(nsIDOMDocument* aSourceDoc)
+{
+  // Try to determine whether we should use a sanitizing fragment sink
+  bool isSafe = false;
+  nsCOMPtr<nsIDOMDocument> destdomdoc;
+  GetDocument(getter_AddRefs(destdomdoc));
+
+  nsCOMPtr<nsIDocument> destdoc = do_QueryInterface(destdomdoc);
+  NS_ASSERTION(destdoc, "Where is our destination doc?");
+  nsCOMPtr<nsISupports> container = destdoc->GetContainer();
+  nsCOMPtr<nsIDocShellTreeItem> dsti(do_QueryInterface(container));
+  nsCOMPtr<nsIDocShellTreeItem> root;
+  if (dsti)
+    dsti->GetRootTreeItem(getter_AddRefs(root));
+  nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
+  PRUint32 appType;
+  if (docShell && NS_SUCCEEDED(docShell->GetAppType(&appType)))
+    isSafe = appType == nsIDocShell::APP_TYPE_EDITOR;
+  if (!isSafe && aSourceDoc) {
+    nsCOMPtr<nsIDocument> srcdoc = do_QueryInterface(aSourceDoc);
+    NS_ASSERTION(srcdoc, "Where is our source doc?");
+
+    nsIPrincipal* srcPrincipal = srcdoc->NodePrincipal();
+    nsIPrincipal* destPrincipal = destdoc->NodePrincipal();
+    NS_ASSERTION(srcPrincipal && destPrincipal, "How come we don't have a principal?");
+    srcPrincipal->Subsumes(destPrincipal, &isSafe);
+  }
+
+  return isSafe;
+}
+
+nsresult nsHTMLEditor::InsertObject(const char* aType, nsISupports* aObject, bool aIsSafe,
+                                    nsIDOMDocument *aSourceDoc,
+                                    nsIDOMNode *aDestinationNode,
+                                    PRInt32 aDestOffset,
+                                    bool aDoDeleteSelection)
+{
+  nsresult rv;
+
+  const char* type = aType;
+
+  // Check to see if we can insert an image file
+  bool insertAsImage = false;
+  nsCOMPtr<nsIURI> fileURI;
+  if (0 == nsCRT::strcmp(type, kFileMime))
+  {
+    nsCOMPtr<nsIFile> fileObj(do_QueryInterface(aObject));
+    if (fileObj)
+    {
+      rv = NS_NewFileURI(getter_AddRefs(fileURI), fileObj);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1");
+      NS_ENSURE_TRUE(mime, NS_ERROR_FAILURE);
+      nsCAutoString contentType;
+      rv = mime->GetTypeFromFile(fileObj, contentType);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      // Accept any image type fed to us
+      if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/"))) {
+        insertAsImage = true;
+        type = contentType.get();
+      }
+    }
+  }
+
+  if (0 == nsCRT::strcmp(type, kJPEGImageMime) ||
+      0 == nsCRT::strcmp(type, kPNGImageMime) ||
+      0 == nsCRT::strcmp(type, kGIFImageMime) ||
+      insertAsImage)
+  {
+    nsCOMPtr<nsIInputStream> imageStream;
+    if (insertAsImage) {
+      NS_ASSERTION(fileURI, "The file URI should be retrieved earlier");
+      rv = NS_OpenURI(getter_AddRefs(imageStream), fileURI);
+      NS_ENSURE_SUCCESS(rv, rv);
+    } else {
+      imageStream = do_QueryInterface(aObject);
+      NS_ENSURE_TRUE(imageStream, NS_ERROR_FAILURE);
+    }
+
+    nsCString imageData;
+    rv = NS_ConsumeStream(imageStream, PR_UINT32_MAX, imageData);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = imageStream->Close();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    char * base64 = PL_Base64Encode(imageData.get(), imageData.Length(), nsnull);
+    NS_ENSURE_TRUE(base64, NS_ERROR_OUT_OF_MEMORY);
+
+    nsAutoString stuffToPaste;
+    stuffToPaste.AssignLiteral("<IMG src=\"data:");
+    AppendUTF8toUTF16(aType, stuffToPaste);
+    stuffToPaste.AppendLiteral(";base64,");
+    AppendUTF8toUTF16(base64, stuffToPaste);
+    stuffToPaste.AppendLiteral("\" alt=\"\" >");
+    nsAutoEditBatch beginBatching(this);
+    rv = DoInsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(), 
+                                 NS_LITERAL_STRING(kFileMime),
+                                 aSourceDoc,
+                                 aDestinationNode, aDestOffset,
+                                 aDoDeleteSelection,
+                                 aIsSafe);
+    PR_Free(base64);
+  }
+
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable, 
                                                    nsIDOMDocument *aSourceDoc,
                                                    const nsAString & aContextStr,
                                                    const nsAString & aInfoStr,
                                                    nsIDOMNode *aDestinationNode,
                                                    PRInt32 aDestOffset,
                                                    bool aDoDeleteSelection)
 {
@@ -1221,69 +1330,26 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTr
     nsAutoTxnsConserveSelection dontSpazMySelection(this);
     nsAutoString flavor;
     flavor.AssignWithConversion(bestFlavor);
     nsAutoString stuffToPaste;
 #ifdef DEBUG_clipboard
     printf("Got flavor [%s]\n", bestFlavor.get());
 #endif
 
-    // Try to determine whether we should use a sanitizing fragment sink
-    bool isSafe = false;
-    nsCOMPtr<nsIDOMDocument> destdomdoc;
-    rv = GetDocument(getter_AddRefs(destdomdoc));
-    NS_ENSURE_SUCCESS(rv, rv);
-    nsCOMPtr<nsIDocument> destdoc = do_QueryInterface(destdomdoc);
-    NS_ASSERTION(destdoc, "Where is our destination doc?");
-    nsCOMPtr<nsISupports> container = destdoc->GetContainer();
-    nsCOMPtr<nsIDocShellTreeItem> dsti(do_QueryInterface(container));
-    nsCOMPtr<nsIDocShellTreeItem> root;
-    if (dsti)
-      dsti->GetRootTreeItem(getter_AddRefs(root));
-    nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
-    PRUint32 appType;
-    if (docShell && NS_SUCCEEDED(docShell->GetAppType(&appType)))
-      isSafe = appType == nsIDocShell::APP_TYPE_EDITOR;
-    if (!isSafe && aSourceDoc) {
-      nsCOMPtr<nsIDocument> srcdoc = do_QueryInterface(aSourceDoc);
-      NS_ASSERTION(srcdoc, "Where is our source doc?");
-
-      nsIPrincipal* srcPrincipal = srcdoc->NodePrincipal();
-      nsIPrincipal* destPrincipal = destdoc->NodePrincipal();
-      NS_ASSERTION(srcPrincipal && destPrincipal, "How come we don't have a principal?");
-      rv = srcPrincipal->Subsumes(destPrincipal, &isSafe);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
+    bool isSafe = IsSafeToInsertData(aSourceDoc);
 
-    // Check to see if we can insert an image file
-    bool insertAsImage = false;
-    nsCOMPtr<nsIURI> fileURI;
-    if (0 == nsCRT::strcmp(bestFlavor, kFileMime))
-    {
-      nsCOMPtr<nsIFile> fileObj(do_QueryInterface(genericDataObj));
-      if (fileObj && len > 0)
-      {
-        rv = NS_NewFileURI(getter_AddRefs(fileURI), fileObj);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1");
-        NS_ENSURE_TRUE(mime, NS_ERROR_FAILURE);
-        nsCAutoString contentType;
-        rv = mime->GetTypeFromFile(fileObj, contentType);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        // Accept any image type fed to us
-        if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/"))) {
-          insertAsImage = true;
-          bestFlavor = contentType;
-        }
-      }
+  	if (0 == nsCRT::strcmp(bestFlavor, kFileMime) ||
+        0 == nsCRT::strcmp(bestFlavor, kJPEGImageMime) ||
+        0 == nsCRT::strcmp(bestFlavor, kPNGImageMime) ||
+        0 == nsCRT::strcmp(bestFlavor, kGIFImageMime)) {
+      rv = InsertObject(bestFlavor, genericDataObj, isSafe,
+                        aSourceDoc, aDestinationNode, aDestOffset, aDoDeleteSelection);
     }
-
-    if (0 == nsCRT::strcmp(bestFlavor, kNativeHTMLMime))
+    else if (0 == nsCRT::strcmp(bestFlavor, kNativeHTMLMime))
     {
       // note cf_html uses utf8, hence use length = len, not len/2 as in flavors below
       nsCOMPtr<nsISupportsCString> textDataObj(do_QueryInterface(genericDataObj));
       if (textDataObj && len > 0)
       {
         nsCAutoString cfhtml;
         textDataObj->GetData(cfhtml);
         NS_ASSERTION(cfhtml.Length() <= (len), "Invalid length!");
@@ -1297,438 +1363,155 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTr
                                        cfcontext, cfselection, flavor,
                                        aSourceDoc,
                                        aDestinationNode, aDestOffset,
                                        aDoDeleteSelection,
                                        isSafe);
         }
       }
     }
-    else if (0 == nsCRT::strcmp(bestFlavor, kHTMLMime))
-    {
-      nsCOMPtr<nsISupportsString> textDataObj(do_QueryInterface(genericDataObj));
-      if (textDataObj && len > 0)
-      {
-        nsAutoString text;
-        textDataObj->GetData(text);
-        NS_ASSERTION(text.Length() <= (len/2), "Invalid length!");
-        stuffToPaste.Assign(text.get(), len / 2);
-        nsAutoEditBatch beginBatching(this);
-        rv = DoInsertHTMLWithContext(stuffToPaste,
-                                     aContextStr, aInfoStr, flavor,
-                                     aSourceDoc,
-                                     aDestinationNode, aDestOffset,
-                                     aDoDeleteSelection,
-                                     isSafe);
-      }
-    }
-    else if (0 == nsCRT::strcmp(bestFlavor, kUnicodeMime) ||
-             0 == nsCRT::strcmp(bestFlavor, kMozTextInternal))
-    {
+    else if (0 == nsCRT::strcmp(bestFlavor, kHTMLMime) ||
+             0 == nsCRT::strcmp(bestFlavor, kUnicodeMime) ||
+             0 == nsCRT::strcmp(bestFlavor, kMozTextInternal)) {
       nsCOMPtr<nsISupportsString> textDataObj(do_QueryInterface(genericDataObj));
       if (textDataObj && len > 0)
       {
         nsAutoString text;
         textDataObj->GetData(text);
         NS_ASSERTION(text.Length() <= (len/2), "Invalid length!");
         stuffToPaste.Assign(text.get(), len / 2);
+
         nsAutoEditBatch beginBatching(this);
-        // need to provide a hook from this point
-        rv = InsertTextAt(stuffToPaste, aDestinationNode, aDestOffset, aDoDeleteSelection);
+        if (0 == nsCRT::strcmp(bestFlavor, kHTMLMime)) {
+          rv = DoInsertHTMLWithContext(stuffToPaste,
+                                       aContextStr, aInfoStr, flavor,
+                                       aSourceDoc,
+                                       aDestinationNode, aDestOffset,
+                                       aDoDeleteSelection,
+                                       isSafe);
+        } else {
+          rv = InsertTextAt(stuffToPaste, aDestinationNode, aDestOffset, aDoDeleteSelection);
+        }
       }
     }
-    else if (0 == nsCRT::strcmp(bestFlavor, kJPEGImageMime) ||
-             0 == nsCRT::strcmp(bestFlavor, kPNGImageMime) ||
-             0 == nsCRT::strcmp(bestFlavor, kGIFImageMime) ||
-             insertAsImage)
-    {
-      nsCOMPtr<nsIInputStream> imageStream;
-      if (insertAsImage) {
-        NS_ASSERTION(fileURI, "The file URI should be retrieved earlier");
-        rv = NS_OpenURI(getter_AddRefs(imageStream), fileURI);
-        NS_ENSURE_SUCCESS(rv, rv);
-      } else {
-        imageStream = do_QueryInterface(genericDataObj);
-        NS_ENSURE_TRUE(imageStream, NS_ERROR_FAILURE);
-      }
-
-      nsCString imageData;
-      rv = NS_ConsumeStream(imageStream, PR_UINT32_MAX, imageData);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      rv = imageStream->Close();
-      NS_ENSURE_SUCCESS(rv, rv);
+  }
 
-      char * base64 = PL_Base64Encode(imageData.get(), imageData.Length(), nsnull);
-      NS_ENSURE_TRUE(base64, NS_ERROR_OUT_OF_MEMORY);
-
-      stuffToPaste.AssignLiteral("<IMG src=\"data:");
-      AppendUTF8toUTF16(bestFlavor, stuffToPaste);
-      stuffToPaste.AppendLiteral(";base64,");
-      AppendUTF8toUTF16(base64, stuffToPaste);
-      stuffToPaste.AppendLiteral("\" alt=\"\" >");
-      nsAutoEditBatch beginBatching(this);
-      rv = DoInsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(), 
-                                   NS_LITERAL_STRING(kFileMime),
-                                   aSourceDoc,
-                                   aDestinationNode, aDestOffset,
-                                   aDoDeleteSelection,
-                                   isSafe);
-      PR_Free(base64);
-    }
-  }
-      
-  // Try to scroll the selection into view if the paste/drop succeeded
-
-  // After ScrollSelectionIntoView(), the pending notifications might be
-  // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
+  // Try to scroll the selection into view if the paste succeeded
   if (NS_SUCCEEDED(rv))
     ScrollSelectionIntoView(false);
 
   return rv;
 }
 
-NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
+static void
+GetStringFromDataTransfer(nsIDOMDataTransfer *aDataTransfer, const nsAString& aType,
+                          PRInt32 aIndex, nsAString& aOutputString)
 {
-  ForceCompositionEnd();
-  
-  nsresult rv;
-  nsCOMPtr<nsIDragService> dragService = 
-           do_GetService("@mozilla.org/widget/dragservice;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIDragSession> dragSession;
-  dragService->GetCurrentSession(getter_AddRefs(dragSession)); 
-  NS_ENSURE_TRUE(dragSession, NS_OK);
-
-  // transferable hooks here
-  nsCOMPtr<nsIDOMDocument> domdoc;
-  GetDocument(getter_AddRefs(domdoc));
+  nsCOMPtr<nsIVariant> variant;
+  aDataTransfer->MozGetDataAt(aType, aIndex, getter_AddRefs(variant));
+  if (variant)
+    variant->GetAsAString(aOutputString);
+}
 
-  // find out if we have our internal html flavor on the clipboard.  We don't want to mess
-  // around with cfhtml if we do.
-  bool bHavePrivateHTMLFlavor = false;
-  rv = dragSession->IsDataFlavorSupported(kHTMLContext, &bHavePrivateHTMLFlavor);
-  NS_ENSURE_SUCCESS(rv, rv);
-  
-  // Get the nsITransferable interface for getting the data from the drop
-  nsCOMPtr<nsITransferable> trans;
-  rv = PrepareHTMLTransferable(getter_AddRefs(trans), bHavePrivateHTMLFlavor);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(trans, NS_OK);  // NS_ERROR_FAILURE; SHOULD WE FAIL?
+nsresult nsHTMLEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
+                                              PRInt32 aIndex,
+                                              nsIDOMDocument *aSourceDoc,
+                                              nsIDOMNode *aDestinationNode,
+                                              PRInt32 aDestOffset,
+                                              bool aDoDeleteSelection)
+{
+  nsresult rv = NS_OK;
+
+  nsCOMPtr<nsIDOMDOMStringList> types;
+  aDataTransfer->MozTypesAt(aIndex, getter_AddRefs(types));
 
-  PRUint32 numItems = 0; 
-  rv = dragSession->GetNumDropItems(&numItems);
-  NS_ENSURE_SUCCESS(rv, rv);
+  bool hasPrivateHTMLFlavor;
+  types->Contains(NS_LITERAL_STRING(kHTMLContext), &hasPrivateHTMLFlavor);
 
-  // Combine any deletion and drop insertion into one transaction
-  nsAutoEditBatch beginBatching(this);
-
-  // We never have to delete if selection is already collapsed
-  bool deleteSelection = false;
-  nsCOMPtr<nsIDOMNode> newSelectionParent;
-  PRInt32 newSelectionOffset = 0;
+  bool isText = IsPlaintextEditor();
+  bool isSafe = IsSafeToInsertData(aSourceDoc);
+  
+  PRUint32 length;
+  types->GetLength(&length);
+  for (PRUint32 t = 0; t < length; t++) {
+    nsAutoString type;
+    types->Item(t, type);
 
-  // Source doc is null if source is *not* the current editor document
-  nsCOMPtr<nsIDOMDocument> srcdomdoc;
-  rv = dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRUint32 i; 
-  bool doPlaceCaret = true;
-  for (i = 0; i < numItems; ++i)
-  {
-    rv = dragSession->GetData(trans, i);
-    NS_ENSURE_SUCCESS(rv, rv);
-    NS_ENSURE_TRUE(trans, NS_OK); // NS_ERROR_FAILURE; Should we fail?
+    if (!isText) {
+      if (type.EqualsLiteral(kFileMime) ||
+          type.EqualsLiteral(kJPEGImageMime) ||
+          type.EqualsLiteral(kPNGImageMime) ||
+          type.EqualsLiteral(kGIFImageMime)) {
+        nsCOMPtr<nsIVariant> variant;
+        aDataTransfer->MozGetDataAt(type, aIndex, getter_AddRefs(variant));
+        if (variant) {
+          nsCOMPtr<nsISupports> object;
+          variant->GetAsISupports(getter_AddRefs(object));
+          rv = InsertObject(NS_ConvertUTF16toUTF8(type).get(), object, isSafe,
+                            aSourceDoc, aDestinationNode, aDestOffset, aDoDeleteSelection);
+          if (NS_SUCCEEDED(rv))
+            return NS_OK;
+        }
+      }
+      else if (!hasPrivateHTMLFlavor && type.EqualsLiteral(kNativeHTMLMime)) {
+        nsAutoString text;
+        GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kNativeHTMLMime), aIndex, text);
+        NS_ConvertUTF16toUTF8 cfhtml(text);
 
-    // get additional html copy hints, if present
-    nsAutoString contextStr, infoStr;
-    nsCOMPtr<nsISupports> contextDataObj, infoDataObj;
-    PRUint32 contextLen, infoLen;
-    nsCOMPtr<nsISupportsString> textDataObj;
-    
-    nsCOMPtr<nsITransferable> contextTrans =
-                      do_CreateInstance("@mozilla.org/widget/transferable;1");
-    NS_ENSURE_TRUE(contextTrans, NS_ERROR_NULL_POINTER);
-    contextTrans->AddDataFlavor(kHTMLContext);
-    dragSession->GetData(contextTrans, i);
-    contextTrans->GetTransferData(kHTMLContext, getter_AddRefs(contextDataObj), &contextLen);
+        nsXPIDLString cfcontext, cffragment, cfselection; // cfselection left emtpy for now
+           
+        rv = ParseCFHTML(cfhtml, getter_Copies(cffragment), getter_Copies(cfcontext));
+        if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty())
+        {
+          nsAutoEditBatch beginBatching(this);
+          rv = DoInsertHTMLWithContext(cffragment,
+                                       cfcontext, cfselection, type,
+                                       aSourceDoc,
+                                       aDestinationNode, aDestOffset,
+                                       aDoDeleteSelection,
+                                       isSafe);
+          if (NS_SUCCEEDED(rv))
+            return NS_OK;
+        }
+      }
+      else if (type.EqualsLiteral(kHTMLMime)) {
+        nsAutoString text, contextString, infoString;
+        GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
+        GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), aIndex, contextString);
+        GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), aIndex, infoString);
 
-    nsCOMPtr<nsITransferable> infoTrans =
-                      do_CreateInstance("@mozilla.org/widget/transferable;1");
-    NS_ENSURE_TRUE(infoTrans, NS_ERROR_NULL_POINTER);
-    infoTrans->AddDataFlavor(kHTMLInfo);
-    dragSession->GetData(infoTrans, i);
-    infoTrans->GetTransferData(kHTMLInfo, getter_AddRefs(infoDataObj), &infoLen);
-    
-    if (contextDataObj)
-    {
-      nsAutoString text;
-      textDataObj = do_QueryInterface(contextDataObj);
-      textDataObj->GetData(text);
-      NS_ASSERTION(text.Length() <= (contextLen/2), "Invalid length!");
-      contextStr.Assign(text.get(), contextLen / 2);
-    }
-    
-    if (infoDataObj)
-    {
-      nsAutoString text;
-      textDataObj = do_QueryInterface(infoDataObj);
-      textDataObj->GetData(text);
-      NS_ASSERTION(text.Length() <= (infoLen/2), "Invalid length!");
-      infoStr.Assign(text.get(), infoLen / 2);
+        nsAutoEditBatch beginBatching(this);
+        if (type.EqualsLiteral(kHTMLMime)) {
+          rv = DoInsertHTMLWithContext(text,
+                                       contextString, infoString, type,
+                                       aSourceDoc,
+                                       aDestinationNode, aDestOffset,
+                                       aDoDeleteSelection,
+                                       isSafe);
+          if (NS_SUCCEEDED(rv))
+            return NS_OK;
+        }
+      }
     }
 
-    if (doPlaceCaret)
-    {
-      // check if the user pressed the key to force a copy rather than a move
-      // if we run into problems here, we'll just assume the user doesn't want a copy
-      bool userWantsCopy = false;
-
-      nsCOMPtr<nsIDOMUIEvent> uiEvent = do_QueryInterface(aDropEvent);
-      NS_ENSURE_TRUE(uiEvent, NS_ERROR_FAILURE);
-
-      nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aDropEvent);
-      if (mouseEvent) {
-#if defined(XP_MACOSX)
-        mouseEvent->GetAltKey(&userWantsCopy);
-#else
-        mouseEvent->GetCtrlKey(&userWantsCopy);
-#endif
-      }
-
-      // Current doc is destination
-      nsCOMPtr<nsIDOMDocument> destdomdoc; 
-      rv = GetDocument(getter_AddRefs(destdomdoc)); 
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      nsCOMPtr<nsISelection> selection;
-      rv = GetSelection(getter_AddRefs(selection));
-      NS_ENSURE_SUCCESS(rv, rv);
-      NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
-      bool isCollapsed;
-      rv = selection->GetIsCollapsed(&isCollapsed);
-      NS_ENSURE_SUCCESS(rv, rv);
-      
-      // Parent and offset under the mouse cursor
-      rv = uiEvent->GetRangeParent(getter_AddRefs(newSelectionParent));
-      NS_ENSURE_SUCCESS(rv, rv);
-      NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
-
-      rv = uiEvent->GetRangeOffset(&newSelectionOffset);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      // XXX: This userSelectNode code is a workaround for bug 195957.
-      //
-      // Check to see if newSelectionParent is part of a "-moz-user-select: all"
-      // subtree. If it is, we need to make sure we don't drop into it!
-
-      nsCOMPtr<nsIDOMNode> userSelectNode = FindUserSelectAllNode(newSelectionParent);
-
-      if (userSelectNode)
-      {
-        // The drop is happening over a "-moz-user-select: all"
-        // subtree so make sure the content we insert goes before
-        // the root of the subtree.
-        //
-        // XXX: Note that inserting before the subtree matches the
-        //      current behavior when dropping on top of an image.
-        //      The decision for dropping before or after the
-        //      subtree should really be done based on coordinates.
-
-        rv = GetNodeLocation(userSelectNode, address_of(newSelectionParent),
-                             &newSelectionOffset);
+    if (type.EqualsLiteral(kTextMime) ||
+        type.EqualsLiteral(kMozTextInternal)) {
+      nsAutoString text;
+      GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
 
-        NS_ENSURE_SUCCESS(rv, rv);
-        NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
-      }
-
-      // We never have to delete if selection is already collapsed
-      bool cursorIsInSelection = false;
-
-      // Check if mouse is in the selection
-      if (!isCollapsed)
-      {
-        PRInt32 rangeCount;
-        rv = selection->GetRangeCount(&rangeCount);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        for (PRInt32 j = 0; j < rangeCount; j++)
-        {
-          nsCOMPtr<nsIDOMRange> range;
-
-          rv = selection->GetRangeAt(j, getter_AddRefs(range));
-          if (NS_FAILED(rv) || !range) 
-            continue;//don't bail yet, iterate through them all
-
-          rv = range->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
-          if(cursorIsInSelection)
-            break;
-        }
-        if (cursorIsInSelection)
-        {
-          // Dragging within same doc can't drop on itself -- leave!
-          // (We shouldn't get here - drag event shouldn't have started if over selection)
-          if (srcdomdoc == destdomdoc)
-            return NS_OK;
-          
-          // Dragging from another window onto a selection
-          // XXX Decision made to NOT do this,
-          //     note that 4.x does replace if dropped on
-          //deleteSelection = true;
-        }
-        else 
-        {
-          // We are NOT over the selection
-          if (srcdomdoc == destdomdoc)
-          {
-            // Within the same doc: delete if user doesn't want to copy
-            deleteSelection = !userWantsCopy;
-          }
-          else
-          {
-            // Different source doc: Don't delete
-            deleteSelection = false;
-          }
-        }
-      }
-
-      // We have to figure out whether to delete/relocate caret only once
-      doPlaceCaret = false;
+      nsAutoEditBatch beginBatching(this);
+      rv = InsertTextAt(text, aDestinationNode, aDestOffset, aDoDeleteSelection);
+      if (NS_SUCCEEDED(rv))
+        return NS_OK;
     }
-    
-    // handle transferable hooks
-    if (!nsEditorHookUtils::DoInsertionHook(domdoc, aDropEvent, trans))
-      return NS_OK;
-
-    // Beware! This may flush notifications via synchronous
-    // ScrollSelectionIntoView.
-    rv = InsertFromTransferable(trans, srcdomdoc, contextStr, infoStr,
-                                newSelectionParent,
-                                newSelectionOffset, deleteSelection);
   }
 
   return rv;
 }
 
-NS_IMETHODIMP nsHTMLEditor::CanDrag(nsIDOMEvent *aDragEvent, bool *aCanDrag)
-{
-  return nsPlaintextEditor::CanDrag(aDragEvent, aCanDrag);
-}
-
-nsresult
-nsHTMLEditor::PutDragDataInTransferable(nsITransferable **aTransferable)
-{
-  NS_ENSURE_ARG_POINTER(aTransferable);
-  *aTransferable = nsnull;
-  nsCOMPtr<nsIDocumentEncoder> docEncoder;
-  nsresult rv = SetupDocEncoder(getter_AddRefs(docEncoder));
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
-
-  // grab a string
-  nsAutoString buffer, parents, info;
-
-  // find out if we're a plaintext control or not
-  if (!IsPlaintextEditor())
-  {
-    // encode the selection as html with contextual info
-    rv = docEncoder->EncodeToStringWithContext(parents, info, buffer);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  else
-  {
-    // encode the selection
-    rv = docEncoder->EncodeToString(buffer);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  // if we have an empty string, we're done; otherwise continue
-  if ( buffer.IsEmpty() )
-    return NS_OK;
-
-  nsCOMPtr<nsISupportsString> dataWrapper, contextWrapper, infoWrapper;
-
-  dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = dataWrapper->SetData(buffer);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  /* create html flavor transferable */
-  nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1");
-  NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
-
-  if (IsPlaintextEditor())
-  {
-    // Add the unicode flavor to the transferable
-    rv = trans->AddDataFlavor(kUnicodeMime);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // QI the data object an |nsISupports| so that when the transferable holds
-    // onto it, it will addref the correct interface.
-    nsCOMPtr<nsISupports> genericDataObj(do_QueryInterface(dataWrapper));
-    rv = trans->SetTransferData(kUnicodeMime, genericDataObj,
-                                buffer.Length() * sizeof(PRUnichar));
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  else
-  {
-    contextWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-    NS_ENSURE_TRUE(contextWrapper, NS_ERROR_FAILURE);
-    infoWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-    NS_ENSURE_TRUE(infoWrapper, NS_ERROR_FAILURE);
-
-    contextWrapper->SetData(parents);
-    infoWrapper->SetData(info);
-
-    rv = trans->AddDataFlavor(kHTMLMime);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIFormatConverter> htmlConverter =
-             do_CreateInstance("@mozilla.org/widget/htmlformatconverter;1");
-    NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
-
-    rv = trans->SetConverter(htmlConverter);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsISupports> genericDataObj(do_QueryInterface(dataWrapper));
-    rv = trans->SetTransferData(kHTMLMime, genericDataObj,
-                                buffer.Length() * sizeof(PRUnichar));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (!parents.IsEmpty())
-    {
-      // Add the htmlcontext DataFlavor to the transferable
-      trans->AddDataFlavor(kHTMLContext);
-      genericDataObj = do_QueryInterface(contextWrapper);
-      trans->SetTransferData(kHTMLContext, genericDataObj,
-                             parents.Length() * sizeof(PRUnichar));
-    }
-    if (!info.IsEmpty())
-    {
-      // Add the htmlinfo DataFlavor to the transferable
-      trans->AddDataFlavor(kHTMLInfo);
-      genericDataObj = do_QueryInterface(infoWrapper);
-      trans->SetTransferData(kHTMLInfo, genericDataObj,
-                             info.Length() * sizeof(PRUnichar));
-    }
-  }
-
-  *aTransferable = trans; 
-  NS_ADDREF(*aTransferable);
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent)
-{
-  return nsPlaintextEditor::DoDrag(aDragEvent);
-}
-
 bool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard)
 {
   // check the clipboard for our special kHTMLContext flavor.  If that is there, we know
   // we have our own internal html format on clipboard.
   
   NS_ENSURE_TRUE(aClipboard, false);
   bool bHavePrivateHTMLFlavor = false;
   
@@ -1809,18 +1592,16 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt3
       }
 
       // handle transferable hooks
       nsCOMPtr<nsIDOMDocument> domdoc;
       GetDocument(getter_AddRefs(domdoc));
       if (!nsEditorHookUtils::DoInsertionHook(domdoc, nsnull, trans))
         return NS_OK;
 
-      // Beware! This may flush notifications via synchronous
-      // ScrollSelectionIntoView.
       rv = InsertFromTransferable(trans, nsnull, contextStr, infoStr,
                                   nsnull, 0, true);
     }
   }
 
   return rv;
 }
 
@@ -1830,18 +1611,16 @@ NS_IMETHODIMP nsHTMLEditor::PasteTransfe
     return NS_OK;
 
   // handle transferable hooks
   nsCOMPtr<nsIDOMDocument> domdoc;
   GetDocument(getter_AddRefs(domdoc));
   if (!nsEditorHookUtils::DoInsertionHook(domdoc, nsnull, aTransferable))
     return NS_OK;
 
-  // Beware! This may flush notifications via synchronous
-  // ScrollSelectionIntoView.
   nsAutoString contextStr, infoStr;
   return InsertFromTransferable(aTransferable, nsnull, contextStr, infoStr,
                                 nsnull, 0, true);
 }
 
 // 
 // HTML PasteNoFormatting. Ignore any HTML styles and formating in paste source
 //
@@ -1859,18 +1638,16 @@ NS_IMETHODIMP nsHTMLEditor::PasteNoForma
   nsCOMPtr<nsITransferable> trans;
   rv = nsPlaintextEditor::PrepareTransferable(getter_AddRefs(trans));
   if (NS_SUCCEEDED(rv) && trans)
   {
     // Get the Data from the clipboard  
     if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) && IsModifiable())
     {
       const nsAFlatString& empty = EmptyString();
-      // Beware! This may flush notifications via synchronous
-      // ScrollSelectionIntoView.
       rv = InsertFromTransferable(trans, nsnull, empty, empty, nsnull, 0,
                                   true);
     }
   }
 
   return rv;
 }
 
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -108,17 +108,16 @@ static char hrefText[] = "href";
 static char anchorTxt[] = "anchor";
 static char namedanchorText[] = "namedanchor";
 
 #define IsLinkTag(s) (s.EqualsIgnoreCase(hrefText))
 #define IsNamedAnchorTag(s) (s.EqualsIgnoreCase(anchorTxt) || s.EqualsIgnoreCase(namedanchorText))
 
 nsHTMLEditor::nsHTMLEditor()
 : nsPlaintextEditor()
-, mIgnoreSpuriousDragEvent(false)
 , mCRInParagraphCreatesParagraph(false)
 , mSelectedCellIndex(0)
 , mIsObjectResizingEnabled(true)
 , mIsResizing(false)
 , mIsAbsolutelyPositioningEnabled(true)
 , mResizedObjectIsAbsolutelyPositioned(false)
 , mGrabberClicked(false)
 , mIsMoving(false)
@@ -5307,23 +5306,16 @@ nsHTMLEditor::EndUpdateViewBatch()
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
     res = CheckSelectionStateForAnonymousButtons(selection);
   }
   return res;
 }
 
 NS_IMETHODIMP
-nsHTMLEditor::IgnoreSpuriousDragEvent(bool aIgnoreSpuriousDragEvent)
-{
-  mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsHTMLEditor::GetSelectionContainer(nsIDOMElement ** aReturn)
 {
   nsCOMPtr<nsISelection>selection;
   nsresult res = GetSelection(getter_AddRefs(selection));
   // if we don't get the selection, just skip this
   if (NS_FAILED(res) || !selection) return res;
 
   bool bCollapsed;
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -365,18 +365,17 @@ public:
                               nsresult aStatus);
 
   /* ------------ Utility Routines, not part of public API -------------- */
   NS_IMETHOD TypedText(const nsAString& aString, PRInt32 aAction);
   nsresult InsertNodeAtPoint( nsIDOMNode *aNode, 
                               nsCOMPtr<nsIDOMNode> *ioParent, 
                               PRInt32 *ioOffset, 
                               bool aNoEmptyNodes);
-  already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode);
-                                
+  virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode);
 
   /** returns the absolute position of the end points of aSelection
     * in the document as a text stream.
     */
   nsresult GetTextSelectionOffsets(nsISelection *aSelection,
                                    PRInt32 &aStartOffset, 
                                    PRInt32 &aEndOffset);
 
@@ -567,28 +566,43 @@ protected:
     *                        (usually true, unless those characters
     *                        have already been added.)
     * @return aNodeInserted  The node spanning the insertion, if applicable.
     *                        If aAddCites is false, this will be null.
     */
   NS_IMETHOD InsertAsPlaintextQuotation(const nsAString & aQuotedText,
                                         bool aAddCites,
                                         nsIDOMNode **aNodeInserted);
+  // Return true if the data is safe to insert as the source and destination
+  // principals match, or we are in a editor context where this doesn't matter.
+  // Otherwise, the data must be sanitized first.
+  bool IsSafeToInsertData(nsIDOMDocument* aSourceDoc);
+
+  nsresult InsertObject(const char* aType, nsISupports* aObject, bool aIsSafe,
+                        nsIDOMDocument *aSourceDoc,
+                        nsIDOMNode *aDestinationNode,
+                        PRInt32 aDestOffset,
+                        bool aDoDeleteSelection);
 
   // factored methods for handling insertion of data from transferables (drag&drop or clipboard)
   NS_IMETHOD PrepareTransferable(nsITransferable **transferable);
   NS_IMETHOD PrepareHTMLTransferable(nsITransferable **transferable, bool havePrivFlavor);
-  nsresult   PutDragDataInTransferable(nsITransferable **aTransferable);
   NS_IMETHOD InsertFromTransferable(nsITransferable *transferable, 
                                     nsIDOMDocument *aSourceDoc,
                                     const nsAString & aContextStr,
                                     const nsAString & aInfoStr,
                                     nsIDOMNode *aDestinationNode,
                                     PRInt32 aDestinationOffset,
                                     bool aDoDeleteSelection);
+  nsresult InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
+                                  PRInt32 aIndex,
+                                  nsIDOMDocument *aSourceDoc,
+                                  nsIDOMNode *aDestinationNode,
+                                  PRInt32 aDestOffset,
+                                  bool aDoDeleteSelection);
   bool HavePrivateHTMLFlavor( nsIClipboard *clipboard );
   nsresult   ParseCFHTML(nsCString & aCfhtml, PRUnichar **aStuffToPaste, PRUnichar **aCfcontext);
   nsresult   DoContentFilterCallback(const nsAString &aFlavor,
                                      nsIDOMDocument *aSourceDoc,
                                      bool aWillDeleteSelection,
                                      nsIDOMNode **aFragmentAsNode,      
                                      nsIDOMNode **aFragStartNode,
                                      PRInt32 *aFragStartOffset,
@@ -717,19 +731,16 @@ protected:
   nsresult IsFirstEditableChild( nsIDOMNode *aNode, bool *aOutIsFirst);
   nsresult IsLastEditableChild( nsIDOMNode *aNode, bool *aOutIsLast);
   nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
   nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
 
   nsresult GetFirstEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstLeaf);
   nsresult GetLastEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastLeaf);
 
-  //XXX Kludge: Used to suppress spurious drag/drop events (bug 50703)
-  bool     mIgnoreSpuriousDragEvent;
-
   nsresult GetInlinePropertyBase(nsIAtom *aProperty, 
                              const nsAString *aAttribute,
                              const nsAString *aValue,
                              bool *aFirst, 
                              bool *aAny, 
                              bool *aAll,
                              nsAString *outValue,
                              bool aCheckDefaults = true);
--- a/editor/libeditor/text/nsPlaintextDataTransfer.cpp
+++ b/editor/libeditor/text/nsPlaintextDataTransfer.cpp
@@ -47,25 +47,27 @@
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIDOMDragEvent.h"
 #include "nsISelection.h"
 #include "nsCRT.h"
 #include "nsServiceManagerUtils.h"
 
 #include "nsIDOMRange.h"
+#include "nsIDOMDOMStringList.h"
 #include "nsIDocumentEncoder.h"
 #include "nsISupportsPrimitives.h"
 
 // Drag & Drop, Clipboard
 #include "nsIClipboard.h"
 #include "nsITransferable.h"
 #include "nsIDragService.h"
 #include "nsIDOMUIEvent.h"
 #include "nsCopySupport.h"
+#include "nsITransferable.h"
 
 // Misc
 #include "nsEditorUtils.h"
 #include "nsContentCID.h"
 #include "nsISelectionPrivate.h"
 #include "nsFrameSelection.h"
 #include "nsEventDispatcher.h"
 #include "nsContentUtils.h"
@@ -146,50 +148,58 @@ NS_IMETHODIMP nsPlaintextEditor::InsertT
       nsAutoEditBatch beginBatching(this);
       rv = InsertTextAt(stuffToPaste, aDestinationNode, aDestOffset, aDoDeleteSelection);
     }
   }
   NS_Free(bestFlavor);
       
   // Try to scroll the selection into view if the paste/drop succeeded
 
-  // After ScrollSelectionIntoView(), the pending notifications might be flushed
-  // and PresShell/PresContext/Frames may be dead. See bug 418470.
   if (NS_SUCCEEDED(rv))
     ScrollSelectionIntoView(false);
 
   return rv;
 }
 
-NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
+nsresult nsPlaintextEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
+                                                   PRInt32 aIndex,
+                                                   nsIDOMDocument *aSourceDoc,
+                                                   nsIDOMNode *aDestinationNode,
+                                                   PRInt32 aDestOffset,
+                                                   bool aDoDeleteSelection)
+{
+  nsCOMPtr<nsIVariant> data;
+  aDataTransfer->MozGetDataAt(NS_LITERAL_STRING("text/plain"), aIndex,
+                              getter_AddRefs(data));
+  nsAutoString insertText;
+  data->GetAsAString(insertText);
+  nsContentUtils::PlatformToDOMLineBreaks(insertText);
+
+  nsAutoEditBatch beginBatching(this);
+  return InsertTextAt(insertText, aDestinationNode, aDestOffset, aDoDeleteSelection);
+}
+
+nsresult nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
 {
   ForceCompositionEnd();
-  
-  nsresult rv;
-  nsCOMPtr<nsIDragService> dragService = 
-           do_GetService("@mozilla.org/widget/dragservice;1", &rv);
+
+  nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aDropEvent));
+  NS_ENSURE_TRUE(dragEvent, NS_ERROR_FAILURE);
+
+  nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
+  nsresult rv = dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIDragSession> dragSession;
-  dragService->GetCurrentSession(getter_AddRefs(dragSession));
-  NS_ENSURE_TRUE(dragSession, NS_OK);
-
   // Current doc is destination
   nsCOMPtr<nsIDOMDocument> destdomdoc; 
   rv = GetDocument(getter_AddRefs(destdomdoc)); 
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Get the nsITransferable interface for getting the data from the drop
-  nsCOMPtr<nsITransferable> trans;
-  rv = PrepareTransferable(getter_AddRefs(trans));
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(trans, NS_OK);  // NS_ERROR_FAILURE; SHOULD WE FAIL?
-
-  PRUint32 numItems = 0; 
-  rv = dragSession->GetNumDropItems(&numItems);
+  PRUint32 numItems = 0;
+  rv = dataTransfer->GetMozItemCount(&numItems);
   NS_ENSURE_SUCCESS(rv, rv);
   if (numItems < 1) return NS_ERROR_FAILURE;  // nothing to drop?
 
   // Combine any deletion and drop insertion into one transaction
   nsAutoEditBatch beginBatching(this);
 
   bool deleteSelection = false;
 
@@ -211,16 +221,45 @@ NS_IMETHODIMP nsPlaintextEditor::InsertF
   rv = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
 
   bool isCollapsed;
   rv = selection->GetIsCollapsed(&isCollapsed);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  nsCOMPtr<nsIDOMNode> sourceNode;
+  dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
+
+  nsCOMPtr<nsIDOMDocument> srcdomdoc;
+  if (sourceNode) {
+    sourceNode->GetOwnerDocument(getter_AddRefs(srcdomdoc));
+    NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
+  }
+
+  // Only the nsHTMLEditor::FindUserSelectAllNode returns a node.
+  nsCOMPtr<nsIDOMNode> userSelectNode = FindUserSelectAllNode(newSelectionParent);
+  if (userSelectNode)
+  {
+    // The drop is happening over a "-moz-user-select: all"
+    // subtree so make sure the content we insert goes before
+    // the root of the subtree.
+    //
+    // XXX: Note that inserting before the subtree matches the
+    //      current behavior when dropping on top of an image.
+    //      The decision for dropping before or after the
+    //      subtree should really be done based on coordinates.
+
+    rv = GetNodeLocation(userSelectNode, address_of(newSelectionParent),
+                         &newSelectionOffset);
+
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
+  }
+
   // Check if mouse is in the selection
   // if so, jump through some hoops to determine if mouse is over selection (bail)
   // and whether user wants to copy selection or delete it
   if (!isCollapsed)
   {
     // We never have to delete if selection is already collapsed
     bool cursorIsInSelection = false;
 
@@ -235,22 +274,16 @@ NS_IMETHODIMP nsPlaintextEditor::InsertF
       if (NS_FAILED(rv) || !range) 
         continue;  // don't bail yet, iterate through them all
 
       rv = range->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
       if (cursorIsInSelection)
         break;
     }
 
-    // Source doc is null if source is *not* the current editor document
-    // Current doc is destination (set earlier)
-    nsCOMPtr<nsIDOMDocument> srcdomdoc;
-    rv = dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc));
-    NS_ENSURE_SUCCESS(rv, rv);
-
     if (cursorIsInSelection)
     {
       // Dragging within same doc can't drop on itself -- leave!
       if (srcdomdoc == destdomdoc)
         return NS_OK;
 
       // Dragging from another window onto a selection
       // XXX Decision made to NOT do this,
@@ -258,162 +291,48 @@ NS_IMETHODIMP nsPlaintextEditor::InsertF
       //deleteSelection = true;
     }
     else 
     {
       // We are NOT over the selection
       if (srcdomdoc == destdomdoc)
       {
         // Within the same doc: delete if user doesn't want to copy
-        PRUint32 action;
-        dragSession->GetDragAction(&action);
-        deleteSelection = !(action & nsIDragService::DRAGDROP_ACTION_COPY);
+        PRUint32 dropEffect;
+        dataTransfer->GetDropEffectInt(&dropEffect);
+        deleteSelection = !(dropEffect & nsIDragService::DRAGDROP_ACTION_COPY);
       }
       else
       {
         // Different source doc: Don't delete
         deleteSelection = false;
       }
     }
   }
 
-  nsCOMPtr<nsIContent> newSelectionContent =
-    do_QueryInterface(newSelectionParent);
-  nsIContent *content = newSelectionContent;
-
-  while (content) {
-    nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(content));
-
-    if (formControl && !formControl->AllowDrop()) {
-      // Don't allow dropping into a form control that doesn't allow being
-      // dropped into.
-
-      return NS_OK;
-    }
-
-    content = content->GetParent();
-  }
-
-  PRUint32 i; 
-  for (i = 0; i < numItems; ++i)
-  {
-    rv = dragSession->GetData(trans, i);
-    NS_ENSURE_SUCCESS(rv, rv);
-    NS_ENSURE_TRUE(trans, NS_OK); // NS_ERROR_FAILURE; Should we fail?
-
-    // Beware! This may flush notifications via synchronous
-    // ScrollSelectionIntoView.
-    rv = InsertTextFromTransferable(trans, newSelectionParent, newSelectionOffset, deleteSelection);
-  }
-
-  return rv;
-}
-
-NS_IMETHODIMP nsPlaintextEditor::CanDrag(nsIDOMEvent *aDragEvent, bool *aCanDrag)
-{
-  NS_ENSURE_TRUE(aCanDrag, NS_ERROR_NULL_POINTER);
-  /* we really should be checking the XY coordinates of the mouseevent and ensure that
-   * that particular point is actually within the selection (not just that there is a selection)
-   */
-  *aCanDrag = false;
- 
-  // KLUDGE to work around bug 50703
-  // After double click and object property editing, 
-  //  we get a spurious drag event
-  if (mIgnoreSpuriousDragEvent)
-  {
-    mIgnoreSpuriousDragEvent = false;
-    return NS_OK;
-  }
-   
-  nsCOMPtr<nsISelection> selection;
-  nsresult res = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
-    
-  bool isCollapsed;
-  res = selection->GetIsCollapsed(&isCollapsed);
-  NS_ENSURE_SUCCESS(res, res);
-  
-  // if we are collapsed, we have no selection so nothing to drag
-  if ( isCollapsed )
-    return NS_OK;
-
-  nsCOMPtr<nsIDOMEventTarget> eventTarget;
-
-  nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aDragEvent));
-  if (nsevent) {
-    res = nsevent->GetTmpRealOriginalTarget(getter_AddRefs(eventTarget));
-    NS_ENSURE_SUCCESS(res, res);
-  }
-
-  if (eventTarget)
-  {
-    nsCOMPtr<nsIDOMNode> eventTargetDomNode = do_QueryInterface(eventTarget);
-    if ( eventTargetDomNode )
-    {
-      bool isTargetedCorrectly = false;
-      res = selection->ContainsNode(eventTargetDomNode, false, &isTargetedCorrectly);
-      NS_ENSURE_SUCCESS(res, res);
-
-      *aCanDrag = isTargetedCorrectly;
+  if (IsPlaintextEditor()) {
+    nsCOMPtr<nsIContent> content = do_QueryInterface(newSelectionParent);
+    while (content) {
+      nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(content));
+      if (formControl && !formControl->AllowDrop()) {
+        // Don't allow dropping into a form control that doesn't allow being
+        // dropped into.
+        return NS_OK;
+      }
+      content = content->GetParent();
     }
   }
 
-  return res;
-}
-
-NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent)
-{
-  nsresult rv;
-
-  nsCOMPtr<nsITransferable> trans;
-  rv = PutDragDataInTransferable(getter_AddRefs(trans));
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(trans, NS_OK); // maybe there was nothing to copy?
-
- /* get the drag service */
-  nsCOMPtr<nsIDragService> dragService = 
-           do_GetService("@mozilla.org/widget/dragservice;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  /* create an array of transferables */
-  nsCOMPtr<nsISupportsArray> transferableArray;
-  NS_NewISupportsArray(getter_AddRefs(transferableArray));
-  NS_ENSURE_TRUE(transferableArray, NS_ERROR_OUT_OF_MEMORY);
-
-  /* add the transferable to the array */
-  rv = transferableArray->AppendElement(trans);
-  NS_ENSURE_SUCCESS(rv, rv);
+  for (PRUint32 i = 0; i < numItems; ++i) {
+    InsertFromDataTransfer(dataTransfer, i, srcdomdoc, newSelectionParent,
+                           newSelectionOffset, deleteSelection);
+  }
 
-  // check our transferable hooks (if any)
-  nsCOMPtr<nsIDOMDocument> domdoc;
-  GetDocument(getter_AddRefs(domdoc));
-
-  /* invoke drag */
-  nsCOMPtr<nsIDOMEventTarget> eventTarget;
-  rv = aDragEvent->GetTarget(getter_AddRefs(eventTarget));
-  NS_ENSURE_SUCCESS(rv, rv);
-  nsCOMPtr<nsIDOMNode> domnode = do_QueryInterface(eventTarget);
-
-  nsCOMPtr<nsIScriptableRegion> selRegion;
-  nsCOMPtr<nsISelection> selection;
-  rv = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  unsigned int flags;
-  // in some cases we'll want to cut rather than copy... hmmmmm...
-  flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE;
-
-  nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aDragEvent));
-  rv = dragService->InvokeDragSessionWithSelection(selection, transferableArray,
-                                                   flags, dragEvent, nsnull);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  aDragEvent->StopPropagation();
-  aDragEvent->PreventDefault();
+  if (NS_SUCCEEDED(rv))
+    ScrollSelectionIntoView(false);
 
   return rv;
 }
 
 NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
 {
   if (!FireClipboardEvent(NS_PASTE))
     return NS_OK;
@@ -433,18 +352,16 @@ NS_IMETHODIMP nsPlaintextEditor::Paste(P
     if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) && IsModifiable())
     {
       // handle transferable hooks
       nsCOMPtr<nsIDOMDocument> domdoc;
       GetDocument(getter_AddRefs(domdoc));
       if (!nsEditorHookUtils::DoInsertionHook(domdoc, nsnull, trans))
         return NS_OK;
 
-      // Beware! This may flush notifications via synchronous
-      // ScrollSelectionIntoView.
       rv = InsertTextFromTransferable(trans, nsnull, nsnull, true);
     }
   }
 
   return rv;
 }
 
 NS_IMETHODIMP nsPlaintextEditor::PasteTransferable(nsITransferable *aTransferable)
@@ -456,18 +373,16 @@ NS_IMETHODIMP nsPlaintextEditor::PasteTr
     return NS_OK;
 
   // handle transferable hooks
   nsCOMPtr<nsIDOMDocument> domdoc;
   GetDocument(getter_AddRefs(domdoc));
   if (!nsEditorHookUtils::DoInsertionHook(domdoc, nsnull, aTransferable))
     return NS_OK;
 
-  // Beware! This may flush notifications via synchronous
-  // ScrollSelectionIntoView.
   return InsertTextFromTransferable(aTransferable, nsnull, nsnull, true);
 }
 
 NS_IMETHODIMP nsPlaintextEditor::CanPaste(PRInt32 aSelectionType, bool *aCanPaste)
 {
   NS_ENSURE_ARG_POINTER(aCanPaste);
   *aCanPaste = false;
 
@@ -516,107 +431,8 @@ NS_IMETHODIMP nsPlaintextEditor::CanPast
                                                &dataLen);
   if (NS_SUCCEEDED(rv) && data)
     *aCanPaste = true;
   else
     *aCanPaste = false;
   
   return NS_OK;
 }
-
-
-nsresult
-nsPlaintextEditor::SetupDocEncoder(nsIDocumentEncoder **aDocEncoder)
-{
-  nsCOMPtr<nsIDOMDocument> domDoc;
-  nsresult rv = GetDocument(getter_AddRefs(domDoc));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // find out if we're a plaintext control or not
-  // get correct mimeType and document encoder flags set
-  nsAutoString mimeType;
-  PRUint32 docEncoderFlags = 0;
-  if (IsPlaintextEditor())
-  {
-    docEncoderFlags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted;
-    mimeType.AssignLiteral(kUnicodeMime);
-  }
-  else
-    mimeType.AssignLiteral(kHTMLMime);
-
-  // set up docEncoder
-  nsCOMPtr<nsIDocumentEncoder> encoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID);
-  NS_ENSURE_TRUE(encoder, NS_ERROR_OUT_OF_MEMORY);
-
-  rv = encoder->Init(domDoc, mimeType, docEncoderFlags);
-  NS_ENSURE_SUCCESS(rv, rv);
-    
-  /* get the selection to be dragged */
-  nsCOMPtr<nsISelection> selection;
-  rv = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = encoder->SetSelection(selection);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  *aDocEncoder = encoder;
-  NS_ADDREF(*aDocEncoder);
-  return NS_OK;
-}
-
-nsresult
-nsPlaintextEditor::PutDragDataInTransferable(nsITransferable **aTransferable)
-{
-  *aTransferable = nsnull;
-  nsCOMPtr<nsIDocumentEncoder> docEncoder;
-  nsresult rv = SetupDocEncoder(getter_AddRefs(docEncoder));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // grab a string
-  nsAutoString buffer;
-  rv = docEncoder->EncodeToString(buffer);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // if we have an empty string, we're done; otherwise continue
-  if (buffer.IsEmpty())
-    return NS_OK;
-
-  nsCOMPtr<nsISupportsString> dataWrapper =
-                        do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = dataWrapper->SetData(buffer);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  /* create html flavor transferable */
-  nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // find out if we're a plaintext control or not
-  if (IsPlaintextEditor())
-  {
-    // Add the unicode flavor to the transferable
-    rv = trans->AddDataFlavor(kUnicodeMime);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  else
-  {
-    rv = trans->AddDataFlavor(kHTMLMime);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIFormatConverter> htmlConverter = do_CreateInstance("@mozilla.org/widget/htmlformatconverter;1");
-    NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
-
-    rv = trans->SetConverter(htmlConverter);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  // QI the data object an |nsISupports| so that when the transferable holds
-  // onto it, it will addref the correct interface.
-  nsCOMPtr<nsISupports> nsisupportsDataWrapper = do_QueryInterface(dataWrapper);
-  rv = trans->SetTransferData(IsPlaintextEditor() ? kUnicodeMime : kHTMLMime,
-                   nsisupportsDataWrapper, buffer.Length() * sizeof(PRUnichar));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  *aTransferable = trans;
-  NS_ADDREF(*aTransferable);
-  return NS_OK;
-}
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -83,17 +83,16 @@
 #include "nsCopySupport.h"
 
 #include "mozilla/FunctionTimer.h"
 
 using namespace mozilla;
 
 nsPlaintextEditor::nsPlaintextEditor()
 : nsEditor()
-, mIgnoreSpuriousDragEvent(false)
 , mRules(nsnull)
 , mWrapToWindow(false)
 , mWrapColumn(0)
 , mMaxTextLength(-1)
 , mInitTriggerCounter(0)
 , mNewlineHandling(nsIPlaintextEditor::eNewlinesPasteToFirst)
 #ifdef XP_WIN
 , mCaretStyle(1)
--- a/editor/libeditor/text/nsPlaintextEditor.h
+++ b/editor/libeditor/text/nsPlaintextEditor.h
@@ -113,20 +113,16 @@ public:
   NS_IMETHOD CanCut(bool *aCanCut);
   NS_IMETHOD Copy();
   NS_IMETHOD CanCopy(bool *aCanCopy);
   NS_IMETHOD Paste(PRInt32 aSelectionType);
   NS_IMETHOD CanPaste(PRInt32 aSelectionType, bool *aCanPaste);
   NS_IMETHOD PasteTransferable(nsITransferable *aTransferable);
   NS_IMETHOD CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste);
 
-  NS_IMETHOD CanDrag(nsIDOMEvent *aDragEvent, bool *aCanDrag);
-  NS_IMETHOD DoDrag(nsIDOMEvent *aDragEvent);
-  NS_IMETHOD InsertFromDrop(nsIDOMEvent* aDropEvent);
-
   NS_IMETHOD OutputToString(const nsAString& aFormatType,
                             PRUint32 aFlags,
                             nsAString& aOutputString);
                             
   NS_IMETHOD OutputToStream(nsIOutputStream* aOutputStream,
                             const nsAString& aFormatType,
                             const nsACString& aCharsetOverride,
                             PRUint32 aFlags);
@@ -162,16 +158,25 @@ public:
                                    PRUint32 &aStartOffset, 
                                    PRUint32 &aEndOffset);
 
   nsresult InsertTextAt(const nsAString &aStringToInsert,
                         nsIDOMNode *aDestinationNode,
                         PRInt32 aDestOffset,
                         bool aDoDeleteSelection);
 
+  virtual nsresult InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
+                                          PRInt32 aIndex,
+                                          nsIDOMDocument *aSourceDoc,
+                                          nsIDOMNode *aDestinationNode,
+                                          PRInt32 aDestOffset,
+                                          bool aDoDeleteSelection);
+
+  virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent);
+
   /**
    * Extends the selection for given deletion operation
    * If done, also update aAction to what's actually left to do after the
    * extension.
    */
   nsresult ExtendSelectionForDelete(nsISelection* aSelection,
                                     nsIEditor::EDirection *aAction);
 
@@ -200,29 +205,23 @@ protected:
   nsresult InsertBR(nsCOMPtr<nsIDOMNode>* outBRNode);
 
   // factored methods for handling insertion of data from transferables (drag&drop or clipboard)
   NS_IMETHOD PrepareTransferable(nsITransferable **transferable);
   NS_IMETHOD InsertTextFromTransferable(nsITransferable *transferable,
                                         nsIDOMNode *aDestinationNode,
                                         PRInt32 aDestOffset,
                                         bool aDoDeleteSelection);
-  virtual nsresult SetupDocEncoder(nsIDocumentEncoder **aDocEncoder);
-  virtual nsresult PutDragDataInTransferable(nsITransferable **aTransferable);
 
   /** shared outputstring; returns whether selection is collapsed and resulting string */
   nsresult SharedOutputString(PRUint32 aFlags, bool* aIsCollapsed, nsAString& aResult);
 
   /* small utility routine to test the eEditorReadonly bit */
   bool IsModifiable();
 
-  //XXX Kludge: Used to suppress spurious drag/drop events (bug 50703)
-  bool     mIgnoreSpuriousDragEvent;
-  NS_IMETHOD IgnoreSpuriousDragEvent(bool aIgnoreSpuriousDragEvent) {mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent; return NS_OK;}
-
   bool CanCutOrCopy();
   bool FireClipboardEvent(PRInt32 aType);
 
   bool UpdateMetaCharset(nsIDOMDocument* aDocument,
                          const nsACString& aCharacterSet);
 
 // Data members
 protected:
--- a/embedding/browser/webBrowser/nsIWebBrowserChrome.idl
+++ b/embedding/browser/webBrowser/nsIWebBrowserChrome.idl
@@ -42,17 +42,17 @@
 interface nsIWebBrowser;
 interface nsIDocShellTreeItem;
 
 /**
  * nsIWebBrowserChrome corresponds to the top-level, outermost window
  * containing an embedded Gecko web browser.
  */
 
-[scriptable, uuid(BA434C60-9D52-11d3-AFB0-00A024FFC08C)]
+[scriptable, uuid(E8C414C4-DC38-4BA3-AB4E-EC4CBBE22907)]
 interface nsIWebBrowserChrome : nsISupports
 {
     const unsigned long STATUS_SCRIPT         = 0x00000001;
     const unsigned long STATUS_SCRIPT_DEFAULT = 0x00000002;
     const unsigned long STATUS_LINK           = 0x00000003;
 
     /**
      * Called when the status text in the chrome needs to be updated.
@@ -70,53 +70,57 @@ interface nsIWebBrowserChrome : nsISuppo
      * as if it had created the WebBrowser itself.  This includes positioning
      * setting up listeners etc.
      */
     attribute nsIWebBrowser webBrowser;
 
     /**
      * Definitions for the chrome flags
      */
-    const unsigned long CHROME_DEFAULT          = 0x00000001;
-    const unsigned long CHROME_WINDOW_BORDERS   = 0x00000002;
-    const unsigned long CHROME_WINDOW_CLOSE     = 0x00000004;
-    const unsigned long CHROME_WINDOW_RESIZE    = 0x00000008;
-    const unsigned long CHROME_MENUBAR          = 0x00000010;
-    const unsigned long CHROME_TOOLBAR          = 0x00000020;
-    const unsigned long CHROME_LOCATIONBAR      = 0x00000040;
-    const unsigned long CHROME_STATUSBAR        = 0x00000080;
-    const unsigned long CHROME_PERSONAL_TOOLBAR = 0x00000100;
-    const unsigned long CHROME_SCROLLBARS       = 0x00000200;
-    const unsigned long CHROME_TITLEBAR         = 0x00000400;
-    const unsigned long CHROME_EXTRA            = 0x00000800;
+    const unsigned long CHROME_DEFAULT                = 0x00000001;
+    const unsigned long CHROME_WINDOW_BORDERS         = 0x00000002;
+    const unsigned long CHROME_WINDOW_CLOSE           = 0x00000004;
+    const unsigned long CHROME_WINDOW_RESIZE          = 0x00000008;
+    const unsigned long CHROME_MENUBAR                = 0x00000010;
+    const unsigned long CHROME_TOOLBAR                = 0x00000020;
+    const unsigned long CHROME_LOCATIONBAR            = 0x00000040;
+    const unsigned long CHROME_STATUSBAR              = 0x00000080;
+    const unsigned long CHROME_PERSONAL_TOOLBAR       = 0x00000100;
+    const unsigned long CHROME_SCROLLBARS             = 0x00000200;
+    const unsigned long CHROME_TITLEBAR               = 0x00000400;
+    const unsigned long CHROME_EXTRA                  = 0x00000800;
     
     // createBrowserWindow specific flags
-    const unsigned long CHROME_WITH_SIZE        = 0x00001000;
-    const unsigned long CHROME_WITH_POSITION    = 0x00002000;
+    const unsigned long CHROME_WITH_SIZE              = 0x00001000;
+    const unsigned long CHROME_WITH_POSITION          = 0x00002000;
 
     // special cases
-    const unsigned long CHROME_WINDOW_MIN       = 0x00004000;
-    const unsigned long CHROME_WINDOW_POPUP     = 0x00008000;
+    const unsigned long CHROME_WINDOW_MIN             = 0x00004000;
+    const unsigned long CHROME_WINDOW_POPUP           = 0x00008000;
 
-    const unsigned long CHROME_WINDOW_RAISED    = 0x02000000;
-    const unsigned long CHROME_WINDOW_LOWERED   = 0x04000000;
-    const unsigned long CHROME_CENTER_SCREEN    = 0x08000000;
+    // Prevents new window animations on Mac OS X Lion.  Ignored on other
+    // platforms.
+    const unsigned long CHROME_MAC_SUPPRESS_ANIMATION = 0x01000000;
+
+    const unsigned long CHROME_WINDOW_RAISED          = 0x02000000;
+    const unsigned long CHROME_WINDOW_LOWERED         = 0x04000000;
+    const unsigned long CHROME_CENTER_SCREEN          = 0x08000000;
 
     // Make the new window dependent on the parent.  This flag is only
     // meaningful if CHROME_OPENAS_CHROME is set; content windows should not be
     // dependent.
-    const unsigned long CHROME_DEPENDENT        = 0x10000000;
+    const unsigned long CHROME_DEPENDENT              = 0x10000000;
 
     // Note: The modal style bit just affects the way the window looks and does
     //       mean it's actually modal.
-    const unsigned long CHROME_MODAL            = 0x20000000; 
-    const unsigned long CHROME_OPENAS_DIALOG    = 0x40000000;
-    const unsigned long CHROME_OPENAS_CHROME    = 0x80000000;
+    const unsigned long CHROME_MODAL                  = 0x20000000; 
+    const unsigned long CHROME_OPENAS_DIALOG          = 0x40000000;
+    const unsigned long CHROME_OPENAS_CHROME          = 0x80000000;
     
-    const unsigned long CHROME_ALL              = 0x00000ffe;
+    const unsigned long CHROME_ALL                    = 0x00000ffe;
     
     /**
      * The chrome flags for this browser chrome. The implementation should
      * reflect the value of this attribute by hiding or showing its chrome
      * appropriately.
      */
     attribute unsigned long chromeFlags;
 
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
@@ -1522,16 +1522,19 @@ PRUint32 nsWindowWatcher::CalculateChrom
      instructions. (Note modality implies dependence.) */
 
   if (WinHasOption(aFeatures, "alwaysLowered", 0, nsnull) ||
       WinHasOption(aFeatures, "z-lock", 0, nsnull))
     chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
   else if (WinHasOption(aFeatures, "alwaysRaised", 0, nsnull))
     chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_RAISED;
 
+  chromeFlags |= WinHasOption(aFeatures, "macsuppressanimation", 0, nsnull) ?
+    nsIWebBrowserChrome::CHROME_MAC_SUPPRESS_ANIMATION : 0;
+
   chromeFlags |= WinHasOption(aFeatures, "chrome", 0, nsnull) ?
     nsIWebBrowserChrome::CHROME_OPENAS_CHROME : 0;
   chromeFlags |= WinHasOption(aFeatures, "extrachrome", 0, nsnull) ?
     nsIWebBrowserChrome::CHROME_EXTRA : 0;
   chromeFlags |= WinHasOption(aFeatures, "centerscreen", 0, nsnull) ?
     nsIWebBrowserChrome::CHROME_CENTER_SCREEN : 0;
   chromeFlags |= WinHasOption(aFeatures, "dependent", 0, nsnull) ?
     nsIWebBrowserChrome::CHROME_DEPENDENT : 0;
--- a/extensions/auth/nsHttpNegotiateAuth.cpp
+++ b/extensions/auth/nsHttpNegotiateAuth.cpp
@@ -65,23 +65,25 @@
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsNetCID.h"
 #include "plbase64.h"
 #include "plstr.h"
 #include "prprf.h"
 #include "prlog.h"
 #include "prmem.h"
+#include "prnetdb.h"
 
 //-----------------------------------------------------------------------------
 
 static const char kNegotiate[] = "Negotiate";
 static const char kNegotiateAuthTrustedURIs[] = "network.negotiate-auth.trusted-uris";
 static const char kNegotiateAuthDelegationURIs[] = "network.negotiate-auth.delegation-uris";
 static const char kNegotiateAuthAllowProxies[] = "network.negotiate-auth.allow-proxies";
+static const char kNegotiateAuthAllowNonFqdn[] = "network.negotiate-auth.allow-non-fqdn";
 static const char kNegotiateAuthSSPI[] = "network.auth.use-sspi";
 
 #define kNegotiateLen  (sizeof(kNegotiate)-1)
 
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpNegotiateAuth::GetAuthFlags(PRUint32 *flags)
@@ -138,17 +140,18 @@ nsHttpNegotiateAuth::ChallengeReceived(n
 
         nsCOMPtr<nsIProxyInfo> proxyInfo;
         authChannel->GetProxyInfo(getter_AddRefs(proxyInfo));
         NS_ENSURE_STATE(proxyInfo);
 
         proxyInfo->GetHost(service);
     }
     else {
-        bool allowed = TestPref(uri, kNegotiateAuthTrustedURIs);
+        bool allowed = TestNonFqdn(uri) ||
+                       TestPref(uri, kNegotiateAuthTrustedURIs);
         if (!allowed) {
             LOG(("nsHttpNegotiateAuth::ChallengeReceived URI blocked\n"));
             return NS_ERROR_ABORT;
         }
 
         bool delegation = TestPref(uri, kNegotiateAuthDelegationURIs);
         if (delegation) {
             LOG(("  using REQ_DELEGATE\n"));
@@ -327,16 +330,33 @@ nsHttpNegotiateAuth::TestBoolPref(const 
     nsresult rv = prefs->GetBoolPref(pref, &val);
     if (NS_FAILED(rv))
         return false;
 
     return val;
 }
 
 bool
+nsHttpNegotiateAuth::TestNonFqdn(nsIURI *uri)
+{
+    nsCAutoString host;
+    PRNetAddr addr;
+
+    if (!TestBoolPref(kNegotiateAuthAllowNonFqdn))
+        return false;
+
+    if (NS_FAILED(uri->GetAsciiHost(host)))
+        return false;
+
+    // return true if host does not contain a dot and is not an ip address
+    return !host.IsEmpty() && host.FindChar('.') == kNotFound &&
+           PR_StringToNetAddr(host.BeginReading(), &addr) != PR_SUCCESS;
+}
+
+bool
 nsHttpNegotiateAuth::TestPref(nsIURI *uri, const char *pref)
 {
     nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (!prefs)
         return false;
 
     nsCAutoString scheme, host;
     PRInt32 port;
--- a/extensions/auth/nsHttpNegotiateAuth.h
+++ b/extensions/auth/nsHttpNegotiateAuth.h
@@ -53,16 +53,19 @@ class nsHttpNegotiateAuth : public nsIHt
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIHTTPAUTHENTICATOR
 
 private:
     // returns the value of the given boolean pref
     bool TestBoolPref(const char *pref);
 
+    // tests if the host part of an uri is fully qualified
+    bool TestNonFqdn(nsIURI *uri);
+
     // returns true if URI is accepted by the list of hosts in the pref
     bool TestPref(nsIURI *, const char *pref);
 
     bool MatchesBaseURI(const nsCSubstring &scheme,
                           const nsCSubstring &host,
                           PRInt32             port,
                           const char         *baseStart,
                           const char         *baseEnd);
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -628,17 +628,17 @@ DrawTargetD2D::DrawSurfaceWithShadow(Sou
                                            (-Float(aSurface->GetSize().height) / mSize.height) * 2.0f));
   mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
     SetFloatVector(ShaderConstantRectD3D10(0, 0, Float(srcSurfSize.width) / tmpSurfSize.width,
                                                  Float(srcSurfSize.height) / tmpSurfSize.height));
 
   if (mPushedClips.size()) {
     mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(maskSRView);
     mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
-      SetFloatVector(ShaderConstantRectD3D10(shadowDest.x / mSize.width, shadowDest.y / mSize.width,
+      SetFloatVector(ShaderConstantRectD3D10(shadowDest.x / mSize.width, shadowDest.y / mSize.height,
                                              Float(aSurface->GetSize().width) / mSize.width,
                                              Float(aSurface->GetSize().height) / mSize.height));
     mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")->
       GetPassByIndex(2)->Apply(0);
   } else {
     mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")->
       GetPassByIndex(1)->Apply(0);
   }
@@ -653,17 +653,17 @@ DrawTargetD2D::DrawSurfaceWithShadow(Sou
                                            (Float(aSurface->GetSize().width) / mSize.width) * 2.0f,
                                            (-Float(aSurface->GetSize().height) / mSize.height) * 2.0f));
   mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(static_cast<SourceSurfaceD2DTarget*>(aSurface)->GetSRView());
   mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
     SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
 
   if (mPushedClips.size()) {
     mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
-      SetFloatVector(ShaderConstantRectD3D10(aDest.x / mSize.width, aDest.y / mSize.width,
+      SetFloatVector(ShaderConstantRectD3D10(aDest.x / mSize.width, aDest.y / mSize.height,
                                              Float(aSurface->GetSize().width) / mSize.width,
                                              Float(aSurface->GetSize().height) / mSize.height));
     mPrivateData->mEffect->GetTechniqueByName("SampleMaskedTexture")->
       GetPassByIndex(0)->Apply(0);
   } else {
     mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->
       GetPassByIndex(0)->Apply(0);
   }
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -130,16 +130,18 @@ static void (*CGContextClipToMaskPtr) (C
 static void (*CGContextDrawTiledImagePtr) (CGContextRef, CGRect, CGImageRef) = NULL;
 static unsigned int (*CGContextGet