Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Tue, 21 Feb 2012 15:08:22 -0800
changeset 112159 61980734d3a21c29f3783ae946733af29ebcd2bd
parent 112157 82c6ca0616d0561c5e68ceecf3d4d24330db0bff (current diff)
parent 90148 7dcbce54a953090ae8e537f93c6c99ab8eb0dc62 (diff)
child 112160 5a061abdf807b2adfacf74e0febcde810bb5ce2b
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge from mozilla-central.
accessible/src/base/Makefile.in
accessible/src/base/nsAccessible.cpp
accessible/src/html/nsHTMLTableAccessible.cpp
accessible/tests/mochitest/common.js
b2g/installer/package-manifest.in
browser/app/profile/firefox.js
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
browser/components/nsBrowserContentHandler.js
browser/devtools/styleinspector/CssHtmlTree.jsm
browser/devtools/styleinspector/CssLogic.jsm
caps/src/nsScriptSecurityManager.cpp
config/autoconf.mk.in
configure.in
content/base/public/nsIContent.h
content/base/public/nsINode.h
content/base/public/nsIXMLHttpRequest.idl
content/base/src/mozSanitizingSerializer.cpp
content/base/src/nsAttrAndChildArray.cpp
content/base/src/nsContentAreaDragDrop.cpp
content/base/src/nsContentAreaDragDrop.h
content/base/src/nsContentUtils.cpp
content/base/src/nsCopySupport.cpp
content/base/src/nsDOMAttribute.cpp
content/base/src/nsDocument.cpp
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsGenericElement.cpp
content/base/src/nsGkAtomList.h
content/base/src/nsXMLHttpRequest.cpp
content/base/test/test_XHR.html
content/canvas/src/CustomQS_WebGL.h
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMEvent.h
content/events/src/nsEventStateManager.cpp
content/events/src/nsEventStateManager.h
content/html/content/public/nsHTMLMediaElement.h
content/html/content/src/nsHTMLMediaElement.cpp
content/html/content/src/nsHTMLTableElement.cpp
content/media/nsBuiltinDecoder.cpp
content/media/nsBuiltinDecoderStateMachine.cpp
content/svg/content/src/SVGPathData.cpp
content/svg/content/src/nsSVGElement.cpp
content/svg/content/src/nsSVGElement.h
content/svg/content/src/nsSVGForeignObjectElement.cpp
content/svg/content/src/nsSVGForeignObjectElement.h
content/svg/content/src/nsSVGGraphicElement.cpp
content/svg/content/src/nsSVGGraphicElement.h
content/svg/content/src/nsSVGPathElement.cpp
content/svg/content/src/nsSVGSVGElement.cpp
content/svg/content/src/nsSVGSVGElement.h
content/svg/content/src/nsSVGUseElement.cpp
content/svg/content/src/nsSVGUseElement.h
docshell/base/nsDocShell.cpp
docshell/build/nsDocShellModule.cpp
dom/Makefile.in
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsDOMWindowUtils.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsGlobalWindowCommands.cpp
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
dom/base/nsPIDOMWindow.h
dom/dom-config.mk
dom/indexedDB/IDBIndex.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/plugins/base/nsJSNPRuntime.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/src/events/nsJSEventListener.cpp
dom/workers/WorkerScope.cpp
dom/workers/XMLHttpRequest.cpp
dom/workers/XMLHttpRequestPrivate.cpp
editor/libeditor/base/nsEditor.cpp
editor/libeditor/base/nsEditor.h
editor/libeditor/base/nsEditorEventListener.cpp
editor/libeditor/base/nsEditorUtils.h
editor/libeditor/html/nsHTMLDataTransfer.cpp
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/html/nsHTMLEditor.h
editor/libeditor/text/nsPlaintextDataTransfer.cpp
editor/libeditor/text/nsPlaintextEditor.cpp
editor/libeditor/text/nsPlaintextEditor.h
extensions/auth/nsHttpNegotiateAuth.cpp
extensions/auth/nsHttpNegotiateAuth.h
gfx/gl/GLContext.cpp
gfx/gl/GLContextProviderEGL.cpp
gfx/src/nsDeviceContext.cpp
gfx/src/nsDeviceContext.h
gfx/src/nsSystemFontsAndroid.cpp
gfx/src/nsSystemFontsAndroid.h
gfx/src/nsSystemFontsGTK2.cpp
gfx/src/nsSystemFontsGTK2.h
gfx/src/nsSystemFontsMac.h
gfx/src/nsSystemFontsMac.mm
gfx/src/nsSystemFontsOS2.cpp
gfx/src/nsSystemFontsOS2.h
gfx/src/nsSystemFontsQt.cpp
gfx/src/nsSystemFontsQt.h
gfx/src/nsSystemFontsWin.cpp
gfx/src/nsSystemFontsWin.h
gfx/thebes/gfx3DMatrix.cpp
gfx/thebes/gfx3DMatrix.h
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxHarfBuzzShaper.cpp
intl/unicharutil/src/nsUnicodeNormalizer.cpp
intl/unicharutil/src/nsUnicodeNormalizer.h
js/jsd/jsd_xpc.cpp
js/src/Makefile.in
js/src/MemoryMetrics.cpp
js/src/frontend/Parser.cpp
js/src/gc/Barrier.h
js/src/gc/Statistics.h
js/src/ion/Ion.cpp
js/src/ion/IonFrames.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsatom.cpp
js/src/jsbool.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsdate.cpp
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsgcinlines.h
js/src/jsgcmark.cpp
js/src/jsgcmark.h
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jspropertycache.cpp
js/src/jsproxy.cpp
js/src/jsscope.cpp
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jsweakmap.cpp
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/MethodJIT.h
js/src/methodjit/PolyIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/src/vm/RegExpObject-inl.h
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/xpconnect/idl/nsIXPConnect.idl
js/xpconnect/src/XPCInlines.h
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/src/xpcpublic.h
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsDocumentViewer.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsPresShell.cpp
layout/build/Makefile.in
layout/build/nsLayoutModule.cpp
layout/build/nsLayoutStatics.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsSimplePageSequence.cpp
layout/generic/nsSubDocumentFrame.h
layout/reftests/svg/moz-only/reftest.list
layout/reftests/svg/reftest.list
layout/reftests/text/reftest.list
layout/style/Declaration.cpp
layout/style/Declaration.h
layout/style/nsCSSParser.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsRuleNode.h
layout/style/nsStyleAnimation.cpp
layout/style/nsStyleAnimation.h
layout/style/nsStyleStruct.cpp
layout/style/test/property_database.js
layout/svg/base/src/nsSVGClipPathFrame.cpp
layout/svg/base/src/nsSVGContainerFrame.cpp
layout/svg/base/src/nsSVGForeignObjectFrame.cpp
layout/svg/base/src/nsSVGGlyphFrame.cpp
layout/svg/base/src/nsSVGGlyphFrame.h
layout/svg/base/src/nsSVGImageFrame.cpp
layout/svg/base/src/nsSVGInnerSVGFrame.cpp
layout/svg/base/src/nsSVGPathGeometryFrame.cpp
layout/svg/base/src/nsSVGSwitchFrame.cpp
layout/svg/base/src/nsSVGTextFrame.cpp
layout/svg/base/src/nsSVGUtils.cpp
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/xul/installer/package-manifest.in
modules/libpref/src/init/all.js
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/SpdySession.cpp
netwerk/protocol/http/SpdySession.h
netwerk/protocol/http/SpdyStream.cpp
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpNTLMAuth.cpp
nsprpub/TAG-INFO
nsprpub/config/prdepend.h
security/manager/ssl/src/nsSmartCardEvent.cpp
security/patches/bug-717906-lowhash
services/sync/tests/unit/test_jpakeclient.js
testing/mochitest/runtests.py
testing/mochitest/tests/SimpleTest/setup.js
testing/peptest/tests/firefox/examples/example_tests.ini
testing/peptest/tests/firefox/examples/test_contextMenu.js
testing/peptest/tests/firefox/examples/test_openBlankTab.js
testing/peptest/tests/firefox/examples/test_openBookmarksMenu.js
testing/peptest/tests/firefox/examples/test_openWindow.js
testing/peptest/tests/firefox/examples/test_resizeWindow.js
testing/peptest/tests/firefox/examples/test_searchGoogle.js
testing/testsuite-targets.mk
testing/xpcshell/xpcshell.ini
toolkit/components/aboutmemory/content/aboutMemory.js
toolkit/components/places/nsAnnotationService.cpp
toolkit/components/places/nsNavHistory.cpp
toolkit/components/places/tests/head_common.js
toolkit/components/telemetry/TelemetryHistograms.h
toolkit/components/telemetry/TelemetryPing.js
toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
toolkit/components/typeaheadfind/nsTypeAheadFind.h
widget/LookAndFeel.h
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidJNI.cpp
widget/android/nsAppShell.cpp
widget/android/nsAppShell.h
widget/android/nsLookAndFeel.cpp
widget/android/nsLookAndFeel.h
widget/cocoa/GfxInfo.mm
widget/gtk2/nsLookAndFeel.cpp
widget/gtk2/nsLookAndFeel.h
widget/gtk2/nsNativeThemeGTK.cpp
widget/windows/GfxInfo.cpp
widget/windows/nsTextStore.cpp
widget/xpwidgets/nsXPLookAndFeel.cpp
widget/xpwidgets/nsXPLookAndFeel.h
xpcom/base/nsCycleCollector.cpp
xpcom/ds/TimeStamp.h
xpcom/io/nsLocalFileWin.cpp
xpcom/string/public/nsTSubstring.h
xpcom/string/src/nsTSubstring.cpp
xulrunner/stub/nsXULStub.cpp
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -71,16 +71,17 @@ CPPSRCS = \
   nsEventShell.cpp \
   nsFormControlAccessible.cpp \
   nsRootAccessible.cpp \
   nsApplicationAccessible.cpp \
   nsCaretAccessible.cpp \
   nsTextAccessible.cpp \
   nsTextEquivUtils.cpp \
   nsTextAttrs.cpp \
+  StyleInfo.cpp \
   TextUpdater.cpp \
   $(NULL)
 
 EXPORTS = \
   a11yGeneric.h \
   nsAccDocManager.h \
   nsAccessibilityService.h \
   nsAccessible.h \
@@ -102,16 +103,17 @@ FORCE_STATIC_LIB = 1
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../xpcom \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xul \
   -I$(srcdir)/../../../layout/generic \
+  -I$(srcdir)/../../../layout/style \
   -I$(srcdir)/../../../layout/xul/base/src \
   -I$(srcdir)/../xforms \
   $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../atk \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/StyleInfo.cpp
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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
+ * 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 ***** */
+
+#include "StyleInfo.h"
+
+#include "mozilla/dom/Element.h"
+#include "nsComputedDOMStyle.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+StyleInfo::StyleInfo(dom::Element* aElement, nsIPresShell* aPresShell) :
+  mElement(aElement)
+{
+  mStyleContext =
+    nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
+                                                         nsnull,
+                                                         aPresShell);
+}
+
+void
+StyleInfo::Display(nsAString& aValue)
+{
+  aValue.Truncate();
+  AppendASCIItoUTF16(
+    nsCSSProps::ValueToKeyword(mStyleContext->GetStyleDisplay()->mDisplay,
+                               nsCSSProps::kDisplayKTable), aValue);
+}
+
+void
+StyleInfo::TextAlign(nsAString& aValue)
+{
+  aValue.Truncate();
+  AppendASCIItoUTF16(
+    nsCSSProps::ValueToKeyword(mStyleContext->GetStyleText()->mTextAlign,
+                               nsCSSProps::kTextAlignKTable), aValue);
+}
+
+void
+StyleInfo::TextIndent(nsAString& aValue)
+{
+  aValue.Truncate();
+
+  const nsStyleCoord& styleCoord =
+    mStyleContext->GetStyleText()->mTextIndent;
+
+  nscoord coordVal;
+  switch (styleCoord.GetUnit()) {
+    case eStyleUnit_Coord:
+      coordVal = styleCoord.GetCoordValue();
+      break;
+
+    case eStyleUnit_Percent:
+    {
+      nsIFrame* frame = mElement->GetPrimaryFrame();
+      nsIFrame* containerFrame = frame->GetContainingBlock();
+      nscoord percentageBase = containerFrame->GetContentRect().width;
+      coordVal = NSCoordSaturatingMultiply(percentageBase,
+                                           styleCoord.GetPercentValue());
+      break;
+    }
+  }
+
+  aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
+  aValue.AppendLiteral("px");
+}
+
+void
+StyleInfo::Margin(css::Side aSide, nsAString& aValue)
+{
+  aValue.Truncate();
+
+  nscoord coordVal = mElement->GetPrimaryFrame()->GetUsedMargin().Side(aSide);
+  aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
+  aValue.AppendLiteral("px");
+}
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/StyleInfo.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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
+ * 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 ***** */
+
+#ifndef _mozilla_a11y_style_h_
+#define _mozilla_a11y_style_h_
+
+#include "mozilla/gfx/Types.h"
+#include "nsStyleContext.h"
+
+namespace mozilla {
+namespace a11y {
+
+class StyleInfo
+{
+public:
+  StyleInfo(dom::Element* aElement, nsIPresShell* aPresShell);
+  ~StyleInfo() { };
+
+  void Display(nsAString& aValue);
+  void TextAlign(nsAString& aValue);
+  void TextIndent(nsAString& aValue);
+  void MarginLeft(nsAString& aValue) { Margin(css::eSideLeft, aValue); }
+  void MarginRight(nsAString& aValue) { Margin(css::eSideRight, aValue); }
+  void MarginTop(nsAString& aValue) { Margin(css::eSideTop, aValue); }
+  void MarginBottom(nsAString& aValue) { Margin(css::eSideBottom, aValue); }
+
+private:
+  StyleInfo() MOZ_DELETE;
+  StyleInfo(const StyleInfo&) MOZ_DELETE;
+  StyleInfo& operator = (const StyleInfo&) MOZ_DELETE;
+
+  void Margin(css::Side aSide, nsAString& aValue);
+
+  dom::Element* mElement;
+  nsRefPtr<nsStyleContext> mStyleContext;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
--- a/accessible/src/base/TextUpdater.cpp
+++ b/accessible/src/base/TextUpdater.cpp
@@ -89,18 +89,18 @@ TextUpdater::DoUpdate(const nsAString& a
 
   // Trim coinciding substrings from the end.
   PRUint32 skipEnd = 0;
   while (minLen - skipEnd > aSkipStart &&
          aNewText[newLen - skipEnd - 1] == aOldText[oldLen - skipEnd - 1]) {
     skipEnd++;
   }
 
-  PRInt32 strLen1 = oldLen - aSkipStart - skipEnd;
-  PRInt32 strLen2 = newLen - aSkipStart - skipEnd;
+  PRUint32 strLen1 = oldLen - aSkipStart - skipEnd;
+  PRUint32 strLen2 = newLen - aSkipStart - skipEnd;
 
   const nsAString& str1 = Substring(aOldText, aSkipStart, strLen1);
   const nsAString& str2 = Substring(aNewText, aSkipStart, strLen2);
 
   // Increase offset of the text leaf on skipped characters amount.
   mTextOffset += aSkipStart;
 
   // It could be single insertion or removal or the case of long strings. Do not
@@ -182,17 +182,17 @@ TextUpdater::ComputeTextChangeEvents(con
   PRInt32 colIdx = aStr1.Length(), rowIdx = aStr2.Length();
 
   // Point at which strings last matched.
   PRInt32 colEnd = colIdx;
   PRInt32 rowEnd = rowIdx;
 
   PRInt32 colLen = colEnd + 1;
   PRUint32* row = aEntries + rowIdx * colLen;
-  PRInt32 dist = row[colIdx]; // current Levenshtein distance
+  PRUint32 dist = row[colIdx]; // current Levenshtein distance
   while (rowIdx && colIdx) { // stop when we can't move diagonally
     if (aStr1[colIdx - 1] == aStr2[rowIdx - 1]) { // match
       if (rowIdx < rowEnd) { // deal with any pending insertion
         FireInsertEvent(Substring(aStr2, rowIdx, rowEnd - rowIdx),
                         rowIdx, aEvents);
       }
       if (colIdx < colEnd) { // deal with any pending deletion
         FireDeleteEvent(Substring(aStr1, colIdx, colEnd - colIdx),
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -39,29 +39,28 @@
 
 #include "nsAccessible.h"
 
 #include "nsIXBLAccessible.h"
 
 #include "AccGroupInfo.h"
 #include "AccIterator.h"
 #include "nsAccUtils.h"
-#include "nsDocAccessible.h"
-#include "nsEventShell.h"
-
 #include "nsAccEvent.h"
 #include "nsAccessibleRelation.h"
 #include "nsAccessibilityService.h"
 #include "nsAccTreeWalker.h"
 #include "nsIAccessibleRelation.h"
+#include "nsEventShell.h"
 #include "nsRootAccessible.h"
 #include "nsTextEquivUtils.h"
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
+#include "StyleInfo.h"
 
 #include "nsIDOMCSSValue.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLFormElement.h"
@@ -1437,59 +1436,50 @@ nsAccessible::GetAttributesInternal(nsIP
 
     nsIDocument *parentDoc = doc->GetParentDocument();
     if (!parentDoc)
       break;
 
     startContent = parentDoc->FindContentForSubDocument(doc);      
   }
 
-  // Expose 'display' attribute.
+  if (!mContent->IsElement())
+    return NS_OK;
+
+  // CSS style based object attributes.
   nsAutoString value;
-  nsresult rv = GetComputedStyleValue(EmptyString(),
-                                      NS_LITERAL_STRING("display"),
-                                      value);
-  if (NS_SUCCEEDED(rv))
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::display, value);
+  StyleInfo styleInfo(mContent->AsElement(), mDoc->PresShell());
+
+  // Expose 'display' attribute.
+  styleInfo.Display(value);
+  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::display, value);
 
   // Expose 'text-align' attribute.
-  rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("text-align"),
-                             value);
-  if (NS_SUCCEEDED(rv))
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textAlign, value);
+  styleInfo.TextAlign(value);
+  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textAlign, value);
 
   // Expose 'text-indent' attribute.
-  rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("text-indent"),
-                             value);
-  if (NS_SUCCEEDED(rv))
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textIndent, value);
+  styleInfo.TextIndent(value);
+  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textIndent, value);
 
   // Expose 'margin-left' attribute.
-  rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("margin-left"),
-                             value);
-  if (NS_SUCCEEDED(rv))
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginLeft, value);
+  styleInfo.MarginLeft(value);
+  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginLeft, value);
 
   // Expose 'margin-right' attribute.
-  rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("margin-right"),
-                             value);
-  if (NS_SUCCEEDED(rv))
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginRight, value);
+  styleInfo.MarginRight(value);
+  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginRight, value);
 
   // Expose 'margin-top' attribute.
-  rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("margin-top"),
-                             value);
-  if (NS_SUCCEEDED(rv))
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginTop, value);
+  styleInfo.MarginTop(value);
+  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginTop, value);
 
   // Expose 'margin-bottom' attribute.
