Merge m-c to fx-team
authorPanos Astithas <past@mozilla.com>
Thu, 21 Jun 2012 10:11:14 +0300
changeset 101932 df2e5f99504a2e465d4f05f561c6f7f467fafc06
parent 101931 32975daf82d78efa6aafd7d00ef38ccec0b18161 (current diff)
parent 101921 4d0aa137268bb5f8b109198d064453d6ecb751a6 (diff)
child 101933 9ce5e415d5da386955d6ad4552c8586f8aae6e54
child 102147 1b472fa5c8a47aab6d65b24c253f99e3b5339c68
push id1316
push userakeybl@mozilla.com
push dateMon, 27 Aug 2012 22:37:00 +0000
treeherdermozilla-beta@db4b09302ee2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone16.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 m-c to fx-team
dom/indexedDB/test/unit/test_writer_starvation.js
layout/reftests/svg/dynamic-use-nested-01.svg
mobile/android/base/resources/layout-sw600dp/tabs_panel.xml
mobile/android/base/resources/layout-xlarge/tabs_panel.xml
mobile/android/chrome/content/browser.js
modules/libpref/src/init/all.js
testing/marionette/components/marionettecomponent.js
toolkit/themes/winstripe/global/arrow/panelarrow-down-aero.png
toolkit/themes/winstripe/global/arrow/panelarrow-down.png
toolkit/themes/winstripe/global/arrow/panelarrow-horiz-aero.png
toolkit/themes/winstripe/global/arrow/panelarrow-horiz.png
toolkit/themes/winstripe/global/arrow/panelarrow-up-aero.png
toolkit/themes/winstripe/global/arrow/panelarrow-up.png
toolkit/themes/winstripe/global/popup-aero.css
toolkit/xre/nsAppData.cpp
--- a/Makefile.in
+++ b/Makefile.in
@@ -161,16 +161,17 @@ ifdef USE_ELF_HACK
 endif
 	echo building symbol store
 	$(RM) -r $(DIST)/crashreporter-symbols
 	$(RM) "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
 	$(NSINSTALL) -D $(DIST)/crashreporter-symbols
 	OBJCOPY="$(OBJCOPY)" \
 	$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/symbolstore.py \
 	  $(MAKE_SYM_STORE_ARGS)                                          \
+	  --exclude="*test*" --exclude="*Test*"                           \
 	  $(foreach dir,$(SYM_STORE_SOURCE_DIRS),-s $(dir))               \
 	  $(DUMP_SYMS_BIN)                                                \
 	  $(DIST)/crashreporter-symbols                                   \
 	  $(MAKE_SYM_STORE_PATH) >                                        \
 	  $(DIST)/crashreporter-symbols/$(SYMBOL_INDEX_NAME)
 	echo packing symbols
 	$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
 	cd $(DIST)/crashreporter-symbols && \
--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -83,17 +83,17 @@ AccEvent::CreateXPCOMObject()
   nsAccEvent* event = new nsAccEvent(this);
   NS_IF_ADDREF(event);
   return event;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccEvent cycle collection
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(AccEvent)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(AccEvent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAccessible)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(AccEvent)
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAccessible");
   cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mAccessible));
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -51,17 +51,17 @@ NotificationController::~NotificationCon
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector: AddRef/Release and cycle collection
 
 NS_IMPL_ADDREF(NotificationController)
 NS_IMPL_RELEASE(NotificationController)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(NotificationController)
   if (tmp->mDocument)
     tmp->Shutdown();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(NotificationController)
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDocument");
@@ -807,17 +807,17 @@ NotificationController::ContentInsertion
     }
 
     node = node->GetNextSibling();
   }
 
   return haveToUpdate;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController::ContentInsertion)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController::ContentInsertion)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(NotificationController::ContentInsertion)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContainer)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(NotificationController::ContentInsertion)
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mContainer");
   cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mContainer.get()));
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -58,16 +58,17 @@
 #include "nsIObserverService.h"
 #include "nsLayoutUtils.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsISupportsUtils.h"
 #include "nsObjectFrame.h"
 #include "nsTextFragment.h"
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Util.h"
 
 #ifdef MOZ_XUL
 #include "XULAlertAccessible.h"
 #include "XULColorPickerAccessible.h"
 #include "XULComboboxAccessible.h"
 #include "XULElementAccessibles.h"
@@ -1814,13 +1815,35 @@ nsAccessibilityService::CreateAccessible
   return accessible;
 }
 #endif
 
 ////////////////////////////////////////////////////////////////////////////////
 // Services
 ////////////////////////////////////////////////////////////////////////////////
 
-mozilla::a11y::FocusManager*
-mozilla::a11y::FocusMgr()
+namespace mozilla {
+namespace a11y {
+
+FocusManager*
+FocusMgr()
 {
   return nsAccessibilityService::gAccessibilityService;
 }
+
+EPlatformDisabledState
+PlatformDisabledState()
+{
+  static int disabledState = 0xff;
+
+  if (disabledState == 0xff) {
+    disabledState = Preferences::GetInt("accessibility.force_disabled", 0);
+    if (disabledState < ePlatformIsForceEnabled)
+      disabledState = ePlatformIsForceEnabled;
+    else if (disabledState > ePlatformIsDisabled)
+      disabledState = ePlatformIsDisabled;
+  }
+
+  return (EPlatformDisabledState)disabledState;
+}
+
+}
+}
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -21,16 +21,27 @@ class nsITreeView;
 namespace mozilla {
 namespace a11y {
 
 /**
  * Return focus manager.
  */
 FocusManager* FocusMgr();
 
+enum EPlatformDisabledState {
+  ePlatformIsForceEnabled = -1,
+  ePlatformIsEnabled = 0,
+  ePlatformIsDisabled = 1
+};
+
+/**
+ * Return the platform disabled state.
+ */
+EPlatformDisabledState PlatformDisabledState();
+
 #ifdef MOZ_ACCESSIBILITY_ATK
 /**
  * Perform initialization that should be done as soon as possible, in order
  * to minimize startup time.
  * XXX: this function and the next defined in ApplicationAccessibleWrap.cpp
  */
 void PreInit();
 #endif
--- a/accessible/src/base/nsAccessiblePivot.cpp
+++ b/accessible/src/base/nsAccessiblePivot.cpp
@@ -150,32 +150,36 @@ nsAccessiblePivot::SetTextRange(nsIAcces
   NS_ENSURE_ARG(aTextAccessible);
 
   // Check that start offset is smaller than end offset, and that if a value is
   // smaller than 0, both should be -1.
   NS_ENSURE_TRUE(aStartOffset <= aEndOffset &&
                  (aStartOffset >= 0 || (aStartOffset != -1 && aEndOffset != -1)),
                  NS_ERROR_INVALID_ARG);
 
-  nsRefPtr<HyperTextAccessible> newPosition = do_QueryObject(aTextAccessible);
+  nsRefPtr<Accessible> acc(do_QueryObject(aTextAccessible));
+  if (!acc)
+    return NS_ERROR_INVALID_ARG;
+
+  HyperTextAccessible* newPosition = acc->AsHyperText();
   if (!newPosition || !IsRootDescendant(newPosition))
     return NS_ERROR_INVALID_ARG;
 
   // Make sure the given offsets don't exceed the character count.
   PRInt32 charCount = newPosition->CharacterCount();
 
   if (aEndOffset > charCount)
     return NS_ERROR_FAILURE;
 
   PRInt32 oldStart = mStartOffset, oldEnd = mEndOffset;
   mStartOffset = aStartOffset;
   mEndOffset = aEndOffset;
 
   nsRefPtr<Accessible> oldPosition = mPosition.forget();
-  mPosition = newPosition.forget();
+  mPosition = newPosition;
 
   NotifyOfPivotChange(oldPosition, oldStart, oldEnd);
 
   return NS_OK;
 }
 
 // Traversal functions
 
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -487,10 +487,17 @@ PRUint32 nsTextEquivUtils::gRoleToNameRu
   eNoRule,           // ROLE_CALENDAR
   eNoRule,           // ROLE_COMBOBOX_LIST
   eFromSubtree,      // ROLE_COMBOBOX_OPTION
   eNoRule,           // ROLE_IMAGE_MAP
   eFromSubtree,      // ROLE_OPTION
   eFromSubtree,      // ROLE_RICH_OPTION
   eNoRule,           // ROLE_LISTBOX
   eNoRule,           // ROLE_FLAT_EQUATION
-  eFromSubtree       // ROLE_GRID_CELL
+  eFromSubtree,      // ROLE_GRID_CELL
+  eNoRule,           // ROLE_EMBEDDED_OBJECT
+  eFromSubtree,      // ROLE_NOTE
+  eNoRule,           // ROLE_FIGURE
+  eFromSubtree,      // ROLE_CHECK_RICH_OPTION
+  eFromSubtreeIfRec, // ROLE_DEFINITION_LIST
+  eFromSubtree,      // ROLE_TERM
+  eFromSubtree       // ROLE_DEFINITION
 };
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -106,17 +106,17 @@ NS_IMPL_RELEASE_INHERITED(Accessible, ns
 nsresult
 Accessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
 {
   // Custom-built QueryInterface() knows when we support nsIAccessibleSelectable
   // based on role attribute and aria-multiselectable
   *aInstancePtr = nsnull;
 
   if (aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
-    *aInstancePtr = &NS_CYCLE_COLLECTION_NAME(Accessible);
+    *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(Accessible);
     return NS_OK;
   }
 
   if (aIID.Equals(NS_GET_IID(nsIAccessible))) {
     *aInstancePtr = static_cast<nsIAccessible*>(this);
     NS_ADDREF_THIS();
     return NS_OK;
   }
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -50,22 +50,16 @@ HyperTextAccessible::
 NS_IMPL_ADDREF_INHERITED(HyperTextAccessible, AccessibleWrap)
 NS_IMPL_RELEASE_INHERITED(HyperTextAccessible, AccessibleWrap)
 
 nsresult
 HyperTextAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
 {
   *aInstancePtr = nsnull;
 
-  if (aIID.Equals(NS_GET_IID(HyperTextAccessible))) {
-    *aInstancePtr = static_cast<HyperTextAccessible*>(this);
-    NS_ADDREF_THIS();
-    return NS_OK;
-  }
-
   // ARIA roles that these interfaces are not appropriate for.
   if (!IsTextRole())
     return Accessible::QueryInterface(aIID, aInstancePtr);
 
   if (aIID.Equals(NS_GET_IID(nsIAccessibleText))) {
     *aInstancePtr = static_cast<nsIAccessibleText*>(this);
     NS_ADDREF_THIS();
     return NS_OK;
--- a/accessible/src/generic/HyperTextAccessible.h
+++ b/accessible/src/generic/HyperTextAccessible.h
@@ -19,41 +19,32 @@
 enum EGetTextType { eGetBefore=-1, eGetAt=0, eGetAfter=1 };
 
 // This character marks where in the text returned via nsIAccessibleText(),
 // that embedded object characters exist
 const PRUnichar kEmbeddedObjectChar = 0xfffc;
 const PRUnichar kImaginaryEmbeddedObjectChar = ' ';
 const PRUnichar kForcedNewLineChar = '\n';
 
-#define NS_HYPERTEXTACCESSIBLE_IMPL_CID                 \
-{  /* 245f3bc9-224f-4839-a92e-95239705f30b */           \
-  0x245f3bc9,                                           \
-  0x224f,                                               \
-  0x4839,                                               \
-  { 0xa9, 0x2e, 0x95, 0x23, 0x97, 0x05, 0xf3, 0x0b }    \
-}
-
 /**
   * Special Accessible that knows how contain both text and embedded objects
   */
 class HyperTextAccessible : public AccessibleWrap,
                             public nsIAccessibleText,
                             public nsIAccessibleHyperText,
                             public nsIAccessibleEditableText
 {
 public:
   HyperTextAccessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~HyperTextAccessible() { }
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLETEXT
   NS_DECL_NSIACCESSIBLEHYPERTEXT
   NS_DECL_NSIACCESSIBLEEDITABLETEXT
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_HYPERTEXTACCESSIBLE_IMPL_CID)
 
   // Accessible
   virtual PRInt32 GetLevelInternal();
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
 
@@ -405,19 +396,16 @@ protected:
 
 private:
   /**
    * End text offsets array.
    */
   nsTArray<PRUint32> mOffsets;
 };
 
-NS_DEFINE_STATIC_IID_ACCESSOR(HyperTextAccessible,
-                              NS_HYPERTEXTACCESSIBLE_IMPL_CID)
-
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible downcasting method
 
 inline HyperTextAccessible*
 Accessible::AsHyperText()
 {
   return mFlags & eHyperTextAccessible ?
--- a/accessible/src/html/HTMLFormControlAccessible.cpp
+++ b/accessible/src/html/HTMLFormControlAccessible.cpp
@@ -319,19 +319,18 @@ HTMLButtonAccessible::IsWidget() const
 ////////////////////////////////////////////////////////////////////////////////
 
 HTMLTextFieldAccessible::
   HTMLTextFieldAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc)
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED3(HTMLTextFieldAccessible,
-                             Accessible,
-                             HyperTextAccessible,
+NS_IMPL_ISUPPORTS_INHERITED2(HTMLTextFieldAccessible,
+                             Accessible,                             
                              nsIAccessibleText,
                              nsIAccessibleEditableText)
 
 role
 HTMLTextFieldAccessible::NativeRole()
 {
   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                             nsGkAtoms::password, eIgnoreCase)) {
--- a/accessible/src/mac/ApplicationAccessibleWrap.mm
+++ b/accessible/src/mac/ApplicationAccessibleWrap.mm
@@ -8,22 +8,24 @@
 
 #include "ApplicationAccessibleWrap.h"
 
 #include "nsAppShell.h"
 
 namespace mozilla {
 namespace a11y {
 
+// Mac a11y whitelisting
 static bool sA11yShouldBeEnabled = false;
 
 bool
 ShouldA11yBeEnabled()
 {
-  return sA11yShouldBeEnabled;
+  EPlatformDisabledState disabledState = PlatformDisabledState();
+  return (disabledState == ePlatformIsForceEnabled) || ((disabledState == ePlatformIsEnabled) && sA11yShouldBeEnabled);
 }
 
 }
 }
 
 @interface GeckoNSApplication(a11y)
 -(void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute;
 @end
--- a/accessible/src/mac/mozTextAccessible.mm
+++ b/accessible/src/mac/mozTextAccessible.mm
@@ -52,17 +52,17 @@ ToNSString(id aValue)
 
 @implementation mozTextAccessible
 
 - (id)initWithAccessible:(AccessibleWrap*)accessible
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
   if ((self = [super initWithAccessible:accessible])) {
-    CallQueryInterface(accessible, &mGeckoTextAccessible);
+    mGeckoTextAccessible = accessible->AsHyperText();
     CallQueryInterface(accessible, &mGeckoEditableTextAccessible);
   }
   return self;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (BOOL)accessibilityIsIgnored
@@ -307,17 +307,17 @@ ToNSString(id aValue)
 
   return nil;
 }
 
 - (void)expire
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
-  NS_IF_RELEASE(mGeckoTextAccessible);
+  mGeckoTextAccessible = nsnull;
   NS_IF_RELEASE(mGeckoEditableTextAccessible);
   [super expire];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 #pragma mark -
 
--- a/accessible/src/xforms/nsXFormsFormControlsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsFormControlsAccessible.cpp
@@ -114,19 +114,18 @@ nsXFormsTriggerAccessible::DoAction(PRUi
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXFormsInputAccessible::
   nsXFormsInputAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   nsXFormsEditableAccessible(aContent, aDoc)
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED3(nsXFormsInputAccessible,
+NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsInputAccessible,
                              Accessible,
-                             HyperTextAccessible,
                              nsIAccessibleText,
                              nsIAccessibleEditableText)
 
 role
 nsXFormsInputAccessible::NativeRole()
 {
   return roles::ENTRY;
 }
--- a/accessible/src/xul/XULFormControlAccessible.cpp
+++ b/accessible/src/xul/XULFormControlAccessible.cpp
@@ -680,19 +680,18 @@ XULToolbarSeparatorAccessible::NativeSta
 ////////////////////////////////////////////////////////////////////////////////
 
 XULTextFieldAccessible::
  XULTextFieldAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  HyperTextAccessibleWrap(aContent, aDoc)
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED3(XULTextFieldAccessible,
+NS_IMPL_ISUPPORTS_INHERITED2(XULTextFieldAccessible,
                              Accessible,
-                             HyperTextAccessible,
                              nsIAccessibleText,
                              nsIAccessibleEditableText)
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTextFieldAccessible: nsIAccessible
 
 void
 XULTextFieldAccessible::Value(nsString& aValue)
--- a/accessible/tests/mochitest/attributes/test_text.html
+++ b/accessible/tests/mochitest/attributes/test_text.html
@@ -302,16 +302,34 @@
         "text-line-through-style": "solid",
         "text-line-through-color": gComputedStyle.color
       };
       testTextAttrs(ID, 110, attrs, defAttrs, 109, 122);
 
       attrs = {};
       testTextAttrs(ID, 123, attrs, defAttrs, 122, 130);
 
+      attrs = {
+        "text-line-through-style": "solid",
+        "text-line-through-color": gComputedStyle.color
+      };
+      testTextAttrs(ID, 131, attrs, defAttrs, 130, 143);
+
+      attrs = {};
+      testTextAttrs(ID, 144, attrs, defAttrs, 143, 151);
+
+      attrs = {
+        "text-line-through-style": "solid",
+        "text-line-through-color": gComputedStyle.color
+      };
+      testTextAttrs(ID, 152, attrs, defAttrs, 151, 164);
+
+      attrs = {};
+      testTextAttrs(ID, 165, attrs, defAttrs, 164, 172);
+
       //////////////////////////////////////////////////////////////////////////
       // area10, different single style spans in non-styled paragraph
       ID = "area10";
       defAttrs = buildDefaultTextAttrs(ID, "12pt");
       testDefaultTextAttrs(ID, defAttrs);
 
       attrs = {};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 7);
@@ -616,16 +634,18 @@
 
   <p id="area9" style="font-size: smaller">Small
     <span style="font-size: 120%">bigger</span> smaller
     <span style="background-color: blue;">background blue</span> normal
     <span style="font-style: italic;">Different styling</span> normal
     <span style="font-family: monospace;">Different font</span> normal
     <span style="text-decoration: underline;">underlined</span> normal
     <span style="text-decoration: line-through;">strikethrough</span> normal
+    <s>strikethrough</s> normal
+    <strike>strikethrough</strike> normal
   </p>
 
   <p id="area10">Normal
     <span style="font-size: 120%">bigger</span> smaller
     <span style="background-color: blue;">background blue</span> normal
     <span style="font-style: italic;">Different styling</span> normal
     <span style="font-family: monospace;">Different font</span> normal
     <span style="text-decoration: underline;">underlined</span> normal
--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -112,17 +112,16 @@ if [ "$COMPILER_DEPEND" = "" -a "$MOZ_NA
     config/mkdepend/Makefile
   "
 fi
 
 if [ "$ENABLE_MARIONETTE" ]; then
   add_makefiles "
     testing/marionette/Makefile
     testing/marionette/components/Makefile
-    testing/marionette/tests/Makefile
   "
 fi
 
 if [ "$ENABLE_TESTS" ]; then
   add_makefiles "
     build/autoconf/test/Makefile
     config/makefiles/test/Makefile
     config/tests/makefiles/autodeps/Makefile
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/unload.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/unload.js
@@ -1,11 +1,28 @@
-/* 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/. */
+// Copyright (c) 2009 Thomas Robinson <tlrobinson.net>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation files
+// (the “Software”), to deal in the Software without restriction,
+// including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software,
+// and to permit persons to whom the Software is furnished to do so,
+// subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 // This module was taken from narwhal:
 //
 // http://narwhaljs.org
 
 var observers = [];
 
 exports.when = function (observer) {
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -1671,28 +1671,28 @@ richlistitem[type~="action"][actiontype=
 }
 
 /* Implements editBookmarkPanel resizing on folderTree un-collapse. */
 #editBMPanel_folderTree {
   min-width: 27em;
 }
 
 .panel-promo-box {
-  margin: 16px 0 -2px;
+  margin: 10px -10px -10px;
+  padding: 8px 10px;
+  border-top: 1px solid ThreeDShadow;
+  background-image: -moz-linear-gradient(hsla(0,0%,0%,.15), hsla(0,0%,0%,.08) 6px);
+  border-bottom-left-radius: 3px;
+  border-bottom-right-radius: 3px;
 }
 
 @media (-moz-windows-default-theme) {
   .panel-promo-box {
-    margin: 8px -16px -16px;
-    padding: 8px 16px;
-%ifndef WINSTRIPE_AERO
-    border-bottom-left-radius: 6px;
-    border-bottom-right-radius: 6px;
-%endif
-    background-color: #f1f5fb;
+    border-top-style: none;
+    background: #f1f5fb;
     color: GrayText;
     box-shadow: 0px 1px 2px rgb(204,214,234) inset;
   }
 }
 
 .panel-promo-icon {
   list-style-image: url("chrome://browser/skin/sync-notification-24.png");
   -moz-margin-end: 10px;
--- a/browser/themes/winstripe/downloads/downloads-aero.css
+++ b/browser/themes/winstripe/downloads/downloads-aero.css
@@ -1,20 +1,16 @@
 /* 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/. */
 
 %define WINSTRIPE_AERO
 %include downloads.css
 %undef WINSTRIPE_AERO
 
-#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent > .panel-inner-arrowcontent {
-  padding: 0;
-}
-
 @media (-moz-windows-default-theme) {
   #downloadsPanel[hasdownloads] > #downloadsHistory {
     background-color: #f1f5fb;
   }
 
   richlistitem[type="download"] {
     border: 1px solid transparent;
     border-bottom: 1px solid hsl(213,40%,90%);
--- a/browser/themes/winstripe/downloads/downloads.css
+++ b/browser/themes/winstripe/downloads/downloads.css
@@ -11,21 +11,16 @@
   border-bottom-right-radius: 6px;
 }
 
 #downloadsPanel:not([hasdownloads]) > #downloadsHistory,
 #downloadsPanel:not([hasdownloads]) > #downloadsHistory:-moz-focusring > .button-box  {
   border-top-left-radius: 6px;
   border-top-right-radius: 6px;
 }
-
-#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
-  /* Avoid that the arrow overlaps the selection on first item */
-  padding-top: 5px;
-}
 %endif
 
 #downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
 }
 
 #downloadsListBox {
   width: 60ch;
--- a/build/autoconf/acoutput-fast.pl
+++ b/build/autoconf/acoutput-fast.pl
@@ -134,17 +134,17 @@ foreach $ac_file (@makefiles) {
   if (-e $ac_file) {
     next if -M _ < -M $ac_file_in;
     print STDERR "updating $ac_file\n";
   } else {
     print STDERR "creating $ac_file\n";
   }
 
   open (INFILE, "<$ac_file_in")
-    or ( warn "can't read $ac_file_in: No such file or directory\n" and next);
+    or ( die "can't read $ac_file_in: No such file or directory\n");
   open (OUTFILE, ">$ac_file")
     or ( warn "Unable to create $ac_file\n" and next);
 
   while (<INFILE>) {
     #if (/\@[_a-zA-Z]*\@.*\@[_a-zA-Z]*\@/) {
     #  warn "Two defines on a line:$ac_file:$.:$_";
     #  push @unhandled, $ac_file;
     #  last;
--- a/build/autoconf/mozconfig2client-mk
+++ b/build/autoconf/mozconfig2client-mk
@@ -6,87 +6,77 @@
 
 # mozconfig2client-mk - Translates .mozconfig into options for client.mk.
 #    Prints defines to stdout.
 #
 # See mozconfig2configure for more details
 
 print_header() {
   _mozconfig=${MOZCONFIG:-$HOME/.mozconfig}
-  cat >> $tmp_file <<EOF
+  cat <<EOF
 # gmake
 # This file is automatically generated for client.mk.
 # Do not edit. Edit $_mozconfig instead.
 
 EOF
 }
 
 ac_add_options() {
-  echo "# $* is used by configure (not client.mk)" >> $tmp_file
+  echo "# $* is used by configure (not client.mk)"
 }
 
 ac_add_app_options() {
-  echo "# $* is used by configure (not client.mk)" >> $tmp_file
+  echo "# $* is used by configure (not client.mk)"
 }
 
 mk_add_options() {
   for _opt
   do
     # Escape shell characters, space, tab, dollar, quote, backslash,
     # and substitute '@<word>@' with '$(<word>)'.
     _opt=`echo "$_opt" | sed -e 's/\([\"\\]\)/\\\1/g; s/@\([^@]*\)@/\$(\1)/g;'`
     echo $_opt;
     opts="${opts:+$opts^}$_opt";
-  done >> $tmp_file
+  done
 }
 
 mk_echo_options() {
-  echo "Adding client.mk options from $FOUND_MOZCONFIG:"
+  echo "Adding client.mk options from $FOUND_MOZCONFIG:" >&2
   IFS=^
   for _opt in $opts; do
-    echo "    $_opt"
+    echo "    $_opt" >&2
   done
 }
 
 # Main
 #--------------------------------------------------
 
 scriptdir=`dirname $0`
 topsrcdir=$1
-out_file=$2
-tmp_file="$out_file-tmp$$"
 opts=""
 
-trap "rm -f $tmp_file; exit 1" 1 2 15
-
-print_header > $tmp_file
+print_header
 
 # If the path changes, configure should be rerun
-echo "# PATH=$PATH" >> $tmp_file
+echo "# PATH=$PATH"
 
 # If FOUND_MOZCONFIG isn't set, look for it and make sure the script doesn't error out
 isfoundset=${FOUND_MOZCONFIG+yes}
 if [ -z $isfoundset ]; then
   FOUND_MOZCONFIG=`$scriptdir/mozconfig-find $topsrcdir`
   if [ $? -ne 0 ]; then
-    echo '$(error Fix above errors before continuing.)' >> $tmp_file
+    echo '$(error Fix above errors before continuing.)'
   else
     isfoundset=yes
   fi
 fi
 
 if [ -n $isfoundset ]; then
   if [ "$FOUND_MOZCONFIG" ]
   then
     . "$FOUND_MOZCONFIG"
   fi
-  echo "export FOUND_MOZCONFIG := $FOUND_MOZCONFIG" >> $tmp_file
+  echo "export FOUND_MOZCONFIG := $FOUND_MOZCONFIG"
 
   if [ "$opts" ]; then
     mk_echo_options
   fi
 fi
-
-if test -f $out_file && cmp -s $tmp_file $out_file; then
-  rm $tmp_file
-else
-  mv -f $tmp_file $out_file
-fi
--- a/build/mobile/devicemanager.py
+++ b/build/mobile/devicemanager.py
@@ -496,16 +496,24 @@ class DeviceManager:
     failure: None
     """
     buf = StringIO.StringIO()
     if self.shell(["/system/bin/logcat", "-d", "dalvikvm:S", "ConnectivityService:S", "WifiMonitor:S", "WifiStateTracker:S", "wpa_supplicant:S", "NetworkStateTracker:S"], buf) != 0:
       return None
 
     return str(buf.getvalue()[0:-1]).rstrip().split('\r')
 
+  @abstractmethod
+  def chmodDir(self, remoteDir):
+    """
+    external function
+    returns:
+    success: True
+    failure: False
+    """
     
 class NetworkTools:
   def __init__(self):
     pass
 
   # Utilities to get the local ip address
   def getInterfaceIp(self, ifname):
     if os.name != "nt":
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -163,34 +163,31 @@ class DeviceManagerADB(DeviceManager):
           self.checkCmdAs(["shell", "dd", "if=" + remoteTmpFile, "of=" + destname])
         else:
           self.checkCmdAs(["shell", "cp", remoteTmpFile, destname])
         self.checkCmd(["shell", "rm", remoteTmpFile])
       else:
         self.checkCmd(["push", os.path.realpath(localname), destname])
       if (self.isDir(destname)):
         destname = destname + "/" + os.path.basename(localname)
-      self.chmodDir(destname)
       return True
     except:
       return False
 
   # external function
   # returns:
   #  success: directory name
   #  failure: None
   def mkDir(self, name):
     try:
       result = self.runCmdAs(["shell", "mkdir", name]).stdout.read()
       if 'read-only file system' in result.lower():
         return None
       if 'file exists' in result.lower():
         return name
-
-      self.chmodDir(name)
       return name
     except:
       return None
 
   # make directory structure on the device
   # external function
   # returns:
   #  success: directory structure that we created
@@ -248,17 +245,16 @@ class DeviceManagerADB(DeviceManager):
             self.pushFile(localFile, remoteFile)
           for dir in dirs:
             targetDir = remoteDir + "/"
             if (relRoot!="."):
               targetDir = targetDir + relRoot + "/"
             targetDir = targetDir + dir
             if (not self.dirExists(targetDir)):
               self.mkDir(targetDir)
-      self.checkCmdAs(["shell", "chmod", "777", remoteDir])
       return remoteDir
     except:
       print "pushing " + localDir + " to " + remoteDir + " failed"
       return None
 
   # external function
   # returns:
   #  success: True
@@ -747,30 +743,36 @@ class DeviceManagerADB(DeviceManager):
     return subprocess.check_call(finalArgs)
 
   def checkCmdAs(self, args):
     if (self.useRunAs):
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
     return self.checkCmd(args)
 
+  # external function
+  # returns:
+  #  success: True
+  #  failure: False
   def chmodDir(self, remoteDir):
     if (self.isDir(remoteDir)):
       files = self.listFiles(remoteDir.strip())
       for f in files:
-        if (self.isDir(remoteDir.strip() + "/" + f.strip())):
-          self.chmodDir(remoteDir.strip() + "/" + f.strip())
+        remoteEntry = remoteDir.strip() + "/" + f.strip()
+        if (self.isDir(remoteEntry)):
+          self.chmodDir(remoteEntry)
         else:
-          self.checkCmdAs(["shell", "chmod", "777", remoteDir.strip()])
-          print "chmod " + remoteDir.strip()
+          self.checkCmdAs(["shell", "chmod", "777", remoteEntry])
+          print "chmod " + remoteEntry
       self.checkCmdAs(["shell", "chmod", "777", remoteDir])
       print "chmod " + remoteDir
     else:
       self.checkCmdAs(["shell", "chmod", "777", remoteDir.strip()])
       print "chmod " + remoteDir.strip()
+    return True
 
   def verifyADB(self):
     # Check to see if adb itself can be executed.
     if self.adbPath != 'adb':
       if not os.access(self.adbPath, os.X_OK):
         raise DMError("invalid adb path, or adb not executable: %s", self.adbPath)
 
     try:
--- a/build/mobile/devicemanagerSUT.py
+++ b/build/mobile/devicemanagerSUT.py
@@ -1177,16 +1177,27 @@ class DeviceManagerSUT(DeviceManager):
     try:
       self.runCmds(["exec setprop persist.tegra.dpy%s.mode.width %s" % (screentype, width)])
       self.runCmds(["exec setprop persist.tegra.dpy%s.mode.height %s" % (screentype, height)])
     except AgentError:
       return False
 
     return True
 
+  # external function
+  # returns:
+  #  success: True
+  #  failure: False
+  def chmodDir(self, remoteDir):
+    try:
+      self.runCmds(["chmod "+remoteDir])
+    except AgentError:
+      return False
+    return True
+
 gCallbackData = ''
 
 class myServer(SocketServer.TCPServer):
   allow_reuse_address = True
 
 class callbackServer():
   def __init__(self, ip, port, debuglevel):
     global gCallbackData
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -164,16 +164,17 @@ public class DoCommand {
         UNINST ("uninst"),
         TEST ("test"),
         DBG ("dbg"),
         TRACE ("trace"),
         VER ("ver"),
         TZGET ("tzget"),
         TZSET ("tzset"),
         ADB ("adb"),
+        CHMOD ("chmod"),
         UNKNOWN ("unknown");
 
         private final String theCmd;
 
         Command(String theCmd) { this.theCmd = theCmd; }
 
         public String theCmd() {return theCmd;}
 
@@ -727,16 +728,23 @@ public class DoCommand {
             case UNZP:
                 strReturn = Unzip(Argv[1], (Argc == 3 ? Argv[2] : ""));
                 break;
 
             case ZIP:
                 strReturn = Zip(Argv[1], (Argc == 3 ? Argv[2] : ""));
                 break;
 
+            case CHMOD:
+                if (Argc == 2)
+                    strReturn = ChmodDir(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for chmod command!";
+                break;
+
             case HELP:
                 strReturn = PrintUsage();
                 break;
 
             default:
                 strReturn = sErrorPrefix + "[" + Argv[0] + "] command";
                 if (Argc > 1)
                     {
@@ -1905,24 +1913,16 @@ private void CancelNotification()
                     }
                     lRead += nRead;
                 }
             }
 
             if (dstFile != null) {
                 dstFile.flush();
                 dstFile.close();
-                // set the new file's permissions to rwxrwxrwx, if possible
-                Process pProc = Runtime.getRuntime().exec("chmod 777 "+sTmpFileName);
-                RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
-                outThrd.start();
-                try {
-                    outThrd.join(5000);
-                } catch (InterruptedException e) {
-                }
             }
 
             if (lRead == lSize)    {
                 sRet = HashFile(sTmpFileName);
             }
         }
         catch (IOException e) {
             e.printStackTrace();
@@ -2253,28 +2253,16 @@ private void CancelNotification()
             if (cr.update(ffxFiles, cv, sTmpDir, null) == 1) {
                 sRet = sDir + " successfully created";
             }
         }
         else {
             File dir = new File(sTmpDir);
 
             if (dir.mkdirs()) {
-                // set the new dir's permissions to rwxrwxrwx, if possible
-                try {
-                    Process pProc = Runtime.getRuntime().exec("chmod 777 "+sTmpDir);
-                    RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
-                    outThrd.start();
-                    try {
-                        outThrd.join(5000);
-                    } catch (InterruptedException e) {
-                    }
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
                 sRet = sDir + " successfully created";
             }
         }
 
         return (sRet);
         }
     // move this to SUTAgentAndroid.java
     public String GetScreenInfo()
@@ -3667,16 +3655,73 @@ private void CancelNotification()
             {
             e.printStackTrace();
             sRet = "Timed out!";
             }
 
         return (sRet);
         }
 
+    public String ChmodDir(String sDir)
+        {
+        String sRet = "";
+        int nFiles = 0;
+        String sSubDir = null;
+        String sTmpDir = fixFileName(sDir);
+
+        File dir = new File(sTmpDir);
+
+        if (dir.isDirectory()) {
+            sRet = "Changing permissions for " + sTmpDir;
+
+            File [] files = dir.listFiles();
+            if (files != null) {
+                if ((nFiles = files.length) > 0) {
+                    for (int lcv = 0; lcv < nFiles; lcv++) {
+                        if (files[lcv].isDirectory()) {
+                            sSubDir = files[lcv].getAbsolutePath();
+                            sRet += "\n" + ChmodDir(sSubDir);
+                        }
+                        else {
+                            // set the new file's permissions to rwxrwxrwx, if possible
+                            try {
+                                Process pProc = Runtime.getRuntime().exec("chmod 777 "+files[lcv]);
+                                RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+                                outThrd.start();
+                                outThrd.join(5000);
+                                sRet += "\n\tchmod " + files[lcv].getName() + " ok";
+                            } catch (InterruptedException e) {
+                                sRet += "\n\ttimeout waiting for chmod " + files[lcv].getName();
+                            } catch (IOException e) {
+                                sRet += "\n\tunable to chmod " + files[lcv].getName();
+                            }
+                        }
+                    }
+                }
+                else
+                    sRet += "\n\t<empty>";
+                }
+            }
+
+        // set the new directory's (or file's) permissions to rwxrwxrwx, if possible
+        try {
+            Process pProc = Runtime.getRuntime().exec("chmod 777 "+sTmpDir);
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+            outThrd.start();
+            outThrd.join(5000);
+            sRet += "\n\tchmod " + sTmpDir + " ok";
+        } catch (InterruptedException e) {
+            sRet += "\n\ttimeout waiting for chmod " + sTmpDir;
+        } catch (IOException e) {
+            sRet += "\n\tunable to chmod " + sTmpDir;
+        }
+
+        return(sRet);
+        }
+
     private String PrintUsage()
         {
         String sRet =
             "run [cmdline]                - start program no wait\n" +
             "exec [env pairs] [cmdline]   - start program no wait optionally pass env\n" +
             "                               key=value pairs (comma separated)\n" +
             "kill [program name]          - kill program no path\n" +
             "killall                      - kill all processes started\n" +
@@ -3701,16 +3746,17 @@ private void CancelNotification()
             "cwd                          - display cwd\n" +
             "mv file1 file2               - move file1 to file2\n" +
             "push filename                - push file to device\n" +
             "rm file                      - delete file\n" +
             "rmdr directory               - delete directory even if not empty\n" +
             "mkdr directory               - create directory\n" +
             "dirw directory               - tests whether the directory is writable\n" +
             "isdir directory              - test whether the directory exists\n" +
+            "chmod directory|file         - change permissions of directory and contents (or file) to 777\n" +
             "stat processid               - stat process\n" +
             "dead processid               - print whether the process is alive or hung\n" +
             "mems                         - dump memory stats\n" +
             "ls                           - print directory\n" +
             "tmpd                         - print temp directory\n" +
             "ping [hostname/ipaddr]       - ping a network device\n" +
             "unzp zipfile destdir         - unzip the zipfile into the destination dir\n" +
             "zip zipfile src              - zip the source file/dir into zipfile\n" +
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -54,16 +54,17 @@
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIChromeRegistry.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/StandardInteger.h"
+#include "mozilla/ClearOnShutdown.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
 nsIIOService    *nsScriptSecurityManager::sIOService = nsnull;
 nsIXPConnect    *nsScriptSecurityManager::sXPConnect = nsnull;
@@ -3139,29 +3140,28 @@ nsresult nsScriptSecurityManager::Init()
     JS_SetSecurityCallbacks(sRuntime, &securityCallbacks);
     JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy);
 
     JS_SetTrustedPrincipals(sRuntime, system);
 
     return NS_OK;
 }
 
-static nsScriptSecurityManager *gScriptSecMan = nsnull;
+static nsRefPtr<nsScriptSecurityManager> gScriptSecMan;
 
 jsid nsScriptSecurityManager::sEnabledID   = JSID_VOID;
 
 nsScriptSecurityManager::~nsScriptSecurityManager(void)
 {
     Preferences::RemoveObservers(this, kObservedPrefs);
     NS_ASSERTION(!mContextPrincipals, "Leaking mContextPrincipals");
     delete mOriginToPolicyMap;
     if(mDefaultPolicy)
         mDefaultPolicy->Drop();
     delete mCapabilities;
-    gScriptSecMan = nsnull;
 }
 
 void
 nsScriptSecurityManager::Shutdown()
 {
     if (sRuntime) {
         JS_SetSecurityCallbacks(sRuntime, NULL);
         JS_SetTrustedPrincipals(sRuntime, NULL);
@@ -3175,35 +3175,33 @@ nsScriptSecurityManager::Shutdown()
     NS_IF_RELEASE(sStrBundle);
 }
 
 nsScriptSecurityManager *
 nsScriptSecurityManager::GetScriptSecurityManager()
 {
     if (!gScriptSecMan)
     {
-        nsScriptSecurityManager* ssManager = new nsScriptSecurityManager();
-        if (!ssManager)
-            return nsnull;
+        nsRefPtr<nsScriptSecurityManager> ssManager = new nsScriptSecurityManager();
+
         nsresult rv;
         rv = ssManager->Init();
         NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to initialize nsScriptSecurityManager");
         if (NS_FAILED(rv)) {
-            delete ssManager;
             return nsnull;
         }
  
         rv = sXPConnect->SetDefaultSecurityManager(ssManager,
                                                    nsIXPCSecurityManager::HOOK_ALL);
         if (NS_FAILED(rv)) {
             NS_WARNING("Failed to install xpconnect security manager!");
-            delete ssManager;
             return nsnull;
         }
 
+        ClearOnShutdown(&gScriptSecMan);
         gScriptSecMan = ssManager;
     }
     return gScriptSecMan;
 }
 
 // Currently this nsGenericFactory constructor is used only from FastLoad
 // (XPCOM object deserialization) code, when "creating" the system principal
 // singleton.
--- a/client.mk
+++ b/client.mk
@@ -90,20 +90,25 @@ endif
 # Load mozconfig Options
 
 # See build pages, http://www.mozilla.org/build/ for how to set up mozconfig.
 
 MOZCONFIG_LOADER := build/autoconf/mozconfig2client-mk
 MOZCONFIG_FINDER := build/autoconf/mozconfig-find 
 MOZCONFIG_MODULES := build/unix/uniq.pl
 
-run_for_side_effects := \
-  $(shell $(TOPSRCDIR)/$(MOZCONFIG_LOADER) $(TOPSRCDIR) $(TOPSRCDIR)/.mozconfig.mk > $(TOPSRCDIR)/.mozconfig.out)
+define CR
+
+
+endef
 
-include $(TOPSRCDIR)/.mozconfig.mk
+# As $(shell) doesn't preserve newlines, use sed to replace them with an
+# unlikely sequence (||), which is then replaced back to newlines by make
+# before evaluation.
+$(eval $(subst ||,$(CR),$(shell $(TOPSRCDIR)/$(MOZCONFIG_LOADER) $(TOPSRCDIR) 2> $(TOPSRCDIR)/.mozconfig.out | sed 's/$$/||/')))
 
 ifndef MOZ_OBJDIR
   MOZ_OBJDIR = obj-$(CONFIG_GUESS)
 else
 # On Windows Pymake builds check MOZ_OBJDIR doesn't start with "/"
   ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
   ifeq (1_a,$(.PYMAKE)_$(firstword a$(subst /, ,$(MOZ_OBJDIR))))
   $(error For Windows Pymake builds, MOZ_OBJDIR must be a Windows [and not MSYS] style path.)
@@ -288,17 +293,17 @@ configure-files: $(CONFIGURES)
 
 configure-preqs = \
   configure-files \
   $(call mkdir_deps,$(OBJDIR)) \
   $(if $(MOZ_BUILD_PROJECTS),$(call mkdir_deps,$(MOZ_OBJDIR))) \
   save-mozconfig \
   $(NULL)
 
-save-mozconfig:
+save-mozconfig: $(FOUND_MOZCONFIG)
 	-cp $(FOUND_MOZCONFIG) $(OBJDIR)/.mozconfig
 
 configure:: $(configure-preqs)
 	@echo cd $(OBJDIR);
 	@echo $(CONFIGURE) $(CONFIGURE_ARGS)
 	@cd $(OBJDIR) && $(BUILD_PROJECT_ARG) $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
 	  || ( echo "*** Fix above errors and then restart with\
                \"$(MAKE) -f client.mk build\"" && exit 1 )
--- a/config/config.mk
+++ b/config/config.mk
@@ -57,19 +57,20 @@ space :=$(nullstr) # EOL
 core_winabspath = $(firstword $(subst /, ,$(call core_abspath,$(1)))):$(subst $(space),,$(patsubst %,\\%,$(wordlist 2,$(words $(subst /, ,$(call core_abspath,$(1)))), $(strip $(subst /, ,$(call core_abspath,$(1)))))))
 
 # LIBXUL_DIST is not defined under js/src, thus we make it mean DIST there.
 LIBXUL_DIST ?= $(DIST)
 
 # FINAL_TARGET specifies the location into which we copy end-user-shipped
 # build products (typelibs, components, chrome).
 #
-# It will usually be the well-loved $(DIST)/bin, today, but can also be an
-# XPI-contents staging directory for ambitious and right-thinking extensions.
-FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)
+# If XPI_NAME is set, the files will be shipped to $(DIST)/xpi-stage/$(XPI_NAME)
+# If DIST_SUBDIR is set, the files will be shipped to $(DIST)/$(DIST_SUBDIR)
+# Otherwise, the default $(DIST)/bin will be used.
+FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(if $(DIST_SUBDIR),$(DIST)/bin/$(DIST_SUBDIR),$(DIST)/bin))
 
 ifdef XPI_NAME
 DEFINES += -DXPI_NAME=$(XPI_NAME)
 endif
 
 # The VERSION_NUMBER is suffixed onto the end of the DLLs we ship.
 VERSION_NUMBER		= 50
 
--- a/configure.in
+++ b/configure.in
@@ -49,17 +49,17 @@ dnl ====================================
 _SUBDIR_HOST_CXXFLAGS="$HOST_CXXFLAGS"
 _SUBDIR_HOST_LDFLAGS="$HOST_LDFLAGS"
 _SUBDIR_CONFIG_ARGS="$ac_configure_args"
 
 dnl Set the version number of the libs included with mozilla
 dnl ========================================================
 MOZJPEG=62
 MOZPNG=10509
-MOZZLIB=0x1230
+MOZZLIB=1.2.3
 NSPR_VERSION=4
 NSS_VERSION=3
 
 dnl Set the minimum version of toolkit libs used by mozilla
 dnl ========================================================
 GLIB_VERSION=1.2.0
 PERL_VERSION=5.006
 PYTHON_VERSION=2.5
@@ -214,17 +214,16 @@ if test -n "$gonkdir" ; then
         HOST_LDFLAGS=" "
     fi
 
     AC_DEFINE(ANDROID)
     AC_DEFINE(HAVE_SYS_UIO_H)
     AC_DEFINE(HAVE_PTHREADS)
     CROSS_COMPILE=1
     MOZ_CHROME_FILE_FORMAT=omni
-    ZLIB_DIR=yes
     direct_nspr_config=1
 else
     MOZ_ANDROID_NDK
 
     case "$target" in
     *-android*|*-linuxandroid*)
         if test -z "$ANDROID_PACKAGE_NAME" ; then
             ANDROID_PACKAGE_NAME='org.mozilla.$(MOZ_APP_NAME)'
@@ -804,18 +803,16 @@ AC_SUBST(MIDL_FLAGS)
 AC_SUBST(_MSC_VER)
 
 AC_SUBST(GNU_AS)
 AC_SUBST(GNU_LD)
 AC_SUBST(GNU_CC)
 AC_SUBST(GNU_CXX)
 AC_SUBST(INTEL_CC)
 AC_SUBST(INTEL_CXX)
-AC_SUBST(CLANG_CC)
-AC_SUBST(CLANG_CXX)
 
 AC_SUBST(STL_FLAGS)
 AC_SUBST(WRAP_STL_INCLUDES)
 AC_SUBST(MOZ_MSVC_STL_WRAP__Throw)
 AC_SUBST(MOZ_MSVC_STL_WRAP__RAISE)
 
 dnl ========================================================
 dnl Checks for programs.
@@ -1723,17 +1720,16 @@ MOZ_ARG_ENABLE_BOOL(dmd,
     MOZ_DMD=1,
     MOZ_DMD= )
 if test -n "$MOZ_DMD"; then
     MOZ_CHECK_HEADER([valgrind/valgrind.h], [],
         AC_MSG_ERROR(
             [--enable-dmd specified but Valgrind is not installed]))
     AC_DEFINE(MOZ_DMD)
 fi
-AC_SUBST(MOZ_DMD)
 
 dnl ========================================================
 dnl jprof
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(jprof,
 [  --enable-jprof          Enable jprof profiling tool (needs mozilla/tools/jprof). Implies --enable-profiling.],
     MOZ_JPROF=1,
     MOZ_JPROF= )
@@ -1890,17 +1886,16 @@ if test "$_python_res" != 0; then
 fi
 AC_MSG_RESULT([yes])
 
 dnl Check for using a custom <stdint.h> implementation
 dnl ========================================================
 AC_MSG_CHECKING(for custom <stdint.h> implementation)
 if test "$MOZ_CUSTOM_STDINT_H"; then
   AC_DEFINE_UNQUOTED(MOZ_CUSTOM_STDINT_H, "$MOZ_CUSTOM_STDINT_H")
-  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`
@@ -4052,17 +4047,17 @@ if test "$SYSTEM_JPEG" = 1; then
     LIBS="$JPEG_LIBS $LIBS"
     AC_TRY_COMPILE([ #include <stdio.h>
                      #include <sys/types.h>
                      #include <jpeglib.h> ],
                    [ #if JPEG_LIB_VERSION < $MOZJPEG
                      #error "Insufficient JPEG library version ($MOZJPEG required)."
                      #endif ],
                    SYSTEM_JPEG=1,
-                   [SYSTEM_JPEG= JPEG_CFLAGS= JPEG_LIBS=])
+                   AC_MSG_ERROR([Insufficient JPEG library version for --with-system-jpeg]))
 fi
 CFLAGS=$_SAVE_CFLAGS
 LDFLAGS=$_SAVE_LDFLAGS
 LIBS=$_SAVE_LIBS
 
 if test -n "${JPEG_DIR}" -a -d "${JPEG_DIR}" -a "$SYSTEM_JPEG" = 1; then
     JPEG_CFLAGS="-I${JPEG_DIR}/include"
     JPEG_LIBS="-L${JPEG_DIR}/lib ${JPEG_LIBS}"
@@ -4085,24 +4080,25 @@ fi
 if test -z "$ZLIB_DIR" -o "$ZLIB_DIR" = no; then
     SYSTEM_ZLIB=
 else
     AC_CHECK_LIB(z, gzread, [SYSTEM_ZLIB=1 ZLIB_LIBS="-lz $ZLIB_LIBS"],
 	[SYSTEM_ZLIB= ZLIB_CFLAGS= ZLIB_LIBS=], $ZLIB_LIBS)
 fi
 if test "$SYSTEM_ZLIB" = 1; then
     LIBS="$ZLIB_LIBS $LIBS"
+    MOZZLIBNUM=`echo $MOZZLIB | awk -F. '{printf "0x%x\n", ((($1 * 16 + $2) * 16) + $3) * 16 + $4}'`
     AC_TRY_COMPILE([ #include <stdio.h>
                      #include <string.h>
                      #include <zlib.h> ],
-                   [ #if ZLIB_VERNUM < $MOZZLIB
-                     #error "Insufficient zlib version ($MOZZLIB required)."
+                   [ #if ZLIB_VERNUM < $MOZZLIBNUM
+                     #error "Insufficient zlib version ($MOZZLIBNUM required)."
                      #endif ],
                    SYSTEM_ZLIB=1,
-                   [SYSTEM_ZLIB= ZLIB_CFLAGS= ZLIB_LIBS=])
+                   AC_MSG_ERROR([Insufficient zlib version for --with-system-zlib ($MOZZLIB required)]))
 fi
 CFLAGS=$_SAVE_CFLAGS
 LDFLAGS=$_SAVE_LDFLAGS
 LIBS=$_SAVE_LIBS
 
 if test "${ZLIB_DIR}" -a -d "${ZLIB_DIR}" -a "$SYSTEM_ZLIB" = 1; then
     ZLIB_CFLAGS="-I${ZLIB_DIR}/include"
     ZLIB_LIBS="-L${ZLIB_DIR}/lib ${ZLIB_LIBS}"
@@ -4307,25 +4303,17 @@ NECKO_WIFI=1
 NECKO_COOKIES=1
 NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device"
 USE_ARM_KUSER=
 BUILD_CTYPES=1
 MOZ_USE_NATIVE_POPUP_WINDOWS=
 MOZ_ANDROID_HISTORY=
 MOZ_WEBSMS_BACKEND=
 MOZ_GRAPHITE=1
-
-case "${target}" in
-*darwin*)
-    ACCESSIBILITY=
-    ;;
-*)
-    ACCESSIBILITY=1
-    ;;
-esac
+ACCESSIBILITY=1
 
 case "$target_os" in
     mingw*)
         NS_ENABLE_TSF=1
         AC_DEFINE(NS_ENABLE_TSF)
         ;;
 esac
 
@@ -5264,20 +5252,19 @@ MOZ_ARG_DISABLE_BOOL(dbm,
     NSS_DISABLE_DBM=)
 
 dnl bi-directional support always on
 IBMBIDI=1
 AC_DEFINE(IBMBIDI)
 
 dnl ========================================================
 dnl accessibility support on by default on all platforms
-dnl except OS X.
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(accessibility,
-[  --disable-accessibility Disable accessibility support (off by default on OS X)],
+[  --disable-accessibility Disable accessibility support],
     ACCESSIBILITY=,
     ACCESSIBILITY=1 )
 if test "$ACCESSIBILITY"; then
     AC_DEFINE(ACCESSIBILITY)
 fi
 
 dnl ========================================================
 dnl Disable printing
@@ -8289,25 +8276,23 @@ AC_SUBST(MOZ_DEBUG)
 AC_SUBST(MOZ_DEBUG_SYMBOLS)
 AC_SUBST(MOZ_DEBUG_ENABLE_DEFS)
 AC_SUBST(MOZ_DEBUG_DISABLE_DEFS)
 AC_SUBST(MOZ_DEBUG_FLAGS)
 AC_SUBST(MOZ_DEBUG_LDFLAGS)
 AC_SUBST(WARNINGS_AS_ERRORS)
 AC_SUBST(MOZ_EXTENSIONS)
 AC_SUBST(MOZ_JSDEBUGGER)
-AC_SUBST(MOZ_LOG_REFCNT)
 AC_SUBST(MOZ_ENABLE_PROFILER_SPS)
 AC_SUBST(MOZ_JPROF)
 AC_SUBST(MOZ_SHARK)
 AC_SUBST(MOZ_CALLGRIND)
 AC_SUBST(MOZ_VTUNE)
 AC_SUBST(MOZ_ETW)
 AC_SUBST(MOZ_PROFILING)
-AC_SUBST(MOZ_QUANTIFY)
 AC_SUBST(LIBICONV)
 AC_SUBST(MOZ_PLACES)
 AC_SUBST(MOZ_TOOLKIT_SEARCH)
 AC_SUBST(MOZ_FEEDS)
 AC_SUBST(NS_PRINTING)
 AC_SUBST(MOZ_WEBGL)
 AC_SUBST(MOZ_HELP_VIEWER)
 
@@ -8320,17 +8305,16 @@ AC_SUBST(MOZ_PROFILELOCKING)
 AC_SUBST(ENABLE_TESTS)
 AC_SUBST(ENABLE_MARIONETTE)
 AC_SUBST(IBMBIDI)
 AC_SUBST(MOZ_UNIVERSALCHARDET)
 AC_SUBST(ACCESSIBILITY)
 AC_SUBST(MOZ_SPELLCHECK)
 AC_SUBST(MOZ_JAVA_COMPOSITOR)
 AC_SUBST(MOZ_ONLY_TOUCH_EVENTS)
-AC_SUBST(MOZ_USER_DIR)
 AC_SUBST(MOZ_CRASHREPORTER)
 AC_SUBST(MOZ_MAINTENANCE_SERVICE)
 AC_SUBST(MOZ_VERIFY_MAR_SIGNATURE)
 AC_SUBST(MOZ_ENABLE_SIGNMAR)
 AC_SUBST(MOZ_UPDATER)
 AC_SUBST(MOZ_ANGLE)
 AC_SUBST(MOZ_DIRECTX_SDK_PATH)
 AC_SUBST(MOZ_DIRECTX_SDK_CPU_SUFFIX)
@@ -8568,17 +8552,16 @@ AC_SUBST(TARGET_MD_ARCH)
 AC_SUBST(TARGET_XPCOM_ABI)
 AC_SUBST(OS_TARGET)
 AC_SUBST(OS_ARCH)
 AC_SUBST(OS_RELEASE)
 AC_SUBST(OS_TEST)
 AC_SUBST(CPU_ARCH)
 AC_SUBST(INTEL_ARCHITECTURE)
 
-AC_SUBST(MOZ_DISABLE_JAR_PACKAGING)
 AC_SUBST(MOZ_CHROME_FILE_FORMAT)
 
 AC_SUBST(WRAP_LDFLAGS)
 AC_SUBST(MKSHLIB)
 AC_SUBST(MKCSHLIB)
 AC_SUBST(MKSHLIB_FORCE_ALL)
 AC_SUBST(MKSHLIB_UNFORCE_ALL)
 AC_SUBST(DSO_CFLAGS)
@@ -8874,16 +8857,20 @@ dnl Run a perl script to quickly create 
 dnl If it succeeds, it outputs a shell command to set CONFIG_FILES
 dnl   for the files it cannot handle correctly. This way, config.status
 dnl   will handle these files.
 dnl If it fails, nothing is set and config.status will run as usual.
 dnl
 dnl This does not change the $MAKEFILES variable.
 dnl
 echo $MAKEFILES | ${PERL} $srcdir/build/autoconf/acoutput-fast.pl > conftest.sh
+res="$?"
+if test "$res" != 0; then
+    exit $res
+fi
 . ./conftest.sh
 rm conftest.sh
 
 echo $MAKEFILES > unallmakefiles
 
 mv -f config/autoconf.mk config/autoconf.mk.orig 2> /dev/null
 
 AC_OUTPUT($MAKEFILES)
@@ -8936,17 +8923,19 @@ if test "$MOZ_JEMALLOC" -a "$MOZ_MEMORY"
   unset CONFIG_FILES
   if test -z "$MOZ_TLS"; then
     ac_configure_args="$ac_configure_args --disable-tls"
   fi
   EXTRA_CFLAGS="$CFLAGS"
   for var in AS CC CXX CPP LD AR RANLIB STRIP CPPFLAGS EXTRA_CFLAGS LDFLAGS; do
     ac_configure_args="$ac_configure_args $var='`eval echo \\${${var}}`'"
   done
-  ac_configure_args="$ac_configure_args je_cv_static_page_shift=12"
+  if test "$CROSS_COMPILE"; then
+    ac_configure_args="$ac_configure_args je_cv_static_page_shift=12"
+  fi
   _save_cache_file="$cache_file"
   cache_file=$_objdir/memory/jemalloc/src/config.cache
   AC_OUTPUT_SUBDIRS(memory/jemalloc/src)
   cache_file="$_save_cache_file"
   ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 fi
 
 dnl Build libunwind for Android profiling builds
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -2153,17 +2153,17 @@ private:
   static nsString* sModifierSeparator;
 };
 
 typedef nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
                                                     HTMLSplitOnSpacesTokenizer;
 
 #define NS_HOLD_JS_OBJECTS(obj, clazz)                                         \
   nsContentUtils::HoldJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz),        \
-                                &NS_CYCLE_COLLECTION_NAME(clazz))
+                                NS_CYCLE_COLLECTION_PARTICIPANT(clazz))
 
 #define NS_DROP_JS_OBJECTS(obj, clazz)                                         \
   nsContentUtils::DropJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz))
 
 
 class NS_STACK_CLASS nsCxPusher
 {
 public:
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -246,75 +246,16 @@ public:
    * the term, i.e. not in an XHTML/XML document).
    */
   inline bool IsInHTMLDocument() const
   {
     return OwnerDoc()->IsHTML();
   }
 
   /**
-   * Get the namespace that this element's tag is defined in
-   * @return the namespace
-   */
-  PRInt32 GetNameSpaceID() const
-  {
-    return mNodeInfo->NamespaceID();
-  }
-
-  /**
-   * Get the tag for this element. This will always return a non-null
-   * atom pointer (as implied by the naming of the method).
-   */
-  nsIAtom *Tag() const
-  {
-    return mNodeInfo->NameAtom();
-  }
-
-  /**
-   * Get the NodeInfo for this element
-   * @return the nodes node info
-   */
-  nsINodeInfo *NodeInfo() const
-  {
-    return mNodeInfo;
-  }
-
-  inline bool IsInNamespace(PRInt32 aNamespace) const {
-    return mNodeInfo->NamespaceID() == aNamespace;
-  }
-
-  inline bool IsHTML() const {
-    return IsInNamespace(kNameSpaceID_XHTML);
-  }
-
-  inline bool IsHTML(nsIAtom* aTag) const {
-    return mNodeInfo->Equals(aTag, kNameSpaceID_XHTML);
-  }
-
-  inline bool IsSVG() const {
-    return IsInNamespace(kNameSpaceID_SVG);
-  }
-
-  inline bool IsSVG(nsIAtom* aTag) const {
-    return mNodeInfo->Equals(aTag, kNameSpaceID_SVG);
-  }
-
-  inline bool IsXUL() const {
-    return IsInNamespace(kNameSpaceID_XUL);
-  }
-
-  inline bool IsMathML() const {
-    return IsInNamespace(kNameSpaceID_MathML);
-  }
-
-  inline bool IsMathML(nsIAtom* aTag) const {
-    return mNodeInfo->Equals(aTag, kNameSpaceID_MathML);
-  }
-
-  /**
    * Returns an atom holding the name of the attribute of type ID on
    * this content node (if applicable).  Returns null for non-element
    * content nodes.
    */
   virtual nsIAtom *GetIDAttributeName() const = 0;
 
   /**
    * Normalizes an attribute name and returns it as a nodeinfo if an attribute
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -471,16 +471,85 @@ public:
   {
     return mNodeInfo->NodeName();
   }
   const nsString& LocalName() const
   {
     return mNodeInfo->LocalName();
   }
 
+  /**
+   * Get the namespace that this element's tag is defined in
+   * @return the namespace
+   */
+  PRInt32 GetNameSpaceID() const
+  {
+    return mNodeInfo->NamespaceID();
+  }
+
+  /**
+   * Get the tag for this element. This will always return a non-null atom
+   * pointer (as implied by the naming of the method).  For elements this is
+   * the non-namespaced tag, and for other nodes it's something like "#text",
+   * "#comment", "#document", etc.
+   */
+  nsIAtom* Tag() const
+  {
+    return mNodeInfo->NameAtom();
+  }
+
+  /**
+   * Get the NodeInfo for this element
+   * @return the nodes node info
+   */
+  nsINodeInfo* NodeInfo() const
+  {
+    return mNodeInfo;
+  }
+
+  bool IsInNamespace(PRInt32 aNamespace) const
+  {
+    return mNodeInfo->NamespaceID() == aNamespace;
+  }
+
+  bool IsHTML() const
+  {
+    return IsInNamespace(kNameSpaceID_XHTML);
+  }
+
+  bool IsHTML(nsIAtom* aTag) const
+  {
+    return mNodeInfo->Equals(aTag, kNameSpaceID_XHTML);
+  }
+
+  bool IsSVG() const
+  {
+    return IsInNamespace(kNameSpaceID_SVG);
+  }
+
+  bool IsSVG(nsIAtom* aTag) const
+  {
+    return mNodeInfo->Equals(aTag, kNameSpaceID_SVG);
+  }
+
+  bool IsXUL() const
+  {
+    return IsInNamespace(kNameSpaceID_XUL);
+  }
+
+  bool IsMathML() const
+  {
+    return IsInNamespace(kNameSpaceID_MathML);
+  }
+
+  bool IsMathML(nsIAtom* aTag) const
+  {
+    return mNodeInfo->Equals(aTag, kNameSpaceID_MathML);
+  }
+
   nsINode*
   InsertBefore(nsINode *aNewChild, nsINode *aRefChild, nsresult *aReturn)
   {
     return ReplaceOrInsertBefore(false, aNewChild, aRefChild, aReturn);
   }
   nsINode*
   ReplaceChild(nsINode *aNewChild, nsINode *aOldChild, nsresult *aReturn)
   {
--- a/content/base/src/ThirdPartyUtil.h
+++ b/content/base/src/ThirdPartyUtil.h
@@ -4,22 +4,23 @@
 
 #ifndef ThirdPartyUtil_h__
 #define ThirdPartyUtil_h__
 
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "mozIThirdPartyUtil.h"
 #include "nsIEffectiveTLDService.h"
+#include "mozilla/Attributes.h"
 
 class nsIURI;
 class nsIChannel;
 class nsIDOMWindow;
 
-class ThirdPartyUtil : public mozIThirdPartyUtil
+class ThirdPartyUtil MOZ_FINAL : public mozIThirdPartyUtil
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_MOZITHIRDPARTYUTIL
 
   nsresult Init();
 
 private:
--- a/content/base/src/nsCCUncollectableMarker.h
+++ b/content/base/src/nsCCUncollectableMarker.h
@@ -1,19 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIObserver.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Attributes.h"
 
 struct JSTracer;
 
-class nsCCUncollectableMarker : public nsIObserver
+class nsCCUncollectableMarker MOZ_FINAL : public nsIObserver
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   /**
    * Inits a global nsCCUncollectableMarker. Should only be called once.
    */
   static nsresult Init();
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -176,16 +176,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 
 #include "nsWrapperCacheInlines.h"
 #include "nsIDOMDocumentType.h"
 #include "nsCharSeparatedTokenizer.h"
 
 #include "nsICharsetDetector.h"
 #include "nsICharsetDetectionObserver.h"
 #include "nsIPlatformCharset.h"
+#include "mozilla/Attributes.h"
 
 extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
                                       const char** next, PRUnichar* result);
 extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
                                  int ns_aware, const char** colon);
 
 using namespace mozilla::dom;
 using namespace mozilla::layers;
@@ -302,25 +303,25 @@ EventListenerManagerHashClearEntry(PLDHa
 {
   EventListenerManagerMapEntry *lm =
     static_cast<EventListenerManagerMapEntry *>(entry);
 
   // Let the EventListenerManagerMapEntry clean itself up...
   lm->~EventListenerManagerMapEntry();
 }
 
-class SameOriginChecker : public nsIChannelEventSink,
-                          public nsIInterfaceRequestor
+class SameOriginChecker MOZ_FINAL : public nsIChannelEventSink,
+                                    public nsIInterfaceRequestor
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
 };
 
-class CharsetDetectionObserver : public nsICharsetDetectionObserver
+class CharsetDetectionObserver MOZ_FINAL : public nsICharsetDetectionObserver
 {
 public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf)
   {
     mCharset = aCharset;
     return NS_OK;
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -804,19 +804,19 @@ nsCORSListenerProxy::UpdateChannel(nsICh
   return NS_OK;
 }
 
 //////////////////////////////////////////////////////////////////////////
 // Preflight proxy
 
 // Class used as streamlistener and notification callback when
 // doing the initial OPTIONS request for a CORS check
-class nsCORSPreflightListener : public nsIStreamListener,
-                                public nsIInterfaceRequestor,
-                                public nsIChannelEventSink
+class nsCORSPreflightListener MOZ_FINAL : public nsIStreamListener,
+                                          public nsIInterfaceRequestor,
+                                          public nsIChannelEventSink
 {
 public:
   nsCORSPreflightListener(nsIChannel* aOuterChannel,
                           nsIStreamListener* aOuterListener,
                           nsISupports* aOuterContext,
                           nsIPrincipal* aReferrerPrincipal,
                           const nsACString& aRequestMethod,
                           bool aWithCredentials)
--- a/content/base/src/nsCrossSiteListenerProxy.h
+++ b/content/base/src/nsCrossSiteListenerProxy.h
@@ -10,36 +10,37 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsIURI.h"
 #include "nsTArray.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIChannelEventSink.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
+#include "mozilla/Attributes.h"
 
 class nsIURI;
 class nsIParser;
 class nsIPrincipal;
 
 extern bool
 IsValidHTTPToken(const nsCSubstring& aToken);
 
 nsresult
 NS_StartCORSPreflight(nsIChannel* aRequestChannel,
                       nsIStreamListener* aListener,
                       nsIPrincipal* aPrincipal,
                       bool aWithCredentials,
                       nsTArray<nsCString>& aACUnsafeHeaders,
                       nsIChannel** aPreflightChannel);
 
-class nsCORSListenerProxy : public nsIStreamListener,
-                            public nsIInterfaceRequestor,
-                            public nsIChannelEventSink,
-                            public nsIAsyncVerifyRedirectCallback
+class nsCORSListenerProxy MOZ_FINAL : public nsIStreamListener,
+                                      public nsIInterfaceRequestor,
+                                      public nsIChannelEventSink,
+                                      public nsIAsyncVerifyRedirectCallback
 {
 public:
   nsCORSListenerProxy(nsIStreamListener* aOuter,
                       nsIPrincipal* aRequestingPrincipal,
                       nsIChannel* aChannel,
                       bool aWithCredentials,
                       nsresult* aResult);
   nsCORSListenerProxy(nsIStreamListener* aOuter,
--- a/content/base/src/nsDOMBlobBuilder.h
+++ b/content/base/src/nsDOMBlobBuilder.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsDOMBlobBuilder_h
 #define nsDOMBlobBuilder_h
 
 #include "nsDOMFile.h"
 
 #include "mozilla/CheckedInt.h"
+#include "mozilla/Attributes.h"
 
 using namespace mozilla;
 
 class nsDOMMultipartFile : public nsDOMFile,
                            public nsIJSNativeInitializer
 {
 public:
   // Create as a file
@@ -136,18 +137,18 @@ protected:
   }
 
   nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
   void* mData;
   PRUint64 mDataLen;
   PRUint64 mDataBufferLen;
 };
 
-class nsDOMBlobBuilder : public nsIDOMMozBlobBuilder,
-                         public nsIJSNativeInitializer
+class nsDOMBlobBuilder MOZ_FINAL : public nsIDOMMozBlobBuilder,
+                                   public nsIJSNativeInitializer
 {
 public:
   nsDOMBlobBuilder()
     : mBlobSet()
   {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMOZBLOBBUILDER
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -26,31 +26,32 @@
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsIUUIDGenerator.h"
 #include "nsBlobProtocolHandler.h"
 #include "nsStringStream.h"
 #include "nsJSUtils.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/Attributes.h"
 
 #include "plbase64.h"
 #include "prmem.h"
 #include "dombindings.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 // XXXkhuey the input stream that we pass out of a DOMFile
 // can outlive the actual DOMFile object.  Thus, we must
 // ensure that the buffer underlying the stream we get
 // from NS_NewByteInputStream is held alive as long as the
 // stream is.  We do that by passing back this class instead.
-class DataOwnerAdapter : public nsIInputStream,
-                         public nsISeekableStream
+class DataOwnerAdapter MOZ_FINAL : public nsIInputStream,
+                                   public nsISeekableStream
 {
   typedef nsDOMMemoryFile::DataOwner DataOwner;
 public:
   static nsresult Create(DataOwner* aDataOwner,
                          PRUint32 aStart,
                          PRUint32 aLength,
                          nsIInputStream** _retval);
 
--- a/content/base/src/nsDOMTokenList.h
+++ b/content/base/src/nsDOMTokenList.h
@@ -39,17 +39,17 @@ public:
   const nsAttrValue* GetParsedAttr() {
     if (!mElement) {
       return nsnull;
     }
     return mElement->GetAttrInfo(kNameSpaceID_None, mAttrAtom).mValue;
   }
 
 protected:
-  ~nsDOMTokenList();
+  virtual ~nsDOMTokenList();
 
   nsresult CheckToken(const nsAString& aStr);
   void AddInternal(const nsAttrValue* aAttr, const nsAString& aToken);
   void RemoveInternal(const nsAttrValue* aAttr, const nsAString& aToken);
 
   nsGenericElement* mElement;
   nsCOMPtr<nsIAtom> mAttrAtom;
 };
--- a/content/base/src/nsDataDocumentContentPolicy.h
+++ b/content/base/src/nsDataDocumentContentPolicy.h
@@ -15,18 +15,19 @@
 /* 1147d32c-215b-4014-b180-07fe7aedf915 */
 #define NS_DATADOCUMENTCONTENTPOLICY_CID \
  {0x1147d32c, 0x215b, 0x4014, {0xb1, 0x80, 0x07, 0xfe, 0x7a, 0xed, 0xf9, 0x15}}
 #define NS_DATADOCUMENTCONTENTPOLICY_CONTRACTID \
  "@mozilla.org/data-document-content-policy;1"
 
 
 #include "nsIContentPolicy.h"
+#include "mozilla/Attributes.h"
 
-class nsDataDocumentContentPolicy : public nsIContentPolicy
+class nsDataDocumentContentPolicy MOZ_FINAL : public nsIContentPolicy
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPOLICY
 
   nsDataDocumentContentPolicy()
   {}
   ~nsDataDocumentContentPolicy()
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1164,18 +1164,17 @@ nsExternalResourceMap::ExternalResource:
 
 // ==================================================================
 // =
 // ==================================================================
 
 // If we ever have an nsIDocumentObserver notification for stylesheet title
 // changes, we could make this inherit from nsDOMStringList instead of
 // reimplementing nsIDOMDOMStringList.
-class nsDOMStyleSheetSetList : public nsIDOMDOMStringList
-                          
+class nsDOMStyleSheetSetList MOZ_FINAL : public nsIDOMDOMStringList
 {
 public:
   NS_DECL_ISUPPORTS
 
   NS_DECL_NSIDOMDOMSTRINGLIST
 
   nsDOMStyleSheetSetList(nsIDocument* aDocument);
 
@@ -7682,17 +7681,17 @@ nsDocument::GetDocumentState()
 }
 
 namespace {
 
 /**
  * Stub for LoadSheet(), since all we want is to get the sheet into
  * the CSSLoader's style cache
  */
-class StubCSSLoaderObserver : public nsICSSLoaderObserver {
+class StubCSSLoaderObserver MOZ_FINAL : public nsICSSLoaderObserver {
 public:
   NS_IMETHOD
   StyleSheetLoaded(nsCSSStyleSheet*, bool, nsresult)
   {
     return NS_OK;
   }
   NS_DECL_ISUPPORTS
 };
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -63,16 +63,17 @@
 #include "nsISecurityEventSink.h"
 #include "nsIChannelEventSink.h"
 #include "imgIRequest.h"
 #include "nsIDOMDOMImplementation.h"
 #include "nsIDOMTouchEvent.h"
 #include "nsIInlineEventHandlers.h"
 #include "nsDataHashtable.h"
 #include "mozilla/TimeStamp.h"
+#include "mozilla/Attributes.h"
 
 #define XML_DECLARATION_BITS_DECLARATION_EXISTS   (1 << 0)
 #define XML_DECLARATION_BITS_ENCODING_EXISTS      (1 << 1)
 #define XML_DECLARATION_BITS_STANDALONE_EXISTS    (1 << 2)
 #define XML_DECLARATION_BITS_STANDALONE_YES       (1 << 3)
 
 
 class nsEventListenerManager;
@@ -281,17 +282,17 @@ public:
     return static_cast<nsDOMStyleSheetList*>(list);
   }
 
 protected:
   PRInt32       mLength;
   nsIDocument*  mDocument;
 };
 
-class nsOnloadBlocker : public nsIRequest
+class nsOnloadBlocker MOZ_FINAL : public nsIRequest
 {
 public:
   nsOnloadBlocker() {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUEST
 
 private:
@@ -383,17 +384,17 @@ protected:
 
   private:
     nsRefPtr<nsDocument> mDisplayDocument;
     nsCOMPtr<nsIStreamListener> mTargetListener;
     nsCOMPtr<nsIURI> mURI;
   };
   friend class PendingLoad;
 
-  class LoadgroupCallbacks : public nsIInterfaceRequestor
+  class LoadgroupCallbacks MOZ_FINAL : public nsIInterfaceRequestor
   {
   public:
     LoadgroupCallbacks(nsIInterfaceRequestor* aOtherCallbacks)
       : mCallbacks(aOtherCallbacks)
     {}
     NS_DECL_ISUPPORTS
     NS_DECL_NSIINTERFACEREQUESTOR
   private:
@@ -404,18 +405,18 @@ protected:
 
     // Use shims for interfaces that docshell implements directly so that we
     // don't hand out references to the docshell.  The shims should all allow
     // getInterface back on us, but other than that each one should only
     // implement one interface.
     
     // XXXbz I wish we could just derive the _allcaps thing from _i
 #define DECL_SHIM(_i, _allcaps)                                              \
-    class _i##Shim : public nsIInterfaceRequestor,                           \
-                     public _i                                               \
+    class _i##Shim MOZ_FINAL : public nsIInterfaceRequestor,                 \
+                               public _i                                     \
     {                                                                        \
     public:                                                                  \
       _i##Shim(nsIInterfaceRequestor* aIfreq, _i* aRealPtr)                  \
         : mIfReq(aIfreq), mRealPtr(aRealPtr)                                 \
       {                                                                      \
         NS_ASSERTION(mIfReq, "Expected non-null here");                      \
         NS_ASSERTION(mRealPtr, "Expected non-null here");                    \
       }                                                                      \
--- a/content/base/src/nsEventSource.cpp
+++ b/content/base/src/nsEventSource.cpp
@@ -26,16 +26,17 @@
 #include "nsIChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "xpcpublic.h"
 #include "nsCrossSiteListenerProxy.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsDOMEventTargetHelper.h"
+#include "mozilla/Attributes.h"
 
 using namespace mozilla;
 
 #define REPLACEMENT_CHAR     (PRUnichar)0xFFFD
 #define BOM_CHAR             (PRUnichar)0xFEFF
 #define SPACE_CHAR           (PRUnichar)0x0020
 #define CR_CHAR              (PRUnichar)0x000D
 #define LF_CHAR              (PRUnichar)0x000A
@@ -633,17 +634,17 @@ nsEventSource::OnStopRequest(nsIRequest 
 
   return healthOfRequestResult;
 }
 
 /**
  * Simple helper class that just forwards the redirect callback back
  * to the nsEventSource.
  */
-class AsyncVerifyRedirectCallbackFwr : public nsIAsyncVerifyRedirectCallback
+class AsyncVerifyRedirectCallbackFwr MOZ_FINAL : public nsIAsyncVerifyRedirectCallback
 {
 public:
   AsyncVerifyRedirectCallbackFwr(nsEventSource* aEventsource)
     : mEventSource(aEventsource)
   {
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -16,16 +16,17 @@
 #include "nsIFrameLoader.h"
 #include "nsPoint.h"
 #include "nsSize.h"
 #include "nsIURI.h"
 #include "nsAutoPtr.h"
 #include "nsFrameMessageManager.h"
 #include "Layers.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/Attributes.h"
 
 class nsIURI;
 class nsSubDocumentFrame;
 class nsIView;
 class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
 class nsITabParent;
 
@@ -51,17 +52,17 @@ class QX11EmbedContainer;
  * Defines a target configuration for this <browser>'s content
  * document's view.  If the content document's actual view
  * doesn't match this nsIContentView, then on paints its pixels
  * are transformed to compensate for the difference.
  *
  * Used to support asynchronous re-paints of content pixels; see
  * nsIContentView.
  */
-class nsContentView : public nsIContentView
+class nsContentView MOZ_FINAL : public nsIContentView
 {
 public:
   typedef mozilla::layers::FrameMetrics::ViewID ViewID;
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTVIEW
  
   struct ViewConfig {
     ViewConfig()
@@ -128,18 +129,18 @@ public:
 private:
   nsresult Update(const ViewConfig& aConfig);
 
   ViewID mScrollId;
   ViewConfig mConfig;
 };
 
 
-class nsFrameLoader : public nsIFrameLoader,
-                      public nsIContentViewManager
+class nsFrameLoader MOZ_FINAL : public nsIFrameLoader,
+                                public nsIContentViewManager
 {
   friend class AutoResetInShow;
   typedef mozilla::dom::PBrowserParent PBrowserParent;
   typedef mozilla::dom::TabParent TabParent;
   typedef mozilla::layout::RenderFrameParent RenderFrameParent;
 
 protected:
   nsFrameLoader(mozilla::dom::Element* aOwner, bool aNetworkCreated);
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -15,16 +15,17 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsTArray.h"
 #include "nsIPrincipal.h"
 #include "nsIXPConnect.h"
 #include "nsDataHashtable.h"
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
 #include "nsThreadUtils.h"
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 namespace dom {
 class ContentParent;
 }
 }
 
 class nsAXPCNativeCallContext;
@@ -41,18 +42,18 @@ typedef bool (*nsLoadScriptCallback)(voi
 typedef bool (*nsSyncMessageCallback)(void* aCallbackData,
                                       const nsAString& aMessage,
                                       const nsAString& aJSON,
                                       InfallibleTArray<nsString>* aJSONRetVal);
 typedef bool (*nsAsyncMessageCallback)(void* aCallbackData,
                                        const nsAString& aMessage,
                                        const nsAString& aJSON);
 
-class nsFrameMessageManager : public nsIContentFrameMessageManager,
-                              public nsIChromeFrameMessageManager
+class nsFrameMessageManager MOZ_FINAL : public nsIContentFrameMessageManager,
+                                        public nsIChromeFrameMessageManager
 {
 public:
   nsFrameMessageManager(bool aChrome,
                         nsSyncMessageCallback aSyncCallback,
                         nsAsyncMessageCallback aAsyncCallback,
                         nsLoadScriptCallback aLoadScriptCallback,
                         void* aCallbackData,
                         nsFrameMessageManager* aParentManager,
@@ -231,17 +232,17 @@ public:
         mExec->mDelayedCxDestroy) {
       mExec->DestroyCx();
     }
   }
   nsCOMPtr<nsISupports> mOwner;
   nsFrameScriptExecutor* mExec;
 };
 
-class nsScriptCacheCleaner : public nsIObserver
+class nsScriptCacheCleaner MOZ_FINAL : public nsIObserver
 {
   NS_DECL_ISUPPORTS
 
   nsScriptCacheCleaner()
   {
     nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
     if (obsSvc)
       obsSvc->AddObserver(this, "xpcom-shutdown", false);
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -29,16 +29,17 @@
 #include "nsIDOMXPathNSResolver.h"
 #include "nsPresContext.h"
 #include "nsIDOMDOMStringMap.h"
 #include "nsContentList.h"
 #include "nsDOMClassInfoID.h" // DOMCI_DATA
 #include "nsIDOMTouchEvent.h"
 #include "nsIInlineEventHandlers.h"
 #include "mozilla/CORSMode.h"
+#include "mozilla/Attributes.h"
 
 #include "nsISMILAttr.h"
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIFrame;
 class nsIDOMNamedNodeMap;
 class nsICSSDeclaration;
@@ -57,17 +58,17 @@ struct nsRect;
 typedef PRUptrdiff PtrBits;
 
 /**
  * Class that implements the nsIDOMNodeList interface (a list of children of
  * the content), by holding a reference to the content and delegating GetLength
  * and Item to its existing child list.
  * @see nsIDOMNodeList
  */
-class nsChildContentList : public nsINodeList
+class nsChildContentList MOZ_FINAL : public nsINodeList
 {
 public:
   nsChildContentList(nsINode* aNode)
     : mNode(aNode)
   {
     SetIsDOMBinding();
   }
 
@@ -121,17 +122,17 @@ protected:
 private:
   nsCOMPtr<nsINode> mNode;
 };
 
 /**
  * A class that implements nsIWeakReference
  */
 
-class nsNodeWeakReference : public nsIWeakReference
+class nsNodeWeakReference MOZ_FINAL : public nsIWeakReference
 {
 public:
   nsNodeWeakReference(nsINode* aNode)
     : mNode(aNode)
   {
   }
 
   ~nsNodeWeakReference();
@@ -149,17 +150,17 @@ public:
 
 private:
   nsINode* mNode;
 };
 
 /**
  * Tearoff to use for nodes to implement nsISupportsWeakReference
  */
-class nsNodeSupportsWeakRefTearoff : public nsISupportsWeakReference
+class nsNodeSupportsWeakRefTearoff MOZ_FINAL : public nsISupportsWeakReference
 {
 public:
   nsNodeSupportsWeakRefTearoff(nsINode* aNode)
     : mNode(aNode)
   {
   }
 
   // nsISupports
@@ -172,17 +173,17 @@ public:
 
 private:
   nsCOMPtr<nsINode> mNode;
 };
 
 /**
  * A tearoff class for nsGenericElement to implement NodeSelector
  */
-class nsNodeSelectorTearoff : public nsIDOMNodeSelector
+class nsNodeSelectorTearoff MOZ_FINAL : public nsIDOMNodeSelector
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_DECL_NSIDOMNODESELECTOR
 
   NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeSelectorTearoff)
 
@@ -1033,17 +1034,17 @@ nsresult                                
   _class::Set##_method(const nsAString& aValue)                         \
   {                                                                     \
     return SetAttr(kNameSpaceID_None, nsGkAtoms::_atom, nsnull, aValue, true); \
   }
 
 /**
  * Tearoff class to implement nsITouchEventReceiver
  */
-class nsTouchEventReceiverTearoff : public nsITouchEventReceiver
+class nsTouchEventReceiverTearoff MOZ_FINAL : public nsITouchEventReceiver
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_FORWARD_NSITOUCHEVENTRECEIVER(mElement->)
 
   NS_DECL_CYCLE_COLLECTION_CLASS(nsTouchEventReceiverTearoff)
 
@@ -1053,17 +1054,17 @@ public:
 
 private:
   nsRefPtr<nsGenericElement> mElement;
 };
 
 /**
  * Tearoff class to implement nsIInlineEventHandlers
  */
-class nsInlineEventHandlersTearoff : public nsIInlineEventHandlers
+class nsInlineEventHandlersTearoff MOZ_FINAL : public nsIInlineEventHandlers
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_FORWARD_NSIINLINEEVENTHANDLERS(mElement->)
 
   NS_DECL_CYCLE_COLLECTION_CLASS(nsInlineEventHandlersTearoff)
 
--- a/content/base/src/nsMappedAttributes.h
+++ b/content/base/src/nsMappedAttributes.h
@@ -9,22 +9,23 @@
  */
 
 #ifndef nsMappedAttributes_h___
 #define nsMappedAttributes_h___
 
 #include "nsAttrAndChildArray.h"
 #include "nsMappedAttributeElement.h"
 #include "nsIStyleRule.h"
+#include "mozilla/Attributes.h"
 
 class nsIAtom;
 class nsHTMLStyleSheet;
 class nsRuleWalker;
 
-class nsMappedAttributes : public nsIStyleRule
+class nsMappedAttributes MOZ_FINAL : public nsIStyleRule
 {
 public:
   nsMappedAttributes(nsHTMLStyleSheet* aSheet,
                      nsMapRuleToAttributesFunc aMapRuleFunc);
 
   void* operator new(size_t size, PRUint32 aAttrCount = 1) CPP_THROW_NEW;
 
   nsMappedAttributes* Clone(bool aWillAddAttr);
--- a/content/base/src/nsNoDataProtocolContentPolicy.h
+++ b/content/base/src/nsNoDataProtocolContentPolicy.h
@@ -15,18 +15,19 @@
 /* ac9e3e82-bfbd-4f26-941e-f58c8ee178c1 */
 #define NS_NODATAPROTOCOLCONTENTPOLICY_CID \
  {0xac9e3e82, 0xbfbd, 0x4f26, {0x94, 0x1e, 0xf5, 0x8c, 0x8e, 0xe1, 0x78, 0xc1}}
 #define NS_NODATAPROTOCOLCONTENTPOLICY_CONTRACTID \
  "@mozilla.org/no-data-protocol-content-policy;1"
 
 
 #include "nsIContentPolicy.h"
+#include "mozilla/Attributes.h"
 
-class nsNoDataProtocolContentPolicy : public nsIContentPolicy
+class nsNoDataProtocolContentPolicy MOZ_FINAL : public nsIContentPolicy
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPOLICY
 
   nsNoDataProtocolContentPolicy()
   {}
   ~nsNoDataProtocolContentPolicy()
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -125,17 +125,17 @@ nsNodeInfoManager::~nsNodeInfoManager()
     PR_LOG(gNodeInfoManagerLeakPRLog, PR_LOG_DEBUG,
            ("NODEINFOMANAGER %p destroyed", this));
 #endif
 
   nsLayoutStatics::Release();
 }
 
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfoManager)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsNodeInfoManager, Release)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsNodeInfoManager)
   if (tmp->mDocument &&
       nsCCUncollectableMarker::InGeneration(cb,
                                             tmp->mDocument->GetMarkedCCGeneration())) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -2076,38 +2076,39 @@ nsRange::InsertNode(nsIDOMNode* aNode)
     res = tStartContainer->GetChildNodes(getter_AddRefs(tChildList));
     NS_ENSURE_SUCCESS(res, res);
 
     // find the insertion point in the DOM and insert the Node
     res = tChildList->Item(tStartOffset, getter_AddRefs(referenceNode));
     NS_ENSURE_SUCCESS(res, res);
   }
 
-  // We might need to update the end to include the new node (bug 433662)
+  // We might need to update the end to include the new node (bug 433662).
+  // Ideally we'd only do this if needed, but it's tricky to know when it's
+  // needed in advance (bug 765799).
   PRInt32 newOffset;
 
-  if (Collapsed()) {
-    if (referenceNode) {
-      newOffset = IndexOf(referenceNode);
-    } else {
-      PRUint32 length;
-      res = tChildList->GetLength(&length);
-      NS_ENSURE_SUCCESS(res, res);
-      newOffset = length;
-    }
-
-    nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-    NS_ENSURE_STATE(node);
-    if (node->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
-      newOffset += node->GetChildCount();
-    } else {
-      newOffset++;
-    }
+  if (referenceNode) {
+    newOffset = IndexOf(referenceNode);
+  } else {
+    PRUint32 length;
+    res = tChildList->GetLength(&length);
+    NS_ENSURE_SUCCESS(res, res);
+    newOffset = length;
   }
 
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+  NS_ENSURE_STATE(node);
+  if (node->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+    newOffset += node->GetChildCount();
+  } else {
+    newOffset++;
+  }
+
+  // Now actually insert the node
   nsCOMPtr<nsIDOMNode> tResultNode;
   res = referenceParentNode->InsertBefore(aNode, referenceNode, getter_AddRefs(tResultNode));
   NS_ENSURE_SUCCESS(res, res);
 
   if (Collapsed()) {
     return SetEnd(referenceParentNode, newOffset);
   }
   return NS_OK;
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -40,29 +40,30 @@
 #include "nsChannelPolicy.h"
 #include "nsCRT.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsGenericElement.h"
 #include "nsCrossSiteListenerProxy.h"
 
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/CORSMode.h"
+#include "mozilla/Attributes.h"
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gCspPRLog;
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //////////////////////////////////////////////////////////////
 // Per-request data structure
 //////////////////////////////////////////////////////////////
 
-class nsScriptLoadRequest : public nsISupports {
+class nsScriptLoadRequest MOZ_FINAL : public nsISupports {
 public:
   nsScriptLoadRequest(nsIScriptElement* aElement,
                       PRUint32 aVersion,
                       CORSMode aCORSMode)
     : mElement(aElement),
       mLoading(true),
       mIsInline(true),
       mJSVersion(aVersion),
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -71,16 +71,17 @@
 #include "nsDOMFile.h"
 #include "nsIFileChannel.h"
 #include "mozilla/Telemetry.h"
 #include "jsfriendapi.h"
 #include "sampler.h"
 #include "mozilla/dom/XMLHttpRequestBinding.h"
 #include "nsIDOMFormData.h"
 #include "DictionaryHelpers.h"
+#include "mozilla/Attributes.h"
 
 #include "nsWrapperCacheInlines.h"
 #include "nsStreamListenerWrapper.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define LOAD_STR "load"
@@ -3541,17 +3542,17 @@ nsXMLHttpRequest::ChangeState(PRUint32 a
 
   return rv;
 }
 
 /*
  * Simple helper class that just forwards the redirect callback back
  * to the nsXMLHttpRequest.
  */
-class AsyncVerifyRedirectCallbackForwarder : public nsIAsyncVerifyRedirectCallback
+class AsyncVerifyRedirectCallbackForwarder MOZ_FINAL : public nsIAsyncVerifyRedirectCallback
 {
 public:
   AsyncVerifyRedirectCallbackForwarder(nsXMLHttpRequest *xhr)
     : mXHR(xhr)
   {
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/content/canvas/public/nsICanvasRenderingContextInternal.h
+++ b/content/canvas/public/nsICanvasRenderingContextInternal.h
@@ -45,16 +45,20 @@ public:
   enum {
     RenderFlagPremultAlpha = 0x1
   };
 
   void SetCanvasElement(nsHTMLCanvasElement* aParentCanvas)
   {
     mCanvasElement = aParentCanvas;
   }
+  nsHTMLCanvasElement* GetParentObject() const
+  {
+    return mCanvasElement;
+  }
 
   // Sets the dimensions of the canvas, in pixels.  Called
   // whenever the size of the element changes.
   NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height) = 0;
 
   NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height) = 0;
 
   // Render the canvas at the origin of the given gfxContext
--- a/content/canvas/src/CustomQS_Canvas.h
+++ b/content/canvas/src/CustomQS_Canvas.h
@@ -5,65 +5,32 @@
 #ifndef CustomQS_Canvas_h
 #define CustomQS_Canvas_h
 
 #include "jsapi.h"
 
 #include "mozilla/dom/ImageData.h"
 
 static bool
-GetPositiveInt(JSContext* cx, JSObject& obj, const char* name, uint32_t* out)
-{
-  JS::Value temp;
-  int32_t signedInt;
-  if (!JS_GetProperty(cx, &obj, name, &temp) ||
-      !JS_ValueToECMAInt32(cx, temp, &signedInt)) {
-    return false;
-  }
-  if (signedInt <= 0) {
-    return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
-  }
-  *out = uint32_t(signedInt);
-  return true;
-}
-
-static bool
 GetImageData(JSContext* cx, JS::Value& imageData,
              uint32_t* width, uint32_t* height, JS::Anchor<JSObject*>* array)
 {
   if (!imageData.isObject()) {
     return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
   }
 
   nsIDOMImageData* domImageData;
   xpc_qsSelfRef imageDataRef;
-  if (NS_SUCCEEDED(xpc_qsUnwrapArg<nsIDOMImageData>(cx, imageData,
-                                                    &domImageData,
-                                                    &imageDataRef.ptr,
-                                                    &imageData))) {
-    mozilla::dom::ImageData* concreteImageData =
-      static_cast<mozilla::dom::ImageData*>(domImageData);
-    *width = concreteImageData->GetWidth();
-    *height = concreteImageData->GetHeight();
-    array->set(concreteImageData->GetDataObject());
-    return true;
+  nsresult rv = xpc_qsUnwrapArg<nsIDOMImageData>(cx, imageData, &domImageData,
+                                                 &imageDataRef.ptr, &imageData);
+  if (NS_FAILED(rv)) {
+    return xpc_qsThrow(cx, rv);
   }
 
-  // TODO - bug 625804: Remove support for duck-typed ImageData.
-  JSObject& dataObject = imageData.toObject();
-
-  if (!GetPositiveInt(cx, dataObject, "width", width) ||
-      !GetPositiveInt(cx, dataObject, "height", height)) {
-    return false;
-  }
-
-  JS::Value temp;
-  if (!JS_GetProperty(cx, &dataObject, "data", &temp)) {
-    return false;
-  }
-  if (!temp.isObject()) {
-    return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
-  }
-  array->set(&temp.toObject());
+  mozilla::dom::ImageData* concreteImageData =
+    static_cast<mozilla::dom::ImageData*>(domImageData);
+  *width = concreteImageData->GetWidth();
+  *height = concreteImageData->GetHeight();
+  array->set(concreteImageData->GetDataObject());
   return true;
 }
 
 #endif // CustomQS_Canvas_h
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -1235,17 +1235,18 @@ DOMCI_DATA(WebGLRenderingContext, WebGLC
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
   NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   // If the exact way we cast to nsISupports here ever changes, fix our
   // PreCreate hook!
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWebGLRenderingContext)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports,
+                                   nsICanvasRenderingContextInternal)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLRenderingContext)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLBuffer)
 NS_IMPL_RELEASE(WebGLBuffer)
 
 DOMCI_DATA(WebGLBuffer, WebGLBuffer)
 
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -477,20 +477,16 @@ public:
     WebGLContext();
     virtual ~WebGLContext();
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(WebGLContext,
                                                            nsIDOMWebGLRenderingContext)
 
-    nsINode* GetParentObject() {
-        return mCanvasElement;
-    }
-
     virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                  bool *triedToWrap);
 
     NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
 
     NS_DECL_NSITIMERCALLBACK
 
     // nsICanvasRenderingContextInternal
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -590,19 +590,18 @@ protected:
      * Draws a rectangle in the given style; used by FillRect and StrokeRect.
      */
     nsresult DrawRect(const gfxRect& rect, Style style);
 
     /**
      * Gets the pres shell from either the canvas element or the doc shell
      */
     nsIPresShell *GetPresShell() {
-      nsCOMPtr<nsIContent> content = do_QueryObject(mCanvasElement);
-      if (content) {
-        return content->OwnerDoc()->GetShell();
+      if (mCanvasElement) {
+        return mCanvasElement->OwnerDoc()->GetShell();
       }
       if (mDocShell) {
         nsCOMPtr<nsIPresShell> shell;
         mDocShell->GetPresShell(getter_AddRefs(shell));
         return shell.get();
       }
       return nsnull;
     }
@@ -767,17 +766,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCanvasElement, nsINode)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 DOMCI_DATA(CanvasRenderingContext2D, nsCanvasRenderingContext2D)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCanvasRenderingContext2D)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCanvasRenderingContext2D)
   NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMCanvasRenderingContext2D)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports,
+                                   nsICanvasRenderingContextInternal)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CanvasRenderingContext2D)
 NS_INTERFACE_MAP_END
 
 /**
  ** CanvasRenderingContext2D impl
  **/
 
 
@@ -1172,20 +1172,19 @@ nsCanvasRenderingContext2D::EnsureSurfac
             mWidth = 1;
         } else {
             mZero = false;
         }
 
         gfxASurface::gfxImageFormat format = GetImageFormat();
 
         if (!PR_GetEnv("MOZ_CANVAS_IMAGE_SURFACE")) {
-            nsCOMPtr<nsIContent> content = do_QueryObject(mCanvasElement);
             nsIDocument* ownerDoc = nsnull;
-            if (content)
-                ownerDoc = content->OwnerDoc();
+            if (mCanvasElement)
+                ownerDoc = mCanvasElement->OwnerDoc();
             nsRefPtr<LayerManager> layerManager = nsnull;
 
             if (ownerDoc)
               layerManager =
                 nsContentUtils::PersistentLayerManagerForDocument(ownerDoc);
 
             if (layerManager) {
               surface = layerManager->CreateOptimalSurface(gfxIntSize(mWidth, mHeight), format);
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -84,16 +84,18 @@
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/ipc/PDocumentRendererParent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/unused.h"
+#include "nsCCUncollectableMarker.h"
+#include "nsWrapperCacheInlines.h"
 
 #ifdef XP_WIN
 #include "gfxWindowsPlatform.h"
 #endif
 
 // windows.h (included by chromium code) defines this, in its infinite wisdom
 #undef DrawText
 
@@ -359,17 +361,18 @@ struct nsCanvasBidiProcessorAzure;
 // Cap sigma to avoid overly large temp surfaces.
 static const Float SIGMA_MAX = 100;
 
 /**
  ** nsCanvasRenderingContext2DAzure
  **/
 class nsCanvasRenderingContext2DAzure :
   public nsIDOMCanvasRenderingContext2D,
-  public nsICanvasRenderingContextInternal
+  public nsICanvasRenderingContextInternal,
+  public nsWrapperCache
 {
 public:
   nsCanvasRenderingContext2DAzure();
   virtual ~nsCanvasRenderingContext2DAzure();
 
   nsresult Redraw();
 
   // nsICanvasRenderingContextInternal
@@ -400,17 +403,18 @@ public:
   NS_IMETHOD Redraw(const gfxRect &r) { Redraw(ToRect(r)); return NS_OK; }
 
   // this rect is in mTarget's current user space
   nsresult RedrawUser(const gfxRect &r);
 
   // nsISupports interface + CC
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCanvasRenderingContext2DAzure, nsIDOMCanvasRenderingContext2D)
+  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(
+    nsCanvasRenderingContext2DAzure, nsIDOMCanvasRenderingContext2D)
 
   // nsIDOMCanvasRenderingContext2D interface
   NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D
 
   enum Style {
     STYLE_STROKE = 0,
     STYLE_FILL,
     STYLE_MAX
@@ -581,19 +585,18 @@ protected:
 
     return CurrentState().op;
   }
 
   /**
     * Gets the pres shell from either the canvas element or the doc shell
     */
   nsIPresShell *GetPresShell() {
-    nsCOMPtr<nsIContent> content = do_QueryObject(mCanvasElement);
-    if (content) {
-      return content->OwnerDoc()->GetShell();
+    if (mCanvasElement) {
+      return mCanvasElement->OwnerDoc()->GetShell();
     }
     if (mDocShell) {
       nsCOMPtr<nsIPresShell> shell;
       mDocShell->GetPresShell(getter_AddRefs(shell));
       return shell.get();
     }
     return nsnull;
   }
@@ -933,28 +936,56 @@ protected:
 };
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCanvasRenderingContext2DAzure)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCanvasRenderingContext2DAzure)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCanvasRenderingContext2DAzure)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCanvasRenderingContext2DAzure)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsCanvasRenderingContext2DAzure)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCanvasRenderingContext2DAzure)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCanvasElement, nsINode)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsCanvasRenderingContext2DAzure)
+ if (nsCCUncollectableMarker::sGeneration && tmp->IsBlack()) {
+    nsGenericElement* canvasElement = tmp->mCanvasElement;
+    if (canvasElement) {
+      if (canvasElement->IsPurple()) {
+        canvasElement->RemovePurple();
+      }
+      nsGenericElement::MarkNodeChildren(canvasElement);
+    }
+    return true;
+  }
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
+
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsCanvasRenderingContext2DAzure)
+  return nsCCUncollectableMarker::sGeneration && tmp->IsBlack();
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
+
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsCanvasRenderingContext2DAzure)
+  return nsCCUncollectableMarker::sGeneration && tmp->IsBlack();
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
+
 // XXX
 // DOMCI_DATA(CanvasRenderingContext2D, nsCanvasRenderingContext2DAzure)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCanvasRenderingContext2DAzure)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMCanvasRenderingContext2D)
   NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMCanvasRenderingContext2D)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports,
+                                   nsICanvasRenderingContextInternal)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CanvasRenderingContext2D)
 NS_INTERFACE_MAP_END
 
 /**
  ** CanvasRenderingContext2D impl
  **/
 
 
@@ -1236,20 +1267,19 @@ nsCanvasRenderingContext2DAzure::SetDime
     mZero = false;
   }
 
   // Check that the dimensions are sane
   IntSize size(width, height);
   if (size.width <= 0xFFFF && size.height <= 0xFFFF &&
       size.width >= 0 && size.height >= 0) {
     SurfaceFormat format = GetSurfaceFormat();
-    nsCOMPtr<nsIContent> content = do_QueryObject(mCanvasElement);
     nsIDocument* ownerDoc = nsnull;
-    if (content) {
-      ownerDoc = content->OwnerDoc();
+    if (mCanvasElement) {
+      ownerDoc = mCanvasElement->OwnerDoc();
     }
 
     nsRefPtr<LayerManager> layerManager = nsnull;
 
     if (ownerDoc) {
       layerManager =
         nsContentUtils::PersistentLayerManagerForDocument(ownerDoc);
     }
--- a/content/canvas/test/test_bug613794.html
+++ b/content/canvas/test/test_bug613794.html
@@ -27,25 +27,15 @@ c = c.getContext("2d");
 var threw = true;
 try {
   c.putImageData({ width: 1, height: 1, data: [ 0, 0, 0, 0] }, 0, 0);
   threw = false;
 } catch(e) {
   threw = true;
 }
 
-is(threw, false, "Should be able to pass in custom imagedata objects with array data");
-
-threw = false;
-try {
-  c.putImageData({ width: 1, height: 1, data: null }, 0, 0);
-  threw = false;
-} catch(e) {
-  threw = e.name;
-}
-
-is(threw, "TypeMismatchError",
-   "Should throw TypeMismatchError when data is not an array");
+ok(threw,
+   "Should not be able to pass in custom imagedata objects with array data");
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -3516,17 +3516,17 @@ isPixel(ctx, 55,25, 0,255,0,255, 2);
 
 function test_2d_drawImage_null() {
 
 var canvas = document.getElementById('c121');
 var ctx = canvas.getContext('2d');
 
 var _thrown = undefined; try {
   ctx.drawImage(null, 0, 0);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.drawImage.outsidesource.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.outsidesource</p>
@@ -3688,33 +3688,31 @@ isPixel(ctx, 50,25, 0,255,0,255, 2);
 <!-- [[[ test_2d.drawImage.wrongtype.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.wrongtype</p>
 <canvas id="c127" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 
 function test_2d_drawImage_wrongtype() {
 
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
 var canvas = document.getElementById('c127');
 var ctx = canvas.getContext('2d');
 
 var _thrown = undefined; try {
   ctx.drawImage(undefined, 0, 0);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 var _thrown = undefined; try {
   ctx.drawImage(0, 0, 0);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.result == Components.results.NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL, "should throw NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 var _thrown = undefined; try {
   ctx.drawImage("", 0, 0);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.result == Components.results.NS_ERROR_XPC_BAD_CONVERT_JS, "should throw NS_ERROR_XPC_BAD_CONVERT_JS");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 var _thrown = undefined; try {
   ctx.drawImage(document.createElement('p'), 0, 0);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.drawImage.zerosource.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.zerosource</p>
@@ -9187,17 +9185,17 @@ var _thrown = undefined; try {
 
 function test_2d_imageData_put_null() {
 
 var canvas = document.getElementById('c300');
 var ctx = canvas.getContext('2d');
 
 var _thrown = undefined; try {
   ctx.putImageData(null, 0, 0);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.imageData.put.path.html ]]] -->
 
 <p>Canvas test: 2d.imageData.put.path</p>
@@ -9299,23 +9297,23 @@ for (var i = 0; i < imgdata2.data.length
 function test_2d_imageData_put_wrongtype() {
 
 var canvas = document.getElementById('c304');
 var ctx = canvas.getContext('2d');
 
 var imgdata = { width: 1, height: 1, data: [255, 0, 0, 255] };
 var _thrown = undefined; try {
   ctx.putImageData(imgdata, 0, 0);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 var _thrown = undefined; try {
   ctx.putImageData("cheese", 0, 0);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 var _thrown = undefined; try {
   ctx.putImageData(42, 0, 0);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.line.cap.butt.html ]]] -->
 
 <p>Canvas test: 2d.line.cap.butt</p>
@@ -15092,17 +15090,17 @@ var _thrown = undefined; try {
 
 function test_2d_pattern_image_null() {
 
 var canvas = document.getElementById('c467');
 var ctx = canvas.getContext('2d');
 
 var _thrown = undefined; try {
   ctx.createPattern(null, 'repeat');
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.pattern.image.string.html ]]] -->
 
 <p>Canvas test: 2d.pattern.image.string</p>
@@ -15111,17 +15109,17 @@ var _thrown = undefined; try {
 
 function test_2d_pattern_image_string() {
 
 var canvas = document.getElementById('c468');
 var ctx = canvas.getContext('2d');
 
 var _thrown = undefined; try {
   ctx.createPattern('image_red.png', 'repeat');
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.pattern.image.undefined.html ]]] -->
 
 <p>Canvas test: 2d.pattern.image.undefined</p>
@@ -15130,17 +15128,17 @@ var _thrown = undefined; try {
 
 function test_2d_pattern_image_undefined() {
 
 var canvas = document.getElementById('c469');
 var ctx = canvas.getContext('2d');
 
 var _thrown = undefined; try {
   ctx.createPattern(undefined, 'repeat');
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "TypeMismatchError" && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TypeMismatchError");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.pattern.modify.canvas1.html ]]] -->
 
 <p>Canvas test: 2d.pattern.modify.canvas1</p>
@@ -15972,27 +15970,19 @@ isPixel(ctx, 98,48, 0,255,0,255, 0);
 <script>
 
 
 function test_2d_pattern_repeat_null() {
 
 var canvas = document.getElementById('c494');
 var ctx = canvas.getContext('2d');
 
-ctx.fillStyle = '#f00';
-ctx.fillRect(0, 0, 100, 50);
-var img = document.getElementById('green-1x1_2.png');
-var pattern = ctx.createPattern(img, null);
-ctx.fillStyle = pattern;
-ctx.fillRect(0, 0, 100, 50);
-
-isPixel(ctx, 1,1, 0,255,0,255, 0);
-isPixel(ctx, 98,1, 0,255,0,255, 0);
-isPixel(ctx, 1,48, 0,255,0,255, 0);
-isPixel(ctx, 98,48, 0,255,0,255, 0);
+var _thrown = undefined; try {
+  ctx.createPattern(canvas, null);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "SyntaxError" && _thrown.code == DOMException.SYNTAX_ERR, "should throw SyntaxError");
 
 
 }
 </script>
 <img src="image_green-1x1.png" id="green-1x1_2.png" class="resource">
 
 <!-- [[[ test_2d.pattern.repeat.nullsuffix.html ]]] -->
 
@@ -19543,28 +19533,30 @@ isPixel(ctx, 50,25, 0,255,0,255, 0);
 <canvas id="c611" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 
 function test_2d_type_prototype() {
 
 var canvas = document.getElementById('c611');
 var ctx = canvas.getContext('2d');
 
+var fill = window.CanvasRenderingContext2D.prototype.fill;
 ok(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.prototype");
 ok(window.CanvasRenderingContext2D.prototype.fill, "window.CanvasRenderingContext2D.prototype.fill");
 window.CanvasRenderingContext2D.prototype = null;
 ok(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.prototype");
 delete window.CanvasRenderingContext2D.prototype;
 ok(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.prototype");
 window.CanvasRenderingContext2D.prototype.fill = 1;
 ok(window.CanvasRenderingContext2D.prototype.fill === 1, "window.CanvasRenderingContext2D.prototype.fill === 1");
 delete window.CanvasRenderingContext2D.prototype.fill;
 todo(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
 
-
+//restore the original method to ensure that other tests can run successfully
+window.CanvasRenderingContext2D.prototype.fill = fill;
 }
 </script>
 
 <!-- [[[ test_2d.type.replace.html ]]] -->
 
 <p>Canvas test: 2d.type.replace</p>
 <!-- Testing: Interface methods can be overridden -->
 <canvas id="c612" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
--- a/content/events/src/nsDOMDataTransfer.h
+++ b/content/events/src/nsDOMDataTransfer.h
@@ -13,33 +13,34 @@
 #include "nsIDOMDataTransfer.h"
 #include "nsIDragService.h"
 #include "nsIDOMElement.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "nsAutoPtr.h"
 #include "nsIFile.h"
 #include "nsDOMFile.h"
+#include "mozilla/Attributes.h"
 
 class nsITransferable;
 
 /**
  * TransferItem is used to hold data for a particular format. Each piece of
  * data has a principal set from the caller which added it. This allows a
  * caller that wishes to retrieve the data to only be able to access the data
  * it is allowed to, yet still allow a chrome caller to retrieve any of the
  * data.
  */
 struct TransferItem {
   nsString mFormat;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIVariant> mData;
 };
 
-class nsDOMDataTransfer : public nsIDOMDataTransfer
+class nsDOMDataTransfer MOZ_FINAL : public nsIDOMDataTransfer
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMDATATRANSFER
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMDataTransfer, nsIDOMDataTransfer)
 
   friend class nsDOMDragEvent;
--- a/content/events/src/nsDOMDeviceMotionEvent.h
+++ b/content/events/src/nsDOMDeviceMotionEvent.h
@@ -2,49 +2,50 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsDOMDeviceMotionEvent_h__
 #define nsDOMDeviceMotionEvent_h__
 
 #include "nsIDOMDeviceMotionEvent.h"
 #include "nsDOMEvent.h"
+#include "mozilla/Attributes.h"
 
-class nsDOMDeviceRotationRate : public nsIDOMDeviceRotationRate
+class nsDOMDeviceRotationRate MOZ_FINAL : public nsIDOMDeviceRotationRate
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMDEVICEROTATIONRATE
 
   nsDOMDeviceRotationRate(double aAlpha, double aBeta, double aGamma);
 
 private:
   ~nsDOMDeviceRotationRate();
 
 protected:
   double mAlpha, mBeta, mGamma;
 };
 
-class nsDOMDeviceAcceleration : public nsIDOMDeviceAcceleration
+class nsDOMDeviceAcceleration MOZ_FINAL : public nsIDOMDeviceAcceleration
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMDEVICEACCELERATION
 
   nsDOMDeviceAcceleration(double aX, double aY, double aZ);
 
 private:
   ~nsDOMDeviceAcceleration();
 
 protected:
   double mX, mY, mZ;
 };
 
-class nsDOMDeviceMotionEvent : public nsDOMEvent,
-                               public nsIDOMDeviceMotionEvent
+class nsDOMDeviceMotionEvent MOZ_FINAL : public nsDOMEvent,
+                                         public nsIDOMDeviceMotionEvent
 {
 public:
 
   nsDOMDeviceMotionEvent(nsPresContext* aPresContext, nsEvent* aEvent)
   : nsDOMEvent(aPresContext, aEvent)
   {}
 
   NS_DECL_ISUPPORTS_INHERITED
--- a/content/events/src/nsDOMEventTargetHelper.h
+++ b/content/events/src/nsDOMEventTargetHelper.h
@@ -12,18 +12,19 @@
 #include "nsIDOMEventListener.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsPIDOMWindow.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsEventListenerManager.h"
 #include "nsIScriptContext.h"
 #include "nsWrapperCache.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/Attributes.h"
 
-class nsDOMEventListenerWrapper : public nsIDOMEventListener
+class nsDOMEventListenerWrapper MOZ_FINAL : public nsIDOMEventListener
 {
 public:
   nsDOMEventListenerWrapper(nsIDOMEventListener* aListener)
   : mListener(aListener) {}
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMEventListenerWrapper)
 
--- a/content/events/src/nsDOMTouchEvent.h
+++ b/content/events/src/nsDOMTouchEvent.h
@@ -6,18 +6,19 @@
 #define nsDOMTouchEvent_h_
 
 #include "nsDOMUIEvent.h"
 #include "nsIDOMTouchEvent.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIDocument.h"
 #include "dombindings.h"
+#include "mozilla/Attributes.h"
 
-class nsDOMTouch : public nsIDOMTouch
+class nsDOMTouch MOZ_FINAL : public nsIDOMTouch
 {
 public:
   nsDOMTouch(nsIDOMEventTarget* aTarget,
              PRInt32 aIdentifier,
              PRInt32 aPageX,
              PRInt32 aPageY,
              PRInt32 aScreenX,
              PRInt32 aScreenY,
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -140,17 +140,17 @@ nsEventListenerManager::RemoveAllListene
 }
 
 void
 nsEventListenerManager::Shutdown()
 {
   nsDOMEvent::Shutdown();
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventListenerManager)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsEventListenerManager)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsEventListenerManager, Release)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsEventListenerManager)
   PRUint32 count = tmp->mListeners.Length();
   for (PRUint32 i = 0; i < count; i++) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
--- a/content/events/src/nsEventListenerService.h
+++ b/content/events/src/nsEventListenerService.h
@@ -7,16 +7,17 @@
 #define nsEventListenerService_h__
 #include "nsIEventListenerService.h"
 #include "nsAutoPtr.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMEventTarget.h"
 #include "nsString.h"
 #include "nsCycleCollectionParticipant.h"
 #include "jsapi.h"
+#include "mozilla/Attributes.h"
 
 
 class nsEventListenerInfo : public nsIEventListenerInfo
 {
 public:
   nsEventListenerInfo(const nsAString& aType, nsIDOMEventListener* aListener,
                       bool aCapturing, bool aAllowsUntrusted,
                       bool aInSystemEventGroup)
@@ -33,15 +34,15 @@ protected:
   nsString                      mType;
   // nsReftPtr because that is what nsListenerStruct uses too.
   nsRefPtr<nsIDOMEventListener> mListener;
   bool                          mCapturing;
   bool                          mAllowsUntrusted;
   bool                          mInSystemEventGroup;
 };
 
-class nsEventListenerService : public nsIEventListenerService
+class nsEventListenerService MOZ_FINAL : public nsIEventListenerService
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIEVENTLISTENERSERVICE
 };
 #endif
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -91,16 +91,17 @@
 #include "nsIController.h"
 #include "nsICommandParams.h"
 #include "mozilla/Services.h"
 #include "mozAutoDocUpdate.h"
 #include "nsHTMLLabelElement.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
+#include "mozilla/Attributes.h"
 #include "sampler.h"
 
 #include "nsIDOMClientRect.h"
 
 #ifdef XP_MACOSX
 #import <ApplicationServices/ApplicationServices.h>
 #endif
 
@@ -212,17 +213,17 @@ PrintDocTreeAll(nsIDocShellTreeItem* aIt
       break;
     item = parent;
   }
 
   PrintDocTree(item, 0);
 }
 #endif
 
-class nsUITimerCallback : public nsITimerCallback
+class nsUITimerCallback MOZ_FINAL : public nsITimerCallback
 {
 public:
   nsUITimerCallback() : mPreviousCount(0) {}
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 private:
   PRUint32 mPreviousCount;
 };
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -29,16 +29,17 @@
 #include "nsISelectionController.h"
 #include "nsIMutationObserver.h"
 #include "nsContentEventHandler.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "nsIFormControl.h"
 #include "nsIForm.h"
 #include "nsHTMLFormElement.h"
+#include "mozilla/Attributes.h"
 
 using namespace mozilla::widget;
 
 /******************************************************************/
 /* nsIMEStateManager                                              */
 /******************************************************************/
 
 nsIContent*    nsIMEStateManager::sContent      = nsnull;
@@ -381,18 +382,18 @@ nsIMEStateManager::GetWidget(nsPresConte
 }
 
 
 // nsTextStateManager notifies widget of any text and selection changes
 //  in the currently focused editor
 // sTextStateObserver points to the currently active nsTextStateManager
 // sTextStateObserver is null if there is no focused editor
 
-class nsTextStateManager : public nsISelectionListener,
-                           public nsStubMutationObserver
+class nsTextStateManager MOZ_FINAL : public nsISelectionListener,
+                                     public nsStubMutationObserver
 {
 public:
   nsTextStateManager();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISELECTIONLISTENER
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
--- a/content/events/src/nsPaintRequest.h
+++ b/content/events/src/nsPaintRequest.h
@@ -6,18 +6,19 @@
 #ifndef NSPAINTREQUEST_H_
 #define NSPAINTREQUEST_H_
 
 #include "nsIDOMPaintRequest.h"
 #include "nsIDOMPaintRequestList.h"
 #include "nsPresContext.h"
 #include "nsIDOMEvent.h"
 #include "dombindings.h"
+#include "mozilla/Attributes.h"
 
-class nsPaintRequest : public nsIDOMPaintRequest
+class nsPaintRequest MOZ_FINAL : public nsIDOMPaintRequest
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMPAINTREQUEST
 
   nsPaintRequest() { mRequest.mFlags = 0; }
 
   void SetRequest(const nsInvalidateRequestList::Request& aRequest)
--- a/content/events/src/nsPrivateTextRange.h
+++ b/content/events/src/nsPrivateTextRange.h
@@ -4,18 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsPrivateTextRange_h__
 #define nsPrivateTextRange_h__
 
 #include "nsIPrivateTextRange.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
+#include "mozilla/Attributes.h"
 
-class nsPrivateTextRange : public nsIPrivateTextRange 
+class nsPrivateTextRange MOZ_FINAL : public nsIPrivateTextRange
 {
 	NS_DECL_ISUPPORTS
 public:
 
 	nsPrivateTextRange(const nsTextRange &aTextRange);
 	virtual ~nsPrivateTextRange(void);
 
 	NS_IMETHOD    GetRangeStart(PRUint16* aRangeStart);
@@ -26,17 +27,17 @@ public:
 protected:
 
 	PRUint16	mRangeStart;
 	PRUint16	mRangeEnd;
 	PRUint16	mRangeType;
 	nsTextRangeStyle mRangeStyle;
 };
 
-class nsPrivateTextRangeList: public nsIPrivateTextRangeList 
+class nsPrivateTextRangeList MOZ_FINAL : public nsIPrivateTextRangeList
 {
 	NS_DECL_ISUPPORTS
 public:
 	nsPrivateTextRangeList(PRUint16 aLength) : mList(aLength) {}
 
 	void          AppendTextRange(nsRefPtr<nsPrivateTextRange>& aRange);
 
 	NS_IMETHOD_(PRUint16)    GetLength();
--- a/content/events/src/nsXMLEventsManager.h
+++ b/content/events/src/nsXMLEventsManager.h
@@ -9,23 +9,24 @@
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
 #include "nsIContent.h"
 #include "nsCOMArray.h"
 #include "nsIDOMEventListener.h"
 #include "nsInterfaceHashtable.h"
 #include "nsIAtom.h"
 #include "nsStubDocumentObserver.h"
+#include "mozilla/Attributes.h"
 
 /*
  * The implementation of the XML Events Basic profile
  */
 
 class nsXMLEventsManager;
-class nsXMLEventsListener : public nsIDOMEventListener {
+class nsXMLEventsListener MOZ_FINAL : public nsIDOMEventListener {
 public:
   static bool InitXMLEventsListener(nsIDocument * aDocument, 
                                       nsXMLEventsManager * aManager, 
                                       nsIContent * aContent);
   nsXMLEventsListener(nsXMLEventsManager * aManager,
                       nsIContent * aElement,
                       nsIContent* aObserver,
                       nsIContent * aHandler,
@@ -52,17 +53,17 @@ private:
   nsString mEvent;
   nsCOMPtr<nsIAtom> mTarget;
   bool mPhase;
   bool mStopPropagation;
   bool mCancelDefault;
   
 };
 
-class nsXMLEventsManager : public nsStubDocumentObserver {
+class nsXMLEventsManager MOZ_FINAL : public nsStubDocumentObserver {
 public:
   nsXMLEventsManager();
   ~nsXMLEventsManager();
   NS_DECL_ISUPPORTS
 
   // nsIDocumentObserver
   NS_DECL_NSIDOCUMENTOBSERVER_ENDLOAD
 
--- a/content/media/MediaResource.h
+++ b/content/media/MediaResource.h
@@ -10,16 +10,17 @@
 #include "mozilla/XPCOM.h"
 #include "nsIChannel.h"
 #include "nsIPrincipal.h"
 #include "nsIURI.h"
 #include "nsIStreamListener.h"
 #include "nsIChannelEventSink.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsMediaCache.h"
+#include "mozilla/Attributes.h"
 
 // For HTTP seeking, if number of bytes needing to be
 // seeked forward is less than this value then a read is
 // done rather than a byte range request.
 static const PRInt64 SEEK_VS_READ_THRESHOLD = 32*1024;
 
 static const PRUint32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE = 416;
 
@@ -385,19 +386,19 @@ public:
   virtual double  GetDownloadRate(bool* aIsReliable);
   virtual PRInt64 GetLength();
   virtual PRInt64 GetNextCachedData(PRInt64 aOffset);
   virtual PRInt64 GetCachedDataEnd(PRInt64 aOffset);
   virtual bool    IsDataCachedToEndOfResource(PRInt64 aOffset);
   virtual bool    IsSuspendedByCache(MediaResource** aActiveResource);
   virtual bool    IsSuspended();
 
-  class Listener : public nsIStreamListener,
-                   public nsIInterfaceRequestor,
-                   public nsIChannelEventSink
+  class Listener MOZ_FINAL : public nsIStreamListener,
+                             public nsIInterfaceRequestor,
+                             public nsIChannelEventSink
   {
   public:
     Listener(ChannelMediaResource* aResource) : mResource(aResource) {}
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIREQUESTOBSERVER
     NS_DECL_NSISTREAMLISTENER
     NS_DECL_NSICHANNELEVENTSINK
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -12,16 +12,17 @@
 #include "nsContentUtils.h"
 #include "nsIAppShell.h"
 #include "nsIObserver.h"
 #include "nsServiceManagerUtils.h"
 #include "nsWidgetsCID.h"
 #include "nsXPCOMCIDInternal.h"
 #include "prlog.h"
 #include "VideoUtils.h"
+#include "mozilla/Attributes.h"
 
 using namespace mozilla::layers;
 
 namespace mozilla {
 
 namespace {
 
 #ifdef PR_LOGGING
@@ -1464,17 +1465,17 @@ public:
     mStream->GraphImpl()->AddStream(mStream);
   }
   virtual void Process()
   {
     mStream->Init();
   }
 };
 
-class MediaStreamGraphShutdownObserver : public nsIObserver
+class MediaStreamGraphShutdownObserver MOZ_FINAL : public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 };
 
 }
 
--- a/content/media/nsMediaCache.cpp
+++ b/content/media/nsMediaCache.cpp
@@ -15,16 +15,17 @@
 #include "prio.h"
 #include "nsContentUtils.h"
 #include "nsThreadUtils.h"
 #include "MediaResource.h"
 #include "nsMathUtils.h"
 #include "prlog.h"
 #include "mozilla/Preferences.h"
 #include "FileBlockCache.h"
+#include "mozilla/Attributes.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gMediaCacheLog;
 #define LOG(type, msg) PR_LOG(gMediaCacheLog, type, msg)
 #else
 #define LOG(type, msg)
@@ -54,18 +55,18 @@ static const PRUint32 FREE_BLOCK_SCAN_LI
 // #define DEBUG_VERIFY_CACHE
 #endif
 
 // There is at most one media cache (although that could quite easily be
 // relaxed if we wanted to manage multiple caches with independent
 // size limits).
 static nsMediaCache* gMediaCache;
 
-class nsMediaCacheFlusher : public nsIObserver,
-                            public nsSupportsWeakReference {
+class nsMediaCacheFlusher MOZ_FINAL : public nsIObserver,
+                                      public nsSupportsWeakReference {
   nsMediaCacheFlusher() {}
   ~nsMediaCacheFlusher();
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   static void Init();
 };
--- a/content/svg/content/src/DOMSVGAnimatedLengthList.h
+++ b/content/svg/content/src/DOMSVGAnimatedLengthList.h
@@ -6,16 +6,17 @@
 #ifndef MOZILLA_DOMSVGANIMATEDLENGTHLIST_H__
 #define MOZILLA_DOMSVGANIMATEDLENGTHLIST_H__
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMSVGAnimatedLengthList.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 
 class SVGAnimatedLengthList;
 class SVGLengthList;
 class DOMSVGLengthList;
 
 /**
@@ -98,17 +99,17 @@ class DOMSVGLengthList;
  *
  *      .----<!----.                .----<!----.        .----<!----.
  *      |          |                |          |        |          |
  *   element ~> DOMSVGAnimatedLengthList ~> DOMSVGLengthList ~> DOMSVGLength
  *
  * One drawback of this design is that objects must look up their parent
  * chain to find their element, but that overhead is relatively small.
  */
-class DOMSVGAnimatedLengthList : public nsIDOMSVGAnimatedLengthList
+class DOMSVGAnimatedLengthList MOZ_FINAL : public nsIDOMSVGAnimatedLengthList
 {
   friend class DOMSVGLengthList;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGAnimatedLengthList)
   NS_DECL_NSIDOMSVGANIMATEDLENGTHLIST
 
--- a/content/svg/content/src/DOMSVGAnimatedNumberList.h
+++ b/content/svg/content/src/DOMSVGAnimatedNumberList.h
@@ -6,16 +6,17 @@
 #ifndef MOZILLA_DOMSVGANIMATEDNUMBERLIST_H__
 #define MOZILLA_DOMSVGANIMATEDNUMBERLIST_H__
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMSVGAnimatedNumberList.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 
 class DOMSVGNumberList;
 class SVGAnimatedNumberList;
 class SVGNumberList;
 
 /**
@@ -28,17 +29,17 @@ class SVGNumberList;
  * LENGTH list). The comment for that class largly applies to this one too
  * and will go a long way to helping you understand the architecture here.
  *
  * This class is strongly intertwined with DOMSVGNumberList and DOMSVGNumber.
  * Our DOMSVGNumberList base and anim vals are friends and take care of nulling
  * out our pointers to them when they die (making our pointers to them true
  * weak refs).
  */
-class DOMSVGAnimatedNumberList : public nsIDOMSVGAnimatedNumberList
+class DOMSVGAnimatedNumberList MOZ_FINAL : public nsIDOMSVGAnimatedNumberList
 {
   friend class DOMSVGNumberList;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGAnimatedNumberList)
   NS_DECL_NSIDOMSVGANIMATEDNUMBERLIST
 
--- a/content/svg/content/src/DOMSVGAnimatedTransformList.h
+++ b/content/svg/content/src/DOMSVGAnimatedTransformList.h
@@ -7,16 +7,17 @@
 #ifndef MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__
 #define MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMSVGAnimTransformList.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 
 class DOMSVGTransformList;
 class SVGAnimatedTransformList;
 
 /**
  * Class DOMSVGAnimatedTransformList
@@ -29,17 +30,17 @@ class SVGAnimatedTransformList;
  * and will go a long way to helping you understand the architecture here.
  *
  * This class is strongly intertwined with DOMSVGTransformList and
  * DOMSVGTransform.
  * Our DOMSVGTransformList base and anim vals are friends and take care of
  * nulling out our pointers to them when they die (making our pointers to them
  * true weak refs).
  */
-class DOMSVGAnimatedTransformList : public nsIDOMSVGAnimatedTransformList
+class DOMSVGAnimatedTransformList MOZ_FINAL : public nsIDOMSVGAnimatedTransformList
 {
   friend class DOMSVGTransformList;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGAnimatedTransformList)
   NS_DECL_NSIDOMSVGANIMATEDTRANSFORMLIST
 
--- a/content/svg/content/src/DOMSVGLength.h
+++ b/content/svg/content/src/DOMSVGLength.h
@@ -8,16 +8,17 @@
 
 #include "DOMSVGLengthList.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsIDOMSVGLength.h"
 #include "nsTArray.h"
 #include "SVGLength.h"
+#include "mozilla/Attributes.h"
 
 class nsSVGElement;
 
 // We make DOMSVGLength a pseudo-interface to allow us to QI to it in order to
 // check that the objects that scripts pass to DOMSVGLengthList methods are our
 // *native* length objects.
 //
 // {A8468350-7F7B-4976-9A7E-3765A1DADF9A}
@@ -60,17 +61,17 @@ namespace mozilla {
  * type can find their corresponding internal SVGLength.
  *
  * To use these classes for <length> attributes as well as <list-of-length>
  * attributes, we would need to take a bit from mListIndex and use that to
  * indicate whether the object belongs to a list or non-list attribute, then
  * if-else as appropriate. The bug for doing that work is:
  * https://bugzilla.mozilla.org/show_bug.cgi?id=571734
  */
-class DOMSVGLength : public nsIDOMSVGLength
+class DOMSVGLength MOZ_FINAL : public nsIDOMSVGLength
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGLENGTH_IID)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGLength)
   NS_DECL_NSIDOMSVGLENGTH
 
   /**
--- a/content/svg/content/src/DOMSVGLengthList.h
+++ b/content/svg/content/src/DOMSVGLengthList.h
@@ -8,16 +8,17 @@
 
 #include "DOMSVGAnimatedLengthList.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsIDOMSVGLengthList.h"
 #include "nsTArray.h"
 #include "SVGLengthList.h"
+#include "mozilla/Attributes.h"
 
 class nsIDOMSVGLength;
 class nsSVGElement;
 
 namespace mozilla {
 
 class DOMSVGLength;
 
@@ -33,18 +34,18 @@ class DOMSVGLength;
  * DOMSVGLength. We are a friend of DOMSVGAnimatedLengthList, and are
  * responsible for nulling out our DOMSVGAnimatedLengthList's pointer to us
  * when we die, essentially making its pointer to us a weak pointer. Similarly,
  * our DOMSVGLength items are friends of us and responsible for nulling out our
  * pointers to them.
  *
  * Our DOM items are created lazily on demand as and when script requests them.
  */
-class DOMSVGLengthList : public nsIDOMSVGLengthList,
-                         public nsWrapperCache
+class DOMSVGLengthList MOZ_FINAL : public nsIDOMSVGLengthList,
+                                   public nsWrapperCache
 {
   friend class DOMSVGLength;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGLengthList)
   NS_DECL_NSIDOMSVGLENGTHLIST
 
--- a/content/svg/content/src/DOMSVGMatrix.h
+++ b/content/svg/content/src/DOMSVGMatrix.h
@@ -37,32 +37,33 @@
 #ifndef MOZILLA_DOMSVGMATRIX_H__
 #define MOZILLA_DOMSVGMATRIX_H__
 
 #include "DOMSVGTransform.h"
 #include "gfxMatrix.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMSVGMatrix.h"
+#include "mozilla/Attributes.h"
 
 // We make DOMSVGMatrix a pseudo-interface to allow us to QI to it in order
 // to check that the objects that scripts pass in are our *native* matrix
 // objects.
 //
 // {633419E5-7E88-4C3E-8A9A-856F635E90A3}
 #define MOZILLA_DOMSVGMATRIX_IID \
   { 0x633419E5, 0x7E88, 0x4C3E, \
     { 0x8A, 0x9A, 0x85, 0x6F, 0x63, 0x5E, 0x90, 0xA3 } }
 
 namespace mozilla {
 
 /**
  * DOM wrapper for an SVG matrix.
  */
-class DOMSVGMatrix : public nsIDOMSVGMatrix
+class DOMSVGMatrix MOZ_FINAL : public nsIDOMSVGMatrix
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGMATRIX_IID)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGMatrix)
   NS_DECL_NSIDOMSVGMATRIX
 
   /**
--- a/content/svg/content/src/DOMSVGNumber.h
+++ b/content/svg/content/src/DOMSVGNumber.h
@@ -6,16 +6,17 @@
 #ifndef MOZILLA_DOMSVGNUMBER_H__
 #define MOZILLA_DOMSVGNUMBER_H__
 
 #include "DOMSVGNumberList.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMSVGNumber.h"
 #include "nsTArray.h"
+#include "mozilla/Attributes.h"
 
 class nsSVGElement;
 
 // We make DOMSVGNumber a pseudo-interface to allow us to QI to it in order to
 // check that the objects that scripts pass to DOMSVGNumberList methods are our
 // *native* number objects.
 //
 // {2CA92412-2E1F-4DDB-A16C-52B3B582270D}
@@ -35,17 +36,17 @@ namespace mozilla {
  * SVGSVGElement.createSVGNumber().
  *
  * For the DOM wrapper classes for non-list SVGNumber, see nsSVGNumber2.h.
  *
  * See the architecture comment in DOMSVGAnimatedNumberList.h.
  *
  * See the comment in DOMSVGLength.h (yes, LENGTH), which applies here too.
  */
-class DOMSVGNumber : public nsIDOMSVGNumber
+class DOMSVGNumber MOZ_FINAL : public nsIDOMSVGNumber
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGNUMBER_IID)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGNumber)
   NS_DECL_NSIDOMSVGNUMBER
 
   /**
--- a/content/svg/content/src/DOMSVGNumberList.h
+++ b/content/svg/content/src/DOMSVGNumberList.h
@@ -8,16 +8,17 @@
 
 #include "DOMSVGAnimatedNumberList.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsIDOMSVGNumberList.h"
 #include "nsTArray.h"
 #include "SVGNumberList.h"
+#include "mozilla/Attributes.h"
 
 class nsSVGElement;
 
 namespace mozilla {
 
 class DOMSVGNumber;
 
 /**
@@ -32,18 +33,18 @@ class DOMSVGNumber;
  * DOMSVGNumber. We are a friend of DOMSVGAnimatedNumberList, and are
  * responsible for nulling out our DOMSVGAnimatedNumberList's pointer to us
  * when we die, essentially making its pointer to us a weak pointer. Similarly,
  * our DOMSVGNumber items are friends of us and responsible for nulling out our
  * pointers to them.
  *
  * Our DOM items are created lazily on demand as and when script requests them.
  */
-class DOMSVGNumberList : public nsIDOMSVGNumberList,
-                         public nsWrapperCache
+class DOMSVGNumberList MOZ_FINAL : public nsIDOMSVGNumberList,
+                                   public nsWrapperCache
 {
   friend class DOMSVGNumber;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGNumberList)
   NS_DECL_NSIDOMSVGNUMBERLIST
 
--- a/content/svg/content/src/DOMSVGPathSegList.h
+++ b/content/svg/content/src/DOMSVGPathSegList.h
@@ -9,16 +9,17 @@
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsIDOMSVGPathSegList.h"
 #include "nsSVGElement.h"
 #include "nsTArray.h"
 #include "SVGPathData.h" // IWYU pragma: keep
+#include "mozilla/Attributes.h"
 
 class nsIDOMSVGPathSeg;
 
 namespace mozilla {
 
 class DOMSVGPathSeg;
 class SVGAnimatedPathSegList;
 
@@ -42,18 +43,18 @@ class SVGAnimatedPathSegList;
  * DOMSVGAnimatedLengthList) is contained in this class.
  *
  * This class is strongly intertwined with DOMSVGPathSeg. Our DOMSVGPathSeg
  * items are friends of us and responsible for nulling out our pointers to
  * them when they die.
  *
  * Our DOM items are created lazily on demand as and when script requests them.
  */
-class DOMSVGPathSegList : public nsIDOMSVGPathSegList,
-                          public nsWrapperCache
+class DOMSVGPathSegList MOZ_FINAL : public nsIDOMSVGPathSegList,
+                                    public nsWrapperCache
 {
   friend class DOMSVGPathSeg;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPathSegList)
   NS_DECL_NSIDOMSVGPATHSEGLIST
 
--- a/content/svg/content/src/DOMSVGPoint.h
+++ b/content/svg/content/src/DOMSVGPoint.h
@@ -9,16 +9,17 @@
 #include "DOMSVGPointList.h"
 #include "gfxPoint.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsIDOMSVGPoint.h"
 #include "nsTArray.h"
 #include "SVGPoint.h"
+#include "mozilla/Attributes.h"
 
 class nsSVGElement;
 
 // We make DOMSVGPoint a pseudo-interface to allow us to QI to it in order to
 // check that the objects that scripts pass to DOMSVGPointList methods are
 // our *native* point objects.
 //
 // {d6b6c440-af8d-40ee-856b-02a317cab275}
@@ -39,17 +40,17 @@ namespace mozilla {
  * objects.
  *
  * See the architecture comment in DOMSVGPointList.h for an overview of the
  * important points regarding these DOM wrapper structures.
  *
  * See the architecture comment in DOMSVGLength.h (yes, LENGTH) for an overview
  * of the important points regarding how this specific class works.
  */
-class DOMSVGPoint : public nsIDOMSVGPoint
+class DOMSVGPoint MOZ_FINAL : public nsIDOMSVGPoint
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGPOINT_IID)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGPoint)
   NS_DECL_NSIDOMSVGPOINT
 
   /**
--- a/content/svg/content/src/DOMSVGPointList.h
+++ b/content/svg/content/src/DOMSVGPointList.h
@@ -9,16 +9,17 @@
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsIDOMSVGPointList.h"
 #include "nsSVGElement.h"
 #include "nsTArray.h"
 #include "SVGPointList.h" // IWYU pragma: keep
+#include "mozilla/Attributes.h"
 
 class nsIDOMSVGPoint;
 
 namespace mozilla {
 
 class DOMSVGPoint;
 class SVGAnimatedPointList;
 
@@ -42,18 +43,18 @@ class SVGAnimatedPointList;
  * DOMSVGAnimatedLengthList) is contained in this class.
  *
  * This class is strongly intertwined with DOMSVGPoint. Our DOMSVGPoint
  * items are friends of us and responsible for nulling out our pointers to
  * them when they die.
  *
  * Our DOM items are created lazily on demand as and when script requests them.
  */
-class DOMSVGPointList : public nsIDOMSVGPointList,
-                        public nsWrapperCache
+class DOMSVGPointList MOZ_FINAL : public nsIDOMSVGPointList,
+                                  public nsWrapperCache
 {
   friend class DOMSVGPoint;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPointList)
   NS_DECL_NSIDOMSVGPOINTLIST
 
--- a/content/svg/content/src/DOMSVGStringList.h
+++ b/content/svg/content/src/DOMSVGStringList.h
@@ -6,16 +6,17 @@
 #ifndef MOZILLA_DOMSVGSTRINGLIST_H__
 #define MOZILLA_DOMSVGSTRINGLIST_H__
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMSVGStringList.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 
 class SVGStringList;
 
 /**
  * Class DOMSVGStringList
  *
@@ -37,17 +38,17 @@ class SVGStringList;
  * Second, since there is no nsIDOMSVGString interface in SVG, we have no
  * DOMSVGString items to maintain. As far as script is concerned, objects
  * of this class contain a list of strings, not a list of mutable objects
  * like the other SVG list types. As a result, unlike the other SVG list
  * types, this class does not create its items lazily on demand and store
  * them so it can return the same objects each time. It simply returns a new
  * string each time any given item is requested.
  */
-class DOMSVGStringList : public nsIDOMSVGStringList
+class DOMSVGStringList MOZ_FINAL : public nsIDOMSVGStringList
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGStringList)
   NS_DECL_NSIDOMSVGSTRINGLIST
 
   /**
    * Factory method to create and return a DOMSVGStringList wrapper
--- a/content/svg/content/src/DOMSVGTests.h
+++ b/content/svg/content/src/DOMSVGTests.h
@@ -19,16 +19,18 @@ class DOMSVGStringList;
 }
 
 class DOMSVGTests : public nsIDOMSVGTests
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMSVGTESTS
 
+  virtual ~DOMSVGTests() {}
+
   friend class mozilla::DOMSVGStringList;
   typedef mozilla::SVGStringList SVGStringList;
 
   /**
    * Compare the language name(s) in a systemLanguage attribute to the
    * user's language preferences, as defined in
    * http://www.w3.org/TR/SVG11/struct.html#SystemLanguageAttribute
    * We have a match if a language name in the users language preferences
--- a/content/svg/content/src/DOMSVGTransform.h
+++ b/content/svg/content/src/DOMSVGTransform.h
@@ -10,16 +10,17 @@
 #include "DOMSVGTransformList.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsID.h"
 #include "nsIDOMSVGTransform.h"
 #include "nsTArray.h"
 #include "SVGTransform.h"
+#include "mozilla/Attributes.h"
 
 class nsSVGElement;
 
 struct gfxMatrix;
 
 // We make DOMSVGTransform a pseudo-interface to allow us to QI to it in order
 // to check that the objects that scripts pass in are our our *native* transform
 // objects.
@@ -33,17 +34,17 @@ struct gfxMatrix;
 
 namespace mozilla {
 
 class DOMSVGMatrix;
 
 /**
  * DOM wrapper for an SVG transform. See DOMSVGLength.h.
  */
-class DOMSVGTransform : public nsIDOMSVGTransform
+class DOMSVGTransform MOZ_FINAL : public nsIDOMSVGTransform
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGTRANSFORM_IID)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGTransform)
   NS_DECL_NSIDOMSVGTRANSFORM
 
   /**
--- a/content/svg/content/src/DOMSVGTransformList.h
+++ b/content/svg/content/src/DOMSVGTransformList.h
@@ -9,34 +9,35 @@
 
 #include "DOMSVGAnimatedTransformList.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsIDOMSVGTransformList.h"
 #include "nsTArray.h"
 #include "SVGTransformList.h"
+#include "mozilla/Attributes.h"
 
 class nsIDOMSVGTransform;
 class nsSVGElement;
 
 namespace mozilla {
 
 class DOMSVGTransform;
 
 /**
  * Class DOMSVGTransformList
  *
  * This class is used to create the DOM tearoff objects that wrap internal
  * SVGTransformList objects.
  *
  * See the architecture comment in DOMSVGAnimatedTransformList.h.
  */
-class DOMSVGTransformList : public nsIDOMSVGTransformList,
-                            public nsWrapperCache
+class DOMSVGTransformList MOZ_FINAL : public nsIDOMSVGTransformList,
+                                      public nsWrapperCache
 {
   friend class DOMSVGTransform;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGTransformList)
   NS_DECL_NSIDOMSVGTRANSFORMLIST
 
--- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.h
+++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.h
@@ -9,16 +9,17 @@
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMError.h"
 #include "nsError.h"
 #include "nsIDOMSVGAnimPresAspRatio.h"
 #include "nsIDOMSVGPresAspectRatio.h"
 #include "nsISMILAttr.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsISMILAnimationElement;
 class nsSMILValue;
 
 namespace mozilla {
 
 class SVGAnimatedPreserveAspectRatio;
 
@@ -142,17 +143,17 @@ private:
   bool mIsBaseSet;
 
   nsresult ToDOMBaseVal(nsIDOMSVGPreserveAspectRatio **aResult,
                         nsSVGElement* aSVGElement);
   nsresult ToDOMAnimVal(nsIDOMSVGPreserveAspectRatio **aResult,
                         nsSVGElement* aSVGElement);
 
 public:
-  struct DOMBaseVal : public nsIDOMSVGPreserveAspectRatio
+  struct DOMBaseVal MOZ_FINAL : public nsIDOMSVGPreserveAspectRatio
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMBaseVal)
 
     DOMBaseVal(SVGAnimatedPreserveAspectRatio* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     SVGAnimatedPreserveAspectRatio* mVal; // kept alive because it belongs to mSVGElement
@@ -164,17 +165,17 @@ public:
       { return mVal->SetBaseAlign(aAlign, mSVGElement); }
 
     NS_IMETHOD GetMeetOrSlice(PRUint16* aMeetOrSlice)
       { *aMeetOrSlice = mVal->GetBaseValue().GetMeetOrSlice(); return NS_OK; }
     NS_IMETHOD SetMeetOrSlice(PRUint16 aMeetOrSlice)
       { return mVal->SetBaseMeetOrSlice(aMeetOrSlice, mSVGElement); }
   };
 
-  struct DOMAnimVal : public nsIDOMSVGPreserveAspectRatio
+  struct DOMAnimVal MOZ_FINAL : public nsIDOMSVGPreserveAspectRatio
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimVal)
 
     DOMAnimVal(SVGAnimatedPreserveAspectRatio* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     SVGAnimatedPreserveAspectRatio* mVal; // kept alive because it belongs to mSVGElement
@@ -196,17 +197,17 @@ public:
       mSVGElement->FlushAnimations();
       *aMeetOrSlice = mVal->GetAnimValue().GetMeetOrSlice();
       return NS_OK;
     }
     NS_IMETHOD SetMeetOrSlice(PRUint16 aValue)
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
   };
 
-  struct DOMAnimPAspectRatio : public nsIDOMSVGAnimatedPreserveAspectRatio
+  struct DOMAnimPAspectRatio MOZ_FINAL : public nsIDOMSVGAnimatedPreserveAspectRatio
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimPAspectRatio)
 
     DOMAnimPAspectRatio(SVGAnimatedPreserveAspectRatio* aVal,
                         nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
@@ -217,17 +218,17 @@ public:
 
     NS_IMETHOD GetBaseVal(nsIDOMSVGPreserveAspectRatio **aBaseVal)
       { return mVal->ToDOMBaseVal(aBaseVal, mSVGElement); }
 
     NS_IMETHOD GetAnimVal(nsIDOMSVGPreserveAspectRatio **aAnimVal)
       { return mVal->ToDOMAnimVal(aAnimVal, mSVGElement); }
   };
 
-  struct SMILPreserveAspectRatio : public nsISMILAttr
+  struct SMILPreserveAspectRatio MOZ_FINAL : public nsISMILAttr
   {
   public:
     SMILPreserveAspectRatio(SVGAnimatedPreserveAspectRatio* aVal,
                             nsSVGElement* aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     // These will stay alive because a nsISMILAttr only lives as long
     // as the Compositing step, and DOM elements don't get a chance to
--- a/content/svg/content/src/nsSVGAngle.cpp
+++ b/content/svg/content/src/nsSVGAngle.cpp
@@ -9,28 +9,29 @@
 #include "prdtoa.h"
 #include "nsTextFormatter.h"
 #include "nsSVGUtils.h"
 #include "nsSVGMarkerElement.h"
 #include "nsMathUtils.h"
 #include "nsContentUtils.h" // NS_ENSURE_FINITE
 #include "nsSMILValue.h"
 #include "SVGOrientSMILType.h"
+#include "mozilla/Attributes.h"
 
 using namespace mozilla;
 
 /**
  * Mutable SVGAngle class for SVGSVGElement.createSVGAngle().
  *
  * Note that this class holds its own nsSVGAngle, which therefore can't be
  * animated. This means SVGMarkerElement::setOrientToAngle(angle) must copy
  * any DOMSVGAngle passed in. Perhaps this is wrong and inconsistent with
  * other parts of SVG, but it's how the code works for now.
  */
-class DOMSVGAngle : public nsIDOMSVGAngle
+class DOMSVGAngle MOZ_FINAL : public nsIDOMSVGAngle
 {
 public:
   NS_DECL_ISUPPORTS
 
   DOMSVGAngle()
     { mVal.Init(); }
     
   NS_IMETHOD GetUnitType(PRUint16* aResult)
--- a/content/svg/content/src/nsSVGAngle.h
+++ b/content/svg/content/src/nsSVGAngle.h
@@ -9,16 +9,17 @@
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMError.h"
 #include "nsError.h"
 #include "nsIDOMSVGAngle.h"
 #include "nsIDOMSVGAnimatedAngle.h"
 #include "nsISMILAttr.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsISMILAnimationElement;
 class nsSMILValue;
 class nsSVGOrientType;
 
 class nsSVGAngle
 {
   friend class DOMSVGAngle;
@@ -72,17 +73,17 @@ private:
   void SetBaseValueInSpecifiedUnits(float aValue, nsSVGElement *aSVGElement);
   nsresult NewValueSpecifiedUnits(PRUint16 aUnitType, float aValue,
                                   nsSVGElement *aSVGElement);
   nsresult ConvertToSpecifiedUnits(PRUint16 aUnitType, nsSVGElement *aSVGElement);
   nsresult ToDOMBaseVal(nsIDOMSVGAngle **aResult, nsSVGElement* aSVGElement);
   nsresult ToDOMAnimVal(nsIDOMSVGAngle **aResult, nsSVGElement* aSVGElement);
 
 public:
-  struct DOMBaseVal : public nsIDOMSVGAngle
+  struct DOMBaseVal MOZ_FINAL : public nsIDOMSVGAngle
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMBaseVal)
 
     DOMBaseVal(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGAngle* mVal; // kept alive because it belongs to mSVGElement
@@ -111,17 +112,17 @@ public:
                                       float valueInSpecifiedUnits)
       { return mVal->NewValueSpecifiedUnits(unitType, valueInSpecifiedUnits,
                                      mSVGElement); }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { return mVal->ConvertToSpecifiedUnits(unitType, mSVGElement); }
   };
 
-  struct DOMAnimVal : public nsIDOMSVGAngle
+  struct DOMAnimVal MOZ_FINAL : public nsIDOMSVGAngle
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimVal)
 
     DOMAnimVal(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGAngle* mVal; // kept alive because it belongs to mSVGElement
@@ -148,17 +149,17 @@ public:
     NS_IMETHOD NewValueSpecifiedUnits(PRUint16 unitType,
                                       float valueInSpecifiedUnits)
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
   };
 
-  struct DOMAnimatedAngle : public nsIDOMSVGAnimatedAngle
+  struct DOMAnimatedAngle MOZ_FINAL : public nsIDOMSVGAnimatedAngle
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedAngle)
 
     DOMAnimatedAngle(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGAngle* mVal; // kept alive because it belongs to content
@@ -171,17 +172,17 @@ public:
       { return mVal->ToDOMAnimVal(aAnimVal, mSVGElement); }
   };
 
   // We do not currently implemente a SMILAngle struct because in SVG 1.1 the
   // only *animatable* attribute that takes an <angle> is 'orient', on the
   // 'marker' element, and 'orient' must be special cased since it can also
   // take the value 'auto', making it a more complex type.
 
-  struct SMILOrient : public nsISMILAttr
+  struct SMILOrient MOZ_FINAL : public nsISMILAttr
   {
   public:
     SMILOrient(nsSVGOrientType* aOrientType,
                nsSVGAngle* aAngle,
                nsSVGElement* aSVGElement)
       : mOrientType(aOrientType)
       , mAngle(aAngle)
       , mSVGElement(aSVGElement)
--- a/content/svg/content/src/nsSVGBoolean.h
+++ b/content/svg/content/src/nsSVGBoolean.h
@@ -8,16 +8,17 @@
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsError.h"
 #include "nsIDOMSVGAnimatedBoolean.h"
 #include "nsISMILAttr.h"
 #include "nsISupportsImpl.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsISMILAnimationElement;
 class nsSMILValue;
 
 class nsSVGBoolean
 {
 
 public:
@@ -46,17 +47,17 @@ public:
 private:
 
   bool mAnimVal;
   bool mBaseVal;
   bool mIsAnimated;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
 public:
-  struct DOMAnimatedBoolean : public nsIDOMSVGAnimatedBoolean
+  struct DOMAnimatedBoolean MOZ_FINAL : public nsIDOMSVGAnimatedBoolean
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedBoolean)
 
     DOMAnimatedBoolean(nsSVGBoolean* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGBoolean* mVal; // kept alive because it belongs to content
--- a/content/svg/content/src/nsSVGClass.h
+++ b/content/svg/content/src/nsSVGClass.h
@@ -7,16 +7,17 @@
 #define __NS_SVGCLASS_H__
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMError.h"
 #include "nsIDOMSVGAnimatedString.h"
 #include "nsISMILAttr.h"
 #include "nsString.h"
+#include "mozilla/Attributes.h"
 
 class nsSVGStylableElement;
 
 class nsSVGClass
 {
 
 public:
   void Init() {
@@ -38,17 +39,17 @@ public:
   // Returns a new nsISMILAttr object that the caller must delete
   nsISMILAttr* ToSMILAttr(nsSVGStylableElement *aSVGElement);
 
 private:
 
   nsAutoPtr<nsString> mAnimVal;
 
 public:
-  struct DOMAnimatedString : public nsIDOMSVGAnimatedString
+  struct DOMAnimatedString MOZ_FINAL : public nsIDOMSVGAnimatedString
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedString)
 
     DOMAnimatedString(nsSVGClass *aVal, nsSVGStylableElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGClass* mVal; // kept alive because it belongs to content
--- a/content/svg/content/src/nsSVGEnum.h
+++ b/content/svg/content/src/nsSVGEnum.h
@@ -7,16 +7,17 @@
 #define __NS_SVGENUM_H__
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsError.h"
 #include "nsIDOMSVGAnimatedEnum.h"
 #include "nsISMILAttr.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsIAtom;
 class nsISMILAnimationElement;
 class nsSMILValue;
 
 typedef PRUint8 nsSVGEnumValue;
 
 struct nsSVGEnumMapping {
@@ -57,17 +58,17 @@ private:
   nsSVGEnumValue mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
   bool mIsAnimated;
   bool mIsBaseSet;
 
   nsSVGEnumMapping *GetMapping(nsSVGElement *aSVGElement);
 
 public:
-  struct DOMAnimatedEnum : public nsIDOMSVGAnimatedEnumeration
+  struct DOMAnimatedEnum MOZ_FINAL : public nsIDOMSVGAnimatedEnumeration
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedEnum)
 
     DOMAnimatedEnum(nsSVGEnum* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGEnum *mVal; // kept alive because it belongs to content
--- a/content/svg/content/src/nsSVGInteger.h
+++ b/content/svg/content/src/nsSVGInteger.h
@@ -7,16 +7,17 @@
 #define __NS_SVGINTEGER_H__
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsError.h"
 #include "nsIDOMSVGAnimatedInteger.h"
 #include "nsISMILAttr.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsISMILAnimationElement;
 class nsSMILValue;
 
 class nsSVGInteger
 {
 
 public:
@@ -56,17 +57,17 @@ private:
 
   PRInt32 mAnimVal;
   PRInt32 mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
   bool mIsAnimated;
   bool mIsBaseSet;
 
 public:
-  struct DOMAnimatedInteger : public nsIDOMSVGAnimatedInteger
+  struct DOMAnimatedInteger MOZ_FINAL : public nsIDOMSVGAnimatedInteger
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedInteger)
 
     DOMAnimatedInteger(nsSVGInteger* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGInteger* mVal; // kept alive because it belongs to content
--- a/content/svg/content/src/nsSVGIntegerPair.h
+++ b/content/svg/content/src/nsSVGIntegerPair.h
@@ -7,16 +7,17 @@
 #define __NS_SVGINTEGERPAIR_H__
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsError.h"
 #include "nsIDOMSVGAnimatedInteger.h"
 #include "nsISMILAttr.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsISMILAnimationElement;
 class nsSMILValue;
 
 class nsSVGIntegerPair
 {
 
 public:
@@ -63,17 +64,17 @@ private:
 
   PRInt32 mAnimVal[2];
   PRInt32 mBaseVal[2];
   PRUint8 mAttrEnum; // element specified tracking for attribute
   bool mIsAnimated;
   bool mIsBaseSet;
 
 public:
-  struct DOMAnimatedInteger : public nsIDOMSVGAnimatedInteger
+  struct DOMAnimatedInteger MOZ_FINAL : public nsIDOMSVGAnimatedInteger
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedInteger)
 
     DOMAnimatedInteger(nsSVGIntegerPair* aVal, PairIndex aIndex, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement), mIndex(aIndex) {}
 
     nsSVGIntegerPair* mVal; // kept alive because it belongs to content
--- a/content/svg/content/src/nsSVGLength2.cpp
+++ b/content/svg/content/src/nsSVGLength2.cpp
@@ -172,23 +172,24 @@ nsSVGLength2::GetAxisLength(nsSVGSVGElem
     return 1;
 
   return FixAxisLength(aCtx->GetLength(mCtxType));
 }
 
 float
 nsSVGLength2::GetAxisLength(nsIFrame *aNonSVGFrame) const
 {
-  gfxRect rect = nsSVGIntegrationUtils::GetSVGRectForNonSVGFrame(aNonSVGFrame);
+  gfxSize size =
+    nsSVGIntegrationUtils::GetSVGCoordContextForNonSVGFrame(aNonSVGFrame);
   float length;
   switch (mCtxType) {
-  case nsSVGUtils::X: length = rect.Width(); break;
-  case nsSVGUtils::Y: length = rect.Height(); break;
+  case nsSVGUtils::X: length = size.width; break;
+  case nsSVGUtils::Y: length = size.height; break;
   case nsSVGUtils::XY:
-    length = nsSVGUtils::ComputeNormalizedHypotenuse(rect.Width(), rect.Height());
+    length = nsSVGUtils::ComputeNormalizedHypotenuse(size.width, size.height);
     break;
   default:
     NS_NOTREACHED("Unknown axis type");
     length = 1;
     break;
   }
   return FixAxisLength(length);
 }
--- a/content/svg/content/src/nsSVGMarkerElement.h
+++ b/content/svg/content/src/nsSVGMarkerElement.h
@@ -10,16 +10,17 @@
 #include "nsIDOMSVGFitToViewBox.h"
 #include "nsIDOMSVGMarkerElement.h"
 #include "nsSVGAngle.h"
 #include "nsSVGEnum.h"
 #include "nsSVGGraphicElement.h"
 #include "nsSVGLength2.h"
 #include "nsSVGViewBox.h"
 #include "SVGAnimatedPreserveAspectRatio.h"
+#include "mozilla/Attributes.h"
 
 class nsSVGOrientType
 {
 public:
   nsSVGOrientType()
    : mAnimVal(nsIDOMSVGMarkerElement::SVG_MARKER_ORIENT_ANGLE),
      mBaseVal(nsIDOMSVGMarkerElement::SVG_MARKER_ORIENT_ANGLE) {}
 
@@ -41,17 +42,17 @@ public:
 
   nsresult ToDOMAnimatedEnum(nsIDOMSVGAnimatedEnumeration **aResult,
                              nsSVGElement* aSVGElement);
 
 private:
   nsSVGEnumValue mAnimVal;
   nsSVGEnumValue mBaseVal;
 
-  struct DOMAnimatedEnum : public nsIDOMSVGAnimatedEnumeration
+  struct DOMAnimatedEnum MOZ_FINAL : public nsIDOMSVGAnimatedEnumeration
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedEnum)
 
     DOMAnimatedEnum(nsSVGOrientType* aVal,
                     nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
--- a/content/svg/content/src/nsSVGNumber2.cpp
+++ b/content/svg/content/src/nsSVGNumber2.cpp
@@ -7,18 +7,19 @@
 #include "nsSVGUtils.h"
 #include "nsTextFormatter.h"
 #include "prdtoa.h"
 #include "nsMathUtils.h"
 #include "nsContentUtils.h" // NS_ENSURE_FINITE
 #include "nsSMILValue.h"
 #include "nsSMILFloatType.h"
 #include "nsIDOMSVGNumber.h"
+#include "mozilla/Attributes.h"
 
-class DOMSVGNumber : public nsIDOMSVGNumber
+class DOMSVGNumber MOZ_FINAL : public nsIDOMSVGNumber
 {
 public:
   NS_DECL_ISUPPORTS
 
   DOMSVGNumber() 
     : mVal(0) {}
     
   NS_IMETHOD GetValue(float* aResult)
--- a/content/svg/content/src/nsSVGNumber2.h
+++ b/content/svg/content/src/nsSVGNumber2.h
@@ -8,16 +8,17 @@
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsError.h"
 #include "nsIDOMSVGAnimatedNumber.h"
 #include "nsISMILAttr.h"
 #include "nsMathUtils.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsISMILAnimationElement;
 class nsSMILValue;
 
 class nsSVGNumber2
 {
 
 public:
@@ -56,17 +57,17 @@ private:
 
   float mAnimVal;
   float mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
   bool mIsAnimated;
   bool mIsBaseSet;
 
 public:
-  struct DOMAnimatedNumber : public nsIDOMSVGAnimatedNumber
+  struct DOMAnimatedNumber MOZ_FINAL : public nsIDOMSVGAnimatedNumber
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedNumber)
 
     DOMAnimatedNumber(nsSVGNumber2* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGNumber2* mVal; // kept alive because it belongs to content
--- a/content/svg/content/src/nsSVGNumberPair.h
+++ b/content/svg/content/src/nsSVGNumberPair.h
@@ -8,16 +8,17 @@
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsError.h"
 #include "nsIDOMSVGAnimatedNumber.h"
 #include "nsISMILAttr.h"
 #include "nsMathUtils.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsISMILAnimationElement;
 class nsSMILValue;
 
 class nsSVGNumberPair
 {
 
 public:
@@ -64,17 +65,17 @@ private:
 
   float mAnimVal[2];
   float mBaseVal[2];
   PRUint8 mAttrEnum; // element specified tracking for attribute
   bool mIsAnimated;
   bool mIsBaseSet;
 
 public:
-  struct DOMAnimatedNumber : public nsIDOMSVGAnimatedNumber
+  struct DOMAnimatedNumber MOZ_FINAL : public nsIDOMSVGAnimatedNumber
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedNumber)
 
     DOMAnimatedNumber(nsSVGNumberPair* aVal, PairIndex aIndex, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement), mIndex(aIndex) {}
 
     nsSVGNumberPair* mVal; // kept alive because it belongs to content
--- a/content/svg/content/src/nsSVGRect.h
+++ b/content/svg/content/src/nsSVGRect.h
@@ -3,29 +3,30 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __NS_SVGRECT_H__
 #define __NS_SVGRECT_H__
 
 #include "gfxRect.h"
 #include "nsIDOMSVGRect.h"
+#include "mozilla/Attributes.h"
 
 nsresult
 NS_NewSVGRect(nsIDOMSVGRect** result,
               float x=0.0f, float y=0.0f,
               float width=0.0f, float height=0.0f);
 
 nsresult
 NS_NewSVGRect(nsIDOMSVGRect** result, const gfxRect& rect);
 
 ////////////////////////////////////////////////////////////////////////
 // nsSVGRect class
 
-class nsSVGRect : public nsIDOMSVGRect
+class nsSVGRect MOZ_FINAL : public nsIDOMSVGRect
 {
 public:
   nsSVGRect(float x=0.0f, float y=0.0f, float w=0.0f, float h=0.0f);
 
   // nsISupports interface:
   NS_DECL_ISUPPORTS
 
   // nsIDOMSVGRect interface:
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -1140,26 +1140,16 @@ nsSVGSVGElement::GetLength(PRUint8 aCtxT
   case nsSVGUtils::Y:
     return h;
   case nsSVGUtils::XY:
     return float(nsSVGUtils::ComputeNormalizedHypotenuse(w, h));
   }
   return 0;
 }
 
-void
-nsSVGSVGElement::SyncWidthOrHeight(nsIAtom* aName, nsSVGElement *aTarget) const
-{
-  NS_ASSERTION(aName == nsGkAtoms::width || aName == nsGkAtoms::height,
-               "The clue is in the function name");
-
-  PRUint32 index = *sLengthInfo[WIDTH].mName == aName ? WIDTH : HEIGHT;
-  aTarget->SetLength(aName, mLengthAttributes[index]);
-}
-
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 /* virtual */ gfxMatrix
 nsSVGSVGElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
                                           TransformTypes aWhich) const
 {
   NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
--- a/content/svg/content/src/nsSVGSVGElement.h
+++ b/content/svg/content/src/nsSVGSVGElement.h
@@ -13,16 +13,17 @@
 #include "nsIDOMSVGPoint.h"
 #include "nsIDOMSVGSVGElement.h"
 #include "nsIDOMSVGZoomAndPan.h"
 #include "nsSVGEnum.h"
 #include "nsSVGLength2.h"
 #include "nsSVGStylableElement.h"
 #include "nsSVGViewBox.h"
 #include "SVGAnimatedPreserveAspectRatio.h"
+#include "mozilla/Attributes.h"
 
 class nsIDOMSVGMatrix;
 class nsSMILTimeContainer;
 class nsSVGViewElement;
 namespace mozilla {
   class SVGFragmentIdentifier;
 }
 
@@ -54,17 +55,17 @@ public:
   nsresult ToDOMVal(nsSVGSVGElement *aElement, nsIDOMSVGPoint **aResult);
 
   bool operator!=(const nsSVGTranslatePoint &rhs) const {
     return mX != rhs.mX || mY != rhs.mY;
   }
 
 private:
 
-  struct DOMVal : public nsIDOMSVGPoint {
+  struct DOMVal MOZ_FINAL : public nsIDOMSVGPoint {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMVal)
 
     DOMVal(nsSVGTranslatePoint* aVal, nsSVGSVGElement *aElement)
       : mVal(aVal), mElement(aElement) {}
 
     NS_IMETHOD GetX(float *aValue)
       { *aValue = mVal->GetX(); return NS_OK; }
@@ -168,18 +169,16 @@ public:
 
   // nsSVGElement specializations:
   virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
                       TransformTypes aWhich = eAllTransforms) const;
   virtual bool HasValidDimensions() const;
  
   // nsSVGSVGElement methods:
   float GetLength(PRUint8 mCtxType);
-  // Copy our width or height to the target
-  void SyncWidthOrHeight(nsIAtom* aName, nsSVGElement *aTarget) const;
 
   // public helpers:
 
   /**
    * Returns true if this element has a base/anim value for its "viewBox"
    * attribute that defines a viewBox rectangle with finite values.
    *
    * Note that this does not check whether we need to synthesize a viewBox,
--- a/content/svg/content/src/nsSVGString.h
+++ b/content/svg/content/src/nsSVGString.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __NS_SVGSTRING_H__
 #define __NS_SVGSTRING_H__
 
 #include "nsDOMError.h"
 #include "nsIDOMSVGAnimatedString.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsSVGString
 {
 
 public:
   void Init(PRUint8 aAttrEnum) {
     mAnimVal = nsnull;
     mAttrEnum = aAttrEnum;
@@ -44,17 +45,17 @@ public:
 
 private:
 
   nsAutoPtr<nsString> mAnimVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
   bool mIsBaseSet;
 
 public:
-  struct DOMAnimatedString : public nsIDOMSVGAnimatedString
+  struct DOMAnimatedString MOZ_FINAL : public nsIDOMSVGAnimatedString
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedString)
 
     DOMAnimatedString(nsSVGString *aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGString* mVal; // kept alive because it belongs to content
--- a/content/svg/content/src/nsSVGViewBox.h
+++ b/content/svg/content/src/nsSVGViewBox.h
@@ -9,16 +9,17 @@
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMError.h"
 #include "nsError.h"
 #include "nsIDOMSVGAnimatedRect.h"
 #include "nsIDOMSVGRect.h"
 #include "nsISMILAttr.h"
 #include "nsSVGElement.h"
+#include "mozilla/Attributes.h"
 
 class nsISMILAnimationElement;
 class nsSMILValue;
 
 struct nsSVGViewBoxRect
 {
   float x, y;
   float width, height;
@@ -73,17 +74,17 @@ public:
   nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement);
   
 private:
 
   nsSVGViewBoxRect mBaseVal;
   nsAutoPtr<nsSVGViewBoxRect> mAnimVal;
   bool mHasBaseVal;
 
-  struct DOMBaseVal : public nsIDOMSVGRect
+  struct DOMBaseVal MOZ_FINAL : public nsIDOMSVGRect
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMBaseVal)
 
     DOMBaseVal(nsSVGViewBox *aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGViewBox* mVal; // kept alive because it belongs to content
@@ -99,17 +100,17 @@ private:
       { *aHeight = mVal->GetBaseValue().height; return NS_OK; }
 
     NS_IMETHOD SetX(float aX);
     NS_IMETHOD SetY(float aY);
     NS_IMETHOD SetWidth(float aWidth);
     NS_IMETHOD SetHeight(float aHeight);
   };
 
-  struct DOMAnimVal : public nsIDOMSVGRect
+  struct DOMAnimVal MOZ_FINAL : public nsIDOMSVGRect
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimVal)
 
     DOMAnimVal(nsSVGViewBox *aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGViewBox* mVal; // kept alive because it belongs to content
@@ -148,17 +149,17 @@ private:
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
     NS_IMETHOD SetWidth(float aWidth)
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
     NS_IMETHOD SetHeight(float aHeight)
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
   };
 
 public:
-  struct DOMAnimatedRect : public nsIDOMSVGAnimatedRect
+  struct DOMAnimatedRect MOZ_FINAL : public nsIDOMSVGAnimatedRect
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedRect)
 
     DOMAnimatedRect(nsSVGViewBox *aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGViewBox* mVal; // kept alive because it belongs to content
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -50,17 +50,17 @@
 #include "nsIPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsGUIEvent.h"
 
 #include "prprf.h"
 #include "nsNodeUtils.h"
 
 // Nasty hack.  Maybe we could move some of the classinfo utility methods
-// (e.g. WrapNative and ThrowJSException) over to nsContentUtils?
+// (e.g. WrapNative) over to nsContentUtils?
 #include "nsDOMClassInfo.h"
 #include "nsJSUtils.h"
 
 #include "mozilla/dom/Element.h"
 
 // Helper classes
 
 /***********************************************************************/
@@ -113,34 +113,34 @@ XBLResolve(JSContext *cx, JSHandleObject
   // We have this field.  Time to install it.  Get our node.
   JSClass* nodeClass = ::JS_GetClass(origObj);
   if (!nodeClass) {
     return JS_FALSE;
   }
   
   if (~nodeClass->flags &
       (JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS)) {
-    nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
+    xpc::Throw(cx, NS_ERROR_UNEXPECTED);
     return JS_FALSE;
   }
 
   nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
     do_QueryInterface(static_cast<nsISupports*>(::JS_GetPrivate(origObj)));
   if (!xpcWrapper) {
     // Looks like whatever |origObj| is it's not our nsIContent.  It might well
     // be the proto our binding installed, however, where the private is the
     // nsXBLDocumentInfo, so just baul out quietly.  Do NOT throw an exception
     // here.
     // We could make this stricter by checking the class maybe, but whatever
     return JS_TRUE;
   }
 
   nsCOMPtr<nsIContent> content = do_QueryWrappedNative(xpcWrapper);
   if (!content) {
-    nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
+    xpc::Throw(cx, NS_ERROR_UNEXPECTED);
     return JS_FALSE;
   }
 
   // This mirrors code in nsXBLProtoImpl::InstallImplementation
   nsIDocument* doc = content->OwnerDoc();
 
   nsIScriptGlobalObject* global = doc->GetScriptGlobalObject();
   if (!global) {
@@ -155,20 +155,17 @@ XBLResolve(JSContext *cx, JSHandleObject
 
   // Now we either resolve or fail
   bool didInstall;
   nsresult rv = field->InstallField(context, origObj,
                                     content->NodePrincipal(),
                                     protoBinding->DocURI(),
                                     &didInstall);
   if (NS_FAILED(rv)) {
-    if (!::JS_IsExceptionPending(cx)) {
-      nsDOMClassInfo::ThrowJSException(cx, rv);
-    }
-
+    xpc::Throw(cx, rv);
     return JS_FALSE;
   }
 
   if (didInstall) {
     *objp = origObj;
   }
   // else we didn't resolve this field after all
 
@@ -252,17 +249,17 @@ TraverseKey(nsISupports* aKey, nsInserti
   cb.NoteXPCOMChild(aKey);
   if (aData) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(*aData, nsXBLInsertionPoint,
                                                "mInsertionPointTable value")
   }
   return PL_DHASH_NEXT;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLBinding)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLBinding)
   // XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
   //     mPrototypeBinding is weak.
   if (tmp->mContent) {
     nsXBLBinding::UninstallAnonymousContent(tmp->mContent->OwnerDoc(),
                                             tmp->mContent);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent)
--- a/content/xbl/src/nsXBLInsertionPoint.cpp
+++ b/content/xbl/src/nsXBLInsertionPoint.cpp
@@ -19,17 +19,17 @@ nsXBLInsertionPoint::nsXBLInsertionPoint
 nsXBLInsertionPoint::~nsXBLInsertionPoint()
 {
   if (mDefaultContent) {
     nsXBLBinding::UninstallAnonymousContent(mDefaultContent->OwnerDoc(),
                                             mDefaultContent);
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContentTemplate)
   if (tmp->mDefaultContent) {
     nsXBLBinding::UninstallAnonymousContent(tmp->mDefaultContent->OwnerDoc(),
                                             tmp->mDefaultContent);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContent)
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -222,17 +222,17 @@ private:
 
   static nsFixedSizeAllocator* kPool;
   static PRUint32 gRefCnt;
 };
 
 PRUint32 nsXBLInsertionPointEntry::gRefCnt = 0;
 nsFixedSizeAllocator* nsXBLInsertionPointEntry::kPool;
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPointEntry)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPointEntry)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPointEntry)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInsertionParent)
   if (tmp->mDefaultContent) {
     nsAutoScriptBlocker scriptBlocker;
     // mDefaultContent is a sort of anonymous content within the XBL
     // document, and we own and manage it.  Unhook it here, since we're going
     // away.
     tmp->mDefaultContent->UnbindFromTree();
--- a/content/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -48,16 +48,17 @@
 #include "nsXBLSerialize.h"
 
 #ifdef MOZ_XUL
 #include "nsXULPrototypeCache.h"
 #endif
 #include "nsIDOMEventListener.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/Attributes.h"
 
 using namespace mozilla;
 
 #define NS_MAX_XBL_BINDING_RECURSION 20
 
 nsXBLService* nsXBLService::gInstance = nsnull;
 
 static bool
@@ -177,17 +178,18 @@ static const size_t kBucketSizes[] = {
 
 static const PRInt32 kNumBuckets = sizeof(kBucketSizes)/sizeof(size_t);
 static const PRInt32 kNumElements = 64;
 static const PRInt32 kInitialSize = sizeof(nsXBLBindingRequest) * kNumElements;
 
 // nsXBLStreamListener, a helper class used for 
 // asynchronous parsing of URLs
 /* Header file */
-class nsXBLStreamListener : public nsIStreamListener, public nsIDOMEventListener
+class nsXBLStreamListener MOZ_FINAL : public nsIStreamListener,
+                                      public nsIDOMEventListener
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSIDOMEVENTLISTENER
 
   nsXBLStreamListener(nsIDocument* aBoundDocument,
--- a/content/xslt/src/xpath/nsXPathEvaluator.h
+++ b/content/xslt/src/xpath/nsXPathEvaluator.h
@@ -9,22 +9,23 @@
 #include "nsIDOMXPathEvaluator.h"
 #include "nsIXPathEvaluatorInternal.h"
 #include "nsIWeakReference.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "txResultRecycler.h"
 #include "nsAgg.h"
 #include "nsTArray.h"
+#include "mozilla/Attributes.h"
 
 /**
  * A class for evaluating an XPath expression string
  */
-class nsXPathEvaluator : public nsIDOMXPathEvaluator,
-                         public nsIXPathEvaluatorInternal
+class nsXPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator,
+                                   public nsIXPathEvaluatorInternal
 {
 public:
     nsXPathEvaluator(nsISupports *aOuter);
 
     nsresult Init();
 
     // nsISupports interface (support aggregation)
     NS_DECL_AGGREGATED
--- a/content/xslt/src/xpath/nsXPathExpression.h
+++ b/content/xslt/src/xpath/nsXPathExpression.h
@@ -7,25 +7,26 @@
 #define nsXPathExpression_h__
 
 #include "nsIDOMXPathExpression.h"
 #include "nsIDOMNSXPathExpression.h"
 #include "txIXPathContext.h"
 #include "txResultRecycler.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Attributes.h"
 
 class Expr;
 class txXPathNode;
 
 /**
  * A class for evaluating an XPath expression string
  */
-class nsXPathExpression : public nsIDOMXPathExpression,
-                          public nsIDOMNSXPathExpression
+class nsXPathExpression MOZ_FINAL : public nsIDOMXPathExpression,
+                                    public nsIDOMNSXPathExpression
 {
 public:
     nsXPathExpression(nsAutoPtr<Expr>& aExpression, txResultRecycler* aRecycler,
                       nsIDOMDocument *aDocument);
 
     // nsISupports interface
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXPathExpression,
--- a/content/xslt/src/xpath/nsXPathNSResolver.h
+++ b/content/xslt/src/xpath/nsXPathNSResolver.h
@@ -5,21 +5,22 @@
 
 #ifndef nsXPathNSResolver_h__
 #define nsXPathNSResolver_h__
 
 #include "nsIDOMXPathNSResolver.h"
 #include "nsIDOMNode.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Attributes.h"
 
 /**
  * A class for evaluating an XPath expression string
  */
-class nsXPathNSResolver : public nsIDOMXPathNSResolver
+class nsXPathNSResolver MOZ_FINAL : public nsIDOMXPathNSResolver
 {
 public:
     nsXPathNSResolver(nsIDOMNode* aNode);
 
     // nsISupports interface
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(nsXPathNSResolver)
 
--- a/content/xslt/src/xpath/nsXPathResult.h
+++ b/content/xslt/src/xpath/nsXPathResult.h
@@ -9,16 +9,17 @@
 #include "txExprResult.h"
 #include "nsIDOMXPathResult.h"
 #include "nsIDocument.h"
 #include "nsStubMutationObserver.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsWeakPtr.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Attributes.h"
 
 // {662f2c9a-c7cd-4cab-9349-e733df5a838c}
 #define NS_IXPATHRESULT_IID \
 { 0x662f2c9a, 0xc7cd, 0x4cab, {0x93, 0x49, 0xe7, 0x33, 0xdf, 0x5a, 0x83, 0x8c }}
 
 class nsIXPathResult : public nsISupports
 {
 public:
@@ -30,19 +31,19 @@ public:
     virtual nsresult Clone(nsIXPathResult **aResult) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPathResult, NS_IXPATHRESULT_IID)
 
 /**
  * A class for evaluating an XPath expression string
  */
-class nsXPathResult : public nsIDOMXPathResult,
-                      public nsStubMutationObserver,
-                      public nsIXPathResult
+class nsXPathResult MOZ_FINAL : public nsIDOMXPathResult,
+                                public nsStubMutationObserver,
+                                public nsIXPathResult
 {
 public:
     nsXPathResult();
     nsXPathResult(const nsXPathResult &aResult);
     ~nsXPathResult();
 
     // nsISupports interface
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/content/xslt/src/xpath/txXPCOMExtensionFunction.cpp
+++ b/content/xslt/src/xpath/txXPCOMExtensionFunction.cpp
@@ -11,20 +11,21 @@
 #include "nsServiceManagerUtils.h"
 #include "txExpr.h"
 #include "txIFunctionEvaluationContext.h"
 #include "txIXPathContext.h"
 #include "txNodeSetAdaptor.h"
 #include "txXPathTreeWalker.h"
 #include "xptcall.h"
 #include "txXPathObjectAdaptor.h"
+#include "mozilla/Attributes.h"
 
 NS_IMPL_ISUPPORTS1(txXPathObjectAdaptor, txIXPathObject)
 
-class txFunctionEvaluationContext : public txIFunctionEvaluationContext
+class txFunctionEvaluationContext MOZ_FINAL : public txIFunctionEvaluationContext
 {
 public:
     txFunctionEvaluationContext(txIEvalContext *aContext, nsISupports *aState);
 
     NS_DECL_ISUPPORTS
     NS_DECL_TXIFUNCTIONEVALUATIONCONTEXT
 
     void ClearContext()
--- a/content/xslt/src/xpath/txXPathObjectAdaptor.h
+++ b/content/xslt/src/xpath/txXPathObjectAdaptor.h
@@ -19,16 +19,17 @@ class txXPathObjectAdaptor : public txIX
 {
 public:
     txXPathObjectAdaptor(txAExprResult *aValue) : mValue(aValue)
     {
         NS_ASSERTION(aValue,
                      "Don't create a txXPathObjectAdaptor if you don't have a "
                      "txAExprResult");
     }
+    virtual ~txXPathObjectAdaptor() {}
 
     NS_DECL_ISUPPORTS
 
     NS_IMETHODIMP_(txAExprResult*) GetResult()
     {
         return mValue;
     }
 
--- a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp
+++ b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp
@@ -35,16 +35,17 @@
 #include "txStylesheetCompiler.h"
 #include "txXMLUtils.h"
 #include "nsAttrName.h"
 #include "nsIScriptError.h"
 #include "nsIURL.h"
 #include "nsCrossSiteListenerProxy.h"
 #include "nsDOMError.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/Attributes.h"
 
 using namespace mozilla;
 
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
 
 static void
 getSpec(nsIChannel* aChannel, nsAString& aSpec)
 {
@@ -58,20 +59,20 @@ getSpec(nsIChannel* aChannel, nsAString&
         return;
     }
 
     nsCAutoString spec;
     uri->GetSpec(spec);
     AppendUTF8toUTF16(spec, aSpec);
 }
 
-class txStylesheetSink : public nsIXMLContentSink,
-                         public nsIExpatSink,
-                         public nsIStreamListener,
-                         public nsIInterfaceRequestor
+class txStylesheetSink MOZ_FINAL : public nsIXMLContentSink,
+                                   public nsIExpatSink,
+                                   public nsIStreamListener,
+                                   public nsIInterfaceRequestor
 {
 public:
     txStylesheetSink(txStylesheetCompiler* aCompiler, nsIParser* aParser);
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIEXPATSINK
     NS_DECL_NSISTREAMLISTENER
     NS_DECL_NSIREQUESTOBSERVER
@@ -358,17 +359,17 @@ txStylesheetSink::GetInterface(const nsI
         *aResult = rawPtr;
 
         return NS_OK;
     }
 
     return NS_ERROR_NO_INTERFACE;
 }
 
-class txCompileObserver : public txACompileObserver
+class txCompileObserver MOZ_FINAL : public txACompileObserver
 {
 public:
     txCompileObserver(txMozillaXSLTProcessor* aProcessor,
                       nsILoadGroup* aLoadGroup);
 
     TX_DECL_ACOMPILEOBSERVER
     NS_INLINE_DECL_REFCOUNTING(txCompileObserver)
 
@@ -591,17 +592,17 @@ handleNode(nsINode* aNode, txStylesheetC
             rv = handleNode(child, aCompiler);
             NS_ENSURE_SUCCESS(rv, rv);
         }
     }
 
     return NS_OK;
 }
 
-class txSyncCompileObserver : public txACompileObserver
+class txSyncCompileObserver MOZ_FINAL : public txACompileObserver
 {
 public:
     txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor);
 
     TX_DECL_ACOMPILEOBSERVER
     NS_INLINE_DECL_REFCOUNTING(txSyncCompileObserver)
 
 protected:
--- a/content/xslt/src/xslt/txMozillaXMLOutput.h
+++ b/content/xslt/src/xslt/txMozillaXMLOutput.h
@@ -8,31 +8,32 @@
 
 #include "txXMLEventHandler.h"
 #include "nsAutoPtr.h"
 #include "nsIScriptLoaderObserver.h"
 #include "txOutputFormat.h"
 #include "nsCOMArray.h"
 #include "nsICSSLoaderObserver.h"
 #include "txStack.h"
+#include "mozilla/Attributes.h"
 
 class nsIContent;
 class nsIDOMDocument;
 class nsIAtom;
 class nsIDOMDocumentFragment;
 class nsIDOMElement;
 class nsIStyleSheet;
 class nsIDOMNode;
 class nsITransformObserver;
 class nsNodeInfoManager;
 class nsIDocument;
 class nsINode;
 
-class txTransformNotifier : public nsIScriptLoaderObserver,
-                            public nsICSSLoaderObserver
+class txTransformNotifier MOZ_FINAL : public nsIScriptLoaderObserver,
+                                      public nsICSSLoaderObserver
 {
 public:
     txTransformNotifier();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCRIPTLOADEROBSERVER
     
     // nsICSSLoaderObserver
--- a/content/xslt/src/xslt/txMozillaXSLTProcessor.h
+++ b/content/xslt/src/xslt/txMozillaXSLTProcessor.h
@@ -10,16 +10,17 @@
 #include "nsStubMutationObserver.h"
 #include "nsIDocumentTransformer.h"
 #include "nsIXSLTProcessor.h"
 #include "nsIXSLTProcessorPrivate.h"
 #include "txExpandedNameMap.h"
 #include "txNamespaceMap.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Attributes.h"
 
 class nsIDOMNode;
 class nsIPrincipal;
 class nsIURI;
 class nsIXMLContentSink;
 class txStylesheet;
 class txResultRecycler;
 class txIGlobalParameter;
@@ -31,21 +32,21 @@ class txIGlobalParameter;
 #define TRANSFORMIIX_XSLT_PROCESSOR_CONTRACTID \
 "@mozilla.org/document-transformer;1?type=xslt"
 
 #define XSLT_MSGS_URL  "chrome://global/locale/xslt/xslt.properties"
 
 /**
  * txMozillaXSLTProcessor is a front-end to the XSLT Processor.
  */
-class txMozillaXSLTProcessor : public nsIXSLTProcessor,
-                               public nsIXSLTProcessorPrivate,
-                               public nsIDocumentTransformer,
-                               public nsStubMutationObserver,
-                               public nsIJSNativeInitializer
+class txMozillaXSLTProcessor MOZ_FINAL : public nsIXSLTProcessor,
+                                         public nsIXSLTProcessorPrivate,
+                                         public nsIDocumentTransformer,
+                                         public nsStubMutationObserver,
+                                         public nsIJSNativeInitializer
 {
 public:
     /**
      * Creates a new txMozillaXSLTProcessor
      */
     txMozillaXSLTProcessor();
 
     /**
--- a/content/xtf/src/nsXMLContentBuilder.cpp
+++ b/content/xtf/src/nsXMLContentBuilder.cpp
@@ -15,20 +15,21 @@
 #include "nsContentCID.h"
 #include "nsIDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMText.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
+#include "mozilla/Attributes.h"
 
 static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
 
-class nsXMLContentBuilder : public nsIXMLContentBuilder
+class nsXMLContentBuilder MOZ_FINAL : public nsIXMLContentBuilder
 {
 protected:
   friend nsresult NS_NewXMLContentBuilder(nsIXMLContentBuilder** aResult);
   
   nsXMLContentBuilder();
   ~nsXMLContentBuilder();
   
 public:
--- a/content/xtf/src/nsXTFElementWrapper.h
+++ b/content/xtf/src/nsXTFElementWrapper.h
@@ -5,16 +5,17 @@
 
 #ifndef __NS_XTFELEMENTWRAPPER_H__
 #define __NS_XTFELEMENTWRAPPER_H__
 
 #include "nsIXTFElementWrapper.h"
 #include "nsXMLElement.h"
 #include "nsIXTFAttributeHandler.h"
 #include "nsIXTFElement.h"
+#include "mozilla/Attributes.h"
 
 typedef nsXMLElement nsXTFElementWrapperBase;
 class nsXTFClassInfo;
 
 // Pseudo IID for nsXTFElementWrapper
 // {599EB85F-ABC0-4B52-A1B0-EA103D48E3AE}
 #define NS_XTFELEMENTWRAPPER_IID \
 { 0x599eb85f, 0xabc0, 0x4b52, { 0xa1, 0xb0, 0xea, 0x10, 0x3d, 0x48, 0xe3, 0xae } }
@@ -161,17 +162,17 @@ protected:
 
   nsCOMPtr<nsIAtom> mClassAttributeName;
 
   nsRefPtr<nsXTFClassInfo> mClassInfo;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXTFElementWrapper, NS_XTFELEMENTWRAPPER_IID)
 
-class nsXTFClassInfo : public nsXPCClassInfo
+class nsXTFClassInfo MOZ_FINAL : public nsXPCClassInfo
 {
 public:
   nsXTFClassInfo(nsXTFElementWrapper* aWrapper) : mWrapper(aWrapper) {}
 
   void Disconnect() { mWrapper = nsnull; }
 
   NS_DECL_ISUPPORTS
   NS_FORWARD_SAFE_NSICLASSINFO(mWrapper);
--- a/content/xtf/src/nsXTFInterfaceAggregator.cpp
+++ b/content/xtf/src/nsXTFInterfaceAggregator.cpp
@@ -4,24 +4,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsCOMPtr.h"
 #include "nsXPTCUtils.h"
 #include "nsIInterfaceInfo.h"
 #include "nsIInterfaceInfoManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsAutoPtr.h"
+#include "mozilla/Attributes.h"
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
 ////////////////////////////////////////////////////////////////////////
 // nsXTFInterfaceAggregator class
 
-class nsXTFInterfaceAggregator : protected nsAutoXPTCStub
+class nsXTFInterfaceAggregator MOZ_FINAL : protected nsAutoXPTCStub
 {
 protected:
   friend nsresult
   NS_NewXTFInterfaceAggregator(const nsIID& iid,
                                nsISupports* inner,
                                nsISupports* outer,
                                void** result);
 
--- a/content/xtf/src/nsXTFService.cpp
+++ b/content/xtf/src/nsXTFService.cpp
@@ -7,21 +7,22 @@
 #include "nsINodeInfo.h"
 #include "nsIServiceManager.h"
 #include "nsIXTFElement.h"
 #include "nsIXTFElementFactory.h"
 #include "nsIXTFService.h"
 #include "nsInterfaceHashtable.h"
 #include "nsString.h"
 #include "nsXTFElementWrapper.h"
+#include "mozilla/Attributes.h"
 
 
 ////////////////////////////////////////////////////////////////////////
 // nsXTFService class 
-class nsXTFService : public nsIXTFService
+class nsXTFService MOZ_FINAL : public nsIXTFService
 {
 protected:
   friend nsresult NS_NewXTFService(nsIXTFService** aResult);
   
   nsXTFService();
 
 public:
   // nsISupports interface
--- a/content/xtf/src/nsXTFWeakTearoff.cpp
+++ b/content/xtf/src/nsXTFWeakTearoff.cpp
@@ -4,24 +4,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsCOMPtr.h"
 #include "nsXPTCUtils.h"
 #include "nsIInterfaceInfo.h"
 #include "nsIInterfaceInfoManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsAutoPtr.h"
+#include "mozilla/Attributes.h"
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
 ////////////////////////////////////////////////////////////////////////
 // nsXTFWeakTearoff class
 
-class nsXTFWeakTearoff : protected nsAutoXPTCStub
+class nsXTFWeakTearoff MOZ_FINAL : protected nsAutoXPTCStub
 {
 protected:
   ~nsXTFWeakTearoff();
   
 public:
   nsXTFWeakTearoff(const nsIID& iid,
                    nsISupports* obj,
                    nsresult *rv);
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -82,16 +82,17 @@
 #include "nsGkAtoms.h"
 #include "nsXULContentUtils.h"
 #include "nsNodeUtils.h"
 #include "nsFrameLoader.h"
 #include "prlog.h"
 #include "rdf.h"
 #include "nsIControllers.h"
 #include "nsAttrValueOrString.h"
+#include "mozilla/Attributes.h"
 
 // The XUL doc interface
 #include "nsIDOMXULDocument.h"
 
 #include "nsReadableUtils.h"
 #include "nsIFrame.h"
 #include "nsNodeInfoManager.h"
 #include "nsXBLBinding.h"
@@ -101,17 +102,17 @@
 #include "nsIDOMNSEvent.h"
 #include "nsCCUncollectableMarker.h"
 
 namespace css = mozilla::css;
 
 /**
  * A tearoff class for nsXULElement to implement nsIScriptEventHandlerOwner.
  */
-class nsScriptEventHandlerOwnerTearoff : public nsIScriptEventHandlerOwner
+class nsScriptEventHandlerOwnerTearoff MOZ_FINAL : public nsIScriptEventHandlerOwner
 {
 public:
     nsScriptEventHandlerOwnerTearoff(nsXULElement* aElement)
     : mElement(aElement) {}
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(nsScriptEventHandlerOwnerTearoff)
 
@@ -140,18 +141,18 @@ PRUint32             nsXULPrototypeAttri
 PRUint32             nsXULPrototypeAttribute::gNumAttributes;
 PRUint32             nsXULPrototypeAttribute::gNumEventHandlers;
 PRUint32             nsXULPrototypeAttribute::gNumCacheTests;
 PRUint32             nsXULPrototypeAttribute::gNumCacheHits;
 PRUint32             nsXULPrototypeAttribute::gNumCacheSets;
 PRUint32             nsXULPrototypeAttribute::gNumCacheFills;
 #endif
 
-class nsXULElementTearoff : public nsIDOMElementCSSInlineStyle,
-                            public nsIFrameLoaderOwner
+class nsXULElementTearoff MOZ_FINAL : public nsIDOMElementCSSInlineStyle,
+                                      public nsIFrameLoaderOwner
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULElementTearoff,
                                            nsIDOMElementCSSInlineStyle)
 
   nsXULElementTearoff(nsXULElement *aElement)
     : mElement(aElement)
@@ -750,17 +751,17 @@ nsScriptEventHandlerOwnerTearoff::Compil
     if (attr) {
         XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
         // take a copy of the event handler, and tell the language about it.
         if (aHandler) {
             NS_ASSERTION(!attr->mEventHandler, "Leaking handler.");
 
             if (!elem->mHoldsScriptObject) {
                 rv = nsContentUtils::HoldJSObjects(
-                    elem, &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
+                    elem, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
                 NS_ENSURE_SUCCESS(rv, rv);
             }
 
             elem->mHoldsScriptObject = true;
         }
         attr->mEventHandler = aHandler.get();
     }
 
@@ -3093,17 +3094,17 @@ nsXULPrototypeScript::Set(JSScript* aObj
 {
     NS_ASSERTION(!mScriptObject.mObject, "Leaking script object.");
     if (!aObject) {
         mScriptObject.mObject = nsnull;
         return;
     }
 
     nsresult rv = nsContentUtils::HoldJSObjects(
-        this, &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
+        this, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
     if (NS_SUCCEEDED(rv)) {
         mScriptObject.mObject = aObject;
     }
 }
 
 //----------------------------------------------------------------------
 //
 // nsXULPrototypeText
--- a/content/xul/templates/src/nsRDFQuery.h
+++ b/content/xul/templates/src/nsRDFQuery.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsRDFQuery_h__
 #define nsRDFQuery_h__
 
 #include "nsAutoPtr.h"
 #include "nsISimpleEnumerator.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Attributes.h"
 
 #define NS_ITEMPLATERDFQUERY_IID \
   {0x8929ff60, 0x1c9c, 0x4d87, \
     { 0xac, 0x02, 0x09, 0x14, 0x15, 0x3b, 0x48, 0xc4 }}
 
 /**
  * A compiled query in the RDF query processor. This interface should not be
  * used directly outside of the RDF query processor.
@@ -31,17 +32,17 @@ public:
 
     // return the <query> node the query was compiled from
     virtual void GetQueryNode(nsIDOMNode** aQueryNode) = 0;
 
     // remove any results that are cached by the query
     virtual void ClearCachedResults() = 0;
 };
 
-class nsRDFQuery : public nsITemplateRDFQuery
+class nsRDFQuery MOZ_FINAL : public nsITemplateRDFQuery
 {
 public:
 
     nsRDFQuery(nsXULTemplateQueryProcessorRDF* aProcessor)
       : mProcessor(aProcessor),
         mSimple(false),
         mRoot(nsnull),
         mCachedResults(nsnull)
--- a/content/xul/templates/src/nsXMLBinding.cpp
+++ b/content/xul/templates/src/nsXMLBinding.cpp
@@ -5,17 +5,17 @@
 
 #include "nsXULTemplateQueryProcessorXML.h"
 #include "nsXULTemplateResultXML.h"
 #include "nsXMLBinding.h"
 
 NS_IMPL_ADDREF(nsXMLBindingSet)
 NS_IMPL_RELEASE(nsXMLBindingSet)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLBindingSet)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXMLBindingSet)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXMLBindingSet)
   nsXMLBinding* binding = tmp->mFirst;
   while (binding) {
     binding->mExpr = nsnull;
     binding = binding->mNext;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/xul/templates/src/nsXMLBinding.h
+++ b/content/xul/templates/src/nsXMLBinding.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsXMLBinding_h__
 #define nsXMLBinding_h__
 
 #include "nsAutoPtr.h"
 #include "nsIAtom.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Attributes.h"
 
 class nsXULTemplateResultXML;
 class nsXMLBindingValues;
 
 /**
  * Classes related to storing bindings for XML handling.
  */
 
@@ -37,17 +38,17 @@ struct nsXMLBinding {
     MOZ_COUNT_DTOR(nsXMLBinding);
   }
 };
 
 /**
  * a collection of <binding> descriptors. This object is refcounted by
  * nsXMLBindingValues objects and the query processor.
  */
-class nsXMLBindingSet
+class nsXMLBindingSet MOZ_FINAL
 {
 public:
 
   // results hold a reference to a binding set in their
   // nsXMLBindingValues fields
   nsAutoRefCnt mRefCnt;
 
   // pointer to the first binding in a linked list
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h
@@ -25,30 +25,31 @@
 #include "nsRDFBinding.h"
 #include "nsXULTemplateResultSetRDF.h"
 #include "nsCOMArray.h"
 #include "nsIArray.h"
 #include "nsString.h"
 #include "nsClassHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Attributes.h"
 
 #include "prlog.h"
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gXULTemplateLog;
 #endif
 
 class nsIRDFCompositeDataSource;
 class nsXULTemplateResultRDF;
 
 /**
  * An object that generates results from a query on an RDF graph
  */
-class nsXULTemplateQueryProcessorRDF : public nsIXULTemplateQueryProcessor,
-                                       public nsIRDFObserver
+class nsXULTemplateQueryProcessorRDF MOZ_FINAL : public nsIXULTemplateQueryProcessor,
+                                                 public nsIRDFObserver
 {
 public:
 
     nsXULTemplateQueryProcessorRDF();
 
     ~nsXULTemplateQueryProcessorRDF();
 
     nsresult InitGlobals();
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorStorage.h
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorStorage.h
@@ -11,20 +11,21 @@
 
 #include "nsISimpleEnumerator.h"
 #include "nsCOMArray.h"
 #include "nsIVariant.h"
 
 #include "mozIStorageValueArray.h"
 #include "mozIStorageStatement.h"
 #include "mozIStorageConnection.h"
+#include "mozilla/Attributes.h"
 
 class nsXULTemplateQueryProcessorStorage;
 
-class nsXULTemplateResultSetStorage : public nsISimpleEnumerator
+class nsXULTemplateResultSetStorage MOZ_FINAL : public nsISimpleEnumerator
 {
 private:
 
     nsCOMPtr<mozIStorageStatement> mStatement;
 
     nsCOMArray<nsIAtom> mColumnNames;
 
 public:
@@ -38,17 +39,17 @@ public:
     nsXULTemplateResultSetStorage(mozIStorageStatement* aStatement);
 
     PRInt32 GetColumnIndex(nsIAtom* aColumnName);
 
     void FillColumnValues(nsCOMArray<nsIVariant>& aArray);
 
 };
 
-class nsXULTemplateQueryProcessorStorage : public nsIXULTemplateQueryProcessor
+class nsXULTemplateQueryProcessorStorage MOZ_FINAL : public nsIXULTemplateQueryProcessor
 {
 public:
 
     nsXULTemplateQueryProcessorStorage();
 
     // nsISupports interface
     NS_DECL_ISUPPORTS
 
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
@@ -80,17 +80,17 @@ nsXULTemplateResultSetXML::GetNext(nsISu
 static PLDHashOperator
 TraverseRuleToBindingsMap(nsISupports* aKey, nsXMLBindingSet* aMatch, void* aContext)
 {
     nsCycleCollectionTraversalCallback *cb =
         static_cast<nsCycleCollectionTraversalCallback*>(aContext);
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap key");
     cb->NoteXPCOMChild(aKey);
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap value");
-    cb->NoteNativeChild(aMatch, &NS_CYCLE_COLLECTION_NAME(nsXMLBindingSet));
+    cb->NoteNativeChild(aMatch, NS_CYCLE_COLLECTION_PARTICIPANT(nsXMLBindingSet));
     return PL_DHASH_NEXT;
 }
   
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML)
     if (tmp->mRuleToBindingsMap.IsInitialized()) {
         tmp->mRuleToBindingsMap.Clear();
     }
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h
@@ -16,24 +16,25 @@
 #include "nsIDOMElement.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMXPathExpression.h"
 #include "nsIDOMXPathEvaluator.h"
 #include "nsIDOMXPathResult.h"
 #include "nsXMLBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIXMLHttpRequest.h"
+#include "mozilla/Attributes.h"
 
 class nsXULTemplateQueryProcessorXML;
 
 #define NS_IXMLQUERY_IID \
   {0x0358d692, 0xccce, 0x4a97, \
     { 0xb2, 0x51, 0xba, 0x8f, 0x17, 0x0f, 0x3b, 0x6f }}
  
-class nsXMLQuery : public nsISupports
+class nsXMLQuery MOZ_FINAL : public nsISupports
 {
   public:
     NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXMLQUERY_IID)
 
     NS_DECL_ISUPPORTS
 
     // return a weak reference to the processor the query was created from
     nsXULTemplateQueryProcessorXML* Processor() { return mProcessor; }
@@ -74,17 +75,17 @@ class nsXMLQuery : public nsISupports
 
     nsCOMPtr<nsIDOMXPathExpression> mResultsExpr;
 
     nsRefPtr<nsXMLBindingSet> mRequiredBindings;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXMLQuery, NS_IXMLQUERY_IID)
 
-class nsXULTemplateResultSetXML : public nsISimpleEnumerator
+class nsXULTemplateResultSetXML MOZ_FINAL : public nsISimpleEnumerator
 {
 private:
 
     // reference back to the query
     nsCOMPtr<nsXMLQuery> mQuery;
 
     // the binding set created from <assign> nodes
     nsRefPtr<nsXMLBindingSet> mBindingSet;
@@ -108,18 +109,18 @@ public:
                               nsXMLBindingSet* aBindingSet)
         : mQuery(aQuery),
           mBindingSet(aBindingSet),
           mResults(aResults),
           mPosition(0)
     {}
 };
 
-class nsXULTemplateQueryProcessorXML : public nsIXULTemplateQueryProcessor,
-                                       public nsIDOMEventListener
+class nsXULTemplateQueryProcessorXML MOZ_FINAL : public nsIXULTemplateQueryProcessor,
+                                                 public nsIDOMEventListener
 {
 public:
 
     nsXULTemplateQueryProcessorXML()
         : mGenerationStarted(false)
     {}
 
     // nsISupports interface
--- a/content/xul/templates/src/nsXULTemplateResultRDF.h
+++ b/content/xul/templates/src/nsXULTemplateResultRDF.h
@@ -8,21 +8,22 @@
 
 #include "nsCOMPtr.h"
 #include "nsIRDFResource.h"
 #include "nsXULTemplateQueryProcessorRDF.h"
 #include "nsRDFQuery.h"
 #include "nsRuleNetwork.h"
 #include "nsIXULTemplateResult.h"
 #include "nsRDFBinding.h"
+#include "mozilla/Attributes.h"
 
 /**
  * A single result of a query on an RDF graph
  */
-class nsXULTemplateResultRDF : public nsIXULTemplateResult
+class nsXULTemplateResultRDF MOZ_FINAL : public nsIXULTemplateResult
 {
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(nsXULTemplateResultRDF)
 
     NS_DECL_NSIXULTEMPLATERESULT
 
     nsXULTemplateResultRDF(nsIRDFResource* aNode);
--- a/content/xul/templates/src/nsXULTemplateResultSetRDF.h
+++ b/content/xul/templates/src/nsXULTemplateResultSetRDF.h
@@ -6,24 +6,25 @@
 #ifndef nsXULTemplateResultSetRDF_h__
 #define nsXULTemplateResultSetRDF_h__
 
 #include "nsFixedSizeAllocator.h"
 #include "nsISimpleEnumerator.h"
 #include "nsRuleNetwork.h"
 #include "nsRDFQuery.h"
 #include "nsXULTemplateResultRDF.h"
+#include "mozilla/Attributes.h"
 
 class nsXULTemplateQueryProcessorRDF;
 class nsXULTemplateResultRDF;
 
 /**
  * An enumerator used to iterate over a set of results.
  */
-class nsXULTemplateResultSetRDF : public nsISimpleEnumerator
+class nsXULTemplateResultSetRDF MOZ_FINAL : public nsISimpleEnumerator
 {
 private:
     nsXULTemplateQueryProcessorRDF* mProcessor;
 
     nsRDFQuery* mQuery;
 
     const InstantiationSet* mInstantiations;
 
--- a/content/xul/templates/src/nsXULTemplateResultStorage.h
+++ b/content/xul/templates/src/nsXULTemplateResultStorage.h
@@ -5,21 +5,22 @@
 
 #ifndef nsXULTemplateResultStorage_h__
 #define nsXULTemplateResultStorage_h__
 
 #include "nsXULTemplateQueryProcessorStorage.h"
 #include "nsIRDFResource.h"
 #include "nsIXULTemplateResult.h"
 #include "nsAutoPtr.h"
+#include "mozilla/Attributes.h"
 
 /**
  * A single result of a query from mozstorage
  */
-class nsXULTemplateResultStorage : public nsIXULTemplateResult
+class nsXULTemplateResultStorage MOZ_FINAL : public nsIXULTemplateResult
 {
 public:
     NS_DECL_ISUPPORTS
 
     NS_DECL_NSIXULTEMPLATERESULT
 
     nsXULTemplateResultStorage(nsXULTemplateResultSetStorage* aResultSet);
 
--- a/content/xul/templates/src/nsXULTemplateResultXML.h
+++ b/content/xul/templates/src/nsXULTemplateResultXML.h
@@ -6,21 +6,22 @@
 #ifndef nsXULTemplateResultXML_h__
 #define nsXULTemplateResultXML_h__
 
 #include "nsCOMPtr.h"
 #include "nsIURI.h"
 #include "nsIRDFResource.h"
 #include "nsXULTemplateQueryProcessorXML.h"
 #include "nsIXULTemplateResult.h"
+#include "mozilla/Attributes.h"
 
 /**
  * An single result of an query
  */
-class nsXULTemplateResultXML : public nsIXULTemplateResult
+class nsXULTemplateResultXML MOZ_FINAL : public nsIXULTemplateResult
 {
 public:
     NS_DECL_ISUPPORTS
 
     NS_DECL_NSIXULTEMPLATERESULT
 
     nsXULTemplateResultXML(nsXMLQuery* aQuery,
                            nsIDOMNode* aNode,
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -781,17 +781,17 @@ nsDocShell::nsDocShell():
     if (gDocShellLeakLog)
         PR_LOG(gDocShellLeakLog, PR_LOG_DEBUG, ("DOCSHELL %p created\n", this));
 #endif
 
 #ifdef DEBUG
   // We're counting the number of |nsDocShells| to help find leaks
   ++gNumberOfDocShells;
   if (!PR_GetEnv("MOZ_QUIET")) {
-      printf("++DOCSHELL %p == %ld [id = %ld]\n", (void*) this,
+      printf("++DOCSHELL %p == %ld [id = %llu]\n", (void*) this,
              gNumberOfDocShells, mHistoryID);
   }
 #endif
 }
 
 nsDocShell::~nsDocShell()
 {
     Destroy();
@@ -810,17 +810,17 @@ nsDocShell::~nsDocShell()
     if (gDocShellLeakLog)
         PR_LOG(gDocShellLeakLog, PR_LOG_DEBUG, ("DOCSHELL %p destroyed\n", this));
 #endif
 
 #ifdef DEBUG
     // We're counting the number of |nsDocShells| to help find leaks
     --gNumberOfDocShells;
     if (!PR_GetEnv("MOZ_QUIET")) {
-        printf("--DOCSHELL %p == %ld [id = %ld]\n", (void*) this,
+        printf("--DOCSHELL %p == %ld [id = %llu]\n", (void*) this,
                gNumberOfDocShells, mHistoryID);
     }
 #endif
 
     if (mInPrivateBrowsing) {
         DecreasePrivateDocShellCount();
     }
 }
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -19,16 +19,18 @@
 #include "jsdbgapi.h"
 #include "WrapperFactory.h"
 #include "AccessCheck.h"
 #include "XrayWrapper.h"
 
 #include "xpcpublic.h"
 #include "xpcprivate.h"
 #include "XPCWrapper.h"
+#include "XPCQuickStubs.h"
+#include "nsDOMQS.h"
 
 #include "mozilla/dom/RegisterBindings.h"
 
 #include "nscore.h"
 #include "nsDOMClassInfo.h"
 #include "nsCRT.h"
 #include "nsCRTGlue.h"
 #include "nsIServiceManager.h"
@@ -410,18 +412,17 @@
 #include "nsIDOMSVGTSpanElement.h"
 #include "nsIDOMSVGUnitTypes.h"
 #include "nsIDOMSVGURIReference.h"
 #include "nsIDOMSVGUseElement.h"
 #include "nsIDOMSVGViewElement.h"
 #include "nsIDOMSVGZoomAndPan.h"
 #include "nsIDOMSVGZoomEvent.h"
 
-#include "nsIDOMCanvasRenderingContext2D.h"
-#include "nsIDOMWebGLRenderingContext.h"
+#include "nsICanvasRenderingContextInternal.h"
 
 #include "nsIImageDocument.h"
 
 // Storage includes
 #include "nsDOMStorage.h"
 
 // Device Storage
 #include "nsIDOMDeviceStorage.h"
@@ -616,23 +617,31 @@ static const char kDOMStringBundleURL[] 
 #ifdef NS_DEBUG
 #define NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                \
     eDOMClassInfo_##_class##_id,
 #else
 #define NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                \
   // nothing
 #endif
 
-DOMCI_DATA(Crypto, void)
-DOMCI_DATA(CRMFObject, void)
-DOMCI_DATA(SmartCardEvent, void)
-DOMCI_DATA(ContentFrameMessageManager, void)
-
-DOMCI_DATA(DOMPrototype, void)
-DOMCI_DATA(DOMConstructor, void)
+/**
+ * To generate the bitmap for a class that we're sure doesn't implement any of
+ * the interfaces in DOMCI_CASTABLE_INTERFACES.
+ */
+#define DOMCI_DATA_NO_CLASS(_dom_class)                                       \
+const PRUint32 kDOMClassInfo_##_dom_class##_interfaces =                      \
+  0;
+
+DOMCI_DATA_NO_CLASS(Crypto)
+DOMCI_DATA_NO_CLASS(CRMFObject)
+DOMCI_DATA_NO_CLASS(SmartCardEvent)
+DOMCI_DATA_NO_CLASS(ContentFrameMessageManager)
+
+DOMCI_DATA_NO_CLASS(DOMPrototype)
+DOMCI_DATA_NO_CLASS(DOMConstructor)
 
 #define NS_DEFINE_CLASSINFO_DATA_WITH_NAME(_class, _name, _helper,            \
                                            _flags)                            \
   { #_name,                                                                   \
     nsnull,                                                                   \
     { _helper::doCreate },                                                    \
     nsnull,                                                                   \
     nsnull,                                                                   \
@@ -686,16 +695,20 @@ public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData *aData)
   {
     return new IDBEventTargetSH(aData);
   }
 };
 
 } // anonymous namespace
 
+typedef nsNewDOMBindingSH<nsICanvasRenderingContextInternal>
+  nsCanvasRenderingContextSH;
+
+
 // This list of NS_DEFINE_CLASSINFO_DATA macros is what gives the DOM
 // classes their correct behavior when used through XPConnect. The
 // arguments that are passed to NS_DEFINE_CLASSINFO_DATA are
 //
 // 1. Class name as it should appear in JavaScript, this name is also
 //    used to find the id of the class in nsDOMClassInfo
 //    (i.e. e<classname>_id)
 // 2. Scriptable helper class
@@ -1312,17 +1325,18 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGTransformList, nsSVGTransformListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGZoomEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(HTMLCanvasElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CanvasRenderingContext2D, nsDOMGenericSH,
+  NS_DEFINE_CLASSINFO_DATA(CanvasRenderingContext2D,
+                           nsCanvasRenderingContextSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CanvasGradient, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CanvasPattern, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(TextMetrics, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(ImageData, nsDOMGenericSH,
@@ -1997,18 +2011,17 @@ WrapNative(JSContext *cx, JSObject *scop
 }
 
 // Used for cases where PreCreate needs to wrap the native parent, and the
 // native parent is likely to have been wrapped already.  |native| must
 // implement nsWrapperCache, and nativeWrapperCache must be |native|'s
 // nsWrapperCache.
 static inline nsresult
 WrapNativeParent(JSContext *cx, JSObject *scope, nsISupports *native,
-                                        nsWrapperCache *nativeWrapperCache,
-                                        JSObject **parentObj)
+                 nsWrapperCache *nativeWrapperCache, JSObject **parentObj)
 {
   // In the common case, |native| is a wrapper cache with an existing wrapper
 #ifdef DEBUG
   nsWrapperCache* cache = nsnull;
   CallQueryInterface(native, &cache);
   NS_PRECONDITION(nativeWrapperCache &&
                   cache == nativeWrapperCache, "What happened here?");
 #endif
@@ -2028,16 +2041,24 @@ WrapNativeParent(JSContext *cx, JSObject
 
   jsval v;
   nsresult rv = WrapNative(cx, scope, native, nativeWrapperCache, false, &v);
   NS_ENSURE_SUCCESS(rv, rv);
   *parentObj = JSVAL_TO_OBJECT(v);
   return NS_OK;
 }
 
+template<class P>
+static inline nsresult
+WrapNativeParent(JSContext *cx, JSObject *scope, P *parent,
+                 JSObject **parentObj)
+{
+  return WrapNativeParent(cx, scope, ToSupports(parent), parent, parentObj);
+}
+
 // Helper to handle torn-down inner windows.
 static inline nsresult
 SetParentToWindow(nsGlobalWindow *win, JSObject **parent)
 {
   MOZ_ASSERT(win);
   MOZ_ASSERT(win->IsInnerWindow());
   *parent = win->FastGetGlobalJSObject();
 
@@ -2116,80 +2137,16 @@ nsDOMClassInfo::DefineStaticJSVals(JSCon
   SET_JSID_TO_STRING(sUnique_id,          cx, "unique");
   SET_JSID_TO_STRING(sMultiEntry_id,      cx, "multiEntry");
   SET_JSID_TO_STRING(sOnload_id,          cx, "onload");
   SET_JSID_TO_STRING(sOnerror_id,         cx, "onerror");
 
   return NS_OK;
 }
 
-static nsresult
-CreateExceptionFromResult(JSContext *cx, nsresult aResult)
-{
-  nsCOMPtr<nsIExceptionService> xs =
-    do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
-  if (!xs) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIExceptionManager> xm;
-  nsresult rv = xs->GetCurrentExceptionManager(getter_AddRefs(xm));
-  if (NS_FAILED(rv)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIException> exception;
-  rv = xm->GetExceptionFromProvider(aResult, 0, getter_AddRefs(exception));
-  if (NS_FAILED(rv) || !exception) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JS::Value jv;
-  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-  rv = WrapNative(cx, ::JS_GetGlobalObject(cx), exception,
-                  &NS_GET_IID(nsIException), false, &jv,
-                  getter_AddRefs(holder));
-  if (NS_FAILED(rv) || jv.isNull()) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JSAutoEnterCompartment ac;
-
-  if (jv.isObject()) {
-    if (!ac.enter(cx, &jv.toObject())) {
-      return NS_ERROR_UNEXPECTED;
-    }
-  }
-
-  JS_SetPendingException(cx, jv);
-  return NS_OK;
-}
-
-// static
-nsresult
-nsDOMClassInfo::ThrowJSException(JSContext *cx, nsresult aResult)
-{
-  JSAutoRequest ar(cx);
-
-  if (NS_SUCCEEDED(CreateExceptionFromResult(cx, aResult))) {
-    return NS_OK;
-  }
-
-  // XXX This probably wants to be localized, but that can fail in ways that
-  // are hard to report correctly.
-  JSString *str =
-    JS_NewStringCopyZ(cx, "An error occurred throwing an exception");
-  if (!str) {
-    // JS_NewStringCopyZ reported the error for us.
-    return NS_OK; 
-  }
-  JS_SetPendingException(cx, STRING_TO_JSVAL(str));
-  return NS_OK;
-}
-
 // static
 bool
 nsDOMClassInfo::ObjectIsNativeWrapper(JSContext* cx, JSObject* obj)
 {
   return xpc::WrapperFactory::IsXrayWrapper(obj) &&
          !xpc::WrapperFactory::IsPartiallyTransparent(obj);
 }
 
@@ -6746,16 +6703,44 @@ ResolvePrototype(nsIXPConnect *aXPConnec
     return NS_ERROR_UNEXPECTED;
   }
 
   *did_resolve = true;
 
   return NS_OK;
 }
 
+static bool
+ConstructorEnabled(const nsGlobalNameStruct *aStruct, nsGlobalWindow *aWin)
+{
+  MOZ_ASSERT(aStruct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
+             aStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo);
+
+  // Don't expose chrome only constructors to content windows.
+  if (aStruct->mChromeOnly &&
+      !nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal())) {
+    return false;
+  }
+
+  // For now don't expose web sockets unless user has explicitly enabled them
+  if (aStruct->mDOMClassInfoID == eDOMClassInfo_WebSocket_id) {
+    if (!nsWebSocket::PrefEnabled()) {
+      return false;
+    }
+  }
+
+  // For now don't expose server events unless user has explicitly enabled them
+  if (aStruct->mDOMClassInfoID == eDOMClassInfo_EventSource_id) {
+    if (!nsEventSource::PrefEnabled()) {
+      return false;
+    }
+  }
+
+  return true;
+}
 
 // static
 nsresult
 nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                           JSObject *obj, jsid id, bool *did_resolve)
 {
   *did_resolve = false;
 
@@ -6780,29 +6765,40 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
   if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) {
     rv = GetExternalClassInfo(nameSpaceManager, name, name_struct,
                               &name_struct);
     if (NS_FAILED(rv) || !name_struct) {
       return rv;
     }
   }
 
-  if (name_struct->mType == nsGlobalNameStruct::eTypeInterface) {
-    // We're resolving a name of a DOM interface for which there is no
-    // direct DOM class, create a constructor object...
-
+  if (name_struct->mType == nsGlobalNameStruct::eTypeNewDOMBinding ||
+      name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
+      name_struct->mType == nsGlobalNameStruct::eTypeClassProto ||
+      name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     // Lookup new DOM bindings.
     mozilla::dom::binding::DefineInterface define =
       name_struct->mDefineDOMInterface;
-    if (define && mozilla::dom::binding::DefineConstructor(cx, obj, define, &rv)) {
-      *did_resolve = NS_SUCCEEDED(rv);
-
-      return rv;
-    }
-
+    if (define) {
+      if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
+          !ConstructorEnabled(name_struct, aWin)) {
+        return NS_OK;
+      }
+
+      if (mozilla::dom::binding::DefineConstructor(cx, obj, define, &rv)) {
+        *did_resolve = NS_SUCCEEDED(rv);
+
+        return rv;
+      }
+    }
+  }
+
+  if (name_struct->mType == nsGlobalNameStruct::eTypeInterface) {
+    // We're resolving a name of a DOM interface for which there is no
+    // direct DOM class, create a constructor object...
     nsRefPtr<nsDOMConstructor> constructor;
     rv = nsDOMConstructor::Create(class_name,
                                   nsnull,
                                   name_struct,
                                   static_cast<nsPIDOMWindow*>(aWin),
                                   getter_AddRefs(constructor));
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -6827,47 +6823,20 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
 
     *did_resolve = true;
 
     return NS_OK;
   }
 
   if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
       name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
-    // Don't expose chrome only constructors to content windows.
-    if (name_struct->mChromeOnly &&
-        !nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal())) {
+    if (!ConstructorEnabled(name_struct, aWin)) {
       return NS_OK;
     }
 
-    // For now don't expose web sockets unless user has explicitly enabled them
-    if (name_struct->mDOMClassInfoID == eDOMClassInfo_WebSocket_id) {
-      if (!nsWebSocket::PrefEnabled()) {
-        return NS_OK;
-      }
-    }
-
-    // For now don't expose server events unless user has explicitly enabled them
-    if (name_struct->mDOMClassInfoID == eDOMClassInfo_EventSource_id) {
-      if (!nsEventSource::PrefEnabled()) {
-        return NS_OK;
-      }
-    }
-
-    // Lookup new DOM bindings.
-    if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
-      mozilla::dom::binding::DefineInterface define =
-        name_struct->mDefineDOMInterface;
-      if (define && mozilla::dom::binding::DefineConstructor(cx, obj, define, &rv)) {
-        *did_resolve = NS_SUCCEEDED(rv);
-
-        return rv;
-      }
-    }
-
     // Create the XPConnect prototype for our classinfo, PostCreateProto will
     // set up the prototype chain.
     nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
     rv = GetXPCProto(sXPConnect, cx, aWin, name_struct,
                      getter_AddRefs(proto_holder));
 
     if (NS_SUCCEEDED(rv) && obj != aWin->GetGlobalJSObject()) {
       JSObject* dot_prototype;
@@ -6889,26 +6858,16 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
     *did_resolve = NS_SUCCEEDED(rv);
 
     return rv;
   }
 
   if (name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
     // We don't have a XPConnect prototype object, let ResolvePrototype create
     // one.
-
-    // Lookup new DOM bindings.
-    mozilla::dom::binding::DefineInterface define =
-      name_struct->mDefineDOMInterface;
-    if (define && mozilla::dom::binding::DefineConstructor(cx, obj, define, &rv)) {
-      *did_resolve = NS_SUCCEEDED(rv);
-
-      return rv;
-    }
-
     return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, nsnull,
                             name_struct, nameSpaceManager, nsnull, true,
                             did_resolve);
   }
 
   if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
     const nsGlobalNameStruct *alias_struct =
       nameSpaceManager->GetConstructorProto(name_struct);
@@ -7102,19 +7061,17 @@ LocationSetterGuts(JSContext *cx, JSObje
 
 template<class Interface>
 static JSBool
 LocationSetter(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
                jsval *vp)
 {
   nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp);
   if (NS_FAILED(rv)) {
-    if (!::JS_IsExceptionPending(cx)) {
-      nsDOMClassInfo::ThrowJSException(cx, rv);
-    }
+    xpc::Throw(cx, rv);
     return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
 LocationSetterUnwrapper(JSContext *cx, JSHandleObject obj_, JSHandleId id, JSBool strict,
@@ -7777,19 +7734,17 @@ nsNavigatorSH::PreCreate(nsISupports *na
 // DOM Node helper
 
 template<nsresult (*func)(JSContext *cx, JSObject *obj, jsval *vp)>
 static JSBool
 GetterShim(JSContext *cx, JSHandleObject obj, JSHandleId /* unused */, jsval *vp)
 {
   nsresult rv = (*func)(cx, obj, vp);
   if (NS_FAILED(rv)) {
-    if (!::JS_IsExceptionPending(cx)) {
-      nsDOMClassInfo::ThrowJSException(cx, rv);
-    }
+    xpc::Throw(cx, rv);
     return JS_FALSE;
   }
 
   return JS_TRUE;  
 }
 
 // Can't be static so GetterShim will compile
 nsresult
@@ -7969,18 +7924,17 @@ nsNodeSH::PreCreate(nsISupports *nativeO
       NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
   }
 
   // XXXjst: Maybe we need to find the global to use from the
   // nsIScriptGlobalObject that's reachable from the node we're about
   // to wrap here? But that's not always reachable, let's use
   // globalObj for now...
 
-  nsresult rv = WrapNativeParent(cx, globalObj, native_parent, native_parent,
-                                 parentObj);
+  nsresult rv = WrapNativeParent(cx, globalObj, native_parent, parentObj);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return node->IsInNativeAnonymousSubtree() ?
     NS_SUCCESS_CHROME_ACCESS_ONLY : NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
 }
 
 NS_IMETHODIMP
 nsNodeSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
@@ -8945,17 +8899,17 @@ nsHTMLDocumentSH::GetDocumentAllNodeList
 
     list.forget(nodeList);
 
     // ... and store it in our reserved slot.
     JS_SetReservedSlot(obj, 0, collection);
   }
 
   if (NS_FAILED(rv)) {
-    nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_FAILURE);
+    xpc::Throw(cx, NS_ERROR_FAILURE);
 
     return JS_FALSE;
   }
 
   return *nodeList != nsnull;
 }
 
 JSBool
@@ -8997,33 +8951,33 @@ nsHTMLDocumentSH::DocumentAllGetProperty
       if (!GetDocumentAllNodeList(cx, obj, doc, getter_AddRefs(nodeList))) {
         return JS_FALSE;
       }
 
       PRUint32 length;
       rv = nodeList->GetLength(&length);
 
       if (NS_FAILED(rv)) {
-        nsDOMClassInfo::ThrowJSException(cx, rv);
+        xpc::Throw(cx, rv);
 
         return JS_FALSE;
       }
 
       *vp = INT_TO_JSVAL(length);
 
       return JS_TRUE;
     } else if (sTags_id != id) {
       // For all other strings, look for an element by id or name.
 
       nsDependentJSString str(id);
 
       result = doc->GetDocumentAllResult(str, &cache, &rv);
 
       if (NS_FAILED(rv)) {
-        nsDOMClassInfo::ThrowJSException(cx, rv);
+        xpc::Throw(cx, rv);
 
         return JS_FALSE;
       }
     }
     else {
       result = nsnull;
     }
   } else if (JSID_IS_INT(id) && JSID_TO_INT(id) >= 0) {
@@ -9041,17 +8995,17 @@ nsHTMLDocumentSH::DocumentAllGetProperty
     cache = node;
   } else {
     result = nsnull;
   }
 
   if (result) {
     rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx), result, cache, true, vp);
     if (NS_FAILED(rv)) {
-      nsDOMClassInfo::ThrowJSException(cx, rv);
+      xpc::Throw(cx, rv);
 
       return JS_FALSE;
     }
   } else {
     *vp = JSVAL_VOID;
   }
 
   return JS_TRUE;
@@ -9133,17 +9087,17 @@ JSBool
 nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp)
 {
   // Handle document.all("foo") style access to document.all.
 
   if (argc != 1) {
     // XXX: Should throw NS_ERROR_XPC_NOT_ENOUGH_ARGS for argc < 1,
     // and create a new NS_ERROR_XPC_TOO_MANY_ARGS for argc > 1? IE
     // accepts nothing other than one arg.
-    nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_INVALID_ARG);
+    xpc::Throw(cx, NS_ERROR_INVALID_ARG);
 
     return JS_FALSE;
   }
 
   // Convert all types to string.
   JSString *str = ::JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
   if (!str) {
     return JS_FALSE;
@@ -9227,17 +9181,17 @@ nsHTMLDocumentSH::DocumentAllHelperGetPr
     // qualified name. Expose the document.all collection.
 
     if (!vp->isObjectOrNull()) { 
       // First time through, create the collection, and set the
       // document as its private nsISupports data.
       nsresult rv;
       nsCOMPtr<nsIHTMLDocument> doc = do_QueryWrapper(cx, obj, &rv);
       if (NS_FAILED(rv)) {
-        nsDOMClassInfo::ThrowJSException(cx, rv);
+        xpc::Throw(cx, rv);
 
         return JS_FALSE;
       }
 
       JSObject *all = ::JS_NewObject(cx, &sHTMLDocumentAllClass, nsnull,
                                      ::JS_GetGlobalForObject(cx, obj));
       if (!all) {
         return JS_FALSE;
@@ -9305,17 +9259,17 @@ nsHTMLDocumentSH::DocumentAllTagsNewReso
 
     if (tags) {
       jsval v;
       nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
       nsresult rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx),
                                static_cast<nsINodeList*>(tags), tags, true,
                                &v, getter_AddRefs(holder));
       if (NS_FAILED(rv)) {
-        nsDOMClassInfo::ThrowJSException(cx, rv);
+        xpc::Throw(cx, rv);
 
         return JS_FALSE;
       }
 
       if (!::JS_DefinePropertyById(cx, obj, id, v, nsnull, nsnull, 0)) {
         return JS_FALSE;
       }
 
@@ -9405,17 +9359,17 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnec
 
           if (!helper) {
             return NS_ERROR_OUT_OF_MEMORY;
           }
 
           // Insert the helper into our prototype chain. helper's prototype
           // is already obj's current prototype.
           if (!::JS_SetPrototype(cx, obj, helper)) {
-            nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
+            xpc::Throw(cx, NS_ERROR_UNEXPECTED);
 
             return NS_ERROR_UNEXPECTED;
           }
         }
 
         // If we have (or just created) a helper, pass the resolve flags
         // to the helper as its private data.
         if (helper) {
@@ -10305,17 +10259,17 @@ nsCSSStyleDeclSH::PreCreate(nsISupports 
 
   nsICSSDeclaration *declaration = static_cast<nsICSSDeclaration*>(nativeObj);
   nsINode *native_parent = declaration->GetParentObject();
   if (!native_parent) {
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv =
-    WrapNativeParent(cx, globalObj, native_parent, native_parent, parentObj);
+    WrapNativeParent(cx, globalObj, native_parent, parentObj);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
 }
 
 nsresult
 nsCSSStyleDeclSH::GetStringAt(nsISupports *aNative, PRInt32 aIndex,
                               nsAString& aResult)
@@ -10920,33 +10874,36 @@ WebGLExtensionSH::PreCreate(nsISupports 
                             JSObject *globalObj, JSObject **parentObj)
 {
   *parentObj = globalObj;
 
   WebGLExtension *ext = static_cast<WebGLExtension*>(nativeObj);
   WebGLContext *webgl = ext->Context();
   nsINode *node = webgl->GetParentObject();
 
-  return WrapNativeParent(cx, globalObj, node, node, parentObj);
+  return WrapNativeParent(cx, globalObj, node, parentObj);
 }
 
 nsresult
 nsNewDOMBindingNoWrapperCacheSH::PreCreate(nsISupports *nativeObj,
                                            JSContext *cx,
                                            JSObject *globalObj,
                                            JSObject **parentObj)
 {
   // We don't allow this
   return NS_ERROR_UNEXPECTED;
 }
 
-NS_IMETHODIMP
-nsWebGLViewportHandlerSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
-                                    JSObject *globalObj, JSObject **parentObj)
+template<class T, class BaseType>
+NS_IMETHODIMP
+nsNewDOMBindingSH<T, BaseType>::PreCreate(nsISupports *nativeObj,
+                                          JSContext *cx,
+                                          JSObject *globalObj,
+                                          JSObject **parentObj)
 {
   *parentObj = globalObj;
 
-  WebGLContext *webgl = static_cast<WebGLContext*>(
-    static_cast<nsIDOMWebGLRenderingContext*>(nativeObj));
-  nsINode *node = webgl->GetParentObject();
-
-  return WrapNativeParent(cx, globalObj, node, node, parentObj);
-}
+  T *native = static_cast<T*>(static_cast<BaseType*>(nativeObj));
+  if (!native->GetParentObject()) {
+    return NS_OK;
+  }
+  return WrapNativeParent(cx, globalObj, native->GetParentObject(), parentObj);
+}
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -21,16 +21,17 @@ namespace mozilla {
 class DOMSVGLengthList;
 class DOMSVGNumberList;
 class DOMSVGPathSegList;
 class DOMSVGPointList;
 class DOMSVGStringList;
 class DOMSVGTransformList;
 }
 class nsGlobalWindow;
+class nsICanvasRenderingContextInternal;
 class nsIDOMDocument;
 class nsIDOMHTMLOptionsCollection;
 class nsIDOMSVGLength;
 class nsIDOMSVGLengthList;
 class nsIDOMSVGNumber;
 class nsIDOMSVGNumberList;
 class nsIDOMSVGPathSeg;
 class nsIDOMSVGPathSegList;
@@ -116,18 +117,16 @@ public:
 
   static void ShutDown();
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsDOMClassInfo(aData);
   }
 
-  static nsresult ThrowJSException(JSContext *cx, nsresult aResult);
-
   /*
    * The following two functions exist because of the way that Xray wrappers
    * work. In order to allow scriptable helpers to define non-IDL defined but
    * still "safe" properties for Xray wrappers, we call into the scriptable
    * helper with |obj| being the wrapper.
    *
    * Ideally, that would be the end of the story, however due to complications
    * dealing with document.domain, it's possible to end up in a scriptable
@@ -1526,50 +1525,16 @@ protected:
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsFileListSH(aData);
   }
 };
 
-class nsWebGLViewportHandlerSH : public nsDOMGenericSH
-{
-protected:
-  nsWebGLViewportHandlerSH(nsDOMClassInfoData *aData) : nsDOMGenericSH(aData)
-  {
-  }
-
-  virtual ~nsWebGLViewportHandlerSH()
-  {
-  }
-
-public:
-  NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto) {
-    nsresult rv = nsDOMGenericSH::PostCreatePrototype(cx, proto);
-    if (NS_SUCCEEDED(rv)) {
-      if (!::JS_DefineProperty(cx, proto, "VIEWPORT", INT_TO_JSVAL(0x0BA2),
-                               nsnull, nsnull, JSPROP_ENUMERATE))
-      {
-        return NS_ERROR_UNEXPECTED;
-      }
-    }
-    return rv;
-  }
-
-  NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
-
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsWebGLViewportHandlerSH(aData);
-  }
-};
-
-
 // Template for SVGXXXList helpers
  
 template<class ListInterfaceType, class ListType>
 class nsSVGListSH : public nsArraySH
 {
 protected:
   nsSVGListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
   {
@@ -1609,9 +1574,63 @@ protected:
   
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsSVGStringListSH(aData);
   }
 };
 
+template<class T, class BaseType = T>
+class nsNewDOMBindingSH : public nsDOMGenericSH
+{
+protected:
+  nsNewDOMBindingSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
+  {
+  }
+
+  virtual ~nsNewDOMBindingSH()
+  {
+  }
+
+public:
+  NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
+                       JSObject *globalObj, JSObject **parentObj);
+
+  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
+  {
+    return new nsNewDOMBindingSH<T, BaseType>(aData);
+  }
+};
+
+class nsWebGLViewportHandlerSH
+  : public nsNewDOMBindingSH<nsICanvasRenderingContextInternal>
+{
+protected:
+  nsWebGLViewportHandlerSH(nsDOMClassInfoData *aData)
+    : nsNewDOMBindingSH<nsICanvasRenderingContextInternal>(aData)
+  {
+  }
+
+  virtual ~nsWebGLViewportHandlerSH()
+  {
+  }
+
+public:
+  NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto) {
+    nsresult rv = nsDOMGenericSH::PostCreatePrototype(cx, proto);
+    if (NS_SUCCEEDED(rv)) {
+      if (!::JS_DefineProperty(cx, proto, "VIEWPORT", INT_TO_JSVAL(0x0BA2),
+                               nsnull, nsnull, JSPROP_ENUMERATE))
+      {
+        return NS_ERROR_UNEXPECTED;
+      }
+    }
+    return rv;
+  }
+
+  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
+  {
+    return new nsWebGLViewportHandlerSH(aData);
+  }
+};
+
 #endif /* nsDOMClassInfo_h___ */
--- a/dom/base/nsDOMScriptObjectFactory.cpp
+++ b/dom/base/nsDOMScriptObjectFactory.cpp
@@ -50,17 +50,16 @@ nsDOMScriptObjectFactory::nsDOMScriptObj
   nsCOMPtr<nsIExceptionProvider> provider = new nsDOMExceptionProvider();
   nsCOMPtr<nsIExceptionService> xs =
     do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
 
   if (xs) {
     xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM);
     xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_SVG);
     xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM_XPATH);
-    xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_XPCONNECT);
     xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM_INDEXEDDB);
     xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM_FILEHANDLE);
   }
 
   NS_ASSERTION(!gExceptionProvider, "Registered twice?!");
   provider.swap(gExceptionProvider);
 
   // And pre-create the javascript language.
@@ -137,51 +136,28 @@ nsDOMScriptObjectFactory::Observe(nsISup
       if (xs) {
         xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_DOM);
         xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_SVG);
         xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_DOM_XPATH);
         xs->UnregisterExceptionProvider(gExceptionProvider,
-                                        NS_ERROR_MODULE_XPCONNECT);
-        xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_DOM_INDEXEDDB);
         xs->UnregisterExceptionProvider(gExceptionProvider,
                                         NS_ERROR_MODULE_DOM_FILEHANDLE);
       }
 
       NS_RELEASE(gExceptionProvider);
     }
   }
 
   return NS_OK;
 }
 
-static nsresult
-CreateXPConnectException(nsresult aResult, nsIException *aDefaultException,
-                         nsIException **_retval)
-{
-  // See whether we already have a useful XPConnect exception.  If we
-  // do, let's not create one with _less_ information!
-  nsCOMPtr<nsIXPCException> exception(do_QueryInterface(aDefaultException));
-  if (!exception) {
-    nsresult rv = NS_OK;
-    exception = do_CreateInstance("@mozilla.org/js/xpc/Exception;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = exception->Initialize(nsnull, aResult, nsnull, nsnull, nsnull,
-                               nsnull);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  exception.forget(_retval);
-  return NS_OK;
-}
-
 NS_IMETHODIMP
 nsDOMScriptObjectFactory::RegisterDOMClassInfo(const char *aName,
 					       nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
 					       const nsIID *aProtoChainInterface,
 					       const nsIID **aInterfaces,
 					       PRUint32 aScriptableFlags,
 					       bool aHasClassInterface,
 					       const nsCID *aConstructorCID)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -535,17 +535,17 @@ nsTimeout::~nsTimeout()
 
     --gTimeoutCnt;
   }
 #endif
 
   MOZ_COUNT_DTOR(nsTimeout);
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsTimeout)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsTimeout)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsTimeout)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsTimeout)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow,
                                                        nsIScriptGlobalObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptHandler)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout, AddRef)
@@ -1222,17 +1222,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
                                                   nsEventListenerManager)
 
   for (nsTimeout* timeout = tmp->FirstTimeout();
        tmp->IsTimeout(timeout);
        timeout = timeout->Next()) {
-    cb.NoteNativeChild(timeout, &NS_CYCLE_COLLECTION_NAME(nsTimeout));
+    cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(nsTimeout));
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLocalStorage)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSessionStorage)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc)
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -35,17 +35,16 @@
 #include "nsContentUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsIContent.h"
 #include "nsCycleCollector.h"
 #include "nsNetUtil.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsIXULRuntime.h"
 
-#include "nsDOMClassInfo.h"
 #include "xpcpublic.h"
 
 #include "jsdbgapi.h"           // for JS_ClearWatchPointsForObject
 #include "jswrapper.h"
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsDOMScriptObjectHolder.h"
@@ -3695,17 +3694,17 @@ NS_DOMReadStructuredClone(JSContext* cx,
                                  getter_AddRefs(wrapper));
     if (NS_FAILED(rv)) {
       return nsnull;
     }
     return val.toObjectOrNull();
   }
 
   // Don't know what this is. Bail.
-  nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
+  xpc::Throw(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
   return nsnull;
 }
 
 JSBool
 NS_DOMWriteStructuredClone(JSContext* cx,
                            JSStructuredCloneWriter* writer,
                            JSObject* obj,
                            void *closure)
@@ -3729,26 +3728,26 @@ NS_DOMWriteStructuredClone(JSContext* cx
 
     // Write the internals to the stream.
     return JS_WriteUint32Pair(writer, SCTAG_DOM_IMAGEDATA, 0) &&
            JS_WriteUint32Pair(writer, width, height) &&
            JS_WriteTypedArray(writer, dataArray);
   }
 
   // Don't know what this is. Bail.
-  nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
+  xpc::Throw(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
   return JS_FALSE;
 }
 
 void
 NS_DOMStructuredCloneError(JSContext* cx,
                            uint32_t errorid)
 {
   // We don't currently support any extensions to structured cloning.
-  nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
+  xpc::Throw(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
 }
 
 //static
 nsresult
 nsJSRuntime::Init()
 {
   if (sIsInitialized) {
     if (!nsContentUtils::XPConnect())
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -119,23 +119,22 @@ nsScriptNameSpaceManager::~nsScriptNameS
     // Destroy the hash
     PL_DHashTableFinish(&mGlobalNames);
     PL_DHashTableFinish(&mNavigatorNames);
   }
   MOZ_COUNT_DTOR(nsScriptNameSpaceManager);
 }
 
 nsGlobalNameStruct *
-nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const char *aKey,
+nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const nsAString *aKey,
                                     const PRUnichar **aClassName)
 {
-  NS_ConvertASCIItoUTF16 key(aKey);
   GlobalNameMapEntry *entry =
     static_cast<GlobalNameMapEntry *>
-               (PL_DHashTableOperate(aTable, &key, PL_DHASH_ADD));
+               (PL_DHashTableOperate(aTable, aKey, PL_DHASH_ADD));
 
   if (!entry) {
     return nsnull;
   }
 
   if (aClassName) {
     *aClassName = entry->mKey.get();
   }
@@ -340,17 +339,18 @@ nsScriptNameSpaceManager::RegisterInterf
                                             const nsIID *aIfIID,
                                             bool* aFoundOld)
 {
   *aFoundOld = false;
 
   nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aIfName);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
-  if (s->mType != nsGlobalNameStruct::eTypeNotInitialized) {
+  if (s->mType != nsGlobalNameStruct::eTypeNotInitialized &&
+      s->mType != nsGlobalNameStruct::eTypeNewDOMBinding) {
     *aFoundOld = true;
 
     return NS_OK;
   }
 
   s->mType = nsGlobalNameStruct::eTypeInterface;
   s->mIID = *aIfIID;
 
@@ -529,16 +529,17 @@ nsScriptNameSpaceManager::RegisterClassN
   // If a external constructor is already defined with aClassName we
   // won't overwrite it.
 
   if (s->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
     return NS_OK;
   }
 
   NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
+               s->mType == nsGlobalNameStruct::eTypeNewDOMBinding ||
                s->mType == nsGlobalNameStruct::eTypeInterface,
                "Whaaa, JS environment name clash!");
 
   s->mType = nsGlobalNameStruct::eTypeClassConstructor;
   s->mDOMClassInfoID = aDOMClassInfoID;
   s->mChromeOnly = aPrivileged;
   s->mDisabled = aDisabled;
 
@@ -553,16 +554,17 @@ nsScriptNameSpaceManager::RegisterClassP
   NS_ENSURE_ARG_POINTER(aConstructorProtoIID);
 
   *aFoundOld = false;
 
   nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   if (s->mType != nsGlobalNameStruct::eTypeNotInitialized &&
+      s->mType != nsGlobalNameStruct::eTypeNewDOMBinding &&
       s->mType != nsGlobalNameStruct::eTypeInterface) {
     *aFoundOld = true;
 
     return NS_OK;
   }
 
   s->mType = nsGlobalNameStruct::eTypeClassProto;
   s->mIID = *aConstructorProtoIID;
@@ -580,16 +582,17 @@ nsScriptNameSpaceManager::RegisterExtern
   // If an external constructor is already defined with aClassName we
   // won't overwrite it.
 
   if (s->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
     return NS_OK;
   }
 
   NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
+               s->mType == nsGlobalNameStruct::eTypeNewDOMBinding ||
                s->mType == nsGlobalNameStruct::eTypeInterface,
                "Whaaa, JS environment name clash!");
 
   s->mType = nsGlobalNameStruct::eTypeExternalClassInfoCreator;
   s->mCID = aCID;
 
   return NS_OK;
 }
@@ -612,16 +615,17 @@ nsScriptNameSpaceManager::RegisterDOMCID
 
   if (s->mType == nsGlobalNameStruct::eTypeClassConstructor ||
       s->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
     return NS_OK;
   }
 
   // XXX Should we bail out here?
   NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
+               s->mType == nsGlobalNameStruct::eTypeNewDOMBinding ||
                s->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator,
                "Someone tries to register classinfo data for a class that isn't new or external!");
 
   s->mData = new nsExternalDOMClassInfoData;
   NS_ENSURE_TRUE(s->mData, NS_ERROR_OUT_OF_MEMORY);
 
   s->mType = nsGlobalNameStruct::eTypeExternalClassInfo;
   s->mData->mName = aName;
@@ -703,17 +707,18 @@ nsScriptNameSpaceManager::AddCategoryEnt
     nsXPIDLCString constructorProto;
     rv = aCategoryManager->GetCategoryEntry(JAVASCRIPT_GLOBAL_CONSTRUCTOR_PROTO_ALIAS_CATEGORY,
                                             categoryEntry.get(),
                                             getter_Copies(constructorProto));
     if (NS_SUCCEEDED(rv)) {
       nsGlobalNameStruct *s = AddToHash(&mGlobalNames, categoryEntry.get());
       NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
-      if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
+      if (s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
+          s->mType == nsGlobalNameStruct::eTypeNewDOMBinding) {
         s->mAlias = new nsGlobalNameStruct::ConstructorAlias;
         s->mType = nsGlobalNameStruct::eTypeExternalConstructorAlias;
         s->mChromeOnly = false;
         s->mAlias->mCID = cid;
         AppendASCIItoUTF16(constructorProto, s->mAlias->mProtoName);
         s->mAlias->mProto = nsnull;
       } else {
         NS_WARNING("Global script name not overwritten!");
@@ -728,17 +733,18 @@ nsScriptNameSpaceManager::AddCategoryEnt
     table = &mNavigatorNames;
   } else {
     table = &mGlobalNames;
   }
 
   nsGlobalNameStruct *s = AddToHash(table, categoryEntry.get());
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
-  if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
+  if (s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
+      s->mType == nsGlobalNameStruct::eTypeNewDOMBinding) {
     s->mType = type;
     s->mCID = cid;
     s->mChromeOnly =
       strcmp(aCategory, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY) == 0;
   } else {
     NS_WARNING("Global script name not overwritten!");
   }
 
@@ -767,16 +773,19 @@ nsScriptNameSpaceManager::Observe(nsISup
   // TODO: we could observe NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID
   // and NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID but we are safe without it.
   // See bug 600460.
 
   return NS_OK;
 }
 
 void
-nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAString& aName,
+nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAFlatString& aName,
     mozilla::dom::binding::DefineInterface aDefineDOMInterface)
 {
-  nsGlobalNameStruct* s = LookupNameInternal(aName);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, &aName);
   if (s) {
+    if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
+      s->mType = nsGlobalNameStruct::eTypeNewDOMBinding;
+    }
     s->mDefineDOMInterface = aDefineDOMInterface;
   }
 }
--- a/dom/base/nsScriptNameSpaceManager.h
+++ b/dom/base/nsScriptNameSpaceManager.h
@@ -36,16 +36,17 @@ struct nsGlobalNameStruct
   {
     nsCID mCID;
     nsString mProtoName;
     nsGlobalNameStruct* mProto;    
   };
 
   enum nametype {
     eTypeNotInitialized,
+    eTypeNewDOMBinding,
     eTypeInterface,
     eTypeProperty,
     eTypeNavigatorProperty,
     eTypeExternalConstructor,
     eTypeStaticNameSet,
     eTypeDynamicNameSet,
     eTypeClassConstructor,
     eTypeClassProto,
@@ -57,17 +58,17 @@ struct nsGlobalNameStruct
   bool mChromeOnly;
   bool mDisabled;
 
   union {
     PRInt32 mDOMClassInfoID; // eTypeClassConstructor
     nsIID mIID; // eTypeInterface, eTypeClassProto
     nsExternalDOMClassInfoData* mData; // eTypeExternalClassInfo
     ConstructorAlias* mAlias; // eTypeExternalConstructorAlias
-    nsCID mCID; // All other types...
+    nsCID mCID; // All other types except eTypeNewDOMBinding
   };
 
   // For new style DOM bindings.
   mozilla::dom::binding::DefineInterface mDefineDOMInterface;
 
 private:
 
   // copy constructor
@@ -132,26 +133,32 @@ public:
                              const nsIID *aProtoChainInterface,
                              const nsIID **aInterfaces,
                              PRUint32 aScriptableFlags,
                              bool aHasClassInterface,
                              const nsCID *aConstructorCID);
 
   nsGlobalNameStruct* GetConstructorProto(const nsGlobalNameStruct* aStruct);
 
-  void RegisterDefineDOMInterface(const nsAString& aName,
+  void RegisterDefineDOMInterface(const nsAFlatString& aName,
     mozilla::dom::binding::DefineInterface aDefineDOMInterface);
 
 private:
   // Adds a new entry to the hash and returns the nsGlobalNameStruct
   // that aKey will be mapped to. If mType in the returned
   // nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
   // already existed.
+  nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const nsAString *aKey,
+                                const PRUnichar **aClassName = nsnull);
   nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const char *aKey,
-                                const PRUnichar **aClassName = nsnull);
+                                const PRUnichar **aClassName = nsnull)
+  {
+    NS_ConvertASCIItoUTF16 key(aKey);
+    return AddToHash(aTable, &key, aClassName);
+  }
 
   nsresult FillHash(nsICategoryManager *aCategoryManager,
                     const char *aCategory);
   nsresult FillHashWithDOMInterfaces();
   nsresult RegisterInterface(const char* aIfName,
                              const nsIID *aIfIID,
                              bool* aFoundOld);
 
--- a/dom/base/test/Makefile.in
+++ b/dom/base/test/Makefile.in
@@ -10,13 +10,14 @@ relativesrcdir = dom/base/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 TEST_FILES = \
   test_domrequest.html \
   test_gsp-standards.html \
   test_gsp-quirks.html \
+  test_nondomexception.html \
   $(NULL)
 
 libs:: $(TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_nondomexception.html
@@ -0,0 +1,28 @@
+<!-- intentionally omiting doctype because this test requires document.all -->
+<html>
+<head>
+  <title>Test for non-DOM module exceptions</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+"use strict";
+
+try {
+  document.all();
+} catch (e) {
+  is(typeof e, "object");
+  is(e.filename, location);
+  is(e.lineNumber, 18);
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -497,23 +497,23 @@ GetWrapperCache(const ParentObject& aPar
 {
   return aParentObject.mWrapperCache;
 }
 
 template<class T>
 inline nsISupports*
 GetParentPointer(T* aObject)
 {
-  return aObject;
+  return ToSupports(aObject);
 }
 
 inline nsISupports*
 GetParentPointer(const ParentObject& aObject)
 {
-  return aObject.mObject;
+  return ToSupports(aObject.mObject);
 }
 
 // Only set allowNativeWrapper to false if you really know you need it, if in
 // doubt use true. Setting it to false disables security wrappers.
 bool
 XPCOMObjectToJsval(JSContext* cx, JSObject* scope, xpcObjectHelper &helper,
                    const nsIID* iid, bool allowNativeWrapper, JS::Value* rval);
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3,16 +3,17 @@
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # Common codegen classes.
 
 import os
 import string
 
 from WebIDL import *
+from Configuration import NoSuchDescriptorError
 
 AUTOGENERATED_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
 ADDPROPERTY_HOOK_NAME = '_addProperty'
 FINALIZE_HOOK_NAME = '_finalize'
 TRACE_HOOK_NAME = '_trace'
 CONSTRUCT_HOOK_NAME = '_constructor'
 HASINSTANCE_HOOK_NAME = '_hasInstance'
@@ -346,16 +347,22 @@ class CGHeaders(CGWrapper):
                 assert len(s) == 2
                 (returnType, arguments) = s
                 types.append(returnType)
                 types.extend([a.type for a in arguments])
 
             attrs = [a for a in members if a.isAttr()]
             types.extend([a.type for a in attrs])
 
+            for dictionary in dictionaries:
+                curDict = dictionary
+                while curDict:
+                    types.extend([m.type for m in curDict.members])
+                    curDict = curDict.parent
+
             for t in types:
                 if t.unroll().isInterface():
                     if t.unroll().isSpiderMonkeyInterface():
                         bindingHeaders.add("jsfriendapi.h")
                         bindingHeaders.add("mozilla/dom/TypedArray.h")
                     else:
                         typeDesc = d.getDescriptor(t.unroll().inner.identifier.name)
                         if typeDesc is not None:
@@ -1551,25 +1558,25 @@ for (uint32_t i = 0; i < length; ++i) {
             templateBody += str(CallbackObjectUnwrapper(
                     descriptor,
                     "&${val}.toObject()",
                     "${declName}",
                     codeOnFailure=failureCode))
         elif descriptor.workers:
             templateBody += "${declName} = &${val}.toObject();"
         else:
-            # Either external, or new-binding non-castable.  We always have a
-            # holder for these, because we don't actually know whether we have
-            # to addref when unwrapping or not.  So we just pass an
-            # getter_AddRefs(nsRefPtr) to XPConnect and if we'll need a release
-            # it'll put a non-null pointer in there.
+            # External interface.  We always have a holder for these,
+            # because we don't actually know whether we have to addref
+            # when unwrapping or not.  So we just pass an
+            # getter_AddRefs(nsRefPtr) to XPConnect and if we'll need
+            # a release it'll put a non-null pointer in there.
             if forceOwningType:
                 # Don't return a holderType in this case; our declName
                 # will just own stuff.
-                templateBody += "nsRefPtr<" + typeName + "> ${holderName};"
+                templateBody += "nsRefPtr<" + typeName + "> ${holderName};\n"
             else:
                 holderType = "nsRefPtr<" + typeName + ">"
             templateBody += (
                 "jsval tmpVal = ${val};\n" +
                 typePtr + " tmp;\n"
                 "if (NS_FAILED(xpc_qsUnwrapArg<" + typeName + ">(cx, ${val}, &tmp, static_cast<" + typeName + "**>(getter_AddRefs(${holderName})), &tmpVal))) {\n")
             templateBody += CGIndenter(onFailure(failureCode,
                                                  descriptor.workers)).define()
@@ -1602,17 +1609,17 @@ for (uint32_t i = 0; i < length; ++i) {
         if isMember:
             raise TypeError("Can't handle member arraybuffers or "
                             "arraybuffer views because making sure all the "
                             "objects are properly rooted is hard")
         name = type.name
         if type.isArrayBuffer():
             jsname = "ArrayBufferObject"
         elif type.isArrayBufferView():
-            jsname = "TypedArrayObject"
+            jsname = "ArrayBufferViewObject"
         else:
             jsname = type.name
 
         # By default, we use a Maybe<> to hold our typed array.  And in the optional
         # non-nullable case we want to pass Optional<TypedArray> to consumers, not
         # Optional<NonNull<TypedArray> >, so jump though some hoops to do that.
         holderType = "Maybe<%s>" % name
         constructLoc = "${holderName}"
@@ -1751,21 +1758,23 @@ for (uint32_t i = 0; i < length; ++i) {
             declType = CGGeneric("NonNull<JSObject>")
         return (template, declType, None, isOptional)
 
     if type.isDictionary():
         if failureCode is not None:
             raise TypeError("Can't handle dictionaries when failureCode is not None")
 
         if type.nullable():
-            typeName = type.inner.inner.identifier.name
+            typeName = CGDictionary.makeDictionaryName(type.inner.inner,
+                                                       descriptorProvider.workers)
             declType = CGGeneric("Nullable<%s>" % typeName)
             selfRef = "${declName}.Value()"
         else:
-            typeName = type.inner.identifier.name
+            typeName = CGDictionary.makeDictionaryName(type.inner,
+                                                       descriptorProvider.workers)
             declType = CGGeneric(typeName)
             selfRef = "${declName}"
         # If we're optional or a member of something else, the const
         # will come from the Optional or our container.
         mutableTypeName = declType
         if not isOptional and not isMember:
             declType = CGWrapper(declType, pre="const ")
             selfRef = "const_cast<%s&>(%s)" % (typeName, selfRef)
@@ -3485,34 +3494,47 @@ class CGNamespacedEnum(CGThing):
         self.node = curr
 
     def declare(self):
         return self.node.declare()
     def define(self):
         assert False # Only for headers.
 
 class CGDictionary(CGThing):
-    def __init__(self, dictionary, workers):
+    def __init__(self, dictionary, descriptorProvider):
         self.dictionary = dictionary;
-        self.workers = workers
-        # Fake a descriptorProvider
-        # XXXbz this will fail for interface types!
-        for member in dictionary.members:
-            if member.type.unroll().isInterface():
-                raise TypeError("No support for interface members of dictionaries: %s.%s" %
-                                (dictionary.identifier.name, member.identifier.name))
-        self.memberInfo = [
-            (member,
-             getJSToNativeConversionTemplate(member.type,
-                                             { "workers": workers },
-                                             isMember=True,
-                                             isOptional=(not member.defaultValue)))
-            for member in dictionary.members ]
+        self.workers = descriptorProvider.workers
+        if dictionary.parent:
+            parentCGThing = CGDictionary(dictionary.parent, descriptorProvider)
+            self.generatable = parentCGThing.generatable
+            if not self.generatable:
+                # Nothing else to do here
+                return
+        else:
+            self.generatable = True
+        # Getting a conversion template for interface types can fail
+        # if we don't have a relevant descriptor when self.workers is True.
+        # If that happens, just mark ourselves as not being
+        # generatable and move on.
+        try:
+            self.memberInfo = [
+                (member,
+                 getJSToNativeConversionTemplate(member.type,
+                                                 descriptorProvider,
+                                                 isMember=True,
+                                                 isOptional=(not member.defaultValue)))
+                for member in dictionary.members ]
+        except NoSuchDescriptorError, err:
+            if not self.workers:
+                raise err
+            self.generatable = False
 
     def declare(self):
+        if not self.generatable:
+            return ""
         d = self.dictionary
         if d.parent:
             inheritance = ": public %s " % self.makeClassName(d.parent)
         else:
             inheritance = ""
         memberDecls = ["  %s %s;" %
                        (self.getMemberType(m), m[0].identifier.name)
                        for m in self.memberInfo]
@@ -3530,16 +3552,18 @@ class CGDictionary(CGThing):
                 "  static bool initedIds;\n" +
                 "\n".join("  static jsid " +
                           self.makeIdName(m.identifier.name) + ";" for
                           m in d.members) + "\n"
                 "};").substitute( { "selfName": self.makeClassName(d),
                                     "inheritance": inheritance }))
 
     def define(self):
+        if not self.generatable:
+            return ""
         d = self.dictionary
         if d.parent:
             initParent = ("// Per spec, we init the parent's members first\n"
                           "if (!%s::Init(cx, obj)) {\n"
                           "  return false;\n"
                           "}\n" % self.makeClassName(d.parent))
         else:
             initParent = ""
@@ -3585,43 +3609,50 @@ class CGDictionary(CGThing):
             "  return true;\n"
             "}").substitute({
                 "selfName": self.makeClassName(d),
                 "initParent": CGIndenter(CGGeneric(initParent)).define(),
                 "initMembers": "\n\n".join(memberInits),
                 "idInit": CGIndenter(idinit).define()
                 })
 
+    @staticmethod
+    def makeDictionaryName(dictionary, workers):
+        suffix = "Workers" if workers else ""
+        return dictionary.identifier.name + suffix
+
     def makeClassName(self, dictionary):
-        suffix = "Workers" if self.workers else ""
-        return dictionary.identifier.name + suffix
+        return self.makeDictionaryName(dictionary, self.workers)
 
     def getMemberType(self, memberInfo):
         (member, (templateBody, declType,
                   holderType, dealWithOptional)) = memberInfo
         # We can't handle having a holderType here
         assert holderType is None
         if dealWithOptional:
             declType = CGWrapper(declType, pre="Optional< ", post=" >")
         return declType.define()
 
     def getMemberConversion(self, memberInfo):
-        # Fake a descriptorProvider
         (member, (templateBody, declType,
                   holderType, dealWithOptional)) = memberInfo
         replacements = { "val": "temp",
                          "valPtr": "&temp",
                          # Use this->%s to refer to members, because we don't
                          # control the member names and want to make sure we're
                          # talking about the member, not some local that
                          # shadows the member.  Another option would be to move
                          # the guts of init to a static method which is passed
                          # an explicit reference to our dictionary object, so
                          # we couldn't screw this up even if we wanted to....
-                         "declName": ("(this->%s)" % member.identifier.name) }
+                         "declName": ("(this->%s)" % member.identifier.name),
+                         # We need a holder name for external interfaces, but
+                         # it's scoped down to the conversion so we can just use
+                         # anything we want.
+                         "holderName": "holder"}
         # We can't handle having a holderType here
         assert holderType is None
         if dealWithOptional:
             replacements["declName"] = "(" + replacements["declName"] + ".Value())"
 
         conversionReplacements = {
             "propId" : self.makeIdName(member.identifier.name),
             "prop": "(this->%s)" % member.identifier.name,
@@ -3691,17 +3722,40 @@ class CGBindingRoot(CGThing):
     """
     def __init__(self, config, prefix, webIDLFile):
         descriptors = config.getDescriptors(webIDLFile=webIDLFile,
                                             hasInterfaceOrInterfacePrototypeObject=True)
         dictionaries = config.getDictionaries(webIDLFile)
 
         forwardDeclares = [CGClassForwardDeclare('XPCWrappedNativeScope')]
 
-        for x in descriptors:
+        descriptorsForForwardDeclaration = list(descriptors)
+        for dictionary in dictionaries:
+            curDict = dictionary
+            ifacemembers = []
+            while curDict:
+                ifacemembers.extend([m.type.unroll().inner for m
+                                     in curDict.members
+                                     if m.type.unroll().isInterface()])
+                curDict = curDict.parent
+            # Put in all the non-worker descriptors
+            descriptorsForForwardDeclaration.extend(
+                [config.getDescriptor(iface.identifier.name, False) for
+                 iface in ifacemembers])
+            # And now the worker ones.  But these may not exist, so we
+            # have to be more careful.
+            for iface in ifacemembers:
+                try:
+                    descriptorsForForwardDeclaration.append(
+                        config.getDescriptor(iface.identifier.name, True))
+                except NoSuchDescriptorError:
+                    # just move along
+                    pass
+
+        for x in descriptorsForForwardDeclaration:
             nativeType = x.nativeType
             components = x.nativeType.split('::')
             className = components[-1]
             # JSObject is a struct, not a class
             declare = CGClassForwardDeclare(className, className is "JSObject")
             if len(components) > 1:
                 declare = CGNamespace.build(components[:-1],
                                             CGWrapper(declare, declarePre='\n',
@@ -3750,18 +3804,20 @@ class CGBindingRoot(CGThing):
         # dictionary in A.  The good news is that I expect this to never happen.
         reSortedDictionaries = []
         while len(dictionaries) != 0:
             toMove = [d for d in dictionaries if d.parent not in dictionaries]
             dictionaries = [d for d in dictionaries if d.parent in dictionaries]
             reSortedDictionaries.extend(toMove)
 
         dictionaries = reSortedDictionaries
-        cgthings.extend([CGDictionary(d, workers=True) for d in dictionaries])
-        cgthings.extend([CGDictionary(d, workers=False) for d in dictionaries])
+        cgthings.extend([CGDictionary(d, config.getDescriptorProvider(True))
+                         for d in dictionaries])
+        cgthings.extend([CGDictionary(d, config.getDescriptorProvider(False))
+                         for d in dictionaries])
 
         # Do codegen for all the descriptors
         cgthings.extend([CGDescriptor(x) for x in descriptors])
 
         # And make sure we have the right number of newlines at the end
         curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
 
         # Wrap all of that in our namespaces.
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -70,23 +70,65 @@ class Configuration:
             else:
                 getter = lambda x: getattr(x, key)
             curr = filter(lambda x: getter(x) == val, curr)
         return curr
     def getEnums(self, webIDLFile):
         return filter(lambda e: e.filename() == webIDLFile, self.enums)
     def getDictionaries(self, webIDLFile):
         return filter(lambda d: d.filename() == webIDLFile, self.dictionaries)
+    def getDescriptor(self, interfaceName, workers):
+        """
+        Gets the appropriate descriptor for the given interface name
+        and the given workers boolean.
+        """
+        iface = self.getInterface(interfaceName)
+        descriptors = self.getDescriptors(interface=iface)
 
-class Descriptor:
+        # The only filter we currently have is workers vs non-workers.
+        matches = filter(lambda x: x.workers is workers, descriptors)
+
+        # After filtering, we should have exactly one result.
+        if len(matches) is not 1:
+            raise NoSuchDescriptorError("For " + interfaceName + " found " +
+                                        str(len(matches)) + " matches");
+        return matches[0]
+    def getDescriptorProvider(self, workers):
+        """
+        Gets a descriptor provider that can provide descriptors as needed,
+        for the given workers boolean
+        """
+        return DescriptorProvider(self, workers)
+
+class NoSuchDescriptorError(TypeError):
+    def __init__(self, str):
+        TypeError.__init__(self, str)
+
+class DescriptorProvider:
+    """
+    A way of getting descriptors for interface names
+    """
+    def __init__(self, config, workers):
+        self.config = config
+        self.workers = workers
+
+    def getDescriptor(self, interfaceName):
+        """
+        Gets the appropriate descriptor for the given interface name given the
+        context of the current descriptor. This selects the appropriate
+        implementation for cases like workers.
+        """
+        return self.config.getDescriptor(interfaceName, self.workers)
+
+class Descriptor(DescriptorProvider):
     """
     Represents a single descriptor for an interface. See Bindings.conf.
     """
     def __init__(self, config, interface, desc):
-        self.config = config
+        DescriptorProvider.__init__(self, config, desc.get('workers', False))
         self.interface = interface
 
         # Read the desc, and fill in the relevant defaults.
         self.nativeType = desc['nativeType']
         self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
 
         headerDefault = self.nativeType
         headerDefault = headerDefault.split("::")[-1] + ".h"
@@ -104,17 +146,16 @@ class Descriptor:
         if self.concrete:
             iface = self.interface
             while iface:
                 iface.setUserData('hasConcreteDescendant', True)
                 iface = iface.parent
 
         self.prefable = desc.get('prefable', False)
 
-        self.workers = desc.get('workers', False)
         self.nativeIsISupports = not self.workers
         self.customTrace = desc.get('customTrace', self.workers)
         self.customFinalize = desc.get('customFinalize', self.workers)
         self.wrapperCache = self.workers or desc.get('wrapperCache', True)
 
         if not self.wrapperCache and self.prefable:
             raise TypeError("Descriptor for %s is prefable but not wrappercached" %
                             self.interface.identifier.name)
@@ -161,34 +202,16 @@ class Descriptor:
         # Forward-declared interfaces don't need either interface object or
         # interface prototype object as they're going to use QI (on main thread)
         # or be passed as a JSObject (on worker threads).
         if self.interface.isExternal():
             return False
 
         return self.interface.hasInterfaceObject() or self.interface.hasInterfacePrototypeObject()
 
-    def getDescriptor(self, interfaceName):
-        """
-        Gets the appropriate descriptor for the given interface name given the
-        context of the current descriptor. This selects the appropriate
-        implementation for cases like workers.
-        """
-        iface = self.config.getInterface(interfaceName)
-        descriptors = self.config.getDescriptors(interface=iface)
-
-        # The only filter we currently have is workers vs non-workers.
-        matches = filter(lambda x: x.workers is self.workers, descriptors)
-
-        # After filtering, we should have exactly one result.
-        if len(matches) is not 1:
-            raise TypeError("For " + interfaceName + " found " +
-                            str(len(matches)) + " matches");
-        return matches[0]
-
     def getExtendedAttributes(self, member, getter=False, setter=False):
         name = member.identifier.name
         if member.isMethod():
             return self.extendedAttributes['all'].get(name, [])
 
         assert member.isAttr()
         assert bool(getter) != bool(setter)
         key = 'getterOnly' if getter else 'setterOnly'
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -629,16 +629,21 @@ class IDLDictionary(IDLObjectWithScope):
                                   extraLocation=self.parent.location)
 
             # Make sure the parent resolves all its members before we start
             # looking at them.
             self.parent.finish(scope)
 
         for member in self.members:
             member.resolve(self)
+            if not member.type.isComplete():
+                type = member.type.complete(scope)
+                assert not isinstance(type, IDLUnresolvedType)
+                assert not isinstance(type.name, IDLUnresolvedIdentifier)
+                member.type = type
 
         # Members of a dictionary are sorted in lexicographic order
         self.members.sort(cmp=cmp, key=lambda x: x.identifier.name)
 
         inheritedMembers = []
         ancestor = self.parent
         while ancestor:
             if ancestor == self:
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -299,9 +299,11 @@ dictionary Dict : ParentDict {
   long a;
   long b = 8;
   long z = 9;
   DOMString str;
 };
 
 dictionary ParentDict : GrandparentDict {
   long c = 5;
+  TestInterface someInterface;
+  TestExternalInterface someExternalInterface;
 };
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -12,22 +12,23 @@
 #include "nsDOMBlobBuilder.h"
 #include "nsNetUtil.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIContentPermissionPrompt.h"
 #include "nsIPrincipal.h"
 #include "mozilla/Preferences.h"
 #include "nsJSUtils.h"
 #include "DictionaryHelpers.h"
+#include "mozilla/Attributes.h"
 
 using namespace mozilla::dom;
 
 #include "nsDirectoryServiceDefs.h"
 
-class DeviceStorageFile : public nsISupports {
+class DeviceStorageFile MOZ_FINAL : public nsISupports {
 public:
 
   nsCOMPtr<nsIFile> mFile;
   nsString mPath;
 
   DeviceStorageFile(nsIFile* aFile, const nsAString& aPath)
   : mPath(aPath)
   {
--- a/dom/file/FileHandle.h
+++ b/dom/file/FileHandle.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_dom_file_filehandle_h__
 #define mozilla_dom_file_filehandle_h__
 
 #include "FileCommon.h"
 
 #include "nsIDOMFileHandle.h"
 #include "nsIFile.h"
+#include "nsIFileStorage.h"
 
 #include "nsDOMEventTargetHelper.h"
 
 class nsIDOMFile;
 class nsIFileStorage;
 
 BEGIN_FILE_NAMESPACE
 
--- a/dom/indexedDB/DatabaseInfo.cpp
+++ b/dom/indexedDB/DatabaseInfo.cpp
@@ -100,24 +100,35 @@ ObjectStoreInfo::ObjectStoreInfo()
 }
 
 ObjectStoreInfo::~ObjectStoreInfo()
 {
   MOZ_COUNT_DTOR(ObjectStoreInfo);
 }
 
 IndexUpdateInfo::IndexUpdateInfo()
+: indexId(0),
+  indexUnique(false)
+{
+  MOZ_COUNT_CTOR(IndexUpdateInfo);
+}
+
+IndexUpdateInfo::IndexUpdateInfo(const IndexUpdateInfo& aOther)
+: indexId(aOther.indexId),
+  indexUnique(aOther.indexUnique),
+  value(aOther.value)
 {
   MOZ_COUNT_CTOR(IndexUpdateInfo);
 }
 
 IndexUpdateInfo::~IndexUpdateInfo()
 {
   MOZ_COUNT_DTOR(IndexUpdateInfo);
 }
+
 #endif /* NS_BUILD_REFCNT_LOGGING */
 
 // static
 bool
 DatabaseInfo::Get(nsIAtom* aId,
                   DatabaseInfo** aInfo)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
--- a/dom/indexedDB/DatabaseInfo.h
+++ b/dom/indexedDB/DatabaseInfo.h
@@ -168,16 +168,17 @@ public:
   // we don't have that ability yet.
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ObjectStoreInfo)
 };
 
 struct IndexUpdateInfo
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
   IndexUpdateInfo();
+  IndexUpdateInfo(const IndexUpdateInfo& aOther);
   ~IndexUpdateInfo();
 #endif
 
   bool operator==(const IndexUpdateInfo& aOther) const
   {
     return this->indexId == aOther.indexId &&
            this->indexUnique == aOther.indexUnique &&
            this->value == aOther.value;
--- a/dom/indexedDB/FileInfo.cpp
+++ b/dom/indexedDB/FileInfo.cpp
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "IndexedDatabaseManager.h"
 #include "FileInfo.h"
 
 USING_INDEXEDDB_NAMESPACE
 
 // static
 FileInfo*
 FileInfo::Create(FileManager* aFileManager, PRInt64 aId)
 {
--- a/dom/indexedDB/FileInfo.h
+++ b/dom/indexedDB/FileInfo.h
@@ -3,18 +3,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_indexeddb_fileinfo_h__
 #define mozilla_dom_indexeddb_fileinfo_h__
 
 #include "IndexedDatabase.h"
+
 #include "nsAtomicRefcnt.h"
 #include "nsThreadUtils.h"
+
 #include "FileManager.h"
 #include "IndexedDatabaseManager.h"
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class FileInfo
 {
   friend class FileManager;
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -238,16 +238,20 @@ IDBDatabase::~IDBDatabase()
   nsContentUtils::ReleaseWrapper(static_cast<nsIDOMEventTarget*>(this), this);
 }
 
 void
 IDBDatabase::Invalidate()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
+  if (IsInvalidated()) {
+    return;
+  }
+
   // Make sure we're closed too.
   Close();
 
   // When the IndexedDatabaseManager needs to invalidate databases, all it has
   // is an origin, so we call back into the manager to cancel any prompts for
   // our owner.
   nsPIDOMWindow* owner = GetOwner();
   if (owner) {
--- a/dom/indexedDB/IDBFileHandle.cpp
+++ b/dom/indexedDB/IDBFileHandle.cpp
@@ -3,20 +3,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IDBFileHandle.h"
 
 #include "nsIStandardFileStream.h"
 
+#include "mozilla/dom/file/File.h"
 #include "nsDOMClassInfoID.h"
 
 #include "FileStream.h"
-#include "mozilla/dom/file/File.h"
+#include "IDBDatabase.h"
 
 USING_INDEXEDDB_NAMESPACE
 
 namespace {
 
 inline
 already_AddRefed<nsIFile>
 GetFileFor(FileInfo* aFileInfo)
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 #include "IDBKeyRange.h"
 
 #include "nsIXPConnect.h"
 
-#include "nsDOMClassInfo.h"
 #include "nsJSUtils.h"
 #include "nsThreadUtils.h"
 #include "nsContentUtils.h"
 
 #include "Key.h"
 
 #include "mozilla/dom/indexedDB/PIndexedDBIndex.h"
 #include "mozilla/dom/indexedDB/PIndexedDBObjectStore.h"
@@ -85,19 +84,17 @@ GetKeyFromJSVal(JSContext* aCx,
 }
 
 inline
 void
 ThrowException(JSContext* aCx,
                nsresult aErrorCode)
 {
   NS_ASSERTION(NS_FAILED(aErrorCode), "Not an error code!");
-  if (!JS_IsExceptionPending(aCx)) {
-    nsDOMClassInfo::ThrowJSException(aCx, aErrorCode);
-  }
+  xpc::Throw(aCx, aErrorCode);
 }
 
 inline
 bool
 GetKeyFromJSValOrThrow(JSContext* aCx,
                        jsval aVal,
                        Key& aKey)
 {
--- a/dom/indexedDB/IDBObjectStore.h
+++ b/dom/indexedDB/IDBObjectStore.h
@@ -19,16 +19,17 @@
 class nsIScriptContext;
 class nsPIDOMWindow;
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class AsyncConnectionHelper;
 class IDBCursor;
 class IDBKeyRange;
+class IDBRequest;
 class IndexedDBObjectStoreChild;
 class IndexedDBObjectStoreParent;
 class Key;
 
 struct IndexInfo;
 struct IndexUpdateInfo;
 struct ObjectStoreInfo;
 struct StructuredCloneReadInfo;
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -245,16 +245,17 @@ nsresult
 IDBTransaction::CommitOrRollback()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!IndexedDatabaseManager::IsMainProcess()) {
     NS_ASSERTION(mActorChild, "Must have an actor!");
 
     mActorChild->SendAllRequestsFinished();
+
     return NS_OK;
   }
 
   nsRefPtr<CommitHelper> helper =
     new CommitHelper(this, mListener, mCreatedObjectStores);
 
   TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
   NS_ENSURE_STATE(pool);
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IndexedDatabaseManager.h"
 #include "DatabaseInfo.h"
 
+#include "nsIAtom.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsIFile.h"
 #include "nsIFileStorage.h"
 #include "nsIObserverService.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISHEntry.h"
 #include "nsISimpleEnumerator.h"
@@ -432,80 +433,89 @@ IndexedDatabaseManager::AllowNextSynchro
       NS_ASSERTION(op->mId && aId, "Why didn't we match earlier?");
     }
   }
 
   NS_NOTREACHED("Why didn't we find a SynchronizedOp?");
 }
 
 nsresult
-IndexedDatabaseManager::AcquireExclusiveAccess(const nsACString& aOrigin, 
-                                               IDBDatabase* aDatabase,
-                                               AsyncConnectionHelper* aHelper,
-                                               WaitingOnDatabasesCallback aCallback,
-                                               void* aClosure)
+IndexedDatabaseManager::AcquireExclusiveAccess(
+                                           const nsACString& aOrigin,
+                                           IDBDatabase* aDatabase,
+                                           AsyncConnectionHelper* aHelper,
+                                           nsIRunnable* aRunnable,
+                                           WaitingOnDatabasesCallback aCallback,
+                                           void* aClosure)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-  NS_ASSERTION(aHelper, "Why are you talking to me?");
+  NS_ASSERTION(!aDatabase || aHelper, "Need a helper with a database!");
+  NS_ASSERTION(aDatabase || aRunnable, "Need a runnable without a database!");
 
   // Find the right SynchronizedOp.
-  SynchronizedOp* op = nsnull;
-  PRUint32 count = mSynchronizedOps.Length();
-  for (PRUint32 index = 0; index < count; index++) {
-    SynchronizedOp* currentop = mSynchronizedOps[index].get();
-    if (currentop->mOrigin.Equals(aOrigin)) {
-      if (!currentop->mId ||
-          (aDatabase && currentop->mId == aDatabase->Id())) {
-        // We've found the right one.
-        NS_ASSERTION(!currentop->mHelper,
-                     "SynchronizedOp already has a helper?!?");
-        op = currentop;
-        break;
-      }
-    }
-  }
+  SynchronizedOp* op =
+    FindSynchronizedOp(aOrigin, aDatabase ? aDatabase->Id() : nsnull);
 
   NS_ASSERTION(op, "We didn't find a SynchronizedOp?");
+  NS_ASSERTION(!op->mHelper, "SynchronizedOp already has a helper?!?");
+  NS_ASSERTION(!op->mRunnable, "SynchronizedOp already has a runnable?!?");
 
   nsTArray<IDBDatabase*>* array;
   mLiveDatabases.Get(aOrigin, &array);
 
   // We need to wait for the databases to go away.
   // Hold on to all database objects that represent the same database file
   // (except the one that is requesting this version change).
   nsTArray<nsRefPtr<IDBDatabase> > liveDatabases;
 
   if (array) {
-    PRUint32 count = array->Length();
-    for (PRUint32 index = 0; index < count; index++) {
-      IDBDatabase*& database = array->ElementAt(index);
-      if (!database->IsClosed() &&
-          (!aDatabase ||
-           (aDatabase &&
+    if (aDatabase) {
+      // Grab all databases that are not yet closed but whose database id match
+      // the one we're looking for.
+      for (PRUint32 index = 0; index < array->Length(); index++) {
+        IDBDatabase*& database = array->ElementAt(index);
+        if (!database->IsClosed() &&
             database != aDatabase &&
-            database->Id() == aDatabase->Id()))) {
-        liveDatabases.AppendElement(database);
+            database->Id() == aDatabase->Id()) {
+          liveDatabases.AppendElement(database);
+        }
       }
     }
+    else {
+      // We want *all* databases, even those that are closed, if we're going to
+      // clear the origin.
+      liveDatabases.AppendElements(*array);
+    }
   }
 
-  if (liveDatabases.IsEmpty()) {
-    IndexedDatabaseManager::DispatchHelper(aHelper);
-    return NS_OK;
+  op->mHelper = aHelper;
+  op->mRunnable = aRunnable;
+
+  if (!liveDatabases.IsEmpty()) {
+    NS_ASSERTION(op->mDatabases.IsEmpty(),
+                 "How do we already have databases here?");
+    op->mDatabases.AppendElements(liveDatabases);
+
+    // Give our callback the databases so it can decide what to do with them.
+    aCallback(liveDatabases, aClosure);
+
+    NS_ASSERTION(liveDatabases.IsEmpty(),
+                 "Should have done something with the array!");
+
+    if (aDatabase) {
+      // Wait for those databases to close.
+      return NS_OK;
+    }
   }
 
-  NS_ASSERTION(op->mDatabases.IsEmpty(), "How do we already have databases here?");
-  op->mDatabases.AppendElements(liveDatabases);
-  op->mHelper = aHelper;
+  // If we're trying to open a database and nothing blocks it, or if we're
+  // clearing an origin, then go ahead and schedule the op.
+  nsresult rv = RunSynchronizedOp(aDatabase, op);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  // Give our callback the databases so it can decide what to do with them.
-  aCallback(liveDatabases, aClosure);
-
-  NS_ASSERTION(liveDatabases.IsEmpty(),
-               "Should have done something with the array!");
   return NS_OK;
 }
 
 // static
 bool
 IndexedDatabaseManager::IsShuttingDown()
 {
   return !!gShutdown;
@@ -580,69 +590,33 @@ IndexedDatabaseManager::HasOpenTransacti
 void
 IndexedDatabaseManager::OnDatabaseClosed(IDBDatabase* aDatabase)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aDatabase, "Null pointer!");
 
   // Check through the list of SynchronizedOps to see if any are waiting for
   // this database to close before proceeding.
-  PRUint32 count = mSynchronizedOps.Length();
-  for (PRUint32 index = 0; index < count; index++) {
-    nsAutoPtr<SynchronizedOp>& op = mSynchronizedOps[index];
-
-    if (op->mOrigin == aDatabase->Origin() &&
-        (op->mId == aDatabase->Id() || !op->mId)) {
-      // This database is in the scope of this SynchronizedOp.  Remove it
-      // from the list if necessary.
-      if (op->mDatabases.RemoveElement(aDatabase)) {
-        // Now set up the helper if there are no more live databases.
-        NS_ASSERTION(op->mHelper, "How did we get rid of the helper before "
-                     "removing the last database?");
-        if (op->mDatabases.IsEmpty()) {
-          // At this point, all databases are closed, so no new transactions
-          // can be started.  There may, however, still be outstanding
-          // transactions that have not completed.  We need to wait for those
-          // before we dispatch the helper.
-
-          FileService* service = FileService::Get();
-          TransactionThreadPool* pool = TransactionThreadPool::Get();
-
-          PRUint32 count = !!service + !!pool;
-
-          nsRefPtr<WaitForTransactionsToFinishRunnable> runnable =
-            new WaitForTransactionsToFinishRunnable(op,
-                                                    NS_MAX<PRUint32>(count, 1));
-
-          if (!count) {
-            runnable->Run();
-          }
-          else {
-            // Use the WaitForTransactionsToxFinishRunnable as the callback.
-
-            if (service) {
-              nsTArray<nsCOMPtr<nsIFileStorage> > array;
-              array.AppendElement(aDatabase);
-
-              if (!service->WaitForAllStoragesToComplete(array, runnable)) {
-                NS_WARNING("Failed to wait for storages to complete!");
-              }
-            }
-
-            if (pool) {
-              nsTArray<nsRefPtr<IDBDatabase> > array;
-              array.AppendElement(aDatabase);
-
-              if (!pool->WaitForAllDatabasesToComplete(array, runnable)) {
-                NS_WARNING("Failed to wait for databases to complete!");
-              }
-            }
-          }
+  SynchronizedOp* op = FindSynchronizedOp(aDatabase->Origin(), aDatabase->Id());
+  if (op) {
+    // This database is in the scope of this SynchronizedOp.  Remove it
+    // from the list if necessary.
+    if (op->mDatabases.RemoveElement(aDatabase)) {
+      // Now set up the helper if there are no more live databases.
+      NS_ASSERTION(op->mHelper || op->mRunnable,
+                   "How did we get rid of the helper/runnable before "
+                    "removing the last database?");
+      if (op->mDatabases.IsEmpty()) {
+        // At this point, all databases are closed, so no new transactions
+        // can be started.  There may, however, still be outstanding
+        // transactions that have not completed.  We need to wait for those
+        // before we dispatch the helper.
+        if (NS_FAILED(RunSynchronizedOp(aDatabase, op))) {
+          NS_WARNING("Failed to run synchronized op!");
         }
-        break;
       }
     }
   }
 }
 
 void
 IndexedDatabaseManager::SetCurrentWindowInternal(nsPIDOMWindow* aWindow)
 {
@@ -1096,51 +1070,72 @@ IndexedDatabaseManager::AsyncDeleteFile(
   rv = mIOThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 // static
 nsresult
-IndexedDatabaseManager::DispatchHelper(AsyncConnectionHelper* aHelper)
+IndexedDatabaseManager::RunSynchronizedOp(IDBDatabase* aDatabase,
+                                          SynchronizedOp* aOp)
 {
-  nsresult rv = NS_OK;
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  NS_ASSERTION(aOp, "Null pointer!");
+  NS_ASSERTION(!aDatabase || aOp->mHelper, "No helper on this op!");
+  NS_ASSERTION(aDatabase || aOp->mRunnable, "No runnable on this op!");
+  NS_ASSERTION(!aDatabase || aOp->mDatabases.IsEmpty(),
+               "This op isn't ready to run!");
 
-  // If the helper has a transaction, dispatch it to the transaction
-  // threadpool.
-  if (aHelper->HasTransaction()) {
-    rv = aHelper->DispatchToTransactionPool();
+  FileService* service = FileService::Get();
+  TransactionThreadPool* pool = TransactionThreadPool::Get();
+
+  nsTArray<nsRefPtr<IDBDatabase> > databases;
+  if (aDatabase) {
+    if (service || pool) {
+      databases.AppendElement(aDatabase);
+    }
   }
   else {
-    // Otherwise, dispatch it to the IO thread.
-    IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
-    NS_ASSERTION(manager, "We should definitely have a manager here");
-
-    rv = aHelper->Dispatch(manager->IOThread());
+    aOp->mDatabases.SwapElements(databases);
   }
 
-  NS_ENSURE_SUCCESS(rv, rv);
-  return rv;
-}
+  PRUint32 waitCount = service && pool && !databases.IsEmpty() ? 2 : 1;
+
+  nsRefPtr<WaitForTransactionsToFinishRunnable> runnable =
+    new WaitForTransactionsToFinishRunnable(aOp, waitCount);
+
+  // There's no point in delaying if we don't yet have a transaction thread pool
+  // or a file service. Also, if we're not waiting on any databases then we can
+  // also run immediately.
+  if (!(service || pool) || databases.IsEmpty()) {
+    nsresult rv = runnable->Run();
+    NS_ENSURE_SUCCESS(rv, rv);
 
-bool
-IndexedDatabaseManager::IsClearOriginPending(const nsACString& origin)
-{
-  // Iterate through our SynchronizedOps to see if we have an entry that matches
-  // this origin and has no id.
-  PRUint32 count = mSynchronizedOps.Length();
-  for (PRUint32 index = 0; index < count; index++) {
-    nsAutoPtr<SynchronizedOp>& op = mSynchronizedOps[index];
-    if (op->mOrigin.Equals(origin) && !op->mId) {
-      return true;
+    return NS_OK;
+  }
+
+  // Ask each service to call us back when they're done with this database.
+  if (service) {
+    // Have to copy here in case the pool needs a list too.
+    nsTArray<nsCOMPtr<nsIFileStorage> > array;
+    array.AppendElements(databases);
+
+    if (!service->WaitForAllStoragesToComplete(array, runnable)) {
+      NS_WARNING("Failed to wait for storages to complete!");
+      return NS_ERROR_FAILURE;
     }
   }
 
-  return false;
+  if (pool && !pool->WaitForAllDatabasesToComplete(databases, runnable)) {
+    NS_WARNING("Failed to wait for databases to complete!");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS2(IndexedDatabaseManager, nsIIndexedDatabaseManager,
                                            nsIObserver)
 
 NS_IMETHODIMP
 IndexedDatabaseManager::GetUsageForURI(
                                      nsIURI* aURI,
@@ -1232,43 +1227,41 @@ IndexedDatabaseManager::ClearDatabasesFo
 
   // If there is a pending or running clear operation for this origin, return
   // immediately.
   if (IsClearOriginPending(origin)) {
     return NS_OK;
   }
 
   // Queue up the origin clear runnable.
-  nsRefPtr<OriginClearRunnable> runnable =
-    new OriginClearRunnable(origin, mIOThread);
+  nsRefPtr<OriginClearRunnable> runnable = new OriginClearRunnable(origin);
 
   rv = WaitForOpenAllowed(origin, nsnull, runnable);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Give the runnable some help by invalidating any databases in the way.
-  // We need to grab references to any live databases here to prevent them from
+  runnable->AdvanceState();
+
+  // Give the runnable some help by invalidating any databases in the way. We
+  // need to grab references to any live databases here to prevent them from
   // dying while we invalidate them.
   nsTArray<nsRefPtr<IDBDatabase> > liveDatabases;
 
-  // Grab all live databases for this origin.
   nsTArray<IDBDatabase*>* array;
   if (mLiveDatabases.Get(origin, &array)) {
     liveDatabases.AppendElements(*array);
   }
 
-  // Invalidate all the live databases first.
   for (PRUint32 index = 0; index < liveDatabases.Length(); index++) {
     liveDatabases[index]->Invalidate();
   }
-  
+
   DatabaseInfo::RemoveAllForOrigin(origin);
 
   // After everything has been invalidated the helper should be dispatched to
   // the end of the event queue.
-
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IndexedDatabaseManager::Observe(nsISupports* aSubject,
                                 const char* aTopic,
                                 const PRUnichar* aData)
 {
@@ -1369,70 +1362,115 @@ IndexedDatabaseManager::Observe(nsISuppo
 
   NS_NOTREACHED("Unknown topic!");
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(IndexedDatabaseManager::OriginClearRunnable,
                               nsIRunnable)
 
+// static
+void
+IndexedDatabaseManager::
+OriginClearRunnable::InvalidateOpenedDatabases(
+                                   nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
+                                   void* aClosure)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  OriginClearRunnable* self = static_cast<OriginClearRunnable*>(aClosure);
+
+  nsTArray<nsRefPtr<IDBDatabase> > databases;
+  databases.SwapElements(aDatabases);
+
+  for (PRUint32 index = 0; index < databases.Length(); index++) {
+    databases[index]->Invalidate();
+  }
+
+  DatabaseInfo::RemoveAllForOrigin(self->mOrigin);
+}
+
 NS_IMETHODIMP
 IndexedDatabaseManager::OriginClearRunnable::Run()
 {
   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
   NS_ASSERTION(mgr, "This should never fail!");
 
-  if (NS_IsMainThread()) {
-    // On the first time on the main thread we dispatch to the IO thread.
-    if (mFirstCallback) {
-      NS_ASSERTION(mThread, "Should have a thread here!");
+  switch (mCallbackState) {
+    case Pending: {
+      NS_NOTREACHED("Should never get here without being dispatched!");
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    case OpenAllowed: {
+      NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+      AdvanceState();
 
-      mFirstCallback = false;
+      // Now we have to wait until the thread pool is done with all of the
+      // databases we care about.
+      nsresult rv =
+        mgr->AcquireExclusiveAccess(mOrigin, this, InvalidateOpenedDatabases,
+                                    this);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      return NS_OK;
+    }
+
+    case IO: {
+      NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
-      nsCOMPtr<nsIThread> thread;
-      mThread.swap(thread);
+      AdvanceState();
+
+      // Remove the directory that contains all our databases.
+      nsCOMPtr<nsIFile> directory;
+      nsresult rv =
+        mgr->GetDirectoryForOrigin(mOrigin, getter_AddRefs(directory));
+      NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to get directory to remove!");
 
-      // Dispatch to the IO thread.
-      if (NS_FAILED(thread->Dispatch(this, NS_DISPATCH_NORMAL))) {
-        NS_WARNING("Failed to dispatch to IO thread!");
+      if (NS_SUCCEEDED(rv)) {
+        bool exists;
+        rv = directory->Exists(&exists);
+        NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
+                         "Failed to check that the directory exists!");
+
+        if (NS_SUCCEEDED(rv) && exists && NS_FAILED(directory->Remove(true))) {
+          // This should never fail if we've closed all database connections
+          // correctly...
+          NS_ERROR("Failed to remove directory!");
+        }
+      }
+
+      // Now dispatch back to the main thread.
+      if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
+        NS_WARNING("Failed to dispatch to main thread!");
         return NS_ERROR_FAILURE;
       }
 
       return NS_OK;
     }
 
-    NS_ASSERTION(!mThread, "Should have been cleared already!");
+    case Complete: {
+      NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-    mgr->InvalidateFileManagersForOrigin(mOrigin);
+      mgr->InvalidateFileManagersForOrigin(mOrigin);
 
-    // Tell the IndexedDatabaseManager that we're done.
-    mgr->AllowNextSynchronizedOp(mOrigin, nsnull);
+      // Tell the IndexedDatabaseManager that we're done.
+      mgr->AllowNextSynchronizedOp(mOrigin, nsnull);
 
-    return NS_OK;
+      return NS_OK;
+    }
+
+    default:
+      NS_ERROR("Unknown state value!");
+      return NS_ERROR_UNEXPECTED;
   }
 
-  NS_ASSERTION(!mThread, "Should have been cleared already!");
-
-  // Remove the directory that contains all our databases.
-  nsCOMPtr<nsIFile> directory;
-  nsresult rv = mgr->GetDirectoryForOrigin(mOrigin, getter_AddRefs(directory));
-  if (NS_SUCCEEDED(rv)) {
-    bool exists;
-    rv = directory->Exists(&exists);
-    if (NS_SUCCEEDED(rv) && exists) {
-      rv = directory->Remove(true);
-    }
-  }
-  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to remove directory!");
-
-  // Switch back to the main thread to complete the sequence.
-  rv = NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
+  NS_NOTREACHED("Should never get here!");
+  return NS_ERROR_UNEXPECTED;
 }
 
 IndexedDatabaseManager::AsyncUsageRunnable::AsyncUsageRunnable(
                                      nsIURI* aURI,
                                      const nsACString& aOrigin,
                                      nsIIndexedDatabaseUsageCallback* aCallback)
 : mURI(aURI),
   mOrigin(aOrigin),
@@ -1586,59 +1624,84 @@ IndexedDatabaseManager::AsyncUsageRunnab
       NS_WARNING("Failed to dispatch to main thread!");
     }
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(IndexedDatabaseManager::WaitForTransactionsToFinishRunnable,
-                              nsIRunnable)
+NS_IMPL_THREADSAFE_ISUPPORTS1(
+                    IndexedDatabaseManager::WaitForTransactionsToFinishRunnable,
+                    nsIRunnable)
 
 NS_IMETHODIMP
 IndexedDatabaseManager::WaitForTransactionsToFinishRunnable::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-  NS_ASSERTION(mOp && mOp->mHelper, "What?");
+  NS_ASSERTION(mOp, "Null op!");
+  NS_ASSERTION(mOp->mHelper || mOp->mRunnable, "Nothing to run!");
   NS_ASSERTION(mCountdown, "Wrong countdown!");
 
   if (--mCountdown) {
     return NS_OK;
   }
 
   // Don't hold the callback alive longer than necessary.
   nsRefPtr<AsyncConnectionHelper> helper;
   helper.swap(mOp->mHelper);
 
+  nsCOMPtr<nsIRunnable> runnable;
+  runnable.swap(mOp->mRunnable);
+
   mOp = nsnull;
 
-  IndexedDatabaseManager::DispatchHelper(helper);
+  nsresult rv;
 
-  // The helper is responsible for calling
+  if (helper && helper->HasTransaction()) {
+    // If the helper has a transaction, dispatch it to the transaction
+    // threadpool.
+    rv = helper->DispatchToTransactionPool();
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  else {
+    // Otherwise, dispatch it to the IO thread.
+    IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
+    NS_ASSERTION(manager, "We should definitely have a manager here");
+
+    nsIEventTarget* target = manager->IOThread();
+
+    rv = helper ?
+         helper->Dispatch(target) :
+         target->Dispatch(runnable, NS_DISPATCH_NORMAL);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  // The helper or runnable is responsible for calling
   // IndexedDatabaseManager::AllowNextSynchronizedOp.
-
   return NS_OK;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(IndexedDatabaseManager::WaitForLockedFilesToFinishRunnable,
-                              nsIRunnable)
+NS_IMPL_THREADSAFE_ISUPPORTS1(
+                     IndexedDatabaseManager::WaitForLockedFilesToFinishRunnable,
+                     nsIRunnable)
 
 NS_IMETHODIMP
 IndexedDatabaseManager::WaitForLockedFilesToFinishRunnable::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   mBusy = false;
 
   return NS_OK;
 }
 
-IndexedDatabaseManager::SynchronizedOp::SynchronizedOp(const nsACString& aOrigin,
-                                                       nsIAtom* aId)
+IndexedDatabaseManager::
+SynchronizedOp::SynchronizedOp(const nsACString& aOrigin,
+                               nsIAtom* aId)
 : mOrigin(aOrigin), mId(aId)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   MOZ_COUNT_CTOR(IndexedDatabaseManager::SynchronizedOp);
 }
 
 IndexedDatabaseManager::SynchronizedOp::~SynchronizedOp()
 {
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -2,44 +2,44 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_indexeddb_indexeddatabasemanager_h__
 #define mozilla_dom_indexeddb_indexeddatabasemanager_h__
 
-#include "mozilla/dom/indexedDB/FileManager.h"
 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
-#include "mozilla/dom/indexedDB/IDBDatabase.h"
-#include "mozilla/dom/indexedDB/IDBRequest.h"
 
 #include "mozilla/Mutex.h"
 
 #include "nsIIndexedDatabaseManager.h"
 #include "nsIObserver.h"
 #include "nsIRunnable.h"
 #include "nsIThread.h"
 #include "nsIURI.h"
 
 #include "nsClassHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsHashKeys.h"
 
 #define INDEXEDDB_MANAGER_CONTRACTID "@mozilla.org/dom/indexeddb/manager;1"
 
 class mozIStorageQuotaCallback;
+class nsIAtom;
 class nsIFile;
 class nsITimer;
+class nsPIDOMWindow;
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class AsyncConnectionHelper;
-
 class CheckQuotaHelper;
+class FileManager;
+class IDBDatabase;
 
 class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager,
                                          public nsIObserver
 {
   friend class IDBDatabase;
 
 public:
   static already_AddRefed<IndexedDatabaseManager> GetOrCreate();
@@ -69,36 +69,39 @@ public:
     return mIOThread;
   }
 
   // Returns true if we've begun the shutdown process.
   static bool IsShuttingDown();
 
   static bool IsClosed();
 
-  typedef void (*WaitingOnDatabasesCallback)(nsTArray<nsRefPtr<IDBDatabase> >&, void*);
+  typedef void
+  (*WaitingOnDatabasesCallback)(nsTArray<nsRefPtr<IDBDatabase> >&, void*);
 
   // Acquire exclusive access to the database given (waits for all others to
   // close).  If databases need to close first, the callback will be invoked
   // with an array of said databases.
   nsresult AcquireExclusiveAccess(IDBDatabase* aDatabase,
+                                  const nsACString& aOrigin,
                                   AsyncConnectionHelper* aHelper,
                                   WaitingOnDatabasesCallback aCallback,
                                   void* aClosure)
   {
     NS_ASSERTION(aDatabase, "Need a DB here!");
-    return AcquireExclusiveAccess(aDatabase->Origin(), aDatabase, aHelper,
+    return AcquireExclusiveAccess(aOrigin, aDatabase, aHelper, nsnull,
                                   aCallback, aClosure);
   }
-  nsresult AcquireExclusiveAccess(const nsACString& aOrigin, 
-                                  AsyncConnectionHelper* aHelper,
+
+  nsresult AcquireExclusiveAccess(const nsACString& aOrigin,
+                                  nsIRunnable* aRunnable,
                                   WaitingOnDatabasesCallback aCallback,
                                   void* aClosure)
   {
-    return AcquireExclusiveAccess(aOrigin, nsnull, aHelper, aCallback,
+    return AcquireExclusiveAccess(aOrigin, nsnull, nsnull, aRunnable, aCallback,
                                   aClosure);
   }
 
   // Called when a window is being purged from the bfcache or the user leaves
   // a page which isn't going into the bfcache. Forces any live database
   // objects to close themselves and aborts any running transactions.
   void AbortCloseDatabasesForWindow(nsPIDOMWindow* aWindow);
 
@@ -192,19 +195,20 @@ public:
   static already_AddRefed<nsIAtom>
   GetDatabaseId(const nsACString& aOrigin,
                 const nsAString& aName);
 
 private:
   IndexedDatabaseManager();
   ~IndexedDatabaseManager();
 
-  nsresult AcquireExclusiveAccess(const nsACString& aOrigin, 
+  nsresult AcquireExclusiveAccess(const nsACString& aOrigin,
                                   IDBDatabase* aDatabase,
                                   AsyncConnectionHelper* aHelper,
+                                  nsIRunnable* aRunnable,
                                   WaitingOnDatabasesCallback aCallback,
                                   void* aClosure);
 
   void SetCurrentWindowInternal(nsPIDOMWindow* aWindow);
   bool QuotaIsLiftedInternal();
   void CancelPromptsForWindowInternal(nsPIDOMWindow* aWindow);
 
   // Called when a database is created.
@@ -221,34 +225,65 @@ private:
   // is called. Runs three times, first on the main thread, next on the IO
   // thread, and then finally again on the main thread. While on the IO thread
   // the runnable will actually remove the origin's database files and the
   // directory that contains them before dispatching itself back to the main
   // thread. When back on the main thread the runnable will notify the
   // IndexedDatabaseManager that the job has been completed.
   class OriginClearRunnable MOZ_FINAL : public nsIRunnable
   {
+    enum CallbackState {
+      // Not yet run.
+      Pending = 0,
+
+      // Running on the main thread in the callback for OpenAllowed.
+      OpenAllowed,
+
+      // Running on the IO thread.
+      IO,
+
+      // Running on the main thread after all work is done.
+      Complete
+    };
+
   public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIRUNNABLE
 
-    OriginClearRunnable(const nsACString& aOrigin,
-                        nsIThread* aThread)
+    OriginClearRunnable(const nsACString& aOrigin)
     : mOrigin(aOrigin),
-      mThread(aThread),
-      mFirstCallback(true)
+      mCallbackState(Pending)
     { }
 
+    void AdvanceState()
+    {
+      switch (mCallbackState) {
+        case Pending:
+          mCallbackState = OpenAllowed;
+          return;
+        case OpenAllowed:
+          mCallbackState = IO;
+          return;
+        case IO:
+          mCallbackState = Complete;
+          return;
+        default:
+          NS_NOTREACHED("Can't advance past Complete!");
+      }
+    }
+
+    static void InvalidateOpenedDatabases(
+                                   nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
+                                   void* aClosure);
+
+  private:
     nsCString mOrigin;
-    nsCOMPtr<nsIThread> mThread;
-    bool mFirstCallback;
+    CallbackState mCallbackState;
   };
 
-  bool IsClearOriginPending(const nsACString& origin);
-
   // Responsible for calculating the amount of space taken up by databases of a
   // certain origin. Created when nsIIDBIndexedDatabaseManager::GetUsageForURI
   // is called. May be canceled with
   // nsIIDBIndexedDatabaseManager::CancelGetUsageForURI. Runs twice, first on
   // the IO thread, then again on the main thread. While on the IO thread the
   // runnable will calculate the size of all files in the origin's directory
   // before dispatching itself back to the main thread. When on the main thread
   // the runnable will call the callback and then notify the
@@ -296,32 +331,34 @@ private:
     bool MustWaitFor(const SynchronizedOp& aRhs) const;
 
     void DelayRunnable(nsIRunnable* aRunnable);
     void DispatchDelayedRunnables();
 
     const nsCString mOrigin;
     nsCOMPtr<nsIAtom> mId;
     nsRefPtr<AsyncConnectionHelper> mHelper;
+    nsCOMPtr<nsIRunnable> mRunnable;
     nsTArray<nsCOMPtr<nsIRunnable> > mDelayedRunnables;
     nsTArray<nsRefPtr<IDBDatabase> > mDatabases;
   };
 
   // A callback runnable used by the TransactionPool when it's safe to proceed
   // with a SetVersion/DeleteDatabase/etc.
   class WaitForTransactionsToFinishRunnable MOZ_FINAL : public nsIRunnable
   {
   public:
     WaitForTransactionsToFinishRunnable(SynchronizedOp* aOp,
                                         PRUint32 aCountdown)
     : mOp(aOp), mCountdown(aCountdown)
     {
       NS_ASSERTION(mOp, "Why don't we have a runnable?");
       NS_ASSERTION(mOp->mDatabases.IsEmpty(), "We're here too early!");
-      NS_ASSERTION(mOp->mHelper, "What are we supposed to do when we're done?");
+      NS_ASSERTION(mOp->mHelper || mOp->mRunnable,
+                   "What are we supposed to do when we're done?");
       NS_ASSERTION(mCountdown, "Wrong countdown!");
     }
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIRUNNABLE
 
   private:
     // The IndexedDatabaseManager holds this alive.
@@ -356,17 +393,36 @@ private:
     AsyncDeleteFileRunnable(const nsAString& aFilePath)
     : mFilePath(aFilePath)
     { }
 
   private:
     nsString mFilePath;
   };
 
-  static nsresult DispatchHelper(AsyncConnectionHelper* aHelper);
+  static nsresult RunSynchronizedOp(IDBDatabase* aDatabase,
+                                    SynchronizedOp* aOp);
+
+  SynchronizedOp* FindSynchronizedOp(const nsACString& aOrigin,
+                                     nsIAtom* aId)
+  {
+    for (PRUint32 index = 0; index < mSynchronizedOps.Length(); index++) {
+      const nsAutoPtr<SynchronizedOp>& currentOp = mSynchronizedOps[index];
+      if (currentOp->mOrigin == aOrigin &&
+          (!currentOp->mId || currentOp->mId == aId)) {
+        return currentOp;
+      }
+    }
+    return nsnull;
+  }
+
+  bool IsClearOriginPending(const nsACString& aOrigin)
+  {
+    return !!FindSynchronizedOp(aOrigin, nsnull);
+  }
 
   // Maintains a list of live databases per origin.
   nsClassHashtable<nsCStringHashKey, nsTArray<IDBDatabase*> > mLiveDatabases;
 
   // TLS storage index for the current thread's window
   PRUintn mCurrentWindowIndex;
 
   // Lock protecting mQuotaHelperHash
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -1875,25 +1875,24 @@ OpenDatabaseHelper::StartSetVersion()
 
   nsRefPtr<SetVersionHelper> helper =
     new SetVersionHelper(transaction, mOpenDBRequest, this, mRequestedVersion,
                          mCurrentVersion);
 
   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
   NS_ASSERTION(mgr, "This should never be null!");
 
-  rv = mgr->AcquireExclusiveAccess(mDatabase, helper,
-            &VersionChangeEventsRunnable::QueueVersionChange<SetVersionHelper>,
+  rv = mgr->AcquireExclusiveAccess(mDatabase, mDatabase->Origin(), helper,
+             &VersionChangeEventsRunnable::QueueVersionChange<SetVersionHelper>,
                                    helper);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   // The SetVersionHelper is responsible for dispatching us back to the
   // main thread again and changing the state to eSetVersionCompleted.
   mState = eSetVersionPending;
-
   return NS_OK;
 }
 
 nsresult
 OpenDatabaseHelper::StartDelete()
 {
   NS_ASSERTION(mState == eDeletePending, "Why are we here?");
 
@@ -1905,18 +1904,18 @@ OpenDatabaseHelper::StartDelete()
 
   nsRefPtr<DeleteDatabaseHelper> helper =
     new DeleteDatabaseHelper(mOpenDBRequest, this, mCurrentVersion, mName,
                              mASCIIOrigin);
 
   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
   NS_ASSERTION(mgr, "This should never be null!");
 
-  rv = mgr->AcquireExclusiveAccess(mDatabase, helper,
-        &VersionChangeEventsRunnable::QueueVersionChange<DeleteDatabaseHelper>,
+  rv = mgr->AcquireExclusiveAccess(mDatabase, mDatabase->Origin(), helper,
+         &VersionChangeEventsRunnable::QueueVersionChange<DeleteDatabaseHelper>,
                                    helper);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   // The DeleteDatabaseHelper is responsible for dispatching us back to the
   // main thread again and changing the state to eDeleteCompleted.
   mState = eDeletePending;
   return NS_OK;
 }
@@ -2131,17 +2130,17 @@ OpenDatabaseHelper::GetSuccessResult(JSC
 
 nsresult
 OpenDatabaseHelper::NotifySetVersionFinished()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread");
   NS_ASSERTION(mState = eSetVersionPending, "How did we get here?");
 
   mState = eSetVersionCompleted;
-  
+
   // Dispatch ourself back to the main thread
   return NS_DispatchToCurrentThread(this);
 }
 
 nsresult
 OpenDatabaseHelper::NotifyDeleteFinished()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread");
--- a/dom/indexedDB/ipc/IndexedDBChild.cpp
+++ b/dom/indexedDB/ipc/IndexedDBChild.cpp
@@ -99,16 +99,48 @@ public:
 
   virtual nsresult
   GetSuccessResult(JSContext* aCx, jsval* aVal) MOZ_OVERRIDE;
 
   virtual nsresult
   DoDatabaseWork(mozIStorageConnection* aConnection) MOZ_OVERRIDE;
 };
 
+class VersionChangeRunnable : public nsRunnable
+{
+  nsRefPtr<IDBDatabase> mDatabase;
+  uint64_t mOldVersion;
+  uint64_t mNewVersion;
+
+public:
+  VersionChangeRunnable(IDBDatabase* aDatabase, const uint64_t& aOldVersion,
+                        const uint64_t& aNewVersion)
+  : mDatabase(aDatabase), mOldVersion(aOldVersion), mNewVersion(aNewVersion)
+  {
+    MOZ_ASSERT(aDatabase);
+  }
+
+  NS_IMETHOD Run() MOZ_OVERRIDE
+  {
+    if (mDatabase->IsClosed()) {
+      return NS_OK;
+    }
+
+    nsRefPtr<nsDOMEvent> event =
+      IDBVersionChangeEvent::Create(mOldVersion, mNewVersion);
+    MOZ_ASSERT(event);
+
+    bool dummy;
+    nsresult rv = mDatabase->DispatchEvent(event, &dummy);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return NS_OK;
+  }
+};
+
 } // anonymous namespace
 
 /*******************************************************************************
  * IndexedDBChild
  ******************************************************************************/
 
 IndexedDBChild::IndexedDBChild(const nsCString& aASCIIOrigin)
 : mFactory(nsnull), mASCIIOrigin(aASCIIOrigin)
@@ -357,43 +389,40 @@ IndexedDBDatabaseChild::RecvError(const 
 }
 
 bool
 IndexedDBDatabaseChild::RecvBlocked(const uint64_t& aOldVersion)
 {
   MOZ_ASSERT(mRequest);
   MOZ_ASSERT(!mDatabase);
 
-  nsRefPtr<nsDOMEvent> event =
-    IDBVersionChangeEvent::CreateBlocked(aOldVersion, mVersion);
+  nsCOMPtr<nsIRunnable> runnable =
+    IDBVersionChangeEvent::CreateBlockedRunnable(aOldVersion, mVersion,
+                                                 mRequest);
 
-  bool dummy;
-  if (NS_FAILED(mRequest->DispatchEvent(event, &dummy))) {
-    NS_WARNING("Failed to dispatch blocked event!");
+  MainThreadEventTarget target;
+  if (NS_FAILED(target.Dispatch(runnable, NS_DISPATCH_NORMAL))) {
+    NS_WARNING("Dispatch of blocked event failed!");
   }
 
   return true;
 }
 
 bool
 IndexedDBDatabaseChild::RecvVersionChange(const uint64_t& aOldVersion,
                                           const uint64_t& aNewVersion)
 {
   MOZ_ASSERT(mDatabase);
 
-  if (mDatabase->IsClosed()) {
-    return true;
-  }
+  nsCOMPtr<nsIRunnable> runnable =
+    new VersionChangeRunnable(mDatabase, aOldVersion, aNewVersion);
 
-  nsRefPtr<nsDOMEvent> event =
-    IDBVersionChangeEvent::Create(aOldVersion, aNewVersion);
-
-  bool dummy;
-  if (NS_FAILED(mDatabase->DispatchEvent(event, &dummy))) {
-    NS_WARNING("Failed to dispatch blocked event!");
+  MainThreadEventTarget target;
+  if (NS_FAILED(target.Dispatch(runnable, NS_DISPATCH_NORMAL))) {
+    NS_WARNING("Dispatch of versionchange event failed!");
   }
 
   return true;
 }
 
 bool
 IndexedDBDatabaseChild::RecvPIndexedDBTransactionConstructor(
                                              PIndexedDBTransactionChild* aActor,
@@ -498,47 +527,62 @@ IndexedDBTransactionChild::SetTransactio
 
   aTransaction->SetActor(this);
 
   mTransaction = aTransaction;
   mStrongTransaction = aTransaction;
 }
 
 void
-IndexedDBTransactionChild::ActorDestroy(ActorDestroyReason aWhy)
-{
-  if (mTransaction) {
-    mTransaction->SetActor(static_cast<IndexedDBTransactionChild*>(NULL));
-#ifdef DEBUG
-    mTransaction = NULL;
-#endif
-  }
-}
-
-bool
-IndexedDBTransactionChild::RecvComplete(const nsresult& aRv)
+IndexedDBTransactionChild::FireCompleteEvent(nsresult aRv)
 {
   MOZ_ASSERT(mTransaction);
   MOZ_ASSERT(mStrongTransaction);
 
   nsRefPtr<IDBTransaction> transaction;
   mStrongTransaction.swap(transaction);
 
   // This is where we should allow the database to start issuing new
   // transactions once we fix the main thread. E.g.:
   //
   //   if (transaction->GetMode() == IDBTransaction::VERSION_CHANGE) {
   //     transaction->Database()->ExitSetVersionTransaction();
   //   }
 
   nsRefPtr<CommitHelper> helper = new CommitHelper(transaction, aRv);
-  if (NS_FAILED(helper->Run())) {
-    NS_WARNING("CommitHelper failed!");
+
+  MainThreadEventTarget target;
+  if (NS_FAILED(target.Dispatch(helper, NS_DISPATCH_NORMAL))) {
+    NS_WARNING("Dispatch of CommitHelper failed!");
+  }
+}
+
+void
+IndexedDBTransactionChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+  if (mStrongTransaction) {
+    // We're being torn down before we received a complete event from the parent
+    // so fake one here.
+    FireCompleteEvent(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+
+    MOZ_ASSERT(!mStrongTransaction);
   }
 
+  if (mTransaction) {
+    mTransaction->SetActor(static_cast<IndexedDBTransactionChild*>(NULL));
+#ifdef DEBUG
+    mTransaction = NULL;
+#endif
+  }
+}
+
+bool
+IndexedDBTransactionChild::RecvComplete(const nsresult& aRv)
+{
+  FireCompleteEvent(aRv);
   return true;
 }
 
 PIndexedDBObjectStoreChild*
 IndexedDBTransactionChild::AllocPIndexedDBObjectStore(
                                     const ObjectStoreConstructorParams& aParams)
 {
   MOZ_NOT_REACHED("Caller is supposed to manually construct an object store!");
@@ -1054,22 +1098,23 @@ IndexedDBDeleteDatabaseRequestChild::Rec
 }
 
 bool
 IndexedDBDeleteDatabaseRequestChild::RecvBlocked(
                                                 const uint64_t& aCurrentVersion)
 {
   MOZ_ASSERT(mOpenRequest);
 
-  nsRefPtr<nsDOMEvent> event =
-    IDBVersionChangeEvent::CreateBlocked(aCurrentVersion, 0);
+  nsCOMPtr<nsIRunnable> runnable =
+    IDBVersionChangeEvent::CreateBlockedRunnable(aCurrentVersion, 0,
+                                                 mOpenRequest);
 
-  bool dummy;
-  if (NS_FAILED(mOpenRequest->DispatchEvent(event, &dummy))) {
-    NS_WARNING("Failed to dispatch blocked event!");
+  MainThreadEventTarget target;
+  if (NS_FAILED(target.Dispatch(runnable, NS_DISPATCH_NORMAL))) {
+    NS_WARNING("Dispatch of blocked event failed!");
   }
 
   return true;
 }
 
 /*******************************************************************************
  * Helpers
  ******************************************************************************/
--- a/dom/indexedDB/ipc/IndexedDBChild.h
+++ b/dom/indexedDB/ipc/IndexedDBChild.h
@@ -150,16 +150,19 @@ public:
 
   IDBTransaction*
   GetTransaction() const
   {
     return mTransaction;
   }
 
 protected:
+  void
+  FireCompleteEvent(nsresult aRv);
+
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   virtual bool
   RecvComplete(const nsresult& aRv) MOZ_OVERRIDE;
 
   virtual PIndexedDBObjectStoreChild*
   AllocPIndexedDBObjectStore(const ObjectStoreConstructorParams& aParams)
--- a/dom/indexedDB/ipc/Makefile.in
+++ b/dom/indexedDB/ipc/Makefile.in
@@ -26,23 +26,19 @@ EXPORTS_mozilla/dom/indexedDB = Serializ
 
 LOCAL_INCLUDES += \
   -I$(topsrcdir)/dom/indexedDB \
   -I$(topsrcdir)/content/events/src \
   $(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
 
-# Test is disabled for the moment to investigate OS X 10.7 crash.
-#
-#TEST_FILES = \
-#  test_ipc.html \
-#  $(NULL)
+TEST_FILES = \
+  test_ipc.html \
+  $(NULL)
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
-# Test is disabled for the moment to investigate OS X 10.7 crash.
-#
-#libs:: $(TEST_FILES)
-#	$(INSTALL) $(foreach f,$^,"$f") \
-#    $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+libs:: $(TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") \
+    $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
--- a/dom/indexedDB/ipc/test_ipc.html
+++ b/dom/indexedDB/ipc/test_ipc.html
@@ -7,17 +7,27 @@
 </head>
   <body>
 
   <script type="application/javascript;version=1.7">
     "use strict";
 
     SimpleTest.waitForExplicitFinish();
 
+    // This isn't a single test, really... It runs the entirety of the IndexedDB
+    // tests. Each of those has a normal timeout handler, so there's no point in
+    // having a timeout here. I'm setting this really high just to avoid getting
+    // killed.
+    SimpleTest.requestLongerTimeout(100);
+
     function iframeScriptFirst() {
+      // Disable this functionality, it breaks later tests.
+      SpecialPowers.prototype.registerProcessCrashObservers = function() { };
+      SpecialPowers.prototype.unregisterProcessCrashObservers = function() { };
+
       content.wrappedJSObject.RunSet.reloadAndRunAll({
         preventDefault: function() { }
       });
     }
 
     function iframeScriptSecond() {
       let TestRunner = content.wrappedJSObject.TestRunner;
 
@@ -36,17 +46,21 @@
       };
 
       let oldLog = TestRunner.log;
       TestRunner.log = function(msg) {
         sendAsyncMessage("test:indexedDB:ipcTestMessage", { msg: msg });
       }
     }
 
-    let regex = /^(TEST-PASS|TEST-UNEXPECTED-PASS|TEST-KNOWN-FAIL|TEST-UNEXPECTED-FAIL|TEST-DEBUG-INFO) \| ([^\|]+) \|(.*)/;
+    let regexString =
+      "^(TEST-PASS|TEST-UNEXPECTED-PASS|TEST-KNOWN-FAIL|TEST-UNEXPECTED-FAIL" +
+      "|TEST-DEBUG-INFO) \\| ([^\\|]+) \\|(.*)";
+
+    let regex = new RegExp(regexString);
 
     function onTestMessage(data) {
       let message = data.json.msg;
       let match = regex.exec(message);
       if (match) {
         let state = match[1];
         let details = match[2] + " | " + match[3];
 
@@ -64,29 +78,18 @@
           case "TEST-DEBUG-INFO":
           default:
             info(details);
         }
       }
     }
 
     function onTestComplete() {
-      let comp = SpecialPowers.wrap(Components);
-
-      let idbManager =
-        comp.classes["@mozilla.org/dom/indexeddb/manager;1"]
-            .getService(comp.interfaces.nsIIndexedDatabaseManager);
-
-      let uri = SpecialPowers.getDocumentURIObject(document);
-      idbManager.clearDatabasesForURI(uri);
-
-      idbManager.getUsageForURI(uri, function(uri, usage, fileUsage) {
-        is(usage, 0, "Cleared ipc databases properly");
-        SimpleTest.executeSoon(function () { SimpleTest.finish(); });
-      });
+      ok(true, "Got test complete message");
+      SimpleTest.executeSoon(function () { SimpleTest.finish(); });
     }
 
     function runTests() {
       let iframe = document.createElement("iframe");
       iframe.mozbrowser = true;
       iframe.id = "iframe";
       iframe.style.width = "100%";
       iframe.style.height = "1000px";
--- a/dom/indexedDB/test/Makefile.in
+++ b/dom/indexedDB/test/Makefile.in
@@ -10,17 +10,16 @@ relativesrcdir = dom/indexedDB/test
 DIRS += unit
 
 include $(DEPTH)/config/autoconf.mk
 
 XPCSHELL_TESTS = unit
 
 include $(topsrcdir)/config/rules.mk
 
-
 TEST_FILES = \
   bfcache_iframe1.html \
   bfcache_iframe2.html \
   error_events_abort_transactions_iframe.html \
   event_propagation_iframe.html \
   exceptions_in_success_events_iframe.html \
   file.js \
   helpers.js \
--- a/dom/indexedDB/test/helpers.js
+++ b/dom/indexedDB/test/helpers.js
@@ -5,40 +5,69 @@
 
 var testGenerator = testSteps();
 
 function executeSoon(aFun)
 {
   SimpleTest.executeSoon(aFun);
 }
 
+function clearAllDatabases(callback) {
+  function runCallback() {
+    SimpleTest.executeSoon(function () { callback(); });
+  }
+
+  if (!SpecialPowers.isMainProcess()) {
+    runCallback();
+    return;
+  }
+
+  let comp = SpecialPowers.wrap(Components);
+
+  let idbManager =
+    comp.classes["@mozilla.org/dom/indexeddb/manager;1"]
+        .getService(comp.interfaces.nsIIndexedDatabaseManager);
+
+  let uri = SpecialPowers.getDocumentURIObject(document);
+
+  idbManager.clearDatabasesForURI(uri);
+  idbManager.getUsageForURI(uri, function(uri, usage, fileUsage) {
+    if (usage) {
+      throw new Error("getUsageForURI returned non-zero usage after " +
+                      "clearing all databases!");
+    }
+    runCallback();
+  });
+}
+
 if (!window.runTest) {
   window.runTest = function(limitedQuota)
   {
+    SimpleTest.waitForExplicitFinish();
+
     allowIndexedDB();
     if (limitedQuota) {
       denyUnlimitedQuota();
     }
     else {
       allowUnlimitedQuota();
     }
 
-    SimpleTest.waitForExplicitFinish();
-    testGenerator.next();
+    clearAllDatabases(function () { testGenerator.next(); });
   }
 }
 
 function finishTest()
 {
   resetUnlimitedQuota();
   resetIndexedDB();
 
   SimpleTest.executeSoon(function() {
     testGenerator.close();
-    SimpleTest.finish();
+    clearAllDatabases(function() { SimpleTest.finish(); });
   });
 }
 
 function browserRunTest()
 {
   testGenerator.next();
 }
 
--- a/dom/indexedDB/test/test_writer_starvation.html
+++ b/dom/indexedDB/test/test_writer_starvation.html
@@ -4,16 +4,107 @@
 -->
 <html>
 <head>
   <title>Indexed Database Property Test</title>
 
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 
-  <script type="text/javascript;version=1.7" src="unit/test_writer_starvation.js"></script>
+  <script type="text/javascript;version=1.7">
+    function testSteps()
+    {
+      const name = window.location.pathname;
+
+      // Needs to be enough to saturate the thread pool.
+      const SYNC_REQUEST_COUNT = 25;
+
+      let request = mozIndexedDB.open(name, 1);
+      request.onerror = errorHandler;
+      request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
+      let event = yield;
+
+      let db = event.target.result;
+      db.onerror = errorHandler;
+
+      is(event.target.transaction.mode, "versionchange", "Correct mode");
+
+      let objectStore = db.createObjectStore("foo", { autoIncrement: true });
+
+      request = objectStore.add({});
+      request.onerror = errorHandler;
+      request.onsuccess = grabEventAndContinueHandler;
+      event = yield;
+
+      let key = event.target.result;
+      ok(key, "Got a key");
+
+      yield;
+
+      let continueReading = true;
+      let readerCount = 0;
+      let writerCount = 0;
+      let callbackCount = 0;
+
+      // Generate a bunch of reads right away without returning to the event
+      // loop.
+      info("Generating " + SYNC_REQUEST_COUNT + " readonly requests");
+
+      for (let i = 0; i < SYNC_REQUEST_COUNT; i++) {
+        readerCount++;
+        let request = db.transaction("foo").objectStore("foo").get(key);
+        request.onsuccess = function(event) {
+          is(event.target.transaction.mode, "readonly", "Correct mode");
+          callbackCount++;
+        };
+      }
+
+      while (continueReading) {
+        readerCount++;
+        info("Generating additional readonly request (" + readerCount + ")");
+        let request = db.transaction("foo").objectStore("foo").get(key);
+        request.onsuccess = function(event) {
+          callbackCount++;
+          info("Received readonly request callback (" + callbackCount + ")");
+          is(event.target.transaction.mode, "readonly", "Correct mode");
+          if (callbackCount == SYNC_REQUEST_COUNT) {
+            writerCount++;
+            info("Generating 1 readwrite request with " + readerCount +
+                 " previous readonly requests");
+            let request = db.transaction("foo", "readwrite")
+                            .objectStore("foo")
+                            .add({}, readerCount);
+            request.onsuccess = function(event) {
+              callbackCount++;
+              info("Received readwrite request callback (" + callbackCount + ")");
+              is(event.target.transaction.mode, "readwrite", "Correct mode");
+              is(event.target.result, callbackCount,
+                 "write callback came before later reads");
+            }
+          }
+          else if (callbackCount == SYNC_REQUEST_COUNT + 5) {
+            continueReading = false;
+          }
+        };
+
+        setTimeout(function() { testGenerator.next(); }, writerCount ? 1000 : 100);
+        yield;
+      }
+
+      while (callbackCount < (readerCount + writerCount)) {
+        executeSoon(function() { testGenerator.next(); });
+        yield;
+      }
+
+      is(callbackCount, readerCount + writerCount, "All requests accounted for");
+
+      finishTest();
+      yield;
+    }
+  </script>
   <script type="text/javascript;version=1.7" src="helpers.js"></script>
 
 </head>
 
 <body onload="runTest();"></body>
 
 </html>
--- a/dom/indexedDB/test/unit/Makefile.in
+++ b/dom/indexedDB/test/unit/Makefile.in
@@ -57,15 +57,13 @@ TEST_FILES = \
   test_setVersion_events.js \
   test_setVersion_exclusion.js \
   test_success_events_after_abort.js \
   test_traffic_jam.js \
   test_transaction_abort.js \
   test_transaction_lifetimes.js \
   test_transaction_lifetimes_nested.js \
   test_transaction_ordering.js \
-  test_writer_starvation.js \
   $(NULL)
 
-
 libs:: $(TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
--- a/dom/indexedDB/test/unit/test_deleteDatabase.js
+++ b/dom/indexedDB/test/unit/test_deleteDatabase.js
@@ -52,18 +52,18 @@ function testSteps()
     onversionchangecalled = true;
     ok(event instanceof IDBVersionChangeEvent, "expect a versionchange event");
     is(event.oldVersion, 10, "oldVersion should be 10");
     ok(event.newVersion === null, "newVersion should be null");
     ok(!(event.newVersion === undefined), "newVersion should be null");
     ok(!(event.newVersion === 0), "newVersion should be null");
     db.close();
     db2.close();
-    db.onversionchange = errorHandler;
-    db2.onversionchange = errorHandler;
+    db.onversionchange = unexpectedSuccessHandler;
+    db2.onversionchange = unexpectedSuccessHandler;
   };
 
   // The IDB spec doesn't guarantee the order that onversionchange will fire
   // on the dbs.
   db.onversionchange = closeDBs;
   db2.onversionchange = closeDBs;
 
   let request = mozIndexedDB.deleteDatabase(name);
--- a/dom/indexedDB/test/unit/test_setVersion_abort.js
+++ b/dom/indexedDB/test/unit/test_setVersion_abort.js
@@ -6,17 +6,17 @@
 var testGenerator = testSteps();
 
 function testSteps()
 {
   const name = this.window ? window.location.pathname : "Splendid Test";
   const description = "My Test Database";
 
   let request = mozIndexedDB.open(name, 1, description);
-  request.onerror = grabEventAndContinueHandler;
+  request.onerror = errorHandler;
   request.onsuccess = unexpectedSuccessHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   let event = yield;
 
   let db = event.target.result;
 
   let objectStore = db.createObjectStore("foo");
   let index = objectStore.createIndex("bar", "baz");
@@ -33,33 +33,45 @@ function testSteps()
   event = yield;
   is(event.type, "abort", "Got transaction abort event");
   is(event.target, transaction, "Right target");
   is(event.target.transaction, null, "No transaction");
 
   is(db.version, 1, "Correct version");
   is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
 
+  request.onerror = grabEventAndContinueHandler;
+  request.onupgradeneeded = unexpectedSuccessHandler;
+
   event = yield;
+
   is(event.type, "error", "Got request error event");
   is(event.target, request, "Right target");
   is(event.target.transaction, null, "No transaction");
 
   event.preventDefault();
 
   request = mozIndexedDB.open(name, 1, description);
-  request.onerror = grabEventAndContinueHandler;
+  request.onerror = errorHandler;
   request.onsuccess = unexpectedSuccessHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
-  let event = yield;
+  event = yield;
+
+  is(event.type, "upgradeneeded", "Got upgradeneeded event");
 
   let db2 = event.target.result;
-  
+
   isnot(db, db2, "Should give a different db instance");
   is(db2.version, 1, "Correct version");
   is(db2.objectStoreNames.length, 0, "Correct objectStoreNames length");
 
   request.onsuccess = grabEventAndContinueHandler;
-  yield;
+  request.onupgradeneeded = unexpectedSuccessHandler;
+  event = yield;
+
+  is(event.target.result, db2, "Correct target");
+  is(event.type, "success", "Got success event");
+  is(db2.version, 1, "Correct version");
+  is(db2.objectStoreNames.length, 0, "Correct objectStoreNames length");
 
   finishTest();
   yield;
 }
--- a/dom/indexedDB/test/unit/test_setVersion_exclusion.js
+++ b/dom/indexedDB/test/unit/test_setVersion_exclusion.js
@@ -12,16 +12,17 @@ function testSteps()
   let request = mozIndexedDB.open(name, 1);
   request.onerror = errorHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   request.onsuccess = unexpectedSuccessHandler;
 
   let request2 = mozIndexedDB.open(name, 2);
   request2.onerror = errorHandler;
   request2.onupgradeneeded = unexpectedSuccessHandler;
+  request2.onsuccess = unexpectedSuccessHandler;
 
   let event = yield;
   is(event.type, "upgradeneeded", "Expect an upgradeneeded event");
   is(event.target, request, "Event should be fired on the request");
   ok(event.target.result instanceof IDBDatabase, "Expect a database here");
 
   let db = event.target.result;
   is(db.version, 1, "Database has correct version");
@@ -36,46 +37,62 @@ function testSteps()
     db.transaction("foo");
     ok(false, "Transactions should be disallowed now!");
   } catch (e) {
     ok(e instanceof DOMException, "Expect a DOMException");
     is(e.name, "InvalidStateError", "Expect an InvalidStateError");
     is(e.code, DOMException.INVALID_STATE_ERR, "Expect an INVALID_STATE_ERR");
   }
 
+  request.onupgradeneeded = unexpectedSuccessHandler;
   request.transaction.oncomplete = grabEventAndContinueHandler;
 
-  yield;
+  event = yield;
+  is(event.type, "complete", "Got complete event");
 
   // The database is still not fully open here.
   try {
     db.transaction("foo");
     ok(false, "Transactions should be disallowed now!");
   } catch (e) {
     ok(e instanceof DOMException, "Expect a DOMException");
     is(e.name, "InvalidStateError", "Expect an InvalidStateError");
     is(e.code, DOMException.INVALID_STATE_ERR, "Expect an INVALID_STATE_ERR");
   }
 
   request.onsuccess = grabEventAndContinueHandler;
 
-  yield;
+  event = yield;
+  is(event.type, "success", "Expect a success event");
+  is(event.target.result, db, "Same database");
 
   db.onversionchange = function() {
     ok(true, "next setVersion was unblocked appropriately");
     db.close();
   }
 
   try {
     db.transaction("foo");
     ok(true, "Transactions should be allowed now!");
   } catch (e) {
     ok(false, "Transactions should be allowed now!");
   }
 
-  request2.onupgradeneeded = null;
+  request.onsuccess = unexpectedSuccessHandler;
+  request2.onupgradeneeded = grabEventAndContinueHandler;
+
+  event = yield;
+  is(event.type, "upgradeneeded", "Expect an upgradeneeded event");
+
+  db = event.target.result;
+  is(db.version, 2, "Database has correct version");
+
+  request2.onupgradeneeded = unexpectedSuccessHandler;
   request2.onsuccess = grabEventAndContinueHandler;
 
-  yield;
+  event = yield;
+  is(event.type, "success", "Expect a success event");
+  is(event.target.result, db, "Same database");
+  is(db.version, 2, "Database has correct version");
 
   finishTest();
   yield;
 }
deleted file mode 100644
--- a/dom/indexedDB/test/unit/test_writer_starvation.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-var testGenerator = testSteps();
-
-function testSteps()
-{
-  const name = this.window ? window.location.pathname : "Splendid Test";
-  const description = "My Test Database";
-
-  let request = mozIndexedDB.open(name, 1, description);
-  request.onerror = errorHandler;
-  request.onupgradeneeded = grabEventAndContinueHandler;
-  request.onsuccess = grabEventAndContinueHandler;
-  let event = yield;
-
-  let db = event.target.result;
-
-  is(event.target.transaction.mode, "versionchange", "Correct mode");
-
-  let objectStore = db.createObjectStore("foo", { autoIncrement: true });
-
-  request = objectStore.add({});
-  request.onerror = errorHandler;
-  request.onsuccess = grabEventAndContinueHandler;
-  event = yield;
-
-  let key = event.target.result;
-  ok(key, "Got a key");
-
-  yield;
-
-  let continueReading = true;
-  let readerCount = 0;
-  let callbackCount = 0;
-  let finalCallbackCount = 0;
-
-  // Generate a bunch of reads right away without returning to the event
-  // loop.
-  for (let i = 0; i < 20; i++) {
-    readerCount++;
-    request = db.transaction("foo").objectStore("foo").get(key);
-    request.onerror = errorHandler;
-    request.onsuccess = function(event) {
-      callbackCount++;
-    };
-  }
-
-  while (continueReading) {
-    readerCount++;
-    request = db.transaction("foo").objectStore("foo").get(key);
-    request.onerror = errorHandler;
-    request.onsuccess = function(event) {
-      is(event.target.transaction.mode, "readonly", "Correct mode");
-      callbackCount++;
-      if (callbackCount == 100) {
-        request = db.transaction("foo", "readwrite")
-                    .objectStore("foo")
-                    .add({}, readerCount);
-        request.onerror = errorHandler;
-        request.onsuccess = function(event) {
-          continueReading = false;
-          finalCallbackCount = callbackCount;
-          is(event.target.result, callbackCount,
-             "write callback came before later reads");
-        }
-      }
-    };
-
-    executeSoon(function() { testGenerator.next(); });
-    yield;
-  }
-
-  while (callbackCount < readerCount) {
-    executeSoon(function() { testGenerator.next(); });
-    yield;
-  }
-
-  is(callbackCount, readerCount, "All requests accounted for");
-  ok(callbackCount > finalCallbackCount, "More readers after writer");
-
-  finishTest();
-  yield;
-}
-
-if (this.window)
-  SimpleTest.requestLongerTimeout(5); // see bug 580875
-
--- a/dom/indexedDB/test/unit/xpcshell.ini
+++ b/dom/indexedDB/test/unit/xpcshell.ini
@@ -46,10 +46,9 @@ tail =
 [test_setVersion_abort.js]
 [test_setVersion_events.js]
 [test_setVersion_exclusion.js]
 [test_success_events_after_abort.js]
 [test_traffic_jam.js]
 [test_transaction_abort.js]
 [test_transaction_lifetimes.js]
 [test_transaction_lifetimes_nested.js]
-[test_transaction_ordering.js]
-[test_writer_starvation.js]
\ No newline at end of file
+[test_transaction_ordering.js]
\ No newline at end of file
--- a/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl
+++ b/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl
@@ -86,17 +86,17 @@ enum CanvasMultiGetterType {
   [noscript] void setFillStyle_multi(in DOMString str, in nsISupports iface);
   [noscript] void getFillStyle_multi(out DOMString str, out nsISupports iface, out long type);
 
   //attribute DOMString fillRule;
   attribute DOMString mozFillRule; /* "evenodd", "nonzero" (default) */
 
   nsIDOMCanvasGradient createLinearGradient (in float x0, in float y0, in float x1, in float y1);
   nsIDOMCanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1);
-  nsIDOMCanvasPattern createPattern(in nsIDOMHTMLElement image, in DOMString repetition);
+  nsIDOMCanvasPattern createPattern(in nsIDOMHTMLElement image, [Null(Stringify)] in DOMString repetition);
   attribute float lineWidth; /* default 1 */
   attribute DOMString lineCap; /* "butt", "round", "square" (default) */
   attribute DOMString lineJoin; /* "round", "bevel", "miter" (default) */
   attribute float miterLimit; /* default 10 */
 
   [implicit_jscontext]
   attribute jsval mozDash; /* default |null| */
   attribute float mozDashOffset; /* default 0.0 */
--- a/dom/network/interfaces/nsIDOMMobileConnection.idl
+++ b/dom/network/interfaces/nsIDOMMobileConnection.idl
@@ -26,27 +26,62 @@ interface nsIDOMMozMobileConnection : ns
   readonly attribute nsIDOMMozMobileConnectionInfo voice;
 
   /**
    * Information about the data connection.
    */
   readonly attribute nsIDOMMozMobileConnectionInfo data;
 
   /**
+   * The selection mode of the voice and data networks.
+   *
+   * Possible values: null (unknown), 'automatic', 'manual'
+   */
+  readonly attribute DOMString networkSelectionMode;
+
+  /**
    * Search for available networks.
    *
    * If successful, the request's onsuccess will be called, and the request's
    * result will be an array of nsIDOMMozMobileNetworkInfo.
    *
    * Otherwise, the request's onerror will be called, and the request's error
-   * will be either 'RadioNotAvailable', 'RequestNotSupported', or 'GenericFailure'.
+   * will be either 'RadioNotAvailable', 'RequestNotSupported',
+   * or 'GenericFailure'.
    */
   nsIDOMDOMRequest getNetworks();
 
   /**
+   * Manually selects the passed in network, overriding the radio's current
+   * selection.
+   *
+   * If successful, the request's onsuccess will be called.
+   * Note: If the network was actually changed by this request,
+   * the 'voicechange' and 'datachange' events will also be fired.
+   *
+   * Otherwise, the request's onerror will be called, and the request's error
+   * will be either 'RadioNotAvailable', 'RequestNotSupported',
+   * 'IllegalSIMorME', or 'GenericFailure'
+   */
+  nsIDOMDOMRequest selectNetwork(in nsIDOMMozMobileNetworkInfo network);
+
+  /**
+   * Tell the radio to automatically select a network.
+   *
+   * If successful, the request's onsuccess will be called.
+   * Note: If the network was actually changed by this request, the
+   * 'voicechange' and 'datachange' events will also be fired.
+   *
+   * Otherwise, the request's onerror will be called, and the request's error
+   * will be either 'RadioNotAvailable', 'RequestNotSupported',
+   * 'IllegalSIMorME', or 'GenericFailure'
+   */
+  nsIDOMDOMRequest selectNetworkAutomatically();
+
+  /**
    * Find out about the status of an ICC lock (e.g. the PIN lock).
    *
    * @param lockType
    *        Identifies the lock type, e.g. "pin" for the PIN lock.
    *
    * @return a DOM Request.
    *         The request's result will be an object containing
    *         information about the specified lock's status,
--- a/dom/network/interfaces/nsIMobileConnectionProvider.idl
+++ b/dom/network/interfaces/nsIMobileConnectionProvider.idl
@@ -1,28 +1,33 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMMozMobileConnectionInfo;
+interface nsIDOMMozMobileNetworkInfo;
 interface nsIDOMDOMRequest;
 interface nsIDOMWindow;
 
 /**
  * XPCOM component (in the content process) that provides the mobile
  * network information.
  */
 [scriptable, uuid(fb3fac34-c1c2-45a9-ad18-a7af0f7997c9)]
 interface nsIMobileConnectionProvider : nsISupports
 {
   readonly attribute DOMString cardState;
   readonly attribute nsIDOMMozMobileConnectionInfo voiceConnectionInfo;
   readonly attribute nsIDOMMozMobileConnectionInfo dataConnectionInfo;
+  readonly attribute DOMString networkSelectionMode;
 
   nsIDOMDOMRequest getNetworks(in nsIDOMWindow window);
+  nsIDOMDOMRequest selectNetwork(in nsIDOMWindow window, in nsIDOMMozMobileNetworkInfo network);
+  nsIDOMDOMRequest selectNetworkAutomatically(in nsIDOMWindow window);
+
   nsIDOMDOMRequest getCardLock(in nsIDOMWindow window, in DOMString lockType);
   nsIDOMDOMRequest unlockCardLock(in nsIDOMWindow window, in jsval info);
   nsIDOMDOMRequest setCardLock(in nsIDOMWindow window, in jsval info);
   nsIDOMDOMRequest sendUSSD(in nsIDOMWindow window, in DOMString ussd);
   nsIDOMDOMRequest cancelUSSD(in nsIDOMWindow window);
 };
--- a/dom/network/src/MobileConnection.cpp
+++ b/dom/network/src/MobileConnection.cpp
@@ -166,28 +166,62 @@ MobileConnection::GetData(nsIDOMMozMobil
   if (!mProvider) {
     *data = nsnull;
     return NS_OK;
   }
   return mProvider->GetDataConnectionInfo(data);
 }
 
 NS_IMETHODIMP
+MobileConnection::GetNetworkSelectionMode(nsAString& networkSelectionMode)
+{
+  if (!mProvider) {
+    networkSelectionMode.SetIsVoid(true);
+    return NS_OK;
+  }
+  return mProvider->GetNetworkSelectionMode(networkSelectionMode);
+}
+
+NS_IMETHODIMP
 MobileConnection::GetNetworks(nsIDOMDOMRequest** request)
 {
   *request = nsnull;
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
   return mProvider->GetNetworks(GetOwner(), request);
 }
 
 NS_IMETHODIMP
+MobileConnection::SelectNetwork(nsIDOMMozMobileNetworkInfo* network, nsIDOMDOMRequest** request)
+{
+  *request = nsnull;
+
+  if (!mProvider) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return mProvider->SelectNetwork(GetOwner(), network, request);
+}
+
+NS_IMETHODIMP
+MobileConnection::SelectNetworkAutomatically(nsIDOMDOMRequest** request)
+{
+  *request = nsnull;
+
+  if (!mProvider) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return mProvider->SelectNetworkAutomatically(GetOwner(), request);
+}
+
+NS_IMETHODIMP
 MobileConnection::GetCardLock(const nsAString& aLockType, nsIDOMDOMRequest** aDomRequest)
 {
   *aDomRequest = nsnull;
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
--- a/dom/network/tests/marionette/test_mobile_networks.js
+++ b/dom/network/tests/marionette/test_mobile_networks.js
@@ -1,76 +1,237 @@
 /* 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/. */
 
 // getNetworks() can take some time..
-MARIONETTE_TIMEOUT = 30000;
+MARIONETTE_TIMEOUT = 60000;
  
 const WHITELIST_PREF = "dom.mobileconnection.whitelist";
 let uriPrePath = window.location.protocol + "//" + window.location.host;
 SpecialPowers.setCharPref(WHITELIST_PREF, uriPrePath);
 
 let connection = navigator.mozMobileConnection;
 ok(connection instanceof MozMobileConnection,
    "connection is instanceof " + connection.constructor);
 
+is(connection.networkSelectionMode, "automatic");
+
+let androidNetwork = null;
+let telkilaNetwork = null;
+
 function isAndroidNetwork(network) {
   is(network.longName, "Android");
   is(network.shortName, "Android");
   is(network.mcc, 310);
   is(network.mnc, 260);
 }
 
+function isTelkilaNetwork(network) {
+  is(network.longName, "TelKila");
+  is(network.shortName, "TelKila");
+  is(network.mcc, 310);
+  is(network.mnc, 295);
+}
+
 function testConnectionInfo() {
   let voice = connection.voice;
   is(voice.connected, true);
   is(voice.emergencyCallsOnly, false);
   is(voice.roaming, false);
   isAndroidNetwork(voice.network);
 
   let data = connection.data;
-  // TODO Bug 762959: enable these checks when data state updates have been implemented
+  // TODO Bug 762959: enable these checks when data state updates are implemented
   // is(data.connected, true);
   // is(data.emergencyCallsOnly, false);
   // is(data.roaming, false);
   isAndroidNetwork(data.network);
 
   testGetNetworks();
 }
 
 function testGetNetworks() {
   let request = connection.getNetworks();
   ok(request instanceof DOMRequest,
-      "request is instanceof " + request.constructor);
+     "request is instanceof " + request.constructor);
 
   request.onerror = function() {
     ok(false, request.error);
-    cleanUp();
+    setTimeout(testSelectNetwork, 0);
   };
 
   request.onsuccess = function() {
     ok('result' in request, "Request did not contain a result");
     let networks = request.result;
 
     // The emulator RIL server should always return 2 networks:
     // {"longName":"Android","shortName":"Android","mcc":310,"mnc":260,"state":"available"}
     // {"longName":"TelKila","shortName":"TelKila","mcc":310,"mnc":295,"state":"available"}
     is(networks.length, 2);
 
-    let network1 = networks[0];
+    let network1 = androidNetwork = networks[0];
     isAndroidNetwork(network1);
     is(network1.state, "available");
 
-    let network2 = networks[1];
-    is(network2.longName, "TelKila");
-    is(network2.shortName, "TelKila");
-    is(network2.mcc, 310);
-    is(network2.mnc, 295);
+    let network2 = telkilaNetwork = networks[1];
+    isTelkilaNetwork(network2);
     is(network2.state, "available");
+
+    setTimeout(testSelectNetwork, 0);
+  };
+}
+
+function testSelectNetwork() {
+  let request = connection.selectNetwork(telkilaNetwork);
+  ok(request instanceof DOMRequest,
+     "request instanceof " + request.constructor);
+
+  connection.addEventListener("voicechange", function voiceChange() {
+    connection.removeEventListener("voicechange", voiceChange);
+
+    isTelkilaNetwork(connection.voice.network);
+    setTimeout(testSelectNetworkAutomatically, 0);
+  });
+
+  request.onsuccess = function() {
+    is(connection.networkSelectionMode, "manual",
+       "selectNetwork sets mode to: " + connection.networkSelectionMode);
+  };
+
+  request.onerror = function() {
+    ok(false, request.error);
+    setTimeout(testSelectNetworkAutomatically, 0);
+  };
+}
+
+function testSelectNetworkAutomatically() {
+  let request = connection.selectNetworkAutomatically();
+  ok(request instanceof DOMRequest,
+     "request instanceof " + request.constructor);
+
+  connection.addEventListener("voicechange", function voiceChange() {
+    connection.removeEventListener("voicechange", voiceChange);
+
+    isAndroidNetwork(connection.voice.network);
+    setTimeout(testSelectNetworkErrors, 0);
+  });
+
+  request.onsuccess = function() {
+    is(connection.networkSelectionMode, "automatic",
+       "selectNetworkAutomatically sets mode to: " +
+       connection.networkSelectionMode);
+  };
+
+  request.onerror = function() {
+    ok(false, request.error);
+    setTimeout(testSelectNetworkErrors, 0);
+  };
+}
+
+function throwsException(fn) {
+  try {
+    fn();
+    ok(false, "function did not throw an exception: " + fn);
+  } catch (e) {
+    ok(true, "function succesfully caught exception: " + e);
+  }
+}
+
+function testSelectNetworkErrors() {
+  throwsException(function() {
+    connection.selectNetwork(null);
+  });
+
+  throwsException(function() {
+    connection.selectNetwork({});
+  });
+
+  connection.addEventListener("voicechange", function voiceChange() {
+    connection.removeEventListener("voicechange", voiceChange);
+    setTimeout(testSelectExistingNetworkManual, 0);
+  });
+
+  let request1 = connection.selectNetwork(telkilaNetwork);
+  request1.onerror = function() {
+    ok(false, request.error);
+    setTimeout(testSelectExistingNetworkManual, 0);
+  };
+
+  // attempt to selectNetwork while one request has already been sent
+  throwsException(function() {
+    connection.selectNetwork(androidNetwork);
+  });
+}
+
+function testSelectExistingNetworkManual() {
+  // When the current network is selected again, the DOMRequest's onsuccess
+  // should be called, but the network shouldn't actually change
+
+  // Telkila should be the currently selected network
+  log("Selecting TelKila (should already be selected");
+  let request = connection.selectNetwork(telkilaNetwork);
+
+  let voiceChanged = false;
+  connection.addEventListener("voicechange", function voiceChange() {
+    connection.removeEventListener("voicechange", voiceChange);
+    voiceChanged = true;
+  });
+
+  function nextTest() {
+    // Switch back to automatic selection to setup the next test
+    let autoRequest = connection.selectNetworkAutomatically();
+    autoRequest.onsuccess = function() {
+      setTimeout(testSelectExistingNetworkAuto, 0);
+    };
+    autoRequest.onerror = function() {
+      ok(false, autoRequest.error);
+      cleanUp();
+    };
+  }
+
+  request.onsuccess = function() {
+    // Give the voicechange event another opportunity to fire
+    setTimeout(function() {
+      is(voiceChanged, false,
+         "voiceNetwork changed while manually selecting Telkila network? " +
+         voiceChanged);
+      nextTest();
+    }, 0);
+  };
+
+  request.onerror = function() {
+    ok(false, request.error);
+    nextTest();
+  };
+}
+
+function testSelectExistingNetworkAuto() {
+  // Now try the same thing but using automatic selection
+  log("Selecting automatically (should already be auto)");
+  let request = connection.selectNetworkAutomatically();
+
+  let voiceChanged = false;
+  connection.addEventListener("voicechange", function voiceChange() {
+    connection.removeEventListener("voicechange", voiceChange);
+    voiceChanged = true;
+  });
+
+  request.onsuccess = function() {
+    // Give the voicechange event another opportunity to fire
+    setTimeout(function() {
+      is(voiceChanged, false,
+         "voiceNetwork changed while automatically selecting network? " +
+         voiceChanged);
+      cleanUp();
+    }, 0);
+  };
+
+  request.onerror = function() {
+    ok(false, request.error);
     cleanUp();
   };
 }
 
 function cleanUp() {
   SpecialPowers.clearUserPref(WHITELIST_PREF);
   finish();
 }
--- a/dom/sms/src/fallback/SmsDatabaseService.h
+++ b/dom/sms/src/fallback/SmsDatabaseService.h
@@ -2,22 +2,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_sms_SmsDatabaseService_h
 #define mozilla_dom_sms_SmsDatabaseService_h
 
 #include "nsISmsDatabaseService.h"
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
-class SmsDatabaseService : public nsISmsDatabaseService
+class SmsDatabaseService MOZ_FINAL : public nsISmsDatabaseService
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISMSDATABASESERVICE
 };
 
 } // namespace sms
 } // namespace dom
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -170,27 +170,27 @@ NetworkManager.prototype = {
         continue;
       }
       this.active = network;
       if (network.type == this.preferredNetworkType) {
         debug("Found our preferred type of network: " + network.name);
         break;
       }
     }
-    if (this.active && (oldActive != this.active)) {
+    if (this.active) {
       this.setDefaultRouteAndDNS(oldActive);
     }
   },
 
   setDefaultRouteAndDNS: function setDefaultRouteAndDNS(oldInterface) {
     debug("Going to change route and DNS to " + this.active.name);
     let options = {
       cmd: this.active.dhcp ? "runDHCPAndSetDefaultRouteAndDNS" : "setDefaultRouteAndDNS",
       ifname: this.active.name,
-      oldIfname: oldInterface ? oldInterface.name : null
+      oldIfname: (oldInterface && oldInterface != this.active) ? oldInterface.name : null
     };
     this.worker.postMessage(options);
   },
 
 };
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
 
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -8,31 +8,35 @@ const {classes: Cc, interfaces: Ci, util
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
 
 var RIL = {};
 Cu.import("resource://gre/modules/ril_consts.js", RIL);
 
-const DEBUG = false; // set to true to see debug messages
+// set to true to in ril_consts.js to see debug messages
+const DEBUG = RIL.DEBUG_CONTENT_HELPER;
 
 const RILCONTENTHELPER_CID =
   Components.ID("{472816e1-1fd6-4405-996c-806f9ea68174}");
 const MOBILECONNECTIONINFO_CID =
   Components.ID("{a35cfd39-2d93-4489-ac7d-396475dacb27}");
 const MOBILENETWORKINFO_CID =
   Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}");
 
 const RIL_IPC_MSG_NAMES = [
   "RIL:CardStateChanged",
   "RIL:VoiceInfoChanged",
   "RIL:DataInfoChanged",
   "RIL:EnumerateCalls",
   "RIL:GetAvailableNetworks",
+  "RIL:NetworkSelectionModeChanged",
+  "RIL:SelectNetwork",
+  "RIL:SelectNetworkAuto",
   "RIL:CallStateChanged",
   "RIL:CallError",
   "RIL:GetCardLock:Return:OK",
   "RIL:GetCardLock:Return:KO",
   "RIL:SetCardLock:Return:OK",
   "RIL:SetCardLock:Return:KO",
   "RIL:UnlockCardLock:Return:OK",
   "RIL:UnlockCardLock:Return:KO",
@@ -151,30 +155,110 @@ RILContentHelper.prototype = {
     network.mcc = srcNetwork.mcc;
   },
 
   // nsIRILContentHelper
 
   cardState:           RIL.GECKO_CARDSTATE_UNAVAILABLE,
   voiceConnectionInfo: null,
   dataConnectionInfo:  null,
+  networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN,
+
+  /**
+   * The network that is currently trying to be selected (or "automatic").
+   * This helps ensure that only one network is selected at a time.
+   */
+  _selectingNetwork: null,
 
   getNetworks: function getNetworks(window) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
 
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     cpmm.sendAsyncMessage("RIL:GetAvailableNetworks", requestId);
     return request;
   },
 
+  selectNetwork: function selectNetwork(window, network) {
+    if (window == null) {
+      throw Components.Exception("Can't get window object",
+                                  Cr.NS_ERROR_UNEXPECTED);
+    }
+
+    if (this._selectingNetwork) {
+      throw new Error("Already selecting a network: " + this._selectingNetwork);
+    }
+
+    if (!network) {
+      throw new Error("Invalid network provided: " + network);
+    }
+
+    let mnc = network.mnc;
+    if (!mnc) {
+      throw new Error("Invalid network MNC: " + mnc);
+    }
+
+    let mcc = network.mcc;
+    if (!mcc) {
+      throw new Error("Invalid network MCC: " + mcc);
+    }
+
+    let request = Services.DOMRequest.createRequest(window);
+    let requestId = this.getRequestId(request);
+
+    if (this.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_MANUAL
+        && this.voiceConnectionInfo.network === network) {
+
+      // Already manually selected this network, so schedule
+      // onsuccess to be fired on the next tick
+      this.dispatchFireRequestSuccess(requestId, null);
+      return request;
+    }
+
+    this._selectingNetwork = network;
+
+    cpmm.sendAsyncMessage("RIL:SelectNetwork", {
+      requestId: requestId,
+      mnc: mnc,
+      mcc: mcc
+    });
+
+    return request;
+  },
+
+  selectNetworkAutomatically: function selectNetworkAutomatically(window) {
+
+    if (window == null) {
+      throw Components.Exception("Can't get window object",
+                                  Cr.NS_ERROR_UNEXPECTED);
+    }
+
+    if (this._selectingNetwork) {
+      throw new Error("Already selecting a network: " + this._selectingNetwork);
+    }
+
+    let request = Services.DOMRequest.createRequest(window);
+    let requestId = this.getRequestId(request);
+
+    if (this.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_AUTOMATIC) {
+      // Already using automatic selection mode, so schedule
+      // onsuccess to be be fired on the next tick
+      this.dispatchFireRequestSuccess(requestId, null);
+      return request;
+    }
+
+    this._selectingNetwork = "automatic";
+    cpmm.sendAsyncMessage("RIL:SelectNetworkAuto", requestId);
+    return request;
+  },
+
   getCardLock: function getCardLock(window, lockType) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
     cpmm.sendAsyncMessage("RIL:GetCardLock", {lockType: lockType, requestId: requestId});
@@ -325,38 +409,49 @@ RILContentHelper.prototype = {
   },
 
   // nsIFrameMessageListener
 
   fireRequestSuccess: function fireRequestSuccess(requestId, result) {
     let request = this.takeRequest(requestId);
     if (!request) {
       if (DEBUG) {
-        debug("not firing success for id: " + requestId + ", result: " + JSON.stringify(result));
+        debug("not firing success for id: " + requestId +
+              ", result: " + JSON.stringify(result));
       }
       return;
     }
 
     if (DEBUG) {
-      debug("fire request success, id: " + requestId + ", result: " + JSON.stringify(result));
+      debug("fire request success, id: " + requestId +
+            ", result: " + JSON.stringify(result));
     }
     Services.DOMRequest.fireSuccess(request, result);
   },
 
+  dispatchFireRequestSuccess: function dispatchFireRequestSuccess(requestId, result) {
+    let currentThread = Services.tm.currentThread;
+
+    currentThread.dispatch(this.fireRequestSuccess.bind(this, requestId, result),
+                           Ci.nsIThread.DISPATCH_NORMAL);
+  },
+
   fireRequestError: function fireRequestError(requestId, error) {
     let request = this.takeRequest(requestId);
     if (!request) {
       if (DEBUG) {
-        debug("not firing error for id: " + requestId + ", error: " + JSON.stringify(error));
+        debug("not firing error for id: " + requestId +
+              ", error: " + JSON.stringify(error));
       }
       return;
     }
 
     if (DEBUG) {
-      debug("fire request error, id: " + requestId + ", result: " + JSON.stringify(error));
+      debug("fire request error, id: " + requestId +
+            ", result: " + JSON.stringify(error));
     }
     Services.DOMRequest.fireError(request, error);
   },
 
   receiveMessage: function receiveMessage(msg) {
     let request;
     debug("Received message '" + msg.name + "': " + JSON.stringify(msg.json));
     switch (msg.name) {
@@ -375,16 +470,27 @@ RILContentHelper.prototype = {
         Services.obs.notifyObservers(null, kDataChangedTopic, null);
         break;
       case "RIL:EnumerateCalls":
         this.handleEnumerateCalls(msg.json);
         break;
       case "RIL:GetAvailableNetworks":
         this.handleGetAvailableNetworks(msg.json);
         break;
+      case "RIL:NetworkSelectionModeChanged":
+        this.networkSelectionMode = msg.json.mode;
+        break;
+      case "RIL:SelectNetwork":
+        this.handleSelectNetwork(msg.json,
+                                 RIL.GECKO_NETWORK_SELECTION_MANUAL);
+        break;
+      case "RIL:SelectNetworkAuto":
+        this.handleSelectNetwork(msg.json,
+                                 RIL.GECKO_NETWORK_SELECTION_AUTOMATIC);
+        break;
       case "RIL:CallStateChanged":
         this._deliverTelephonyCallback("callStateChanged",
                                        [msg.json.callIndex, msg.json.state,
                                         msg.json.number, msg.json.isActive]);
         break;
       case "RIL:CallError":
         this._deliverTelephonyCallback("notifyError",
                                         [msg.json.callIndex,
@@ -468,16 +574,27 @@ RILContentHelper.prototype = {
       }
 
       networks[i] = info;
     }
 
     Services.DOMRequest.fireSuccess(request, networks);
   },
 
+  handleSelectNetwork: function handleSelectNetwork(message, mode) {
+    this._selectingNetwork = null;
+    this.networkSelectionMode = mode;
+
+    if (message.error) {
+      this.fireRequestError(message.requestId, message.error);
+    } else {
+      this.fireRequestSuccess(message.requestId, null);
+    }
+  },
+
   _deliverTelephonyCallback: function _deliverTelephonyCallback(name, args) {
     if (!this._telephonyCallbacks) {
       return;
     }
 
     let callbacks = this._telephonyCallbacks.slice();
     for each (let callback in callbacks) {
       if (this._telephonyCallbacks.indexOf(callback) == -1) {
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -7,17 +7,18 @@
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 var RIL = {};
 Cu.import("resource://gre/modules/ril_consts.js", RIL);
 
-const DEBUG = false; // set to true to see debug messages
+// set to true in ril_consts.js to see debug messages
+const DEBUG = RIL.DEBUG_RIL;
 
 const RADIOINTERFACELAYER_CID =
   Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
 const DATACALLINFO_CID =
   Components.ID("{ef474cd9-94f7-4c05-a31b-29b9de8a10d2}");
 
 const nsIAudioManager = Ci.nsIAudioManager;
 const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
@@ -40,16 +41,18 @@ const RIL_IPC_MSG_NAMES = [
   "RIL:StopTone",
   "RIL:Dial",
   "RIL:HangUp",
   "RIL:AnswerCall",
   "RIL:RejectCall",
   "RIL:HoldCall",
   "RIL:ResumeCall",
   "RIL:GetAvailableNetworks",
+  "RIL:SelectNetwork",
+  "RIL:SelectNetworkAuto",
   "RIL:GetCardLock",
   "RIL:UnlockCardLock",
   "RIL:SetCardLock",
   "RIL:SendUSSD",
   "RIL:CancelUSSD"
 ];
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
@@ -86,16 +89,18 @@ function convertRILCallState(state) {
       return nsIRadioInterfaceLayer.CALL_STATE_HELD;
     case RIL.CALL_STATE_DIALING:
       return nsIRadioInterfaceLayer.CALL_STATE_DIALING;
     case RIL.CALL_STATE_ALERTING:
       return nsIRadioInterfaceLayer.CALL_STATE_ALERTING;
     case RIL.CALL_STATE_INCOMING:
     case RIL.CALL_STATE_WAITING:
       return nsIRadioInterfaceLayer.CALL_STATE_INCOMING; 
+    case RIL.CALL_STATE_BUSY:
+      return nsIRadioInterfaceLayer.CALL_STATE_BUSY;
     default:
       throw new Error("Unknown rilCallState: " + state);
   }
 }
 
 /**
  * Fake nsIAudioManager implementation so that we can run the telephony
  * code in a non-Gonk build.
@@ -244,16 +249,21 @@ RadioInterfaceLayer.prototype = {
         this.holdCall(msg.json);
         break;
       case "RIL:ResumeCall":
         this.resumeCall(msg.json);
         break;
       case "RIL:GetAvailableNetworks":
         this.getAvailableNetworks(msg.json);
         break;