-  rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("margin-bottom"),
-                             value);
-  if (NS_SUCCEEDED(rv))
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginBottom, value);
+  styleInfo.MarginBottom(value);
+  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginBottom, value);
 
   // Expose draggable object attribute?
   nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mContent);
   if (htmlElement) {
     bool draggable = false;
     htmlElement->GetDraggable(&draggable);
     if (draggable) {
       nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::draggable,
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -1489,71 +1489,54 @@ 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");
   }
 
-  // Check for very wide table
-  nsAutoString styledWidth;
-  GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("width"), styledWidth);
-  if (styledWidth.EqualsLiteral("100%")) {
-    RETURN_LAYOUT_ANSWER(true, "<=4 columns and 100% width");
-  }
-  if (styledWidth.Find(NS_LITERAL_STRING("px"))) { // Hardcoded in pixels
-    nsIFrame *tableFrame = GetFrame();
-    NS_ENSURE_TRUE(tableFrame , NS_ERROR_FAILURE);
-    nsSize tableSize  = tableFrame->GetSize();
-
-    nsDocAccessible* docAccessible = Document();
-    NS_ENSURE_TRUE(docAccessible, NS_ERROR_FAILURE);
-    nsIFrame *docFrame = docAccessible->GetFrame();
-    NS_ENSURE_TRUE(docFrame , NS_ERROR_FAILURE);
-
-    nsSize docSize = docFrame->GetSize();
-    if (docSize.width > 0) {
-      PRInt32 percentageOfDocWidth = (100 * tableSize.width) / docSize.width;
-      if (percentageOfDocWidth > 95) {
-        // 3-4 columns, no borders, not a lot of rows, and 95% of the doc's width
-        // Probably for layout
-        RETURN_LAYOUT_ANSWER(true, "<=4 columns, width hardcoded in pixels and 95% of document width");
-      }
+  // Check for very wide table.
+  nsIFrame* documentFrame = Document()->GetFrame();
+  nsSize documentSize = documentFrame->GetSize();
+  if (documentSize.width > 0) {
+    nsSize tableSize = GetFrame()->GetSize();
+    PRInt32 percentageOfDocWidth = (100 * tableSize.width) / documentSize.width;
+    if (percentageOfDocWidth > 95) {
+      // 3-4 columns, no borders, not a lot of rows, and 95% of the doc's width
+      // Probably for layout
+      RETURN_LAYOUT_ANSWER(true,
+                           "<= 4 columns, table width is 95% of document width");
     }
   }
 
   // Two column rules
   if (rows * columns <= 10) {
     RETURN_LAYOUT_ANSWER(true, "2-4 columns, 10 cells or less, non-bordered");
   }
 
--- a/accessible/tests/mochitest/attributes.js
+++ b/accessible/tests/mochitest/attributes.js
@@ -23,16 +23,36 @@ function testAttrs(aAccOrElmOrID, aAttrs
  *                              present (name/value pairs)
  */
 function testAbsentAttrs(aAccOrElmOrID, aAbsentAttrs)
 {
   testAttrsInternal(aAccOrElmOrID, {}, true, aAbsentAttrs);
 }
 
 /**
+ * Test CSS based object attributes.
+ */
+function testCSSAttrs(aID)
+{
+  var node = document.getElementById(aID);
+  var computedStyle = document.defaultView.getComputedStyle(node, "");
+
+  var attrs = {
+    "display": computedStyle.display,
+    "text-align": computedStyle.textAlign,
+    "text-indent": computedStyle.textIndent,
+    "margin-left": computedStyle.marginLeft,
+    "margin-right": computedStyle.marginRight,
+    "margin-top": computedStyle.marginTop,
+    "margin-bottom": computedStyle.marginBottom
+  };
+  testAttrs(aID, attrs, true);
+}
+
+/**
  * Test group object attributes (posinset, setsize and level) and
  * nsIAccessible::groupPosition() method.
  *
  * @param aAccOrElmOrID  [in] the ID, DOM node or accessible
  * @param aPosInSet      [in] the value of 'posinset' attribute
  * @param aSetSize       [in] the value of 'setsize' attribute
  * @param aLevel         [in, optional] the value of 'level' attribute
  */
--- a/accessible/tests/mochitest/attributes/Makefile.in
+++ b/accessible/tests/mochitest/attributes/Makefile.in
@@ -43,16 +43,17 @@ VPATH		= @srcdir@
 relativesrcdir  = accessible/attributes
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_obj.html \
 		test_obj_css.html \
+		test_obj_css.xul \
 		test_obj_group.html \
 		test_obj_group.xul \
 		test_obj_group_tree.xul \
 		test_text.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
--- a/accessible/tests/mochitest/attributes/test_obj_css.html
+++ b/accessible/tests/mochitest/attributes/test_obj_css.html
@@ -13,46 +13,75 @@ https://bugzilla.mozilla.org/show_bug.cg
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../attributes.js"></script>
 
   <script type="application/javascript">
-    function testCSSAttrs(aID)
-    {
-      var node = document.getElementById(aID);
-      var computedStyle = document.defaultView.getComputedStyle(node, "");
-
-      var attrs = {
-        "display": computedStyle.display,
-        "text-align": computedStyle.textAlign,
-        "text-indent": computedStyle.textIndent,
-        "margin-left": computedStyle.marginLeft,
-        "margin-right": computedStyle.marginRight,
-        "margin-top": computedStyle.marginTop,
-        "margin-bottom": computedStyle.marginBottom
-      };
-      testAttrs(aID, attrs, true);
-    }
-
     function doTest()
     {
+      // CSS display
+      testCSSAttrs("display_block");
+      testCSSAttrs("display_inline");
+      testCSSAttrs("display_inline-block");
+      testCSSAttrs("display_list-item");
+      testCSSAttrs("display_table");
+      testCSSAttrs("display_inline-table");
+      testCSSAttrs("display_table-row-group");
+      testCSSAttrs("display_table-column");
+      testCSSAttrs("display_table-column-group");
+      testCSSAttrs("display_table-header-group");
+      testCSSAttrs("display_table-footer-group");
+      testCSSAttrs("display_table-row");
+      testCSSAttrs("display_table-cell");
+      testCSSAttrs("display_table-caption");
+
+      // CSS text-align
+      testCSSAttrs("text-align_left");
+      testCSSAttrs("text-align_right");
+      testCSSAttrs("text-align_center");
+      testCSSAttrs("text-align_justify");
+      testCSSAttrs("text-align_inherit");
+
+      // CSS text-indent
+      testCSSAttrs("text-indent_em");
+      testCSSAttrs("text-indent_ex");
+      testCSSAttrs("text-indent_in");
+      testCSSAttrs("text-indent_cm");
+      testCSSAttrs("text-indent_mm");
+      testCSSAttrs("text-indent_pt");
+      testCSSAttrs("text-indent_pc");
+      testCSSAttrs("text-indent_px");
+      testCSSAttrs("text-indent_percent");
+      testCSSAttrs("text-indent_inherit");
+
+      // CSS margin
+      testCSSAttrs("margin_em");
+      testCSSAttrs("margin_ex");
+      testCSSAttrs("margin_in");
+      testCSSAttrs("margin_cm");
+      testCSSAttrs("margin_mm");
+      testCSSAttrs("margin_pt");
+      testCSSAttrs("margin_pc");
+      testCSSAttrs("margin_px");
+      testCSSAttrs("margin_percent");
+      testCSSAttrs("margin_auto");
+      testCSSAttrs("margin_inherit");
+
+      testCSSAttrs("margin-left");
+      testCSSAttrs("margin-right");
+      testCSSAttrs("margin-top");
+      testCSSAttrs("margin-bottom");
+
+      // Elements
       testCSSAttrs("span");
       testCSSAttrs("div");
-
       testCSSAttrs("p");
-      testCSSAttrs("p2");
-
-      testCSSAttrs("pml");
-      testCSSAttrs("pmr");
-      testCSSAttrs("pmt");
-      testCSSAttrs("pmb");
-
       testCSSAttrs("input");
       testCSSAttrs("table");
       testCSSAttrs("tr");
       testCSSAttrs("td");
 
       SimpleTest.finish();
     }
 
@@ -72,33 +101,93 @@ https://bugzilla.mozilla.org/show_bug.cg
      title="text-indent and text-align should really be object attribute">
     Mozilla Bug 460932
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=689540"
      title="Expose IA2 margin- object attributes">
     Mozilla Bug 689540
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=714579"
+     title="Don't use GetComputedStyle for object attribute calculation">
+    Mozilla Bug 714579
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
+  <div id="display_block" role="img"
+       style="display: block;">display: block</div>
+  <div id="display_inline" role="img"
+       style="display: inline;">display: inline</div>
+  <div id="display_inline-block" role="img"
+       style="display: inline-block;">display: inline-block</div>
+  <div id="display_list-item" role="img"
+       style="display: list-item;">display: list-item</div>
+  <div id="display_table" role="img"
+       style="display: table;">display: table</div>
+  <div id="display_inline-table" role="img"
+       style="display: inline-table;">display: inline-table</div>
+  <div id="display_table-row-group" role="img"
+       style="display: table-row-group;">display: table-row-group</div>
+  <div id="display_table-column" role="img"
+       style="display: table-column;">display: table-column</div>
+  <div id="display_table-column-group" role="img"
+       style="display: table-column-group;">display: table-column-group</div>
+  <div id="display_table-header-group" role="img"
+       style="display: table-header-group;">display: table-header-group</div>
+  <div id="display_table-footer-group" role="img"
+       style="display: table-footer-group;">display: table-footer-group</div>
+  <div id="display_table-row" role="img"
+       style="display: table-row;">display: table-row</div>
+  <div id="display_table-cell" role="img"
+       style="display: table-cell;">display: table-cell</div>
+  <div id="display_table-caption" role="img"
+       style="display: table-caption;">display: table-caption</div>
+
+  <p id="text-align_left" style="text-align: left;">text-align: left</p>
+  <p id="text-align_right" style="text-align: right;">text-align: right</p>
+  <p id="text-align_center" style="text-align: center;">text-align: center</p>
+  <p id="text-align_justify" style="text-align: justify;">text-align: justify</p>
+  <p id="text-align_inherit" style="text-align: inherit;">text-align: inherit</p>
+
+  <p id="text-indent_em" style="text-indent: 0.5em;">text-indent: 0.5em</p>
+  <p id="text-indent_ex" style="text-indent: 1ex;">text-indent: 1ex</p>
+  <p id="text-indent_in" style="text-indent: 0.5in;">text-indent: 0.5in</p>
+  <p id="text-indent_cm" style="text-indent: 2cm;">text-indent: 2cm</p>
+  <p id="text-indent_mm" style="text-indent: 10mm;">text-indent: 10mm</p>
+  <p id="text-indent_pt" style="text-indent: 30pt;">text-indent: 30pt</p>
+  <p id="text-indent_pc" style="text-indent: 2pc;">text-indent: 2pc</p>
+  <p id="text-indent_px" style="text-indent: 5px;">text-indent: 5px</p>
+  <p id="text-indent_percent" style="text-indent: 10%;">text-indent: 10%</p>
+  <p id="text-indent_inherit" style="text-indent: inherit;">text-indent: inherit</p>
+
+  <p id="margin_em" style="margin: 0.5em;">margin: 0.5em</p>
+  <p id="margin_ex" style="margin: 1ex;">margin: 1ex</p>
+  <p id="margin_in" style="margin: 0.5in;">margin: 0.5in</p>
+  <p id="margin_cm" style="margin: 2cm;">margin: 2cm</p>
+  <p id="margin_mm" style="margin: 10mm;">margin: 10mm</p>
+  <p id="margin_pt" style="margin: 30pt;">margin: 30pt</p>
+  <p id="margin_pc" style="margin: 2pc;">margin: 2pc</p>
+  <p id="margin_px" style="margin: 5px;">margin: 5px</p>
+  <p id="margin_percent" style="margin: 10%;">margin: 10%</p>
+  <p id="margin_auto" style="margin: auto;">margin: auto</p>
+  <p id="margin_inherit" style="margin: inherit;">margin: inherit</p>
+
+  <p id="margin-left" style="margin-left: 11px;">margin-left: 11px</p>
+  <p id="margin-right" style="margin-right: 21px;">margin-right</p>
+  <p id="margin-top" style="margin-top: 31px;">margin-top: 31px</p>
+  <p id="margin-bottom" style="margin-bottom: 41px;">margin-bottom: 41px</p>
+
   <span id="span" role="group">It's span</span>
   <div id="div">It's div</div>
-
   <p id="p">It's paragraph"</p>
-  <p id="p2"  style="text-indent: 5px">It's another paragraph</p>
-
-  <p id="pml" style="margin-left : 11px;">It's a paragraph with left margin</p>
-  <p id="pmr" style="margin-right : 21px;">It's a paragraph with right margin</p>
-  <p id="pmt" style="margin-top : 31px;">It's a paragraph with top margin</p>
-  <p id="pmb" style="margin-bottom : 41px;">It's a paragraph with bottom margin</p>
-
   <input id="input"/>
-  <table id="table">
+  <table id="table" style="margin: 2px; text-align: center; text-indent: 10%;">
     <tr id="tr" role="group">
       <td id="td">td</td>
     </tr>
   </table>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_obj_css.xul
@@ -0,0 +1,73 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessibility CSS-based Object Attributes Test.">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+  <script type="application/javascript"
+          src="../attributes.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    function doTest()
+    {
+      // CSS display
+      testCSSAttrs("display_mozbox");
+      testCSSAttrs("display_mozinlinebox");
+      testCSSAttrs("display_mozgrid");
+      testCSSAttrs("display_mozinlinegrid");
+      testCSSAttrs("display_mozgridgroup");
+      testCSSAttrs("display_mozgridline");
+      testCSSAttrs("display_mozstack");
+      testCSSAttrs("display_mozinlinestack");
+      testCSSAttrs("display_mozdeck");
+      testCSSAttrs("display_mozpopup");
+      testCSSAttrs("display_mozgroupbox");
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=714579"
+       title="Don't use GetComputedStyle for object attribute calculation">
+      Mozilla Bug 714579
+    </a><br/>
+
+    <p id="display"></p>
+    <div id="content" style="display: none">
+    </div>
+    <pre id="test">
+    </pre>
+  </body>
+
+  <vbox id="display_mozbox" style="display: -moz-box;" role="img"/>
+  <vbox id="display_mozinlinebox" style="display: -moz-inline-box;" role="img"/>
+  <vbox id="display_mozgrid" style="display: -moz-grid;" role="img"/>
+  <vbox id="display_mozinlinegrid" style="display: -moz-inline-grid;" role="img"/>
+  <vbox id="display_mozgridgroup" style="display: -moz-grid-group;" role="img"/>
+  <vbox id="display_mozgridline" style="display: -moz-grid-line;" role="img"/>
+  <vbox id="display_mozstack" style="display: -moz-stack;" role="img"/>
+  <vbox id="display_mozinlinestack" style="display: -moz-inline-stack;" role="img"/>
+  <vbox id="display_mozdeck" style="display: -moz-deck;" role="img"/>
+  <vbox id="display_mozpopup" style="display: -moz-popup;" role="img"/>
+  <vbox id="display_mozgroupbox" style="display: -moz-groupbox;" role="img"/>
+
+  </hbox>
+</window>
+
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -47,20 +47,27 @@ const nsIDOMNode = Components.interfaces
 const nsIDOMHTMLElement = Components.interfaces.nsIDOMHTMLElement;
 const nsIDOMWindow = Components.interfaces.nsIDOMWindow;
 const nsIDOMXULElement = Components.interfaces.nsIDOMXULElement;
 
 const nsIPropertyElement = Components.interfaces.nsIPropertyElement;
 
 ////////////////////////////////////////////////////////////////////////////////
 // OS detect
-const MAC = (navigator.platform.indexOf("Mac") != -1)? true : false;
-const LINUX = (navigator.platform.indexOf("Linux") != -1)? true : false;
-const SOLARIS = (navigator.platform.indexOf("SunOS") != -1)? true : false;
-const WIN = (navigator.platform.indexOf("Win") != -1)? true : false;
+
+const MAC = (navigator.platform.indexOf("Mac") != -1);
+const LINUX = (navigator.platform.indexOf("Linux") != -1);
+const SOLARIS = (navigator.platform.indexOf("SunOS") != -1);
+const WIN = (navigator.platform.indexOf("Win") != -1);
+
+////////////////////////////////////////////////////////////////////////////////
+// Application detect
+// Firefox is assumed by default.
+
+const SEAMONKEY = navigator.userAgent.match(/ SeaMonkey\//);
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible general
 
 const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
 
 const SCROLL_TYPE_ANYWHERE = nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE;
 
--- a/accessible/tests/mochitest/events/test_focus_autocomplete.xul
+++ b/accessible/tests/mochitest/events/test_focus_autocomplete.xul
@@ -377,16 +377,22 @@
     // Tests
 
     //gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true; // debug stuff
 
     var gInitQueue = null;
     function initTests()
     {
+      if (SEAMONKEY) {
+        todo(false, "Skipping this test on SeaMonkey ftb. (Bug 718237)");
+        SimpleTest.finish();
+        return;
+      }
+
       // register 'test-a11y-search' autocomplete search
       initAutoComplete([ "hello", "hi" ],
                        [ "Beep beep'm beep beep yeah", "Baby you can drive my car" ]);
 
       gInitQueue = new eventQueue();
       gInitQueue.push(new loadFormAutoComplete("iframe"));
       gInitQueue.push(new initFormAutoCompleteBy("iframe", "hello"));
       gInitQueue.push(new initFormAutoCompleteBy("iframe", "hi"));
--- a/accessible/tests/mochitest/tree/test_tabbrowser.xul
+++ b/accessible/tests/mochitest/tree/test_tabbrowser.xul
@@ -47,17 +47,17 @@
           // xul:tabs
           role: ROLE_PAGETABLIST,
           children: [
             // Children depend on application (UI): see below.
           ]
         };
 
         // SeaMonkey and Firefox tabbrowser UIs differ.
-        if ("restoreTab" in tabBrowser) {
+        if (SEAMONKEY) {
           SimpleTest.ok(true, "Testing SeaMonkey tabbrowser UI.");
 
           tabsAccTree.children.splice(0, 0,
             {
               // xul:toolbarbutton ("Open a new tab")
               role: ROLE_PUSHBUTTON,
               children: []
             },
--- 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/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -41,17 +41,17 @@ pref("toolkit.defaultChromeURI", "chrome
 pref("browser.chromeURL", "chrome://browser/content/");
 #ifdef MOZ_OFFICIAL_BRANDING
 pref("browser.homescreenURL", "file:///system/home/homescreen.html");
 #else
 pref("browser.homescreenURL", "file:///data/local/homescreen.html,file:///system/home/homescreen.html");
 #endif
 
 // URL for the dialer application.
-pref("dom.telephony.app.phone.url", "http://localhost:6666/apps/dialer/dialer.html");
+pref("dom.telephony.app.phone.url", "http://localhost:7777/data/local/apps/dialer/dialer.html");
 
 // Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
 pref("browser.viewport.scaleRatio", -1);
 
 /* disable text selection */
 pref("browser.ignoreNativeFrameTextSelection", true);
 
 /* cache prefs */
@@ -399,21 +399,21 @@ pref("browser.link.open_newwindow", 3);
 
 // 0: no restrictions - divert everything
 // 1: don't divert window.open at all
 // 2: don't divert window.open with features
 pref("browser.link.open_newwindow.restriction", 0);
 
 // Enable browser frame
 pref("dom.mozBrowserFramesEnabled", true);
-pref("dom.mozBrowserFramesWhitelist", "http://localhost:6666");
+pref("dom.mozBrowserFramesWhitelist", "http://localhost:7777");
 
 // Temporary permission hack for WebSMS
 pref("dom.sms.enabled", true);
-pref("dom.sms.whitelist", "file://,http://localhost:6666");
+pref("dom.sms.whitelist", "file://,http://localhost:7777");
 
 // Ignore X-Frame-Options headers.
 pref("b2g.ignoreXFrameOptions", true);
 
 // controls if we want camera support
 pref("device.camera.enabled", true);
 pref("media.realtime_decoder.enabled", true);
 
@@ -421,14 +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,34 +21,26 @@ 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);
 });
 
-// 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);
-  let server = new httpd.nsHttpServer();
-  server.registerDirectory('/', new LocalFile(baseDir));
-  server.registerContentType('appcache', 'text/cache-manifest');
-  server.start(port);
-}
+XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function(){
+  return Cc['@mozilla.org/focus-managr;1']
+           .getService(Ci.nsFocusManager);
+});
 
 // FIXME Bug 707625
 // until we have a proper security model, add some rights to
 // the pre-installed web applications
 // XXX never grant 'content-camera' to non-gaia apps
 function addPermissions(urls) {
   let permissions = [
     'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'content-camera'
@@ -57,17 +50,16 @@ function addPermissions(urls) {
     let allow = Ci.nsIPermissionManager.ALLOW_ACTION;
 
     permissions.forEach(function(permission) {
       Services.perms.add(uri, permission, allow);
     });
   });
 }
 
-
 var shell = {
   // FIXME/bug 678695: this should be a system setting
   preferredScreenBrightness: 1.0,
   
   isDebug: false,
 
   get contentBrowser() {
     delete this.contentBrowser;
@@ -100,47 +92,38 @@ 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, '');
-
-        let baseDir = homeURL.split('/');
-        baseDir.pop();
-        baseDir = baseDir.join('/');
-
-        const SERVER_PORT = 6666;
-        startupHttpd(baseDir, SERVER_PORT);
-
-        let baseHost = 'http://localhost';
-        homeURL = homeURL.replace(baseDir, baseHost + ':' + SERVER_PORT);
+        homeURL = 'http://localhost:7777' + homeURL.replace(fileScheme, '');
       }
       addPermissions([homeURL]);
     } catch (e) {
       let msg = 'Fatal error during startup: [' + e + '[' + homeURL + ']';
       return alert(msg);
     }
 
-    // Load webapi+apps.js as a frame script
+    // Load webapi.js as a frame script
     let frameScriptUrl = 'chrome://browser/content/webapi.js';
     try {
       messageManager.loadFrameScript(frameScriptUrl, true);
     } catch (e) {
-      dump('Error when loading ' + frameScriptUrl + ' as a frame script: ' + e + '\n');
+      dump('Error loading ' + frameScriptUrl + ' as a frame script: ' + e + '\n');
     }
 
     let browser = this.contentBrowser;
     browser.homePage = homeURL;
     browser.goHome();
   },
 
   stop: function shell_stop() {
@@ -238,16 +221,24 @@ var shell = {
           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');
@@ -358,8 +349,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/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/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1366,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;
@@ -1558,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;
@@ -3534,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);
--- 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 += \
--- a/browser/base/content/test/browser_homeDrop.js
+++ b/browser/base/content/test/browser_homeDrop.js
@@ -21,16 +21,17 @@ function test() {
 
   let dialogListener = new WindowListener("chrome://global/content/commonDialog.xul", function (domwindow) {
     ok(true, "dialog appeared in response to home button drop");
     domwindow.document.documentElement.cancelDialog();
     Services.wm.removeListener(dialogListener);
 
     // Now trigger the invalid URI test
     executeSoon(function () {
+      info("Dialog closed? " + domwindow.closed + "\n");
       let consoleListener = {
         observe: function (m) {
           info("m: " + m + "\n");
           info("m.message: " + m.message + "\n");
           if (m.message.indexOf("NS_ERROR_DOM_BAD_URI") > -1) {
             ok(true, "drop was blocked");
             executeSoon(finish);
           }
@@ -39,16 +40,24 @@ function test() {
       Services.console.registerListener(consoleListener);
       registerCleanupFunction(function () {
         Services.console.unregisterListener(consoleListener);
       });
 
       // The drop handler throws an exception when dragging URIs that inherit
       // principal, e.g. javascript:
       expectUncaughtException();
+      let originalHandler = homeButtonObserver.onDrop;
+      homeButtonObserver.onDrop = function (aEvent) {
+        info("homeButtonObserver.onDrop called");
+        originalHandler(aEvent);
+      };
+      registerCleanupFunction(function () {
+        homeButtonObserver.onDrop = originalHandler;
+      });
       chromeUtils.synthesizeDrop(homeButton, homeButton, [[{type: "text/plain", data: "javascript:8888"}]], "copy", window, EventUtils);
     })
   });
 
   Services.wm.addListener(dialogListener);
 
   chromeUtils.synthesizeDrop(homeButton, homeButton, [[{type: "text/plain", data: "http://mochi.test:8888/"}]], "copy", window, EventUtils);
 }
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/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -47,36 +47,34 @@ const nsIBrowserHistory      = Component
 const nsIChannel             = Components.interfaces.nsIChannel;
 const nsICommandLine         = Components.interfaces.nsICommandLine;
 const nsICommandLineHandler  = Components.interfaces.nsICommandLineHandler;
 const nsIContentHandler      = Components.interfaces.nsIContentHandler;
 const nsIDocShellTreeItem    = Components.interfaces.nsIDocShellTreeItem;
 const nsIDOMChromeWindow     = Components.interfaces.nsIDOMChromeWindow;
 const nsIDOMWindow           = Components.interfaces.nsIDOMWindow;
 const nsIFileURL             = Components.interfaces.nsIFileURL;
-const nsIHttpProtocolHandler = Components.interfaces.nsIHttpProtocolHandler;
 const nsIInterfaceRequestor  = Components.interfaces.nsIInterfaceRequestor;
 const nsINetUtil             = Components.interfaces.nsINetUtil;
 const nsIPrefBranch          = Components.interfaces.nsIPrefBranch;
 const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;
 const nsISupportsString      = Components.interfaces.nsISupportsString;
 const nsIURIFixup            = Components.interfaces.nsIURIFixup;
 const nsIWebNavigation       = Components.interfaces.nsIWebNavigation;
 const nsIWindowMediator      = Components.interfaces.nsIWindowMediator;
 const nsIWindowWatcher       = Components.interfaces.nsIWindowWatcher;
 const nsIWebNavigationInfo   = Components.interfaces.nsIWebNavigationInfo;
 const nsIBrowserSearchService = Components.interfaces.nsIBrowserSearchService;
 const nsICommandLineValidator = Components.interfaces.nsICommandLineValidator;
-const nsIXULAppInfo          = Components.interfaces.nsIXULAppInfo;
 
 const NS_BINDING_ABORTED = Components.results.NS_BINDING_ABORTED;
 const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
 const NS_ERROR_ABORT = Components.results.NS_ERROR_ABORT;
 
-const URI_INHERITS_SECURITY_CONTEXT = nsIHttpProtocolHandler
+const URI_INHERITS_SECURITY_CONTEXT = Components.interfaces.nsIHttpProtocolHandler
                                         .URI_INHERITS_SECURITY_CONTEXT;
 
 function shouldLoadURI(aURI) {
   if (aURI && !aURI.schemeIs("chrome"))
     return true;
 
   dump("*** Preventing external load of chrome: URI into browser window\n");
   dump("    Use -chrome <uri> instead\n");
@@ -132,26 +130,24 @@ function needHomepageOverride(prefb) {
   var savedmstone = null;
   try {
     savedmstone = prefb.getCharPref("browser.startup.homepage_override.mstone");
   } catch (e) {}
 
   if (savedmstone == "ignore")
     return OVERRIDE_NONE;
 
-  var mstone = Components.classes["@mozilla.org/network/protocol;1?name=http"]
-                         .getService(nsIHttpProtocolHandler).misc;
+  var mstone = Services.appinfo.platformVersion;
 
   var savedBuildID = null;
   try {
     savedBuildID = prefb.getCharPref("browser.startup.homepage_override.buildID");
   } catch (e) {}
 
-  var buildID =  Components.classes["@mozilla.org/xre/app-info;1"]
-                           .getService(nsIXULAppInfo).platformBuildID;
+  var buildID = Services.appinfo.platformBuildID;
 
   if (mstone != savedmstone) {
     // Bug 462254. Previous releases had a default pref to suppress the EULA
     // agreement if the platform's installer had already shown one. Now with
     // about:rights we've removed the EULA stuff and default pref, but we need
     // a way to make existing profiles retain the default that we removed.
     if (savedmstone)
       prefb.setBoolPref("browser.rights.3.shown", true);
--- 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/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/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/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/browser-aero.css
+++ b/browser/themes/winstripe/browser-aero.css
@@ -176,19 +176,19 @@
   #main-window[sizemode=normal][tabsontop=false] #PersonalToolbar:not(:-moz-lwtheme) {
     border-top-left-radius: 3.5px;
     border-top-right-radius: 3.5px;
   }
 
   /* Toolbar shadow behind tabs */
   /* This code is only needed for restored windows (i.e. sizemode=normal)
      because of the border radius on the toolbar below the tab bar. */
-  #main-window[sizemode=normal][tabsontop=true] #nav-bar:not(:-moz-lwtheme),
-  #main-window[sizemode=normal][tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + toolbar:not(:-moz-lwtheme),
-  #main-window[sizemode=normal][tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
+  #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar:not(:-moz-lwtheme),
+  #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + toolbar:not(:-moz-lwtheme),
+  #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
   #main-window[sizemode=normal][tabsontop=true][disablechrome] #navigator-toolbox:not(:-moz-lwtheme)::after {
     border-top: 1px solid @toolbarShadowColor@;
     border-top-left-radius: 3.5px;
     border-top-right-radius: 3.5px;
     background-clip: padding-box;
   }
   #main-window[sizemode=normal] #TabsToolbar[tabsontop=true]:not(:-moz-lwtheme) {
     margin-bottom: -1px;
--- 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)"
--- a/build/unix/build-toolchain/build-gcc.py
+++ b/build/unix/build-toolchain/build-gcc.py
@@ -149,17 +149,17 @@ def build_tar_package(tar, name, base, d
                   directory])
 
 ##############################################
 
 def build_source_dir(prefix, version):
     return source_dir + '/' + prefix + version
 
 binutils_version = "2.21.1"
-glibc_version = "2.7" #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" % \
@@ -219,16 +219,16 @@ os.makedirs(build_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(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
@@ -35,17 +35,17 @@ diff -ru a/csu/Makefile b/csu/Makefile
 -			  "$$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,20 +295,13 @@
+@@ -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'	\
@@ -53,22 +53,43 @@ diff -ru a/elf/Makefile b/elf/Makefile
 -		  > $@.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
- 	readelf -s $@ \
--	  | awk '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 0 }'
-+	  | $(AWK) '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 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
 @@ -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)' \
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -2478,21 +2478,20 @@ nsScriptSecurityManager::doGetObjectPrin
 
         jsClass = js::GetObjectClass(aObj);
     } while (1);
 
 #ifdef DEBUG
     if (aAllowShortCircuit) {
         nsIPrincipal *principal = doGetObjectPrincipal(origObj, false);
 
-        // Location is always wrapped (even for same-compartment), so we can
-        // loosen the check to same-origin instead of same-principal.
-        NS_ASSERTION(strcmp(jsClass->name, "Location") == 0 ?
-                     NS_SUCCEEDED(CheckSameOriginPrincipal(result, principal)) :
-                     result == principal,
+        // Because of inner window reuse, we can have objects with one principal
+        // living in a scope with a different (but same-origin) principal. So
+        // just check same-origin here.
+        NS_ASSERTION(NS_SUCCEEDED(CheckSameOriginPrincipal(result, principal)),
                      "Principal mismatch.  Not good");
     }
 #endif
 
     return result;
 }
 
 nsresult
--- a/client.py
+++ b/client.py
@@ -1,15 +1,16 @@
 #!/usr/bin/python
 
 NSPR_DIRS = (('nsprpub', 'mozilla/nsprpub'),)
 NSS_DIRS  = (('dbm', 'mozilla/dbm'),
              ('security/nss', 'mozilla/security/nss'),
              ('security/coreconf', 'mozilla/security/coreconf'),
              ('security/dbm', 'mozilla/security/dbm'))
+NSSCKBI_DIRS = (('security/nss/lib/ckfw/builtins', 'mozilla/security/nss/lib/ckfw/builtins'),)
 LIBFFI_DIRS = (('js/ctypes/libffi', 'libffi'),)
 
 CVSROOT_MOZILLA = ':pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot'
 CVSROOT_LIBFFI = ':pserver:anoncvs@sources.redhat.com:/cvs/libffi'
 
 import os
 import sys
 import datetime
@@ -86,16 +87,23 @@ elif action in ('update_nspr'):
     do_cvs_export(NSPR_DIRS, tag, options.cvsroot, options.cvs)
     print >>file("nsprpub/TAG-INFO", "w"), tag
 elif action in ('update_nss'):
     tag, = args[1:]
     if not options.cvsroot:
         options.cvsroot = os.environ.get('CVSROOT', CVSROOT_MOZILLA)
     do_cvs_export(NSS_DIRS, tag, options.cvsroot, options.cvs)
     print >>file("security/nss/TAG-INFO", "w"), tag
+    print >>file("security/nss/TAG-INFO-CKBI", "w"), tag
+elif action in ('update_nssckbi'):
+    tag, = args[1:]
+    if not options.cvsroot:
+        options.cvsroot = os.environ.get('CVSROOT', CVSROOT_MOZILLA)
+    do_cvs_export(NSSCKBI_DIRS, tag, options.cvsroot, options.cvs)
+    print >>file("security/nss/TAG-INFO-CKBI", "w"), tag
 elif action in ('update_libffi'):
     tag, = args[1:]
     if not options.cvsroot:
         options.cvsroot = CVSROOT_LIBFFI
     do_cvs_export(LIBFFI_DIRS, tag, options.cvsroot, options.cvs)
 else:
     o.print_help()
     sys.exit(2)
--- a/config/milestone.pl
+++ b/config/milestone.pl
@@ -46,26 +46,27 @@ use vars qw(
             $MILESTONE_FILE
             $MILESTONE
             $MILESTONE_NUM
             @MILESTONE_PARTS
             $MINI_VERSION
             $MICRO_VERSION
             $opt_debug
             $opt_template
+            $opt_uaversion
             $opt_help
             );
 
 $SCRIPTDIR = $0;
 $SCRIPTDIR =~ s/[^\/]*$//;
 push(@INC,$SCRIPTDIR);
 
 require "Moz/Milestone.pm";
 
-&GetOptions('topsrcdir=s' => \$TOPSRCDIR, 'srcdir=s' => \$SRCDIR, 'objdir=s' => \$OBJDIR, 'debug', 'help', 'template');
+&GetOptions('topsrcdir=s' => \$TOPSRCDIR, 'srcdir=s' => \$SRCDIR, 'objdir=s' => \$OBJDIR, 'debug', 'help', 'template', 'uaversion');
 
 if (defined($opt_help)) {
     &usage();
     exit;
 }
 
 if (defined($opt_template)) {
     @TEMPLATE_FILE = @ARGV;
@@ -95,18 +96,24 @@ if (defined(@TEMPLATE_FILE)) {
     if (-e $TFILE) {
 
       Moz::Milestone::build_file($TFILE,$BUILT_FILE);
 
     } else {
       warn("$0:  No such file $TFILE!\n");
     }
   }
+} elsif(defined($opt_uaversion)) {
+  my $uaversion = Moz::Milestone::getMilestoneMajor($milestone) . "." .
+                   Moz::Milestone::getMilestoneMinor($milestone);
+  # strip off trailing pre-release indicators
+  $uaversion =~ s/[a-z]+\d*$//;
+  print "$uaversion\n";
 } else {
   print "$milestone\n";
 }
 
 sub usage() {
   print <<END
-`milestone.pl [--topsrcdir TOPSRCDIR] [--objdir OBJDIR] [--srcdir SRCDIR] --template [file list]`  # will build file list from .tmpl files
+`milestone.pl [--topsrcdir TOPSRCDIR] [--objdir OBJDIR] [--srcdir SRCDIR] --template [file list] --uaversion`  # will build file list from .tmpl files
 END
     ;
 }
--- a/configure.in
+++ b/configure.in
@@ -220,24 +220,17 @@ AC_SUBST(COMPILE_ENVIRONMENT)
 
 MOZ_ARG_WITH_STRING(l10n-base,
 [  --with-l10n-base=DIR    path to l10n repositories],
     L10NBASEDIR=$withval)
 if test -n "$L10NBASEDIR"; then
     if test "$L10NBASEDIR" = "yes" -o "$L10NBASEDIR" = "no"; then
         AC_MSG_ERROR([--with-l10n-base must specify a path])
     elif test -d "$L10NBASEDIR"; then
-        case "$host_os" in
-        mingw*)
-            L10NBASEDIR=`cd "$L10NBASEDIR" && pwd -W`
-            ;;
-        *)
-            L10NBASEDIR=`cd "$L10NBASEDIR" && pwd`
-            ;;
-        esac
+        L10NBASEDIR=`cd "$L10NBASEDIR" && pwd`
     else
         AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist])
     fi
 fi
 AC_SUBST(L10NBASEDIR)
 
 dnl Check for Perl first -- needed for win32 SDK checks
 MOZ_PATH_PROGS(PERL, $PERL perl5 perl )
@@ -2261,26 +2254,28 @@ if test "$MOZ_CUSTOM_STDINT_H"; then
   AC_SUBST(MOZ_CUSTOM_STDINT_H)
   AC_MSG_RESULT(using $MOZ_CUSTOM_STDINT_H)
 else
   AC_MSG_RESULT(none specified)
 fi
 
 dnl Get mozilla version from central milestone file
 MOZILLA_VERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir`
+MOZILLA_UAVERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir -uaversion`
 
 dnl Get version of various core apps from the version files.
 FIREFOX_VERSION=`cat $_topsrcdir/browser/config/version.txt`
 
 if test -z "$FIREFOX_VERSION"; then
     AC_MSG_ERROR([FIREFOX_VERSION is unexpectedly blank.])
 fi
 
 AC_DEFINE_UNQUOTED(MOZILLA_VERSION,"$MOZILLA_VERSION")
 AC_DEFINE_UNQUOTED(MOZILLA_VERSION_U,$MOZILLA_VERSION)
+AC_DEFINE_UNQUOTED(MOZILLA_UAVERSION,"$MOZILLA_UAVERSION")
 
 MOZ_DOING_LTO(lto_is_enabled)
 
 dnl ========================================================
 dnl System overrides of the defaults for target
 dnl ========================================================
 
 case "$target" in
@@ -4087,16 +4082,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])
@@ -4924,17 +4969,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"
@@ -5477,16 +5521,25 @@ AC_SUBST(MOZ_DBUS_GLIB_LIBS)
 dnl ========================================================
 dnl = Enable Android History instead of Places
 dnl ========================================================
 if test -n "$MOZ_ANDROID_HISTORY"; then
      dnl Do this if defined in confvars.sh
      AC_DEFINE(MOZ_ANDROID_HISTORY)
 fi
 
+
+dnl ========================================================
+dnl = Build with the Android Java compositor
+dnl ========================================================
+if test -n "$MOZ_JAVA_COMPOSITOR"; then
+     dnl Do this if defined in confvars.sh
+     AC_DEFINE(MOZ_JAVA_COMPOSITOR)
+fi
+
 dnl ========================================================
 dnl = Disable WebSMS backend
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(websms-backend,
 [  --disable-websms-backend
                            Disable WebSMS backend],
     MOZ_WEBSMS_BACKEND=,
     MOZ_WEBSMS_BACKEND=1)
@@ -9101,17 +9154,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/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -915,27 +915,27 @@ public:
    * If the content is a part of HTML editor, this returns editing
    * host content.  When the content is in designMode, this returns its body
    * element.  Also, when the content isn't editable, this returns null.
    */
   nsIContent* GetEditingHost();
 
   /**
    * Determing language. Look at the nearest ancestor element that has a lang
-   * attribute in the XML namespace or is an HTML element and has a lang in
+   * attribute in the XML namespace or is an HTML/SVG element and has a lang in
    * no namespace attribute.
    */
   void GetLang(nsAString& aResult) const {
     for (const nsIContent* content = this; content; content = content->GetParent()) {
       if (content->GetAttrCount() > 0) {
         // xml:lang has precedence over lang on HTML elements (see
         // XHTML1 section C.7).
         bool hasAttr = content->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang,
                                           aResult);
-        if (!hasAttr && content->IsHTML()) {
+        if (!hasAttr && (content->IsHTML() || content->IsSVG())) {
           hasAttr = content->GetAttr(kNameSpaceID_None, nsGkAtoms::lang,
                                      aResult);
         }
         NS_ASSERTION(hasAttr || aResult.IsEmpty(),
                      "GetAttr that returns false should not make string non-empty");
         if (hasAttr) {
           return;
         }
--- a/content/base/public/nsIFrameLoader.idl
+++ b/content/base/public/nsIFrameLoader.idl
@@ -62,17 +62,17 @@ typedef unsigned long long nsContentView
  * the content document does not (yet) define.
  *
  * The view scroll values are in units of chrome-document CSS
  * pixels.
  *
  * These APIs are designed to be used with nsIDOMWindowUtils
  * setDisplayPort() and setResolution().
  */
-[scriptable, uuid(fbd25468-d2cf-487b-bc58-a0e105398b47)]
+[scriptable, uuid(c04c5c40-fa2a-4e9c-94f5-b362a10a86cb)]
 interface nsIContentView : nsISupports
 {
   /**
    * Scroll view to or by the given chrome-document CSS pixels.
    * Fails if the view is no longer valid.
    */
   void scrollTo(in float xPx, in float yPx);
   void scrollBy(in float dxPx, in float dyPx);
@@ -260,16 +260,23 @@ interface nsIFrameLoader : nsISupports
   attribute unsigned long eventMode;
 
   /**
    * If false, then the subdocument is not clipped to its CSS viewport, and the
    * subdocument's viewport scrollbar(s) are not rendered.
    * Defaults to true.
    */
   attribute boolean clipSubdocument;
+
+  /**
+   * If false, then the subdocument's scroll coordinates will not be clamped
+   * to their scroll boundaries.
+   * Defaults to true.
+   */
+  attribute boolean clampScrollPosition;
 };
 
 native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
 
 [scriptable, uuid(5879040e-83e9-40e3-b2bb-5ddf43b76e47)]
 interface nsIFrameLoaderOwner : nsISupports
 {
   /**
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -306,34 +306,28 @@ public:
   NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
 
   friend class nsNodeUtils;
   friend class nsNodeWeakReference;
   friend class nsNodeSupportsWeakRefTearoff;
   friend class nsAttrAndChildArray;
 
 #ifdef MOZILLA_INTERNAL_API
-  static nsINode *sOrphanNodeHead;
-
   nsINode(already_AddRefed<nsINodeInfo> aNodeInfo)
   : mNodeInfo(aNodeInfo),
     mParent(nsnull),
     mFlags(0),
-    mBoolFlags(1 << NodeIsOrphan),
-    mNextOrphanNode(sOrphanNodeHead->mNextOrphanNode),
-    mPreviousOrphanNode(sOrphanNodeHead),
+    mBoolFlags(0),
+    mNextSibling(nsnull),
+    mPreviousSibling(nsnull),
     mFirstChild(nsnull),
     mSlots(nsnull)
   {
-    NS_ASSERTION(GetBoolFlag(NodeIsOrphan),
-                 "mBoolFlags not initialized correctly!");
+  }
 
-    mNextOrphanNode->mPreviousOrphanNode = this;
-    sOrphanNodeHead->mNextOrphanNode = this;
-  }
 #endif
 
   virtual ~nsINode();
 
   /**
    * Bit-flags to pass (or'ed together) to IsNodeOfType()
    */
   enum {
@@ -1104,73 +1098,18 @@ public:
     return NS_OK;
   }
   nsresult LookupNamespaceURI(const nsAString& aNamespacePrefix,
                               nsAString& aNamespaceURI);
 
   nsresult IsEqualNode(nsIDOMNode* aOther, bool* aReturn);
   bool IsEqualTo(nsINode* aOther);
 
-  nsIContent* GetNextSibling() const
-  {
-    return NS_UNLIKELY(IsOrphan()) ? nsnull : mNextSibling;
-  }
-
-  nsIContent* GetPreviousSibling() const
-  {
-    return NS_UNLIKELY(IsOrphan()) ? nsnull : mPreviousSibling;
-  }
-
-  // Returns true if this node is an orphan node
-  bool IsOrphan() const
-  {
-#ifdef MOZILLA_INTERNAL_API
-    NS_ASSERTION(this != sOrphanNodeHead, "Orphan node head orphan check?!");
-#endif
-
-    return GetBoolFlag(NodeIsOrphan);
-  }
-
-#ifdef MOZILLA_INTERNAL_API
-  // Mark this node as an orphan node. This marking is only relevant
-  // for this node itself, not its children. Its children are not
-  // considered orphan until they themselves are removed from their
-  // parent and get marked as orphans.
-  void MarkAsOrphan()
-  {
-    NS_ASSERTION(!IsOrphan(), "Orphan node orphaned again?");
-    NS_ASSERTION(this != sOrphanNodeHead, "Orphan node head orphaned?!");
-
-    mNextOrphanNode = sOrphanNodeHead->mNextOrphanNode;
-    mPreviousOrphanNode = sOrphanNodeHead;
-    mNextOrphanNode->mPreviousOrphanNode = this;
-    sOrphanNodeHead->mNextOrphanNode = this;
-
-    SetBoolFlag(NodeIsOrphan);
-  }
-
-  // Unmark this node as an orphan node. Do this before inserting this
-  // node into a parent or otherwise associating it with some other
-  // owner.
-  void MarkAsNonOrphan()
-  {
-    NS_ASSERTION(IsOrphan(), "Non-orphan node un-orphaned");
-    NS_ASSERTION(this != sOrphanNodeHead, "Orphan node head unorphaned?!");
-    NS_ASSERTION(!mParent, "Must not have a parent here!");
-
-    mPreviousOrphanNode->mNextOrphanNode = mNextOrphanNode;
-    mNextOrphanNode->mPreviousOrphanNode = mPreviousOrphanNode;
-    mPreviousOrphanNode = nsnull;
-    mNextOrphanNode = nsnull;
-
-    ClearBoolFlag(NodeIsOrphan);
-  }
-#endif
-
-  static void Init();
+  nsIContent* GetNextSibling() const { return mNextSibling; }
+  nsIContent* GetPreviousSibling() const { return mPreviousSibling; }
 
   /**
    * Get the next node in the pre-order tree traversal of the DOM.  If
    * aRoot is non-null, then it must be an ancestor of |this|
    * (possibly equal to |this|) and only nodes that are descendants of
    * aRoot, not including aRoot itself, will be returned.  Returns
    * null if there are no more nodes to traverse.
    */
@@ -1307,18 +1246,16 @@ private:
     NodeIsCCBlackTree,
     // Maybe set if the node is a root of a subtree 
     // which needs to be kept in the purple buffer.
     NodeIsPurpleRoot,
     // Set if the node has an explicit base URI stored
     NodeHasExplicitBaseURI,
     // Set if the element has some style states locked
     ElementHasLockedStyleStates,
-    // Set if the node is an orphan node.
-    NodeIsOrphan,
     // Guard value
     BooleanFlagCount
   };
 
   void SetBoolFlag(BooleanFlag name, bool value) {
     PR_STATIC_ASSERT(BooleanFlagCount <= 8*sizeof(mBoolFlags));
     mBoolFlags = (mBoolFlags & ~(1 << name)) | (value << name);
   }
@@ -1524,34 +1461,18 @@ protected:
 
   PRUint32 mFlags;
 
 private:
   // Boolean flags.
   PRUint32 mBoolFlags;
 
 protected:
-  union {
-    // mNextSibling is used when this node is part of a DOM tree
-    nsIContent* mNextSibling;
-
-    // mNextOrphanNode is used when this is in the linked list of
-    // orphan nodes.
-    nsINode *mNextOrphanNode;
-  };
-
-  union {
-    // mPreviousSibling is used when this node is part of a DOM tree
-    nsIContent* mPreviousSibling;
-
-    // mPreviousOrphanNode is used when this is in the linked list of
-    // orphan nodes.
-    nsINode* mPreviousOrphanNode;
-  };
-
+  nsIContent* mNextSibling;
+  nsIContent* mPreviousSibling;
   nsIContent* mFirstChild;
 
   // Storage for more members that are usually not needed; allocated lazily.
   nsSlots* mSlots;
 };
 
 
 extern const nsIID kThisPtrOffsetsSID;
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -178,19 +178,19 @@ interface nsIXMLHttpRequest : nsISupport
   /**
    * Returns all of the response headers as a string for HTTP
    * requests.
    *
    * Note that this will return all the headers from the *current*
    * part of a multipart request, not from the original channel.
    *
    * @returns A string containing all of the response headers.
-   *          NULL if the response has not yet been received.
+   *          The empty string if the response has not yet been received.
    */
-  string getAllResponseHeaders();
+  DOMString getAllResponseHeaders();
 
   /**
    * Returns the text of the header with the specified name for
    * HTTP requests.
    *
    * @param header The name of the header to retrieve
    * @returns A string containing the text of the header specified.
    *          NULL if the response has not yet been received or the
--- a/content/base/src/mozSanitizingSerializer.cpp
+++ b/content/base/src/mozSanitizingSerializer.cpp
@@ -549,20 +549,19 @@ mozSanitizingHTMLSerializer::IsAllowedAt
 #endif
   nsresult rv;
 
   nsPRUint32Key tag_key(aTag);
   nsIProperties* attr_bag = (nsIProperties*)mAllowedTags.Get(&tag_key);
   NS_ENSURE_TRUE(attr_bag, false);
 
   bool allowed;
-  nsAutoString attr(anAttributeName);
-  ToLowerCase(attr);
-  rv = attr_bag->Has(NS_LossyConvertUTF16toASCII(attr).get(),
-                     &allowed);
+  nsCAutoString attr;
+  ToLowerCase(NS_ConvertUTF16toUTF8(anAttributeName), attr);
+  rv = attr_bag->Has(attr.get(), &allowed);
   if (NS_FAILED(rv))
     return false;
 
 #ifdef DEBUG_BenB
   printf(" Allowed: %s\n", allowed?"yes":"no");
 #endif
   return allowed;
 }
--- a/content/base/src/nsAttrAndChildArray.cpp
+++ b/content/base/src/nsAttrAndChildArray.cpp
@@ -227,29 +227,23 @@ nsAttrAndChildArray::RemoveChildAt(PRUin
 already_AddRefed<nsIContent>
 nsAttrAndChildArray::TakeChildAt(PRUint32 aPos)
 {
   NS_ASSERTION(aPos < ChildCount(), "out-of-bounds");
 
   PRUint32 childCount = ChildCount();
   void** pos = mImpl->mBuffer + AttrSlotsSize() + aPos;
   nsIContent* child = static_cast<nsIContent*>(*pos);
-
-  MOZ_ASSERT(!child->IsOrphan(), "Child should not be an orphan here");
-
   if (child->mPreviousSibling) {
     child->mPreviousSibling->mNextSibling = child->mNextSibling;
   }
   if (child->mNextSibling) {
     child->mNextSibling->mPreviousSibling = child->mPreviousSibling;
   }
-
-  // Mark the child as an orphan now that it's no longer associated
-  // with its old parent.
-  child->MarkAsOrphan();
+  child->mPreviousSibling = child->mNextSibling = nsnull;
 
   memmove(pos, pos + 1, (childCount - aPos - 1) * sizeof(nsIContent*));
   SetChildCount(childCount - 1);
 
   return child;
 }
 
 PRInt32
@@ -658,31 +652,28 @@ nsAttrAndChildArray::Clear()
 
   nsAutoScriptBlocker scriptBlocker;
   PRUint32 end = slotCount * ATTRSIZE + ChildCount();
   for (i = slotCount * ATTRSIZE; i < end; ++i) {
     nsIContent* child = static_cast<nsIContent*>(mImpl->mBuffer[i]);
     // making this false so tree teardown doesn't end up being
     // O(N*D) (number of nodes times average depth of tree).
     child->UnbindFromTree(false); // XXX is it better to let the owner do this?
-    // Mark the child as an orphan now that it's no longer a child of
-    // its old parent, and make sure to unlink our kids from each
-    // other, since someone else could stil be holding references to
-    // some of them.
-
-    child->MarkAsOrphan();
+    // Make sure to unlink our kids from each other, since someone
+    // else could stil be holding references to some of them.
 
     // XXXbz We probably can't push this assignment down into the |aNullParent|
     // case of UnbindFromTree because we still need the assignment in
     // RemoveChildAt.  In particular, ContentRemoved fires between
     // RemoveChildAt and UnbindFromTree, and in ContentRemoved the sibling
     // chain needs to be correct.  Though maybe we could set the prev and next
     // to point to each other but keep the kid being removed pointing to them
     // through ContentRemoved so consumers can find where it used to be in the
     // list?
+    child->mPreviousSibling = child->mNextSibling = nsnull;
     NS_RELEASE(child);
   }
 
   SetAttrSlotAndChildCount(0, 0);
 }
 
 PRUint32
 nsAttrAndChildArray::NonMappedAttrCount() const
@@ -826,26 +817,18 @@ nsAttrAndChildArray::AddAttrSlot()
 
   return true;
 }
 
 inline void
 nsAttrAndChildArray::SetChildAtPos(void** aPos, nsIContent* aChild,
                                    PRUint32 aIndex, PRUint32 aChildCount)
 {
-  MOZ_ASSERT(aChild->IsOrphan(), "aChild should be an orphan here");
-
-  NS_PRECONDITION(aChild->IsOrphan() || !aChild->GetNextSibling(),
-                  "aChild should be orphan and have no next sibling!");
-  NS_PRECONDITION(aChild->IsOrphan() || !aChild->GetPreviousSibling(),
-                  "aChild should be orphan and have no prev sibling!");
-
-  // Unmark this child as an orphan now that it's a child of its new
-  // parent.
-  aChild->MarkAsNonOrphan();
+  NS_PRECONDITION(!aChild->GetNextSibling(), "aChild with next sibling?");
+  NS_PRECONDITION(!aChild->GetPreviousSibling(), "aChild with prev sibling?");
 
   *aPos = aChild;
   NS_ADDREF(aChild);
   if (aIndex != 0) {
     nsIContent* previous = static_cast<nsIContent*>(*(aPos - 1));
     aChild->mPreviousSibling = previous;
     previous->mNextSibling = aChild;
   }
--- 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/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -357,18 +357,16 @@ nsresult
 nsContentUtils::Init()
 {
   if (sInitialized) {
     NS_WARNING("Init() called twice");
 
     return NS_OK;
   }
 
-  nsINode::Init();
-
   nsresult rv = NS_GetNameSpaceManager(&sNameSpaceManager);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsXPConnect* xpconnect = nsXPConnect::GetXPConnect();
   NS_ENSURE_TRUE(xpconnect, NS_ERROR_FAILURE);
 
   sXPConnect = xpconnect;
   sThreadJSContextStack = xpconnect;
--- 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/nsDOMAttribute.cpp
+++ b/content/base/src/nsDOMAttribute.cpp
@@ -86,17 +86,16 @@ nsDOMAttribute::nsDOMAttribute(nsDOMAttr
     content->AddMutationObserver(this);
   }
 }
 
 nsDOMAttribute::~nsDOMAttribute()
 {
   if (mChild) {
     static_cast<nsTextNode*>(mChild)->UnbindFromAttribute();
-    mChild->MarkAsOrphan();
     NS_RELEASE(mChild);
     mFirstChild = nsnull;
   }
 
   nsIContent* content = GetContentInternal();
   if (content) {
     content->RemoveMutationObserver(this);
   }
@@ -117,17 +116,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMAttribute)
   nsINode::Trace(tmp, aCallback, aClosure);
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttribute)
   nsINode::Unlink(tmp);
   if (tmp->mChild) {
     static_cast<nsTextNode*>(tmp->mChild)->UnbindFromAttribute();
-    tmp->mChild->MarkAsOrphan();
     NS_RELEASE(tmp->mChild);
     tmp->mFirstChild = nsnull;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 DOMCI_NODE_DATA(Attr, nsDOMAttribute)
 
 // QueryInterface implementation for nsDOMAttribute
@@ -723,17 +721,16 @@ nsDOMAttribute::EnsureChildState()
   NS_PRECONDITION(!mChild, "Someone screwed up");
 
   nsAutoString value;
   GetValue(value);
 
   if (!value.IsEmpty()) {
     NS_NewTextNode(&mChild, mNodeInfo->NodeInfoManager());
 
-    mChild->MarkAsNonOrphan();
     static_cast<nsTextNode*>(mChild)->BindToAttribute(this);
     mFirstChild = mChild;
 
     mChild->SetText(value, false);
   }
 }
 
 void
@@ -791,11 +788,10 @@ nsDOMAttribute::doRemoveChild(bool aNoti
   NS_RELEASE(mChild);
   mFirstChild = nsnull;
 
   if (aNotify) {
     nsNodeUtils::AttributeChildRemoved(this, child);
   }
 
   child->UnbindFromAttribute();
-  child->MarkAsOrphan();
 }
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -854,17 +854,17 @@ TransferZoomLevels(nsIDocument* aFromDoc
   if (!toShell)
     return;
 
   nsPresContext* toCtxt = toShell->GetPresContext();
   if (!toCtxt)
     return;
 
   toCtxt->SetFullZoom(fromCtxt->GetFullZoom());
-  toCtxt->SetMinFontSize(fromCtxt->MinFontSize());
+  toCtxt->SetMinFontSize(fromCtxt->MinFontSize(nsnull));
   toCtxt->SetTextZoom(fromCtxt->TextZoom());
 }
 
 void
 TransferShowingState(nsIDocument* aFromDoc, nsIDocument* aToDoc)
 {
   NS_ABORT_IF_FALSE(aFromDoc && aToDoc,
                     "transferring showing state from/to null doc");
@@ -1574,18 +1574,17 @@ nsDocument::~nsDocument()
     PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG,
            ("DOCUMENT %p destroyed", this));
 #endif
 
 #ifdef DEBUG
   nsCycleCollector_DEBUG_wasFreed(static_cast<nsIDocument*>(this));
 #endif
 
-  NS_ASSERTION(!mIsShowing, "Deleting a currently-showing document");
-  NS_ASSERTION(IsOrphan(), "Deleted document not an orphan?");
+  NS_ASSERTION(!mIsShowing, "Destroying a currently-showing document");
 
   mInDestructor = true;
   mInUnlinkOrDeletion = true;
 
   // Clear mObservers to keep it in sync with the mutationobserver list
   mObservers.Clear();
 
   if (mStyleSheetSetList) {
@@ -2114,17 +2113,16 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
 #ifdef PR_LOGGING
   if (gDocumentLeakPRLog && PR_LOG_TEST(gDocumentLeakPRLog, PR_LOG_DEBUG)) {
     nsCAutoString spec;
     aURI->GetSpec(spec);
     PR_LogPrint("DOCUMENT %p ResetToURI %s", this, spec.get());
   }
 #endif
 
-  SetPrincipal(nsnull);
   mSecurityInfo = nsnull;
 
   mDocumentLoadGroup = nsnull;
 
   // Delete references to sub-documents and kill the subdocument map,
   // if any. It holds strong references
   if (mSubDocuments) {
     PL_DHashTableDestroy(mSubDocuments);
@@ -2164,16 +2162,22 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
   if (mListenerManager) {
     mListenerManager->Disconnect();
     mListenerManager = nsnull;
   }
 
   // Release the stylesheets list.
   mDOMStyleSheets = nsnull;
 
+  // Release our principal after tearing down the document, rather than before.
+  // This ensures that, during teardown, the document and the dying window (which
+  // already nulled out its document pointer and cached the principal) have
+  // matching principals.
+  SetPrincipal(nsnull);
+
   // Clear the original URI so SetDocumentURI sets it.
   mOriginalURI = nsnull;
 
   SetDocumentURI(aURI);
   // If mDocumentBaseURI is null, nsIDocument::GetBaseURI() returns
   // mDocumentURI.
   mDocumentBaseURI = nsnull;
 
@@ -5124,21 +5128,19 @@ nsDocument::CreateTreeWalker(nsIDOMNode 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsDocument::GetDefaultView(nsIDOMWindow** aDefaultView)
 {
   *aDefaultView = nsnull;
-  nsPIDOMWindow* win = GetWindow();
-  if (!win) {
-    return NS_OK;
-  }
-  return CallQueryInterface(win, aDefaultView);
+  nsCOMPtr<nsPIDOMWindow> win = GetWindow();
+  win.forget(aDefaultView);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::GetLocation(nsIDOMLocation **_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nsnull;
 
@@ -8111,17 +8113,17 @@ nsIDocument::ScheduleFrameRequestCallbac
 {
   if (mFrameRequestCallbackCounter == PR_INT32_MAX) {
     // Can't increment without overflowing; bail out
     return NS_ERROR_NOT_AVAILABLE;
   }
   PRInt32 newHandle = ++mFrameRequestCallbackCounter;
 
   bool alreadyRegistered = !mFrameRequestCallbacks.IsEmpty();
-  FrameRequest *request =
+  DebugOnly<FrameRequest*> request =
     mFrameRequestCallbacks.AppendElement(FrameRequest(aCallback, newHandle));
   NS_ASSERTION(request, "This is supposed to be infallible!");
   if (!alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
     mPresShell->GetPresContext()->RefreshDriver()->
       ScheduleFrameRequestCallbacks(this);
   }
 
   *aHandle = newHandle;
@@ -8294,21 +8296,18 @@ nsDocument::NotifyAudioAvailableListener
 }
 
 nsresult
 nsDocument::RemoveImage(imgIRequest* aImage)
 {
   NS_ENSURE_ARG_POINTER(aImage);
 
   // Get the old count. It should exist and be > 0.
-  PRUint32 count;
-#ifdef DEBUG
-  bool found =
-#endif
-  mImageTracker.Get(aImage, &count);
+  PRUint32 count = 0;
+  DebugOnly<bool> found = mImageTracker.Get(aImage, &count);
   NS_ABORT_IF_FALSE(found, "Removing image that wasn't in the tracker!");
   NS_ABORT_IF_FALSE(count > 0, "Entry in the cache tracker with count 0!");
 
   // We're removing, so decrement the count.
   count--;
 
   // If the count is now zero, remove from the tracker.
   // Otherwise, set the new value.
@@ -8522,17 +8521,17 @@ nsDocument::MozCancelFullScreen()
 class nsSetWindowFullScreen : public nsRunnable {
 public:
   nsSetWindowFullScreen(nsIDocument* aDoc, bool aValue)
     : mDoc(aDoc), mValue(aValue) {}
 
   NS_IMETHOD Run()
   {
     if (mDoc->GetWindow()) {
-      mDoc->GetWindow()->SetFullScreen(mValue);
+      mDoc->GetWindow()->SetFullScreenInternal(mValue, false);
     }
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIDocument> mDoc;
   bool mValue;
 };
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -71,16 +71,17 @@
 #include "nsIJSContextStack.h"
 #include "nsUnicharUtils.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollable.h"
 #include "nsFrameLoader.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIFrame.h"
+#include "nsIScrollableFrame.h"
 #include "nsSubDocumentFrame.h"
 #include "nsDOMError.h"
 #include "nsGUIEvent.h"
 #include "nsEventDispatcher.h"
 #include "nsISHistory.h"
 #include "nsISHistoryInternal.h"
 #include "nsIDocShellHistory.h"
 #include "nsIDOMHTMLDocument.h"
@@ -325,16 +326,17 @@ nsFrameLoader::nsFrameLoader(Element* aO
   , mInSwap(false)
   , mInShow(false)
   , mHideCalled(false)
   , mNetworkCreated(aNetworkCreated)
   , mDelayRemoteDialogs(false)
   , mRemoteBrowserShown(false)
   , mRemoteFrame(false)
   , mClipSubdocument(true)
+  , mClampScrollPosition(true)
   , mCurrentRemoteFrame(nsnull)
   , mRemoteBrowser(nsnull)
   , mRenderMode(RENDER_MODE_DEFAULT)
   , mEventMode(EVENT_MODE_NORMAL_DISPATCH)
 {
 }
 
 nsFrameLoader*
@@ -1750,16 +1752,48 @@ nsFrameLoader::SetClipSubdocument(bool a
             FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
         }
       }
     }
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsFrameLoader::GetClampScrollPosition(bool* aResult)
+{
+  *aResult = mClampScrollPosition;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFrameLoader::SetClampScrollPosition(bool aClamp)
+{
+  mClampScrollPosition = aClamp;
+
+  // When turning clamping on, make sure the current position is clamped.
+  if (aClamp) {
+    nsIFrame* frame = GetPrimaryFrameOfOwningContent();
+    if (frame) {
+      nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
+      if (subdocFrame) {
+        nsIFrame* subdocRootFrame = subdocFrame->GetSubdocumentRootFrame();
+        if (subdocRootFrame) {
+          nsIScrollableFrame* subdocRootScrollFrame = subdocRootFrame->PresContext()->PresShell()->
+            GetRootScrollFrameAsScrollable();
+          if (subdocRootScrollFrame) {
+            subdocRootScrollFrame->ScrollTo(subdocRootScrollFrame->GetScrollPosition(), nsIScrollableFrame::INSTANT);
+          }
+        }
+      }
+    }
+  }
+  return NS_OK;
+}
+
 nsIntSize
 nsFrameLoader::GetSubDocumentSize(const nsIFrame *aIFrame)
 {
   nsSize docSizeAppUnits;
   nsPresContext* presContext = aIFrame->PresContext();
   nsCOMPtr<nsIDOMHTMLFrameElement> frameElem = 
     do_QueryInterface(aIFrame->GetContent());
   if (frameElem) {
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -284,16 +284,18 @@ public:
   }
   nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; }
 
   mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; }
   void SetOwnerContent(mozilla::dom::Element* aContent);
 
   bool ShouldClipSubdocument() { return mClipSubdocument; }
 
+  bool ShouldClampScrollPosition() { return mClampScrollPosition; }
+
 private:
 
   bool ShouldUseRemoteProcess();
 
   /**
    * If we are an IPC frame, set mRemoteFrame. Otherwise, create and
    * initialize mDocShell.
    */
@@ -337,16 +339,17 @@ private:
   // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
   // it may lose the flag.
   bool mNetworkCreated : 1;
 
   bool mDelayRemoteDialogs : 1;
   bool mRemoteBrowserShown : 1;
   bool mRemoteFrame : 1;
   bool mClipSubdocument : 1;
+  bool mClampScrollPosition : 1;
 
   // XXX leaking
   nsCOMPtr<nsIObserver> mChildHost;
   RenderFrameParent* mCurrentRemoteFrame;
   TabParent* mRemoteBrowser;
 
   // See nsIFrameLoader.idl.  Short story, if !(mRenderMode &
   // RENDER_MODE_ASYNC_SCROLL), all the fields below are ignored in
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -344,17 +344,18 @@ nsFrameMessageManager::Atob(const nsAStr
 {
   return NS_OK;
 }
 
 class MMListenerRemover
 {
 public:
   MMListenerRemover(nsFrameMessageManager* aMM)
-  : mMM(aMM), mWasHandlingMessage(aMM->mHandlingMessage)
+    : mWasHandlingMessage(aMM->mHandlingMessage)
+    , mMM(aMM)
   {
     mMM->mHandlingMessage = true;
   }
   ~MMListenerRemover()
   {
     if (!mWasHandlingMessage) {
       mMM->mHandlingMessage = false;
       if (mMM->mDisconnected) {
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -208,26 +208,19 @@ nsINode::nsSlots::Unlink()
   if (mChildNodes) {
     mChildNodes->DropReference();
     NS_RELEASE(mChildNodes);
   }
 }
 
 //----------------------------------------------------------------------
 
-nsINode *nsINode::sOrphanNodeHead = nsnull;
-
 nsINode::~nsINode()
 {
   NS_ASSERTION(!HasSlots(), "nsNodeUtils::LastRelease was not called?");
-
-  MOZ_ASSERT(IsOrphan(), "Node should be orphan by the time it's deleted!");
-
-  mPreviousOrphanNode->mNextOrphanNode = mNextOrphanNode;
-  mNextOrphanNode->mPreviousOrphanNode = mPreviousOrphanNode;
 }
 
 void*
 nsINode::GetProperty(PRUint16 aCategory, nsIAtom *aPropertyName,
                      nsresult *aStatus) const
 {
   return OwnerDoc()->PropertyTable(aCategory)->GetProperty(this, aPropertyName,
                                                            aStatus);
@@ -3264,17 +3257,17 @@ nsGenericElement::UnbindFromTree(bool aD
     DeleteProperty(nsGkAtoms::transitionsProperty);
     DeleteProperty(nsGkAtoms::animationsOfBeforeProperty);
     DeleteProperty(nsGkAtoms::animationsOfAfterProperty);
     DeleteProperty(nsGkAtoms::animationsProperty);
   }
 
   // Unset this since that's what the old code effectively did.
   UnsetFlags(NODE_FORCE_XBL_BINDINGS);
-
+  
 #ifdef MOZ_XUL
   nsXULElement* xulElem = nsXULElement::FromContent(this);
   if (xulElem) {
     xulElem->SetXULBindingParent(nsnull);
   }
   else
 #endif
   {
@@ -3858,32 +3851,17 @@ nsGenericElement::GetTextContent(nsAStri
 }
 
 NS_IMETHODIMP
 nsGenericElement::SetTextContent(const nsAString& aTextContent)
 {
   return nsContentUtils::SetNodeTextContent(this, aTextContent, false);
 }
 
-// static
-void
-nsINode::Init()
-{
-  // Allocate static storage for the head of the list of orphan nodes
-  static MOZ_ALIGNED_DECL(char orphanNodeListHead[sizeof(nsINode)], 8);
-  sOrphanNodeHead = reinterpret_cast<nsINode *>(&orphanNodeListHead[0]);
-
-  sOrphanNodeHead->mNextOrphanNode = sOrphanNodeHead;
-  sOrphanNodeHead->mPreviousOrphanNode = sOrphanNodeHead;
-
-  sOrphanNodeHead->mFirstChild = reinterpret_cast<nsIContent *>(0xdeadbeef);
-  sOrphanNodeHead->mParent = reinterpret_cast<nsIContent *>(0xdeadbeef);
-}
-
-// static
+/* static */
 nsresult
 nsGenericElement::DispatchEvent(nsPresContext* aPresContext,
                                 nsEvent* aEvent,
                                 nsIContent* aTarget,
                                 bool aFullDispatch,
                                 nsEventStatus* aStatus)
 {
   NS_PRECONDITION(aTarget, "Must have target");
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1095,16 +1095,17 @@ GK_ATOM(window, "window")
 GK_ATOM(headerWindowTarget, "window-target")
 GK_ATOM(withParam, "with-param")
 GK_ATOM(wizard, "wizard")
 GK_ATOM(wrap, "wrap")
 GK_ATOM(headerDNSPrefetchControl,"x-dns-prefetch-control")
 GK_ATOM(headerCSP, "x-content-security-policy")
 GK_ATOM(headerCSPReportOnly, "x-content-security-policy-report-only")
 GK_ATOM(headerXFO, "x-frame-options")
+GK_ATOM(x_western, "x-western")
 GK_ATOM(xml, "xml")
 GK_ATOM(xml_stylesheet, "xml-stylesheet")
 GK_ATOM(xmlns, "xmlns")
 GK_ATOM(xmp, "xmp")
 GK_ATOM(xulcontentsgenerated, "xulcontentsgenerated")
 GK_ATOM(yes, "yes")
 GK_ATOM(z_index, "z-index")
 GK_ATOM(zeroDigit, "zero-digit")
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1275,18 +1275,20 @@ nsXMLHttpRequest::CloseRequestWithError(
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
   }
   PRUint32 responseLength = mResponseBody.Length();
   ResetResponse();
   mState |= aFlag;
 
   // If we're in the destructor, don't risk dispatching an event.
-  if (mState & XML_HTTP_REQUEST_DELETED)
+  if (mState & XML_HTTP_REQUEST_DELETED) {
+    mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
     return;
+  }
 
   if (!(mState & (XML_HTTP_REQUEST_UNSENT |
                   XML_HTTP_REQUEST_OPENED |
                   XML_HTTP_REQUEST_DONE))) {
     ChangeState(XML_HTTP_REQUEST_DONE, true);
 
     if (!(mState & XML_HTTP_REQUEST_SYNCLOOPING)) {
       DispatchProgressEvent(this, aType, mLoadLengthComputable, responseLength,
@@ -1312,55 +1314,102 @@ nsXMLHttpRequest::CloseRequestWithError(
 /* void abort (); */
 NS_IMETHODIMP
 nsXMLHttpRequest::Abort()
 {
   CloseRequestWithError(NS_LITERAL_STRING(ABORT_STR), XML_HTTP_REQUEST_ABORTED);
   return NS_OK;
 }
 
-/* string getAllResponseHeaders (); */
+/* DOMString getAllResponseHeaders(); */
 NS_IMETHODIMP
-nsXMLHttpRequest::GetAllResponseHeaders(char **_retval)
+nsXMLHttpRequest::GetAllResponseHeaders(nsAString& aResponseHeaders)
 {
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = nsnull;
+  aResponseHeaders.Truncate();
+
+  // If the state is UNSENT or OPENED,
+  // return the empty string and terminate these steps.
+  if (mState & (XML_HTTP_REQUEST_UNSENT |
+                XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT)) {
+    return NS_OK;
+  }
 
   if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
-    *_retval = ToNewCString(EmptyString());
     return NS_OK;
   }
 
-  nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
-
-  if (httpChannel) {
+  if (nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel()) {
     nsRefPtr<nsHeaderVisitor> visitor = new nsHeaderVisitor();
-    nsresult rv = httpChannel->VisitResponseHeaders(visitor);
-    if (NS_SUCCEEDED(rv))
-      *_retval = ToNewCString(visitor->Headers());
+    if (NS_SUCCEEDED(httpChannel->VisitResponseHeaders(visitor))) {
+      aResponseHeaders = NS_ConvertUTF8toUTF16(visitor->Headers());
+    }
+    return NS_OK;
+  }
+
+  if (!mChannel) {
+    return NS_OK;
   }
- 
-  if (!*_retval) {
-    *_retval = ToNewCString(EmptyString());
+
+  // Even non-http channels supply content type.
+  nsCAutoString value;
+  if (NS_SUCCEEDED(mChannel->GetContentType(value))) {
+    aResponseHeaders.AppendLiteral("Content-Type: ");
+    aResponseHeaders.Append(NS_ConvertUTF8toUTF16(value));
+    if (NS_SUCCEEDED(mChannel->GetContentCharset(value)) &&
+        !value.IsEmpty()) {
+      aResponseHeaders.AppendLiteral(";charset=");
+      aResponseHeaders.Append(NS_ConvertUTF8toUTF16(value));
+    }
+    aResponseHeaders.Append('\n');
   }
-
   return NS_OK;
 }
 
 /* ACString getResponseHeader (in AUTF8String header); */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetResponseHeader(const nsACString& header,
                                     nsACString& _retval)
 {
   nsresult rv = NS_OK;
   _retval.SetIsVoid(true);
 
   nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
 
   if (!httpChannel) {
+    // If the state is UNSENT or OPENED,
+    // return null and terminate these steps.
+    if (mState & (XML_HTTP_REQUEST_UNSENT |
+                  XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT)) {
+      return NS_OK;
+    }
+
+    // Even non-http channels supply content type.
+    // Remember we don't leak header information from denied cross-site
+    // requests.
+    nsresult status;
+    if (!mChannel ||
+        NS_FAILED(mChannel->GetStatus(&status)) ||
+        NS_FAILED(status) ||
+        !header.LowerCaseEqualsASCII("content-type")) {
+      return NS_OK;
+    }
+
+    if (NS_FAILED(mChannel->GetContentType(_retval))) {
+      // Means no content type
+      _retval.SetIsVoid(true);
+      return NS_OK;
+    }
+
+    nsCString value;
+    if (NS_SUCCEEDED(mChannel->GetContentCharset(value)) &&
+        !value.IsEmpty()) {
+      _retval.Append(";charset=");
+      _retval.Append(value);
+    }
+
     return NS_OK;
   }
 
   // See bug #380418. Hide "Set-Cookie" headers from non-chrome scripts.
   bool chrome = false; // default to false in case IsCapabilityEnabled fails
   IsCapabilityEnabled("UniversalXPConnect", &chrome);
   if (!chrome &&
        (header.LowerCaseEqualsASCII("set-cookie") ||
--- a/content/base/test/test_XHR.html
+++ b/content/base/test/test_XHR.html
@@ -17,43 +17,52 @@ SimpleTest.waitForExplicitFinish();
 
 var gen = runTests();
 function continueTest() { gen.next(); }
 
 function runTests() {
 
 var path = "/tests/content/base/test/";
 
-var passFiles = [['file_XHR_pass1.xml', 'GET', 200],
-                 ['file_XHR_pass2.txt', 'GET', 200],
-                 ['file_XHR_pass3.txt', 'GET', 200],
-                 ['data:text/xml,%3Cres%3Ehello%3C/res%3E%0A', 'GET', 0],
-                 ['data:text/plain,hello%20pass%0A', 'GET', 0],
+var passFiles = [['file_XHR_pass1.xml', 'GET', 200, 'text/xml'],
+                 ['file_XHR_pass2.txt', 'GET', 200, 'text/plain'],
+                 ['file_XHR_pass3.txt', 'GET', 200, 'text/plain'],
+                 ['data:text/xml,%3Cres%3Ehello%3C/res%3E%0A', 'GET', 0, 'text/xml'],
+                 ['data:text/plain,hello%20pass%0A', 'GET', 0, 'text/plain'],
+                 ['data:,foo', 'GET', 0, 'text/plain;charset=US-ASCII', 'foo'],
+                 ['data:text/plain;base64,Zm9v', 'GET', 0, 'text/plain', 'foo'],
+                 ['data:text/plain,foo#bar', 'GET', 0, 'text/plain', 'foo'],
+                 ['data:text/plain,foo%23bar', 'GET', 0, 'text/plain', 'foo#bar'],
                  ];
 
 var failFiles = [['//example.com' + path + 'file_XHR_pass1.xml', 'GET'],
                  ['ftp://localhost' + path + 'file_XHR_pass1.xml', 'GET'],
                  ['file_XHR_fail1.txt', 'GET'],
                  ];
 
 for (i = 0; i < passFiles.length; ++i) {
   xhr = new XMLHttpRequest();
+  is(xhr.getResponseHeader("Content-Type"), null, "should be null");
+  is(xhr.getAllResponseHeaders(), "", "should be empty string");
   is(xhr.responseType, "", "wrong initial responseType");
   xhr.open(passFiles[i][1], passFiles[i][0], false); 
   xhr.send(null);
   is(xhr.status, passFiles[i][2], "wrong status");
+  is(xhr.getResponseHeader("Content-Type"), passFiles[i][3], "wrong content type");
+  var headers = xhr.getAllResponseHeaders();
+  ok(/(?:^|\n)Content-Type:\s*([^\n]*)\n/i.test(headers) &&
+     RegExp.$1 === passFiles[i][3], "wrong response headers");
   if (xhr.responseXML) {
     is((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement),
-       "<res>hello</res>",
-       "wrong responseXML");
-    is(xhr.response, "<res>hello</res>\n", "wrong response");
+       passFiles[i][4] || "<res>hello</res>", "wrong responseXML");
+    is(xhr.response, passFiles[i][4] || "<res>hello</res>\n", "wrong response");
   }
   else {
-    is(xhr.responseText, "hello pass\n", "wrong responseText");
-    is(xhr.response, "hello pass\n", "wrong response");
+    is(xhr.responseText, passFiles[i][4] || "hello pass\n", "wrong responseText");
+    is(xhr.response, passFiles[i][4] || "hello pass\n", "wrong response");
   }
 }
 
 for (i = 0; i < failFiles.length; ++i) {
   xhr = new XMLHttpRequest();
   var didthrow = false;
   try {
     xhr.open(failFiles[i][1], failFiles[i][0], false); 
--- a/content/canvas/src/CustomQS_WebGL.h
+++ b/content/canvas/src/CustomQS_WebGL.h
@@ -440,17 +440,17 @@ nsIDOMWebGLRenderingContext_TexImage2D(J
             JSObject *argv5 = JSVAL_TO_OBJECT(argv[5]);
 
             jsval js_width, js_height, js_data;
             JS_GetProperty(cx, argv5, "width", &js_width);
             JS_GetProperty(cx, argv5, "height", &js_height);
             JS_GetProperty(cx, argv5, "data", &js_data);
             if (js_width  == JSVAL_VOID ||
                 js_height == JSVAL_VOID ||
-                js_data   == JSVAL_VOID)
+                !js_data.isObject())
             {
                 xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 5);
                 return JS_FALSE;
             }
             int32_t int_width, int_height;
             JSObject *obj_data = JSVAL_TO_OBJECT(js_data);
             if (!JS_ValueToECMAInt32(cx, js_width, &int_width) ||
                 !JS_ValueToECMAInt32(cx, js_height, &int_height))
@@ -561,17 +561,17 @@ nsIDOMWebGLRenderingContext_TexSubImage2
             // failed to interprete argv[6] as a DOMElement, now try to interprete it as ImageData
             JSObject *argv6 = JSVAL_TO_OBJECT(argv[6]);
             jsval js_width, js_height, js_data;
             JS_GetProperty(cx, argv6, "width", &js_width);
             JS_GetProperty(cx, argv6, "height", &js_height);
             JS_GetProperty(cx, argv6, "data", &js_data);
             if (js_width  == JSVAL_VOID ||
                 js_height == JSVAL_VOID ||
-                js_data   == JSVAL_VOID)
+                !js_data.isObject())
             {
                 xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 6);
                 return JS_FALSE;
             }
             int32_t int_width, int_height;
             JSObject *obj_data = JSVAL_TO_OBJECT(js_data);
             if (!JS_ValueToECMAInt32(cx, js_width, &int_width) ||
                 !JS_ValueToECMAInt32(cx, js_height, &int_height))
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -63,16 +63,17 @@ CPPSRCS	= \
 	$(NULL)
 
 ifdef MOZ_WEBGL
 
 CPPSRCS += \
 	WebGLContext.cpp \
 	WebGLContextGL.cpp \
 	WebGLContextUtils.cpp \
+	WebGLContextReporter.cpp \
 	WebGLContextValidate.cpp \
 	WebGLExtensionStandardDerivatives.cpp \
 	WebGLExtensionLoseContext.cpp \
 	$(NULL)
 
 DEFINES += -DUSE_ANGLE
 USE_ANGLE=1
 
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -70,143 +70,16 @@
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 using namespace mozilla::layers;
 
-WebGLMemoryReporter* WebGLMemoryReporter::sUniqueInstance = nsnull;
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLTextureMemoryUsed,
-                             "webgl-texture-memory",
-                             KIND_OTHER,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetTextureMemoryUsed,
-                             "Memory used by WebGL textures. The OpenGL implementation is free to store these textures in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLTextureCount,
-                             "webgl-texture-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetTextureCount,
-                             "Number of WebGL textures.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLBufferMemoryUsed,
-                             "webgl-buffer-memory",
-                             KIND_OTHER,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetBufferMemoryUsed,
-                             "Memory used by WebGL buffers. The OpenGL implementation is free to store these buffers in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLBufferCacheMemoryUsed,
-                             "explicit/webgl/buffer-cache-memory",
-                             KIND_HEAP,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetBufferCacheMemoryUsed,
-                             "Memory used by WebGL buffer caches. The WebGL implementation caches the contents of element array buffers only. This adds up with the webgl-buffer-memory value, but contrary to it, this one represents bytes on the heap, not managed by OpenGL.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLBufferCount,
-                             "webgl-buffer-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetBufferCount,
-                             "Number of WebGL buffers.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLRenderbufferMemoryUsed,
-                             "webgl-renderbuffer-memory",
-                             KIND_OTHER,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetRenderbufferMemoryUsed,
-                             "Memory used by WebGL renderbuffers. The OpenGL implementation is free to store these renderbuffers in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLRenderbufferCount,
-                             "webgl-renderbuffer-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetRenderbufferCount,
-                             "Number of WebGL renderbuffers.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLShaderSourcesSize,
-                             "explicit/webgl/shader-sources-size",
-                             KIND_HEAP,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetShaderSourcesSize,
-                             "Combined size of WebGL shader ASCII sources, cached on the heap. This should always be at most a few kilobytes, or dozen kilobytes for very shader-intensive WebGL demos.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLShaderTranslationLogsSize,
-                             "explicit/webgl/shader-translationlogs-size",
-                             KIND_HEAP,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetShaderTranslationLogsSize,
-                             "Combined size of WebGL shader ASCII translation logs, cached on the heap.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLShaderCount,
-                             "webgl-shader-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetShaderCount,
-                             "Number of WebGL shaders.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLContextCount,
-                             "webgl-context-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetContextCount,
-                             "Number of WebGL contexts.")
-
-WebGLMemoryReporter* WebGLMemoryReporter::UniqueInstance()
-{
-    if (!sUniqueInstance) {
-        sUniqueInstance = new WebGLMemoryReporter;
-    }
-    return sUniqueInstance;
-}
-
-WebGLMemoryReporter::WebGLMemoryReporter()
-    : mTextureMemoryUsageReporter(new NS_MEMORY_REPORTER_NAME(WebGLTextureMemoryUsed))
-    , mTextureCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLTextureCount))
-    , mBufferMemoryUsageReporter(new NS_MEMORY_REPORTER_NAME(WebGLBufferMemoryUsed))
-    , mBufferCacheMemoryUsageReporter(new NS_MEMORY_REPORTER_NAME(WebGLBufferCacheMemoryUsed))
-    , mBufferCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLBufferCount))
-    , mRenderbufferMemoryUsageReporter(new NS_MEMORY_REPORTER_NAME(WebGLRenderbufferMemoryUsed))
-    , mRenderbufferCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLRenderbufferCount))
-    , mShaderSourcesSizeReporter(new NS_MEMORY_REPORTER_NAME(WebGLShaderSourcesSize))
-    , mShaderTranslationLogsSizeReporter(new NS_MEMORY_REPORTER_NAME(WebGLShaderTranslationLogsSize))
-    , mShaderCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLShaderCount))
-    , mContextCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLContextCount))
-{
-    NS_RegisterMemoryReporter(mTextureMemoryUsageReporter);
-    NS_RegisterMemoryReporter(mTextureCountReporter);
-    NS_RegisterMemoryReporter(mBufferMemoryUsageReporter);
-    NS_RegisterMemoryReporter(mBufferCacheMemoryUsageReporter);    
-    NS_RegisterMemoryReporter(mBufferCountReporter);
-    NS_RegisterMemoryReporter(mRenderbufferMemoryUsageReporter);
-    NS_RegisterMemoryReporter(mRenderbufferCountReporter);
-    NS_RegisterMemoryReporter(mShaderSourcesSizeReporter);
-    NS_RegisterMemoryReporter(mShaderTranslationLogsSizeReporter);
-    NS_RegisterMemoryReporter(mShaderCountReporter);
-    NS_RegisterMemoryReporter(mContextCountReporter);
-}
-
-WebGLMemoryReporter::~WebGLMemoryReporter()
-{
-    NS_UnregisterMemoryReporter(mTextureMemoryUsageReporter);
-    NS_UnregisterMemoryReporter(mTextureCountReporter);
-    NS_UnregisterMemoryReporter(mBufferMemoryUsageReporter);
-    NS_UnregisterMemoryReporter(mBufferCacheMemoryUsageReporter);
-    NS_UnregisterMemoryReporter(mBufferCountReporter);
-    NS_UnregisterMemoryReporter(mRenderbufferMemoryUsageReporter);
-    NS_UnregisterMemoryReporter(mRenderbufferCountReporter);
-    NS_UnregisterMemoryReporter(mShaderSourcesSizeReporter);
-    NS_UnregisterMemoryReporter(mShaderTranslationLogsSizeReporter);
-    NS_UnregisterMemoryReporter(mShaderCountReporter);
-    NS_UnregisterMemoryReporter(mContextCountReporter);
-}
 
 nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
 
 nsresult
 NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult)
 {
     Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
     nsIDOMWebGLRenderingContext* ctx = new WebGLContext();
@@ -284,31 +157,31 @@ WebGLContext::WebGLContext()
     mGLMaxVaryingVectors = 0;
     mGLMaxFragmentUniformVectors = 0;
     mGLMaxVertexUniformVectors = 0;
     
     // See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
     mPixelStorePackAlignment = 4;
     mPixelStoreUnpackAlignment = 4;
 
-    WebGLMemoryReporter::AddWebGLContext(this);
+    WebGLMemoryMultiReporterWrapper::AddWebGLContext(this);
 
     mAllowRestore = true;
     mRobustnessTimerRunning = false;
     mDrawSinceRobustnessTimerSet = false;
     mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
     mContextStatus = ContextStable;
     mContextLostErrorSet = false;
     mContextLostDueToTest = false;
 }
 
 WebGLContext::~WebGLContext()
 {
     DestroyResourcesAndContext();
-    WebGLMemoryReporter::RemoveWebGLContext(this);
+    WebGLMemoryMultiReporterWrapper::RemoveWebGLContext(this);
     TerminateRobustnessTimer();
     mContextRestorer = nsnull;
 }
 
 void
 WebGLContext::DestroyResourcesAndContext()
 {
     if (!gl)
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -50,18 +50,18 @@
 
 #include "nsIDocShell.h"
 
 #include "nsIDOMWebGLRenderingContext.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsHTMLCanvasElement.h"
 #include "nsWeakReference.h"
 #include "nsIDOMHTMLElement.h"
+#include "nsIMemoryReporter.h"
 #include "nsIJSNativeInitializer.h"
-#include "nsIMemoryReporter.h"
 #include "nsContentUtils.h"
 
 #include "GLContextProvider.h"
 #include "Layers.h"
 
 #include "CheckedInt.h"
 
 /* 
@@ -509,17 +509,17 @@ struct WebGLContextOptions {
 
 class WebGLContext :
     public nsIDOMWebGLRenderingContext,
     public nsICanvasRenderingContextInternal,
     public nsSupportsWeakReference,
     public nsITimerCallback,
     public WebGLRectangleObject
 {
-    friend class WebGLMemoryReporter;
+    friend class WebGLMemoryMultiReporterWrapper;
     friend class WebGLExtensionLoseContext;
     friend class WebGLContextUserData;
 
 public:
     WebGLContext();
     virtual ~WebGLContext();
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -1050,16 +1050,20 @@ public:
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteBuffers(1, &mGLName);
         free(mData);
         mData = nsnull;
         mByteLength = 0;
         mContext->mBuffers.RemoveElement(mMonotonicHandle);
     }
 
+    size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+        return aMallocSizeOf(this) + aMallocSizeOf(mData);
+    }
+   
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
     GLuint GLName() const { return mGLName; }
     GLuint ByteLength() const { return mByteLength; }
     GLenum Target() const { return mTarget; }
     const void *Data() const { return mData; }
 
     void SetByteLength(GLuint byteLength) { mByteLength = byteLength; }
@@ -1622,16 +1626,22 @@ public:
         mContext->MakeContextCurrent();
         mGLName = mContext->gl->fCreateShader(mType);
         mMonotonicHandle = mContext->mShaders.AppendElement(this);
     }
 
     ~WebGLShader() {
         DeleteOnce();
     }
+    
+    size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) {
+        return aMallocSizeOf(this) +
+               mSource.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
+               mTranslationLog.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    }
 
     void Delete() {
         mSource.Truncate();
         mTranslationLog.Truncate();
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteShader(mGLName);
         mContext->mShaders.RemoveElement(mMonotonicHandle);
     }
@@ -2510,136 +2520,103 @@ WebGLContext::CanGetConcreteObject(const
                               BaseInterfaceType *aInterface,
                               bool *isNull,
                               bool *isDeleted)
 {
     ConcreteObjectType *aConcreteObject;
     return GetConcreteObject(info, aInterface, &aConcreteObject, isNull, isDeleted, false);
 }
 
-class WebGLMemoryReporter
+class WebGLMemoryMultiReporterWrapper
 {
-    WebGLMemoryReporter();
-    ~WebGLMemoryReporter();
-    static WebGLMemoryReporter* sUniqueInstance;
-
-    // here we store plain pointers, not RefPtrs: we don't want the WebGLMemoryReporter unique instance to keep alive all
+    WebGLMemoryMultiReporterWrapper();
+    ~WebGLMemoryMultiReporterWrapper();
+    static WebGLMemoryMultiReporterWrapper* sUniqueInstance;
+
+    // here we store plain pointers, not RefPtrs: we don't want the 
+    // WebGLMemoryMultiReporterWrapper unique instance to keep alive all		
     // WebGLContexts ever created.
     typedef nsTArray<const WebGLContext*> ContextsArrayType;
     ContextsArrayType mContexts;
     
-    nsCOMPtr<nsIMemoryReporter> mTextureMemoryUsageReporter;
-    nsCOMPtr<nsIMemoryReporter> mTextureCountReporter;
-    nsCOMPtr<nsIMemoryReporter> mBufferMemoryUsageReporter;
-    nsCOMPtr<nsIMemoryReporter> mBufferCacheMemoryUsageReporter;
-    nsCOMPtr<nsIMemoryReporter> mBufferCountReporter;
-    nsCOMPtr<nsIMemoryReporter> mRenderbufferMemoryUsageReporter;
-    nsCOMPtr<nsIMemoryReporter> mRenderbufferCountReporter;
-    nsCOMPtr<nsIMemoryReporter> mShaderSourcesSizeReporter;
-    nsCOMPtr<nsIMemoryReporter> mShaderTranslationLogsSizeReporter;
-    nsCOMPtr<nsIMemoryReporter> mShaderCountReporter;
-    nsCOMPtr<nsIMemoryReporter> mContextCountReporter;
-
-    static WebGLMemoryReporter* UniqueInstance();
+    nsCOMPtr<nsIMemoryMultiReporter> mReporter;
+
+    static WebGLMemoryMultiReporterWrapper* UniqueInstance();
 
     static ContextsArrayType & Contexts() { return UniqueInstance()->mContexts; }
 
   public:
 
     static void AddWebGLContext(const WebGLContext* c) {
         Contexts().AppendElement(c);
     }
 
     static void RemoveWebGLContext(const WebGLContext* c) {
         ContextsArrayType & contexts = Contexts();
         contexts.RemoveElement(c);
         if (contexts.IsEmpty()) {
-            delete sUniqueInstance;
+            delete sUniqueInstance; 
             sUniqueInstance = nsnull;
         }
     }
 
     static PRInt64 GetTextureMemoryUsed() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t t = 0; t < contexts[i]->mTextures.Length(); ++t)
-              result += contexts[i]->mTextures[t]->MemoryUsage();
+            for (size_t j = 0; j < contexts[i]->mTextures.Length(); ++j)
+              result += contexts[i]->mTextures[j]->MemoryUsage();
         return result;
     }
 
     static PRInt64 GetTextureCount() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
             result += contexts[i]->mTextures.Length();
         return result;
     }
 
     static PRInt64 GetBufferMemoryUsed() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t b = 0; b < contexts[i]->mBuffers.Length(); ++b)
-                result += contexts[i]->mBuffers[b]->ByteLength();
+            for (size_t j = 0; j < contexts[i]->mBuffers.Length(); ++j)
+                result += contexts[i]->mBuffers[j]->ByteLength();
         return result;
     }
 
-    static PRInt64 GetBufferCacheMemoryUsed() {
-        const ContextsArrayType & contexts = Contexts();
-        PRInt64 result = 0;
-        for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t b = 0; b < contexts[i]->mBuffers.Length(); ++b)
-                if (contexts[i]->mBuffers[b]->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
-                    result += contexts[i]->mBuffers[b]->ByteLength();
-        return result;
-    }
+    static PRInt64 GetBufferCacheMemoryUsed();
 
     static PRInt64 GetBufferCount() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
             result += contexts[i]->mBuffers.Length();
         return result;
     }
 
     static PRInt64 GetRenderbufferMemoryUsed() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t r = 0; r < contexts[i]->mRenderbuffers.Length(); ++r)
-              result += contexts[i]->mRenderbuffers[r]->MemoryUsage();
+            for (size_t j = 0; j < contexts[i]->mRenderbuffers.Length(); ++j)
+              result += contexts[i]->mRenderbuffers[j]->MemoryUsage();
         return result;
     }
 
     static PRInt64 GetRenderbufferCount() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
             result += contexts[i]->mRenderbuffers.Length();
         return result;
     }
 
-    static PRInt64 GetShaderSourcesSize() {
-        const ContextsArrayType & contexts = Contexts();
-        PRInt64 result = 0;
-        for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t s = 0; s < contexts[i]->mShaders.Length(); ++s)
-                result += contexts[i]->mShaders[s]->Source().Length();
-        return result;
-    }
-
-    static PRInt64 GetShaderTranslationLogsSize() {
-        const ContextsArrayType & contexts = Contexts();
-        PRInt64 result = 0;
-        for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t s = 0; s < contexts[i]->mShaders.Length(); ++s)
-                result += contexts[i]->mShaders[s]->TranslationLog().Length();
-        return result;
-    }
+    static PRInt64 GetShaderSize();
 
     static PRInt64 GetShaderCount() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
             result += contexts[i]->mShaders.Length();
         return result;
     }
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/WebGLContextReporter.cpp
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ *
+ * 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
+ * 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 ***** */
+
+#include "WebGLContext.h"
+#include "nsIMemoryReporter.h"
+
+using namespace mozilla;
+
+
+class WebGLMemoryMultiReporter : public nsIMemoryMultiReporter 
+{
+  public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIMEMORYMULTIREPORTER
+};
+
+NS_IMPL_ISUPPORTS1(WebGLMemoryMultiReporter, nsIMemoryMultiReporter)
+
+NS_IMETHODIMP
+WebGLMemoryMultiReporter::GetName(nsACString &aName)
+{
+  aName.AssignLiteral("webgl");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLMemoryMultiReporter::GetExplicitNonHeap(PRInt64 *aAmount)
+{
+    // WebGLMemoryMultiReporterWrapper has no KIND_NONHEAP measurements.
+    *aAmount = 0;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, 
+                                         nsISupports* aClosure)
+{
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-texture-memory"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES,
+        WebGLMemoryMultiReporterWrapper::GetTextureMemoryUsed(),
+        NS_LITERAL_CSTRING("Memory used by WebGL textures.The OpenGL"
+            " implementation is free to store these textures in either video"
+            " memory or main memory. This measurement is only a lower bound,"
+            " actual memory usage may be higher for example if the storage" 
+            " is strided."),  
+        aClosure);
+   
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-texture-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+         WebGLMemoryMultiReporterWrapper::GetTextureCount(), 
+        NS_LITERAL_CSTRING("Number of WebGL textures."), 
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-buffer-memory"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES,
+         WebGLMemoryMultiReporterWrapper::GetBufferMemoryUsed(), 
+        NS_LITERAL_CSTRING("Memory used by WebGL buffers. The OpenGL"
+            " implementation is free to store these buffers in either video"
+            " memory or main memory. This measurement is only a lower bound,"
+            " actual memory usage may be higher for example if the storage"
+            " is strided."),
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("explicit/webgl/buffer-cache-memory"),
+        nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
+        WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed(),
+        NS_LITERAL_CSTRING("Memory used by WebGL buffer caches. The WebGL"
+            " implementation caches the contents of element array buffers"
+            " only.This adds up with the webgl-buffer-memory value, but"
+            " contrary to it, this one represents bytes on the heap,"
+            " not managed by OpenGL."),
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), NS_LITERAL_CSTRING("webgl-buffer-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+        WebGLMemoryMultiReporterWrapper::GetBufferCount(),
+        NS_LITERAL_CSTRING("Number of WebGL buffers."), 
+        aClosure);
+   
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-renderbuffer-memory"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES,
+        WebGLMemoryMultiReporterWrapper::GetRenderbufferMemoryUsed(), 
+        NS_LITERAL_CSTRING("Memory used by WebGL renderbuffers. The OpenGL"
+            " implementation is free to store these renderbuffers in either"
+            " video memory or main memory. This measurement is only a lower"
+            " bound, actual memory usage may be higher for example if the"
+            " storage is strided."),
+        aClosure);
+   
+    aCb->Callback(
+        EmptyCString(),
+        NS_LITERAL_CSTRING("webgl-renderbuffer-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+        WebGLMemoryMultiReporterWrapper::GetRenderbufferCount(),
+        NS_LITERAL_CSTRING("Number of WebGL renderbuffers."),
+        aClosure);
+  
+    aCb->Callback(
+        EmptyCString(),
+        NS_LITERAL_CSTRING("explicit/webgl/shader"),
+        nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
+        WebGLMemoryMultiReporterWrapper::GetShaderSize(), 
+        NS_LITERAL_CSTRING("Combined size of WebGL shader ASCII sources and"
+            " translation logs cached on the heap."), 
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-shader-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+        WebGLMemoryMultiReporterWrapper::GetShaderCount(), 
+        NS_LITERAL_CSTRING("Number of WebGL shaders."), 
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-context-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+        WebGLMemoryMultiReporterWrapper::GetContextCount(), 
+        NS_LITERAL_CSTRING("Number of WebGL contexts."), 
+        aClosure);
+
+    return NS_OK;
+}
+
+WebGLMemoryMultiReporterWrapper* WebGLMemoryMultiReporterWrapper::sUniqueInstance = nsnull;
+
+WebGLMemoryMultiReporterWrapper* WebGLMemoryMultiReporterWrapper::UniqueInstance()
+{
+    if (!sUniqueInstance) {
+        sUniqueInstance = new WebGLMemoryMultiReporterWrapper;
+    }
+    return sUniqueInstance;     
+}
+
+WebGLMemoryMultiReporterWrapper::WebGLMemoryMultiReporterWrapper()
+{ 
+    mReporter = new WebGLMemoryMultiReporter;   
+    NS_RegisterMemoryMultiReporter(mReporter);
+}
+
+WebGLMemoryMultiReporterWrapper::~WebGLMemoryMultiReporterWrapper()
+{
+    NS_UnregisterMemoryMultiReporter(mReporter);
+}
+
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLBufferMallocSizeOfFun, "webgl-buffer")
+
+PRInt64 
+WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed() {
+    const ContextsArrayType & contexts = Contexts();
+    PRInt64 result = 0;
+    for (size_t i = 0; i < contexts.Length(); ++i) {
+        for (size_t j = 0; j < contexts[i]->mBuffers.Length(); ++j) 
+            if (contexts[i]->mBuffers[j]->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
+               result += contexts[i]->mBuffers[j]->SizeOfIncludingThis(WebGLBufferMallocSizeOfFun);
+    }
+    return result;
+}
+
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLShaderMallocSizeOfFun, "webgl-shader")
+
+PRInt64 
+WebGLMemoryMultiReporterWrapper::GetShaderSize() {
+    const ContextsArrayType & contexts = Contexts();
+    PRInt64 result = 0;
+    for (size_t i = 0; i < contexts.Length(); ++i) {
+        for (size_t j = 0; j < contexts[i]->mShaders.Length(); ++j) 
+            result += contexts[i]->mShaders[j]->SizeOfIncludingThis(WebGLShaderMallocSizeOfFun);
+    }
+    return result;
+}
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -1287,54 +1287,53 @@ nsCanvasRenderingContext2DAzure::Initial
   Reset();
 
   NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
   mDocShell = nsnull;
 
   mWidth = width;
   mHeight = height;
 
-  mTarget = target;
+  // This first time this is called on this object is via
+  // nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
+  // non-null, otherwise we'll return an error here and GetContext won't
+  // return this context object and we'll never enter this code again.
+  // All other times this method is called, if target is null then
+  // mTarget won't be changed, i.e. it will remain non-null, or else it
+  // will be set to non-null.
+  // In all cases, any usable canvas context will have non-null mTarget.
+
+  if (target) {
+    mValid = true;
+    mTarget = target;
+  } else {
+    mValid = false;
+  }
 
   mResetLayer = true;
 
-  /* Create dummy surfaces here - target can be null when a canvas was created
-   * that is too large to support.
-   */
-  if (!target)
-  {
-    mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
-    if (!mTarget) {
-      // SupportsAzure() is controlled by the "gfx.canvas.azure.prefer-skia"
-      // pref so that may be the reason rather than an OOM.
-      mValid = false;
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  } else {
-    mValid = true;
-  }
-
   // set up the initial canvas defaults
   mStyleStack.Clear();
   mPathBuilder = nsnull;
   mPath = nsnull;
   mDSPathBuilder = nsnull;
 
   ContextState *state = mStyleStack.AppendElement();
   state->globalAlpha = 1.0;
 
   state->colorStyles[STYLE_FILL] = NS_RGB(0,0,0);
   state->colorStyles[STYLE_STROKE] = NS_RGB(0,0,0);
   state->shadowColor = NS_RGBA(0,0,0,0);
 
-  mTarget->ClearRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
-    
-  // always force a redraw, because if the surface dimensions were reset
-  // then the surface became cleared, and we need to redraw everything.
-  Redraw();
+  if (mTarget) {
+    mTarget->ClearRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
+    // always force a redraw, because if the surface dimensions were reset
+    // then the surface became cleared, and we need to redraw everything.
+    Redraw();
+  }
 
   return mValid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::SetIsOpaque(bool isOpaque)
 {
   if (isOpaque == mOpaque)
--- 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/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -452,16 +452,22 @@ protected:
   void QueueLoadFromSourceTask();
 
   /**
    * Runs the media resource selection algorithm.
    */
   void SelectResource();
 
   /**
+   * A wrapper function that allows us to cleanly reset flags after a call
+   * to SelectResource()
+   */
+  void SelectResourceWrapper();
+
+  /**
    * Asynchronously awaits a stable state, and then causes SelectResource()
    * to be run on the main thread's event loop.
    */
   void QueueSelectResourceTask();
 
   /**
    * The resource-fetch algorithm step of the load algorithm.
    */
@@ -734,16 +740,19 @@ protected:
   // True if we're delaying the "load" event. They are delayed until either
   // an error occurs, or the first frame is loaded.
   bool mDelayingLoadEvent;
 
   // True when we've got a task queued to call SelectResource(),
   // or while we're running SelectResource().
   bool mIsRunningSelectResource;
 
+  // True when we already have select resource call queued
+  bool mHaveQueuedSelectResource;
+
   // True if we suspended the decoder because we were paused,
   // preloading metadata is enabled, autoplay was not enabled, and we loaded
   // the first frame.
   bool mSuspendedAfterFirstFrame;
 
   // True if we are allowed to suspend the decoder because we were paused,
   // preloading metdata was enabled, autoplay was not enabled, and we loaded
   // the first frame.
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -533,16 +533,17 @@ void nsHTMLMediaElement::AbortExistingLo
   }
 
   mError = nsnull;
   mLoadedFirstFrame = false;
   mAutoplaying = true;
   mIsLoadingFromSourceChildren = false;
   mSuspendedAfterFirstFrame = false;
   mAllowSuspendAfterFirstFrame = true;
+  mHaveQueuedSelectResource = false;
   mLoadIsSuspended = false;
   mSourcePointer = nsnull;
 
   // TODO: The playback rate must be set to the default playback rate.
 
   if (mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
     mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
     ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING);
@@ -620,21 +621,21 @@ void nsHTMLMediaElement::QueueLoadFromSo
   ChangeDelayLoadStatus(true);
   mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
   AsyncAwaitStableState(this, &nsHTMLMediaElement::LoadFromSourceChildren);
 }
 
 void nsHTMLMediaElement::QueueSelectResourceTask()
 {
   // Don't allow multiple async select resource calls to be queued.
-  if (mIsRunningSelectResource)
+  if (mHaveQueuedSelectResource)
     return;
-  mIsRunningSelectResource = true;
+  mHaveQueuedSelectResource = true;
   mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE;
-  AsyncAwaitStableState(this, &nsHTMLMediaElement::SelectResource);
+  AsyncAwaitStableState(this, &nsHTMLMediaElement::SelectResourceWrapper);
 }
 
 /* void load (); */
 NS_IMETHODIMP nsHTMLMediaElement::Load()
 {
   if (mIsRunningLoadMethod)
     return NS_OK;
   SetPlayedOrSeeked(false);
@@ -653,69 +654,78 @@ static bool HasSourceChildren(nsIContent
     if (child->IsHTML(nsGkAtoms::source))
     {
       return true;
     }
   }
   return false;
 }
 
+void nsHTMLMediaElement::SelectResourceWrapper()
+{
+  SelectResource();
+  mIsRunningSelectResource = false;
+  mHaveQueuedSelectResource = false;
+}
+
 void nsHTMLMediaElement::SelectResource()
 {
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::src) && !HasSourceChildren(this)) {
     // The media element has neither a src attribute nor any source
     // element children, abort the load.
     mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
     // This clears mDelayingLoadEvent, so AddRemoveSelfReference will be called
     ChangeDelayLoadStatus(false);
-    mIsRunningSelectResource = false;
     return;
   }
 
   ChangeDelayLoadStatus(true);
 
   mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
   // Load event was delayed, and still is, so no need to call
   // AddRemoveSelfReference, since it must still be held
   DispatchAsyncEvent(NS_LITERAL_STRING("loadstart"));
 
+  // Delay setting mIsRunningSeletResource until after UpdatePreloadAction
+  // so that we don't lose our state change by bailing out of the preload
+  // state update
+  UpdatePreloadAction();
+  mIsRunningSelectResource = true;
+
   // If we have a 'src' attribute, use that exclusively.
   nsAutoString src;
   if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
     nsCOMPtr<nsIURI> uri;
     nsresult rv = NewURIFromString(src, getter_AddRefs(uri));
     if (NS_SUCCEEDED(rv)) {
       LOG(PR_LOG_DEBUG, ("%p Trying load from src=%s", this, NS_ConvertUTF16toUTF8(src).get()));
       NS_ASSERTION(!mIsLoadingFromSourceChildren,
         "Should think we're not loading from source children by default");
       mLoadingSrc = uri;
       if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
         // preload:none media, suspend the load here before we make any
         // network requests.
         SuspendLoad();
-        mIsRunningSelectResource = false;
         return;
       }
 
       rv = LoadResource();
       if (NS_SUCCEEDED(rv)) {
-        mIsRunningSelectResource = false;
         return;
       }
     } else {
       const PRUnichar* params[] = { src.get() };
       ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
     }
     NoSupportedMediaSourceError();
   } else {
     // Otherwise, the source elements will be used.
     mIsLoadingFromSourceChildren = true;
     LoadFromSourceChildren();
   }
-  mIsRunningSelectResource = false;
 }
 
 void nsHTMLMediaElement::NotifyLoadError()
 {
   if (!mIsLoadingFromSourceChildren) {
     LOG(PR_LOG_DEBUG, ("NotifyLoadError(), no supported media error"));
     NoSupportedMediaSourceError();
   } else if (mSourceLoadCandidate) {
@@ -1436,16 +1446,17 @@ nsHTMLMediaElement::nsHTMLMediaElement(a
     mMuted(false),
     mPlayingBeforeSeek(false),
     mPausedForInactiveDocument(false),
     mWaitingFired(false),
     mIsRunningLoadMethod(false),
     mIsLoadingFromSourceChildren(false),
     mDelayingLoadEvent(false),
     mIsRunningSelectResource(false),
+    mHaveQueuedSelectResource(false),
     mSuspendedAfterFirstFrame(false),
     mAllowSuspendAfterFirstFrame(true),
     mHasPlayedOrSeeked(false),
     mHasSelfReference(false),
     mShuttingDown(false),
     mLoadIsSuspended(false),
     mMediaSecurityVerified(false),
     mCORSMode(CORS_NONE)
--- a/content/html/content/src/nsHTMLTableElement.cpp
+++ b/content/html/content/src/nsHTMLTableElement.cpp
@@ -896,17 +896,17 @@ nsHTMLTableElement::ParseAttribute(PRInt
                                    nsIAtom* aAttribute,
                                    const nsAString& aValue,
                                    nsAttrValue& aResult)
 {
   /* ignore summary, just a string */
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::cellspacing ||
         aAttribute == nsGkAtoms::cellpadding) {
-      return aResult.ParseSpecialIntValue(aValue);
+      return aResult.ParseNonNegativeIntValue(aValue);
     }
     if (aAttribute == nsGkAtoms::cols ||
         aAttribute == nsGkAtoms::border) {
       return aResult.ParseIntWithBounds(aValue, 0);
     }
     if (aAttribute == nsGkAtoms::height) {
       return aResult.ParseSpecialIntValue(aValue);
     }
@@ -966,29 +966,20 @@ MapAttributesIntoRule(const nsMappedAttr
 
   nsPresContext* presContext = aData->mPresContext;
   nsCompatibility mode = presContext->CompatibilityMode();
 
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TableBorder)) {
     // cellspacing
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellspacing);
     nsCSSValue* borderSpacing = aData->ValueForBorderSpacing();
-    if (value && value->Type() == nsAttrValue::eInteger) {
-      if (borderSpacing->GetUnit() == eCSSUnit_Null) {
-        borderSpacing->
-          SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-      }
-    }
-    else if (value && value->Type() == nsAttrValue::ePercent &&
-             eCompatibility_NavQuirks == mode) {
-      // in quirks mode, treat a % cellspacing value a pixel value.
-      if (borderSpacing->GetUnit() == eCSSUnit_Null) {
-        borderSpacing->
-         SetFloatValue(100.0f * value->GetPercentValue(), eCSSUnit_Pixel);
-      }
+    if (value && value->Type() == nsAttrValue::eInteger &&
+        borderSpacing->GetUnit() == eCSSUnit_Null) {
+      borderSpacing->
+        SetFloatValue(float(value->GetIntegerValue()), eCSSUnit_Pixel);
     }
   }
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Table)) {
     const nsAttrValue* value;
     // layout
     nsCSSValue* tableLayout = aData->ValueForTableLayout();
     if (tableLayout->GetUnit() == eCSSUnit_Null) {
       value = aAttributes->GetAttr(nsGkAtoms::layout);
@@ -1154,49 +1145,39 @@ nsHTMLTableElement::GetAttributeMappingF
 }
 
 static void
 MapInheritedTableAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                     nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Padding)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellpadding);
-    if (value) {
-      nsAttrValue::ValueType valueType = value->Type();
-      if (valueType == nsAttrValue::eInteger ||
-          valueType == nsAttrValue::ePercent) {
-        // We have cellpadding.  This will override our padding values if we
-        // don't have any set.
-        nsCSSValue padVal;
-        if (valueType == nsAttrValue::eInteger)
-          padVal.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-        else {
-          // when we support % cellpadding in standard mode, uncomment the
-          // following
-          float pctVal = value->GetPercentValue();
-          //if (eCompatibility_NavQuirks == mode) {
-          // in quirks mode treat a pct cellpadding value as a pixel value
-          padVal.SetFloatValue(100.0f * pctVal, eCSSUnit_Pixel);
-          //}
-          //else {
-          //  padVal.SetPercentValue(pctVal);
-          //}
-        }
-        nsCSSValue* paddingLeft = aData->ValueForPaddingLeftValue();
-        if (paddingLeft->GetUnit() == eCSSUnit_Null)
-          *paddingLeft = padVal;
-        nsCSSValue* paddingRight = aData->ValueForPaddingRightValue();
-        if (paddingRight->GetUnit() == eCSSUnit_Null)
-          *paddingRight = padVal;
-        nsCSSValue* paddingTop = aData->ValueForPaddingTop();
-        if (paddingTop->GetUnit() == eCSSUnit_Null)
-          *paddingTop = padVal;
-        nsCSSValue* paddingBottom = aData->ValueForPaddingBottom();
-        if (paddingBottom->GetUnit() == eCSSUnit_Null)
-          *paddingBottom = padVal;
+    if (value && value->Type() == nsAttrValue::eInteger) {
+      // We have cellpadding.  This will override our padding values if we
+      // don't have any set.
+      nsCSSValue padVal(float(value->GetIntegerValue()), eCSSUnit_Pixel);
+
+      nsCSSValue* paddingLeft = aData->ValueForPaddingLeftValue();
+      if (paddingLeft->GetUnit() == eCSSUnit_Null) {
+        *paddingLeft = padVal;
+      }
+
+      nsCSSValue* paddingRight = aData->ValueForPaddingRightValue();
+      if (paddingRight->GetUnit() == eCSSUnit_Null) {
+        *paddingRight = padVal;
+      }
+
+      nsCSSValue* paddingTop = aData->ValueForPaddingTop();
+      if (paddingTop->GetUnit() == eCSSUnit_Null) {
+        *paddingTop = padVal;
+      }
+
+      nsCSSValue* paddingBottom = aData->ValueForPaddingBottom();
+      if (paddingBottom->GetUnit() == eCSSUnit_Null) {
+        *paddingBottom = padVal;
       }
     }
   }
 }
 
 nsMappedAttributes*
 nsHTMLTableElement::GetAttributesMappedForCell()
 {
--- a/content/html/content/test/test_fullscreen-api.html
+++ b/content/html/content/test/test_fullscreen-api.html
@@ -65,15 +65,21 @@ function nextTest() {
     gTestIndex++;
   } else {
     SpecialPowers.setBoolPref("full-screen-api.enabled", prevEnabled);
     SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", prevTrusted);	
     SimpleTest.finish();
   }
 }
 
+try {
+  window.fullScreen = true;
+} catch (e) {
+}
+is(window.fullScreen, false, "Shouldn't be able to set window fullscreen from content");
+
 addLoadEvent(nextTest);
 SimpleTest.waitForExplicitFinish();
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -322,17 +322,19 @@ nsresult nsBuiltinDecoder::Seek(double a
   // If the position we want to seek to is not in a seekable range, we seek
   // to the closest position in the seekable ranges instead. If two positions
   // are equally close, we seek to the closest position from the currentTime.
   // See seeking spec, point 7 :
   // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#seeking
   PRInt32 range = 0;
   if (!IsInRanges(seekable, aTime, range)) {
     if (range != -1) {
-      if (range + 1 < length) {
+      // |range + 1| can't be negative, because the only possible negative value
+      // for |range| is -1.
+      if (PRUint32(range + 1) < length) {
         double leftBound, rightBound;
         res = seekable.End(range, &leftBound);
         NS_ENSURE_SUCCESS(res, NS_OK);
         res = seekable.Start(range + 1, &rightBound);
         NS_ENSURE_SUCCESS(res, NS_OK);
         double distanceLeft = NS_ABS(leftBound - aTime);
         double distanceRight = NS_ABS(rightBound - aTime);
         if (distanceLeft == distanceRight) {
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -44,16 +44,17 @@
 #include "nsBuiltinDecoderStateMachine.h"
 #include "mozilla/mozalloc.h"
 #include "VideoUtils.h"
 #include "nsTimeRanges.h"
 #include "nsDeque.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/StdInt.h"
+#include "mozilla/Util.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gBuiltinDecoderLog;
 #define LOG(type, msg) PR_LOG(gBuiltinDecoderLog, type, msg)
 #else
@@ -302,19 +303,18 @@ StateMachineTracker& StateMachineTracker
 }
 
 void StateMachineTracker::EnsureGlobalStateMachine() 
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   ReentrantMonitorAutoEnter mon(mMonitor);
   if (mStateMachineCount == 0) {
     NS_ASSERTION(!mStateMachineThread, "Should have null state machine thread!");
-    nsresult res = NS_NewThread(&mStateMachineThread,
-                                nsnull);
-    NS_ABORT_IF_FALSE(NS_SUCCEEDED(res), "Can't create media state machine thread");
+    DebugOnly<nsresult> rv = NS_NewThread(&mStateMachineThread, nsnull);
+    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Can't create media state machine thread");
   }
   mStateMachineCount++;
 }
 
 #ifdef DEBUG
 bool StateMachineTracker::IsQueued(nsBuiltinDecoderStateMachine* aStateMachine)
 {
   ReentrantMonitorAutoEnter mon(mMonitor);
--- 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/media/test/test_preload_actions.html
+++ b/content/media/test/test_preload_actions.html
@@ -380,42 +380,42 @@ var tests = [
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("canplaythrough", this.canplaythrough, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
       v.preload = "metadata";
     },
   },
-  
   {
-    // 13. Change preload value from metadata to none after load started,
-    // should still load up to metadata, should not halt immediately.
-    loadeddata:
+    // 13. Change preload value from auto to none after specifying a src
+    // should load according to preload none, no buffering should have taken place
+    suspend:
     function(e) {
       var v = e.target;
       is(v._gotLoadStart, true, "(13) Must get loadstart.");
-      is(v._gotLoadedMetaData, true, "(13) Must get loadedmetadata.");
-      ok(v.readyState >= v.HAVE_CURRENT_DATA, "(13) ReadyState must be >= HAVE_CURRENT_DATA.");
-      is(v.networkState, v.NETWORK_IDLE, "(13) NetworkState must be NETWORK_IDLE.");
+      is(v._gotLoadedMetaData, false, "(13) Must not get loadedmetadata.");
+      is(v.readyState, v.HAVE_NOTHING, "(13) ReadyState must be HAVE_NOTHING");
+      is(v.networkState, v.NETWORK_IDLE, "(13) NetworkState must be NETWORK_IDLE");
       maybeFinish(v, 13);
     },
 
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v.preload = "metadata";
-      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.preload = "auto";
+      v.src = test.name;
+      v.preload = "none";
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
-      v.addEventListener("loadeddata", this.loadeddata, false);
-      v.src = test.name; // Causes implicit load.
-      document.body.appendChild(v);
-      v.preload = "none";
-    },
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("suspend", this.suspend, false);
+      document.body.appendChild(v); // Causes implicit load, should load according to preload none
+      var s = document.createElement("source");
+    }
   },
   {
     // 14. Add preload:metadata video with src to document. Play(), should play through.
     loadeddata:
     function(e) {
       var v = e.target;
       is(v._gotLoadStart, true, "(14) Must get loadstart.");
       is(v._gotLoadedMetaData, true, "(14) Must get loadedmetadata.");
@@ -516,17 +516,45 @@ var tests = [
     setup:
     function(v) {
       v.addEventListener("ended", this.ended, false);
       v.preload = "none";
       v.src = test.name; // Schedules async section to continue load algorithm.
       document.body.appendChild(v);
       v.play(); // Should cause preload:none to be overridden.
     },  
+  },
+  {
+    // 19. Set preload='auto' on first video source then switching preload='none' and swapping the video source to another.
+    // The second video should not start playing as it's preload state has been changed to 'none' from 'auto'
+    loadedmetadata: function(e) {
+      var v = e.target;
+      is(v.preload === "auto", true, "(19) preload is initially auto");
+      setTimeout(function() {
+        // set preload state to none and switch video sources
+        v.preload="none";
+        v.src = test.name + "?asdf";
+        setTimeout(function() {
+          is(v.readyState === 0, true, "(19) no buffering has taken place");
+          maybeFinish(v, 19);
+        }, 2000);
+      }, 2000);
+
+    },
+
+    setup:
+    function(v) {
+      var that = this;
+      v.preload = "auto";
+      v.src = test.name;
+      // add a listener for when the video has loaded, so we know preload auto has worked
+      v.addEventListener( "loadedmetadata", this.loadedmetadata, false);
+      document.body.appendChild(v);
     }
+  }
 ];
 
 var iterationCount = 0;
 function startTest(test, token) {
   if (test == tests[0]) {
     ++iterationCount;
   }
   if (iterationCount == 2) {
--- a/content/svg/content/src/SVGPathData.cpp
+++ b/content/svg/content/src/SVGPathData.cpp
@@ -530,36 +530,32 @@ SVGPathData::ToFlattenedPath(const gfxMa
 
   ctx->SetMatrix(aMatrix);
   ConstructPath(ctx);
   ctx->IdentityMatrix();
 
   return ctx->GetFlattenedPath();
 }
 
-static float AngleOfVector(gfxPoint v)
+static double
+AngleOfVector(const gfxPoint& aVector)
 {
   // C99 says about atan2 "A domain error may occur if both arguments are
   // zero" and "On a domain error, the function returns an implementation-
   // defined value". In the case of atan2 the implementation-defined value
   // seems to commonly be zero, but it could just as easily be a NaN value.
   // We specifically want zero in this case, hence the check:
 
-  return (v != gfxPoint(0.0f, 0.0f)) ? atan2(v.y, v.x) : 0.0f;
+  return (aVector != gfxPoint(0.0, 0.0)) ? atan2(aVector.y, aVector.x) : 0.0;
 }
 
-// TODO replace callers with calls to AngleOfVector
-static double
-CalcVectorAngle(double ux, double uy, double vx, double vy)
+static float
+AngleOfVectorF(const gfxPoint& aVector)
 {
-  double ta = atan2(uy, ux);
-  double tb = atan2(vy, vx);
-  if (tb >= ta)
-    return tb-ta;
-  return 2 * M_PI - (ta-tb);
+  return static_cast<float>(AngleOfVector(aVector));
 }
 
 void
 SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
 {
   // This code should assume that ANY type of segment can appear at ANY index.
   // It should also assume that segments such as M and Z can appear in weird
   // places, and repeat multiple times consecutively.
@@ -583,41 +579,41 @@ SVGPathData::GetMarkerPositioningData(ns
     gfxPoint &segStart = prevSegEnd;
     gfxPoint segEnd;
     float segStartAngle, segEndAngle;
 
     switch (segType) // to find segStartAngle, segEnd and segEndAngle
     {
     case nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH:
       segEnd = pathStart;
-      segStartAngle = segEndAngle = AngleOfVector(segEnd - segStart);
+      segStartAngle = segEndAngle = AngleOfVectorF(segEnd - segStart);
       break;
 
     case nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS:
     case nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL:
       if (segType == nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS) {
         segEnd = gfxPoint(mData[i], mData[i+1]);
       } else {
         segEnd = segStart + gfxPoint(mData[i], mData[i+1]);
       }
       pathStart = segEnd;
       // If authors are going to specify multiple consecutive moveto commands
       // with markers, me might as well make the angle do something useful:
-      segStartAngle = segEndAngle = AngleOfVector(segEnd - segStart);
+      segStartAngle = segEndAngle = AngleOfVectorF(segEnd - segStart);
       i += 2;
       break;
 
     case nsIDOMSVGPathSeg::PATHSEG_LINETO_ABS:
     case nsIDOMSVGPathSeg::PATHSEG_LINETO_REL:
       if (segType == nsIDOMSVGPathSeg::PATHSEG_LINETO_ABS) {
         segEnd = gfxPoint(mData[i], mData[i+1]);
       } else {
         segEnd = segStart + gfxPoint(mData[i], mData[i+1]);
       }
-      segStartAngle = segEndAngle = AngleOfVector(segEnd - segStart);
+      segStartAngle = segEndAngle = AngleOfVectorF(segEnd - segStart);
       i += 2;
       break;
 
     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
     {
       gfxPoint cp1, cp2; // control points
       if (segType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS) {
@@ -631,36 +627,36 @@ SVGPathData::GetMarkerPositioningData(ns
       }
       prevCP = cp2;
       if (cp1 == segStart) {
         cp1 = cp2;
       }
       if (cp2 == segEnd) {
         cp2 = cp1;
       }
-      segStartAngle = AngleOfVector(cp1 - segStart);
-      segEndAngle = AngleOfVector(segEnd - cp2);
+      segStartAngle = AngleOfVectorF(cp1 - segStart);
+      segEndAngle = AngleOfVectorF(segEnd - cp2);
       i += 6;
       break;
     }
 
     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
     {
       gfxPoint cp1, cp2; // control points
       if (segType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS) {
         cp1 = gfxPoint(mData[i],   mData[i+1]);
         segEnd = gfxPoint(mData[i+2], mData[i+3]);
       } else {
         cp1 = segStart + gfxPoint(mData[i],   mData[i+1]);
         segEnd = segStart + gfxPoint(mData[i+2], mData[i+3]);
       }
       prevCP = cp1;
-      segStartAngle = AngleOfVector(cp1 - segStart);
-      segEndAngle = AngleOfVector(segEnd - cp1);
+      segStartAngle = AngleOfVectorF(cp1 - segStart);
+      segEndAngle = AngleOfVectorF(segEnd - cp1);
       i += 4;
       break;
     }
 
     case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
     case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
     {
       double rx = mData[i];
@@ -690,17 +686,17 @@ SVGPathData::GetMarkerPositioningData(ns
       }
 
       // Below we have funny interleaving of F.6.6 (Correction of out-of-range
       // radii) and F.6.5 (Conversion from endpoint to center parameterization)
       // which is designed to avoid some unnecessary calculations.
 
       if (rx == 0.0 || ry == 0.0) {
         // F.6.6 step 1 - straight line or coincidental points
-        segStartAngle = segEndAngle = AngleOfVector(segEnd - segStart);
+        segStartAngle = segEndAngle = AngleOfVectorF(segEnd - segStart);
         i += 7;
         break;
       }
       rx = fabs(rx); // F.6.6.1
       ry = fabs(ry);
 
       // F.6.5.1:
       angle = angle * M_PI/180.0;
@@ -731,19 +727,20 @@ SVGPathData::GetMarkerPositioningData(ns
         ry *= s;
         root = 0.0;
       }
 
       double cxp =  root * rx * y1p / ry;  // F.6.5.2
       double cyp = -root * ry * x1p / rx;
 
       double theta, delta;
-      theta = CalcVectorAngle(1.0, 0.0, (x1p-cxp)/rx, (y1p-cyp)/ry); // F.6.5.5
-      delta = CalcVectorAngle((x1p-cxp)/rx, (y1p-cyp)/ry,
-                              (-x1p-cxp)/rx, (-y1p-cyp)/ry);         // F.6.5.6
+      theta = AngleOfVector(gfxPoint((x1p-cxp)/rx, (y1p-cyp)/ry) -   // F.6.5.5
+                            gfxPoint(1.0, 0.0));
+      delta = AngleOfVector(gfxPoint((-x1p-cxp)/rx, (-y1p-cyp)/ry) - // F.6.5.6
+                            gfxPoint((x1p-cxp)/rx, (y1p-cyp)/ry));
       if (!sweepFlag && delta > 0)
         delta -= 2.0 * M_PI;
       else if (sweepFlag && delta < 0)
         delta += 2.0 * M_PI;
 
       double tx1, ty1, tx2, ty2;
       tx1 = -cos(angle)*rx*sin(theta) - sin(angle)*ry*cos(theta);
       ty1 = -sin(angle)*rx*sin(theta) + cos(angle)*ry*cos(theta);
@@ -752,40 +749,40 @@ SVGPathData::GetMarkerPositioningData(ns
 
       if (delta < 0.0f) {
         tx1 = -tx1;
         ty1 = -ty1;
         tx2 = -tx2;
         ty2 = -ty2;
       }
 
-      segStartAngle = atan2(ty1, tx1);
-      segEndAngle = atan2(ty2, tx2);
+      segStartAngle = static_cast<float>(atan2(ty1, tx1));
+      segEndAngle = static_cast<float>(atan2(ty2, tx2));
       i += 7;
       break;
     }
 
     case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
     case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
       if (segType == nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS) {
         segEnd = gfxPoint(mData[i++], segStart.y);
       } else {
         segEnd = segStart + gfxPoint(mData[i++], 0.0f);
       }
-      segStartAngle = segEndAngle = AngleOfVector(segEnd - segStart);
+      segStartAngle = segEndAngle = AngleOfVectorF(segEnd - segStart);
       break;
 
     case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
     case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
       if (segType == nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS) {
         segEnd = gfxPoint(segStart.x, mData[i++]);
       } else {
         segEnd = segStart + gfxPoint(0.0f, mData[i++]);
       }
-      segStartAngle = segEndAngle = AngleOfVector(segEnd - segStart);
+      segStartAngle = segEndAngle = AngleOfVectorF(segEnd - segStart);
       break;
 
     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
     {
       gfxPoint cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ?
                        segStart * 2 - prevCP : segStart;
       gfxPoint cp2;
@@ -798,36 +795,36 @@ SVGPathData::GetMarkerPositioningData(ns
       }
       prevCP = cp2;
       if (cp1 == segStart) {
         cp1 = cp2;
       }
       if (cp2 == segEnd) {
         cp2 = cp1;
       }
-      segStartAngle = AngleOfVector(cp1 - segStart);
-      segEndAngle = AngleOfVector(segEnd - cp2);
+      segStartAngle = AngleOfVectorF(cp1 - segStart);
+      segEndAngle = AngleOfVectorF(segEnd - cp2);
       i += 4;
       break;
     }
 
     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
     case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
     {
       gfxPoint cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ?
                        segStart * 2 - prevCP : segStart;
       gfxPoint cp2;
       if (segType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS) {
         segEnd = gfxPoint(mData[i], mData[i+1]);
       } else {
         segEnd = segStart + gfxPoint(mData[i], mData[i+1]);
       }
       prevCP = cp1;
-      segStartAngle = AngleOfVector(cp1 - segStart);
-      segEndAngle = AngleOfVector(segEnd - cp1);
+      segStartAngle = AngleOfVectorF(cp1 - segStart);
+      segEndAngle = AngleOfVectorF(segEnd - cp1);
       i += 2;
       break;
     }
 
     default:
       // Leave any existing marks in aMarks so we have a visual indication of
       // when things went wrong.
       NS_ABORT_IF_FALSE(false, "Unknown segment type - path corruption?");
@@ -847,17 +844,18 @@ SVGPathData::GetMarkerPositioningData(ns
       } else {
         if (!(segType == nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH &&
               prevSegType == nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH))
           mark.angle = nsSVGUtils::AngleBisect(prevSegEndAngle, segStartAngle);
       }
     }
 
     // Add the mark at the end of this segment, and set its position:
-    if (!aMarks->AppendElement(nsSVGMark(segEnd.x, segEnd.y, 0))) {
+    if (!aMarks->AppendElement(nsSVGMark(static_cast<float>(segEnd.x),
+                                         static_cast<float>(segEnd.y), 0))) {
       aMarks->Clear(); // OOM, so try to free some
       return;
     }
 
     if (segType == nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH &&
         prevSegType != nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH) {
       aMarks->ElementAt(aMarks->Length() - 1).angle =
         //aMarks->ElementAt(pathStartIndex).angle =
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -903,16 +903,25 @@ nsSVGElement::WalkContentStyleRules(nsRu
       animContentStyleRule->RuleMatched();
       aRuleWalker->Forward(animContentStyleRule);
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP_(bool)
+nsSVGElement::IsAttributeMapped(const nsIAtom* name) const
+{
+  if (name == nsGkAtoms::lang) {
+    return true;
+  }
+  return nsSVGElementBase::IsAttributeMapped(name);
+}
+
 // PresentationAttributes-FillStroke
 /* static */ const nsGenericElement::MappedAttributeEntry
 nsSVGElement::sFillStrokeMap[] = {
   { &nsGkAtoms::fill },
   { &nsGkAtoms::fill_opacity },
   { &nsGkAtoms::fill_rule },
   { &nsGkAtoms::stroke },
   { &nsGkAtoms::stroke_dasharray },
@@ -1150,19 +1159,34 @@ MappedAttrParser::ParseMappedAttrValue(n
   if (!mDecl) {
     mDecl = new css::Declaration();
     mDecl->InitializeEmpty();
   }
 
   // Get the nsCSSProperty ID for our mapped attribute.
   nsCSSProperty propertyID =
     nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName));
-  bool changed; // outparam for ParseProperty. (ignored)
-  mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
-                        mNodePrincipal, mDecl, &changed, false);
+  if (propertyID != eCSSProperty_UNKNOWN) {
+    bool changed; // outparam for ParseProperty. (ignored)
+    mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
+                          mNodePrincipal, mDecl, &changed, false);
+    return;
+  }
+  NS_ABORT_IF_FALSE(aMappedAttrName == nsGkAtoms::lang,
+                    "Only 'lang' should be unrecognized!");
+  // nsCSSParser doesn't know about 'lang', so we need to handle it specially.
+  if (aMappedAttrName == nsGkAtoms::lang) {
+    propertyID = eCSSProperty__x_lang;
+    nsCSSExpandedDataBlock block;
+    mDecl->ExpandTo(&block);
+    nsCSSValue cssValue(PromiseFlatString(aMappedAttrValue), eCSSUnit_Ident);
+    block.AddLonghandProperty(propertyID, cssValue);
+    mDecl->ValueAppended(propertyID);
+    mDecl->CompressFrom(&block);
+  }
 }
 
 already_AddRefed<css::StyleRule>
 MappedAttrParser::CreateStyleRule()
 {
   if (!mDecl) {
     return nsnull; // No mapped attributes were parsed
   }
@@ -1198,16 +1222,26 @@ nsSVGElement::UpdateContentStyleRule()
   MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
                                     GetBaseURI(), NodePrincipal());
 
   for (PRUint32 i = 0; i < attrCount; ++i) {
     const nsAttrName* attrName = mAttrsAndChildren.AttrNameAt(i);
     if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom()))
       continue;
 
+    if (attrName->NamespaceID() != kNameSpaceID_None &&
+        !attrName->Equals(nsGkAtoms::lang, kNameSpaceID_XML)) {
+      continue;
+    }
+
+    if (attrName->Equals(nsGkAtoms::lang, kNameSpaceID_None) &&
+        HasAttr(kNameSpaceID_XML, nsGkAtoms::lang)) {
+      continue; // xml:lang has precedence
+    }
+
     if (Tag() == nsGkAtoms::svg) {
       // Special case: we don't want <svg> 'width'/'height' mapped into style
       // if the attribute value isn't a valid <length> according to SVG (which
       // only supports a subset of the CSS <length> values). We don't enforce
       // this by checking the attribute value in nsSVGSVGElement::
       // IsAttributeMapped since we don't want that method to depend on the
       // value of the attribute that is being checked. Rather we just prevent
       // the actual mapping here, as necessary.
@@ -1481,17 +1515,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
@@ -119,16 +119,18 @@ public:
 
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
 
   virtual bool IsNodeOfType(PRUint32 aFlags) const;
 
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
 
+  NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
+
   static const MappedAttributeEntry sFillStrokeMap[];
   static const MappedAttributeEntry sGraphicsMap[];
   static const MappedAttributeEntry sTextContentElementsMap[];
   static const MappedAttributeEntry sFontSpecificationMap[];
   static const MappedAttributeEntry sGradientStopMap[];
   static const MappedAttributeEntry sViewportsMap[];
   static const MappedAttributeEntry sMarkersMap[];
   static const MappedAttributeEntry sColorMap[];
@@ -146,21 +148,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;
@@ -203,32 +230,32 @@ public:
   void DidChangePointList(const nsAttrValue& aEmptyOrOldValue);
   void DidChangePathSegList(const nsAttrValue& aEmptyOrOldValue);
   void DidChangeTransformList(const nsAttrValue& aEmptyOrOldValue);
   void DidChangeString(PRUint8 aAttrEnum) {}
   void DidChangeStringList(bool aIsConditionalProcessingAttribute,
                            PRUint8 aAttrEnum,
                            const nsAttrValue& aEmptyOrOldValue);
 
-  virtual void DidAnimateLength(PRUint8 aAttrEnum);
-  virtual void DidAnimateNumber(PRUint8 aAttrEnum);
-  virtual void DidAnimateNumberPair(PRUint8 aAttrEnum);
-  virtual void DidAnimateInteger(PRUint8 aAttrEnum);
-  virtual void DidAnimateIntegerPair(PRUint8 aAttrEnum);
-  virtual void DidAnimateAngle(PRUint8 aAttrEnum);
-  virtual void DidAnimateBoolean(PRUint8 aAttrEnum);
-  virtual void DidAnimateEnum(PRUint8 aAttrEnum);
-  virtual void DidAnimateViewBox();
-  virtual void DidAnimatePreserveAspectRatio();
-  virtual void DidAnimateNumberList(PRUint8 aAttrEnum);
-  virtual void DidAnimateLengthList(PRUint8 aAttrEnum);
-  virtual void DidAnimatePointList();
-  virtual void DidAnimatePathSegList();
-  virtual void DidAnimateTransformList();
-  virtual void DidAnimateString(PRUint8 aAttrEnum);
+  void DidAnimateLength(PRUint8 aAttrEnum);
+  void DidAnimateNumber(PRUint8 aAttrEnum);
+  void DidAnimateNumberPair(PRUint8 aAttrEnum);
+  void DidAnimateInteger(PRUint8 aAttrEnum);
+  void DidAnimateIntegerPair(PRUint8 aAttrEnum);
+  void DidAnimateAngle(PRUint8 aAttrEnum);
+  void DidAnimateBoolean(PRUint8 aAttrEnum);
+  void DidAnimateEnum(PRUint8 aAttrEnum);
+  void DidAnimateViewBox();
+  void DidAnimatePreserveAspectRatio();
+  void DidAnimateNumberList(PRUint8 aAttrEnum);
+  void DidAnimateLengthList(PRUint8 aAttrEnum);
+  void DidAnimatePointList();
+  void DidAnimatePathSegList();
+  void DidAnimateTransformList();
+  void DidAnimateString(PRUint8 aAttrEnum);
 
   nsSVGLength2* GetAnimatedLength(const nsIAtom *aAttrName);
   void GetAnimatedLengthValues(float *aFirst, ...);
   void GetAnimatedNumberValues(float *aFirst, ...);
   void GetAnimatedIntegerValues(PRInt32 *aFirst, ...);
   SVGAnimatedNumberList* GetAnimatedNumberList(PRUint8 aAttrEnum);
   SVGAnimatedNumberList* GetAnimatedNumberList(nsIAtom *aAttrName);
   void GetAnimatedLengthListValues(SVGUserUnitList *aFirst, ...);
--- 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;