Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Fri, 06 Apr 2012 16:38:53 -0700
changeset 106096 6040d30988ff69895b11b0541071a6afd295f8e9
parent 106094 ad6e00aaa6cde20f7b844a73f2839e66e2f6521f (current diff)
parent 91169 a402c2064466dee340d4ff19db55c04c74e04a77 (diff)
child 106097 071792b470d9eabfba8785fdd175cdde1708f070
push idunknown
push userunknown
push dateunknown
milestone14.0a1
Merge from mozilla-central.
accessible/src/base/Makefile.in
accessible/src/base/Statistics.h
accessible/src/base/TextAttrs.cpp
accessible/src/base/TextAttrs.h
accessible/src/base/nsARIAMap.cpp
accessible/src/base/nsARIAMap.h
accessible/src/base/nsAccDocManager.cpp
accessible/src/base/nsAccessibilityService.cpp
accessible/src/base/nsAccessible.cpp
accessible/src/base/nsAccessible.h
accessible/src/base/nsFormControlAccessible.cpp
accessible/src/base/nsFormControlAccessible.h
accessible/src/base/nsOuterDocAccessible.cpp
accessible/src/base/nsOuterDocAccessible.h
accessible/src/generic/OuterDocAccessible.cpp
accessible/src/generic/OuterDocAccessible.h
accessible/src/html/nsHTMLFormControlAccessible.cpp
accessible/src/xul/nsXULFormControlAccessible.cpp
accessible/tests/mochitest/Makefile.in
accessible/tests/mochitest/actions/test_tree.xul
accessible/tests/mochitest/events/test_aria_menu.html
accessible/tests/mochitest/events/test_focus_tree.xul
accessible/tests/mochitest/events/test_textattrchange.html
accessible/tests/mochitest/focus/test_takeFocus.html
accessible/tests/mochitest/states.js
accessible/tests/mochitest/states/Makefile.in
accessible/tests/mochitest/test_OuterDocAccessible.html
accessible/tests/mochitest/test_nsOuterDocAccessible.html
aclocal.m4
browser/app/profile/firefox.js
browser/base/content/browser.js
browser/locales/en-US/chrome/browser/browser.properties
build/autoconf/freetype2.m4
build/mobile/devicemanagerADB.py
caps/src/nsScriptSecurityManager.cpp
configure.in
content/base/public/nsIContent.h
content/base/public/nsIDocument.h
content/base/src/nsDocument.cpp
content/base/src/nsGenericDOMDataNode.cpp
content/base/src/nsGenericDOMDataNode.h
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/base/src/nsGkAtomList.h
content/base/src/nsStyledElement.cpp
content/base/src/nsStyledElement.h
content/canvas/src/WebGLContextGL.cpp
content/events/src/nsDOMEvent.cpp
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
content/events/test/Makefile.in
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsHTMLScriptElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/media/webm/nsWebMReader.cpp
content/svg/content/src/nsSVGScriptElement.cpp
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLContentSink.cpp
content/xbl/src/nsXBLDocumentInfo.cpp
content/xbl/src/nsXBLPrototypeBinding.cpp
content/xul/content/src/nsXULElement.cpp
content/xul/content/src/nsXULElement.h
content/xul/document/src/nsXULContentSink.cpp
content/xul/document/src/nsXULContentSink.h
content/xul/document/src/nsXULPrototypeDocument.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsDOMClassInfoClasses.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsJSEnvironment.cpp
dom/interfaces/html/nsIDOMHTMLDocument.idl
dom/interfaces/storage/nsIDOMStorageList.idl
dom/plugins/base/nsJSNPRuntime.cpp
dom/src/storage/nsDOMStorage.cpp
dom/src/storage/nsDOMStorage.h
dom/workers/Events.cpp
dom/workers/Exceptions.cpp
dom/workers/File.cpp
dom/workers/Location.cpp
dom/workers/Navigator.cpp
dom/workers/RuntimeService.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerScope.cpp
dom/workers/XMLHttpRequest.cpp
editor/composer/src/nsComposerCommands.cpp
editor/libeditor/base/nsEditor.h
editor/libeditor/html/nsHTMLEditor.cpp
embedding/android/GeckoAppShell.java
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLContextProviderGLX.cpp
gfx/thebes/gfxDWriteFontList.cpp
gfx/thebes/gfxDWriteFontList.h
gfx/thebes/gfxImageSurface.cpp
gfx/thebes/gfxUserFontSet.cpp
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/nsCoreAnimationSupport.mm
image/src/VectorImage.cpp
intl/unicharutil/util/nsUnicharUtils.cpp
ipc/chromium/src/base/process_util_linux.cc
ipc/testshell/XPCShellEnvironment.cpp
js/ipc/ObjectWrapperParent.cpp
js/src/configure.in
js/src/ctypes/Library.cpp
js/src/gc/Barrier.h
js/src/gc/Statistics.h
js/src/ion/Bailouts.cpp
js/src/ion/Ion.cpp
js/src/ion/Ion.h
js/src/ion/IonCaches.h
js/src/ion/IonCode.h
js/src/ion/IonCompartment.h
js/src/ion/IonFrames.cpp
js/src/jit-test/jit_test.py
js/src/jit-test/tests/debug/Debugger-wrap-01.js
js/src/js.msg
js/src/jsapi-tests/Makefile.in
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsatom.cpp
js/src/jsatom.h
js/src/jsclass.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsdbgapi.cpp
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsgcmark.cpp
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsopcode.cpp
js/src/jsprobes.cpp
js/src/jsproxy.cpp
js/src/jsproxy.h
js/src/jsprvtd.h
js/src/jsscope.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jstypedarrayinlines.h
js/src/jsweakcache.h
js/src/jsweakmap.cpp
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/MethodJIT.h
js/src/methodjit/MonoIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/shell/js.cpp
js/src/shell/jsworkers.cpp
js/src/vm/ArgumentsObject.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/String.h
js/xpconnect/idl/nsIXPConnect.idl
js/xpconnect/public/xpc_map_end.h
js/xpconnect/shell/xpcshell.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/XPCThreadContext.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/XPCWrappedNativeProto.cpp
js/xpconnect/src/XPCWrappedNativeScope.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/src/xpcpublic.h
js/xpconnect/wrappers/AccessCheck.h
js/xpconnect/wrappers/WrapperFactory.cpp
layout/base/nsPresShell.cpp
layout/build/Makefile.in
layout/generic/crashtests/crashtests.list
layout/generic/nsFrame.cpp
layout/reftests/bugs/reftest.list
layout/reftests/margin-collapsing/reftest.list
layout/style/nsDOMCSSAttrDeclaration.cpp
layout/style/nsStyleStruct.h
memory/jemalloc/jemalloc.c
memory/jemalloc/jemalloc.h
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/Makefile.in
mobile/android/base/gfx/FlexibleGLSurfaceView.java
mobile/android/base/resources/menu-v11/gecko_menu.xml.in
mozglue/android/APKOpen.cpp
netwerk/cache/nsCacheEntryDescriptor.cpp
netwerk/cache/nsCacheEntryDescriptor.h
netwerk/dns/nsDNSService2.cpp
netwerk/dns/nsDNSService2.h
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
netwerk/protocol/http/nsHttpPipeline.cpp
netwerk/protocol/http/nsHttpTransaction.cpp
netwerk/protocol/http/nsHttpTransaction.h
parser/xml/src/nsSAXXMLReader.cpp
storage/src/mozStorageConnection.cpp
toolkit/components/filepicker/nsFileView.cpp
toolkit/components/satchel/nsFormFillController.cpp
toolkit/components/telemetry/TelemetryHistograms.h
toolkit/content/widgets/videocontrols.xml
toolkit/mozapps/installer/packager.mk
toolkit/xre/nsXREDirProvider.cpp
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidFlexViewWrapper.cpp
widget/android/AndroidFlexViewWrapper.h
widget/android/AndroidJNI.cpp
widget/android/nsAppShell.cpp
widget/android/nsAppShell.h
widget/android/nsWindow.cpp
widget/gtk2/nsSound.cpp
widget/nsGUIEvent.h
widget/windows/nsDataObj.cpp
xpcom/base/nsMemoryReporterManager.cpp
xpcom/build/BinaryPath.h
xpcom/glue/nsCRTGlue.cpp
xpcom/glue/nsCRTGlue.h
xpcom/io/nsILocalFile.idl
xpcom/io/nsLocalFileCommon.cpp
xpcom/io/nsLocalFileUnix.cpp
xpcom/io/nsLocalFileWin.cpp
xpcom/threads/TimerThread.cpp
--- a/accessible/build/Makefile.in
+++ b/accessible/build/Makefile.in
@@ -53,16 +53,17 @@ GRE_MODULE	= 1
 LIBXUL_LIBRARY	= 1
 
 CPPSRCS		= nsAccessibilityFactory.cpp
 
 LOCAL_INCLUDES	= -I$(srcdir)/../src
 
 SHARED_LIBRARY_LIBS = \
   ../src/base/$(LIB_PREFIX)accessibility_base_s.$(LIB_SUFFIX) \
+  ../src/generic/$(LIB_PREFIX)accessibility_generic_s.$(LIB_SUFFIX) \
   ../src/html/$(LIB_PREFIX)accessibility_html_s.$(LIB_SUFFIX) \
   ../src/xpcom/$(LIB_PREFIX)accessibility_xpcom_s.$(LIB_SUFFIX) \
   ../src/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) \
   ../src/xforms/$(LIB_PREFIX)accessibility_xforms_s.$(LIB_SUFFIX) \
   $(NULL)
 
 ifdef MOZ_XUL
 SHARED_LIBRARY_LIBS += ../src/xul/$(LIB_PREFIX)accessibility_xul_s.$(LIB_SUFFIX)
--- a/accessible/src/Makefile.in
+++ b/accessible/src/Makefile.in
@@ -56,16 +56,17 @@ PLATFORM_DIR += other
 endif
 endif
 endif
 
 DIRS += $(PLATFORM_DIR)
 
 DIRS += \
   base \
+  generic \
   html \
   xpcom \
   xforms \
   $(null)
 
 ifdef MOZ_XUL
 DIRS +=   xul
 endif
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/ARIAStateMap.cpp
@@ -0,0 +1,343 @@
+/* -*- Mode: C++; tab-width: 2; 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 "ARIAStateMap.h"
+
+#include "States.h"
+
+#include "mozilla/dom/Element.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+using namespace mozilla::a11y::aria;
+
+/**
+ * Used to store state map rule data for ARIA attribute of enum type.
+ */
+struct EnumTypeData
+{
+  EnumTypeData(nsIAtom* aAttrName,
+               nsIAtom** aValue1, PRUint64 aState1,
+               nsIAtom** aValue2, PRUint64 aState2,
+               nsIAtom** aValue3 = 0, PRUint64 aState3 = 0) :
+    mState1(aState1), mState2(aState2), mState3(aState3), mDefaultState(0),
+    mAttrName(aAttrName), mValue1(aValue1), mValue2(aValue2), mValue3(aValue3),
+    mNullValue(nsnull)
+  { }
+
+  EnumTypeData(nsIAtom* aAttrName, PRUint64 aDefaultState,
+               nsIAtom** aValue1, PRUint64 aState1) :
+    mState1(aState1), mState2(0), mState3(0), mDefaultState(aDefaultState),
+    mAttrName(aAttrName), mValue1(aValue1), mValue2(nsnull), mValue3(nsnull),
+    mNullValue(nsnull)
+  { }
+
+  // States applied if corresponding enum values are matched.
+  const PRUint64 mState1;
+  const PRUint64 mState2;
+  const PRUint64 mState3;
+
+  // Default state if no one enum value is matched.
+  const PRUint64 mDefaultState;
+
+  // ARIA attribute name.
+  nsIAtom* const mAttrName;
+
+  // States if the attribute value is matched to the enum value. Used as
+  // nsIContent::AttrValuesArray.
+  nsIAtom* const* const mValue1;
+  nsIAtom* const* const mValue2;
+  nsIAtom* const* const mValue3;
+  nsIAtom* const* const mNullValue;
+};
+
+enum ETokenType
+{
+  eBoolType = 0,
+  eMixedType = 1, // can take 'mixed' value
+  eDefinedIfAbsent = 2 // permanent and false state are applied if absent
+};
+
+/**
+ * Used to store state map rule data for ARIA attribute of token type (including
+ * mixed value).
+ */
+struct TokenTypeData
+{
+  TokenTypeData(nsIAtom* aAttrName, PRUint32 aType,
+                PRUint64 aPermanentState,
+                PRUint64 aTrueState,
+                PRUint64 aFalseState = 0) :
+  mAttrName(aAttrName), mType(aType), mPermanentState(aPermanentState),
+  mTrueState(aTrueState), mFalseState(aFalseState)
+  { }
+
+  // ARIA attribute name.
+  nsIAtom* const mAttrName;
+
+  // Type.
+  const PRUint32 mType;
+
+  // State applied if the attribute is defined or mType doesn't have
+  // eDefinedIfAbsent flag set.
+  const PRUint64 mPermanentState;
+
+  // States applied if the attribute value is true/false.
+  const PRUint64 mTrueState;
+  const PRUint64 mFalseState;
+};
+
+/**
+ * Map enum type attribute value to accessible state.
+ */
+static void MapEnumType(dom::Element* aElement, PRUint64* aState,
+                        const EnumTypeData& aData);
+
+/**
+ * Map token type attribute value to states.
+ */
+static void MapTokenType(dom::Element* aContent, PRUint64* aState,
+                         const TokenTypeData& aData);
+
+bool
+aria::MapToState(EStateRule aRule, dom::Element* aElement, PRUint64* aState)
+{
+  switch (aRule) {
+    case eARIAAutoComplete:
+    {
+      static const EnumTypeData data(
+        nsGkAtoms::aria_autocomplete,
+        &nsGkAtoms::inlinevalue, states::SUPPORTS_AUTOCOMPLETION,
+        &nsGkAtoms::list, states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION,
+        &nsGkAtoms::both, states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION);
+
+      MapEnumType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIABusy:
+    {
+      static const EnumTypeData data(
+        nsGkAtoms::aria_busy,
+        &nsGkAtoms::_true, states::BUSY,
+        &nsGkAtoms::error, states::INVALID);
+
+      MapEnumType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIACheckableBool:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_checked, eBoolType | eDefinedIfAbsent,
+        states::CHECKABLE, states::CHECKED);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIACheckableMixed:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_checked, eMixedType | eDefinedIfAbsent,
+        states::CHECKABLE, states::CHECKED);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIACheckedMixed:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_checked, eMixedType,
+        states::CHECKABLE, states::CHECKED);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIADisabled:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_disabled, eBoolType,
+        0, states::UNAVAILABLE);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIAExpanded:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_expanded, eBoolType,
+        0, states::EXPANDED, states::COLLAPSED);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIAHasPopup:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_haspopup, eBoolType,
+        0, states::HASPOPUP);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIAInvalid:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_invalid, eBoolType,
+        0, states::INVALID);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIAMultiline:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_multiline, eBoolType | eDefinedIfAbsent,
+        0, states::MULTI_LINE, states::SINGLE_LINE);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIAMultiSelectable:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_multiselectable, eBoolType,
+        0, states::MULTISELECTABLE | states::EXTSELECTABLE);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIAOrientation:
+    {
+      static const EnumTypeData data(
+        nsGkAtoms::aria_orientation, states::HORIZONTAL,
+        &nsGkAtoms::vertical, states::VERTICAL);
+
+      MapEnumType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIAPressed:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_pressed, eMixedType,
+        states::CHECKABLE, states::PRESSED);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIAReadonly:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_readonly, eBoolType,
+        0, states::READONLY);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIAReadonlyOrEditable:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_readonly, eBoolType | eDefinedIfAbsent,
+        0, states::READONLY, states::EDITABLE);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIARequired:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_required, eBoolType,
+        0, states::REQUIRED);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eARIASelectable:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_selected, eBoolType | eDefinedIfAbsent,
+        states::SELECTABLE, states::SELECTED);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
+    case eReadonlyUntilEditable:
+    {
+      if (!(*aState & states::EDITABLE))
+        *aState |= states::READONLY;
+
+      return true;
+    }
+
+    default:
+      return false;
+  }
+}
+
+static void
+MapEnumType(dom::Element* aElement, PRUint64* aState, const EnumTypeData& aData)
+{
+  switch (aElement->FindAttrValueIn(kNameSpaceID_None, aData.mAttrName,
+                                    &aData.mValue1, eCaseMatters)) {
+    case 0:
+      *aState |= aData.mState1;
+      return;
+    case 1:
+      *aState |= aData.mState2;
+      return;
+    case 2:
+      *aState |= aData.mState3;
+      return;
+  }
+
+  *aState |= aData.mDefaultState;
+}
+
+static void
+MapTokenType(dom::Element* aElement, PRUint64* aState,
+             const TokenTypeData& aData)
+{
+  if (aElement->HasAttr(kNameSpaceID_None, aData.mAttrName)) {
+    if ((aData.mType & eMixedType) &&
+        aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
+                              nsGkAtoms::mixed, eCaseMatters)) {
+      *aState |= aData.mPermanentState | states::MIXED;
+      return;
+    }
+
+    if (aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
+                              nsGkAtoms::_false, eCaseMatters)) {
+      *aState |= aData.mPermanentState | aData.mFalseState;
+      return;
+    }
+
+    if (!aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
+                               nsGkAtoms::_undefined, eCaseMatters) &&
+        !aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
+                               nsGkAtoms::_empty, eCaseMatters)) {
+      *aState |= aData.mPermanentState | aData.mTrueState;
+    }
+    return;
+  }
+
+  if (aData.mType & eDefinedIfAbsent)
+    *aState |= aData.mPermanentState | aData.mFalseState;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/ARIAStateMap.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; 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/. */
+
+#ifndef _mozilla_a11y_aria_ARIAStateMap_h_
+#define _mozilla_a11y_aria_ARIAStateMap_h_
+
+#include "prtypes.h"
+
+namespace mozilla {
+
+namespace dom {
+class Element;
+}
+
+namespace a11y {
+namespace aria {
+
+/**
+ * List of the ARIA state mapping rules.
+ */
+enum EStateRule
+{
+  eARIANone,
+  eARIAAutoComplete,
+  eARIABusy,
+  eARIACheckableBool,
+  eARIACheckableMixed,
+  eARIACheckedMixed,
+  eARIADisabled,
+  eARIAExpanded,
+  eARIAHasPopup,
+  eARIAInvalid,
+  eARIAMultiline,
+  eARIAMultiSelectable,
+  eARIAOrientation,
+  eARIAPressed,
+  eARIAReadonly,
+  eARIAReadonlyOrEditable,
+  eARIARequired,
+  eARIASelectable,
+  eReadonlyUntilEditable
+};
+
+/**
+ * Expose the accessible states for the given element accordingly to state
+ * mapping rule.
+ *
+ * @param  aRule     [in] state mapping rule ID
+ * @param  aElement  [in] node of the accessible
+ * @param  aState    [in/out] accessible states
+ * @return            true if state map rule ID is valid
+ */
+bool MapToState(EStateRule aRule, dom::Element* aElement, PRUint64* aState);
+
+} // namespace aria
+} // namespace a11y
+} // namespace mozilla
+
+#endif
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -47,25 +47,25 @@ LIBRARY_NAME = accessibility_base_s
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS = \
   AccCollector.cpp \
   AccEvent.cpp \
   AccGroupInfo.cpp \
   AccIterator.cpp \
+  ARIAStateMap.cpp \
   filters.cpp \
   FocusManager.cpp \
   NotificationController.cpp \
   nsAccDocManager.cpp \
   nsAccessNode.cpp \
   nsARIAGridAccessible.cpp \
   nsARIAMap.cpp \
   nsDocAccessible.cpp \
-  nsOuterDocAccessible.cpp \
   nsCoreUtils.cpp \
   nsAccUtils.cpp \
   nsAccessibilityService.cpp \
   nsAccessible.cpp \
   nsAccessiblePivot.cpp \
   nsAccTreeWalker.cpp \
   nsBaseWidgetAccessible.cpp \
   nsEventShell.cpp \
@@ -87,16 +87,17 @@ EXPORTS = \
   nsAccessible.h \
   nsAccessNode.h \
   nsARIAMap.h \
   $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/a11y
 
 EXPORTS_mozilla/a11y = \
+  ARIAStateMap.h \
   FocusManager.h \
   States.h \
   Role.h \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
--- a/accessible/src/base/Statistics.h
+++ b/accessible/src/base/Statistics.h
@@ -43,43 +43,37 @@
 
 #include "mozilla/Telemetry.h"
 
 namespace mozilla {
 namespace a11y {
 namespace statistics {
 
   inline void A11yInitialized()
-    { Telemetry::Accumulate(Telemetry::A11Y_INSTANTIATED, 1); }
+    { Telemetry::Accumulate(Telemetry::A11Y_INSTANTIATED_FLAG, true); }
 
   inline void A11yConsumers(PRUint32 aConsumer)
     { Telemetry::Accumulate(Telemetry::A11Y_CONSUMERS, aConsumer); }
 
   /**
    * Report that ISimpleDOM* has been used.
    */
   inline void ISimpleDOMUsed()
-  {
-    static bool firstTime = true;
-    if (firstTime) {
-      Telemetry::Accumulate(Telemetry::A11Y_ISIMPLEDOM_USAGE, 1);
-      firstTime = false;
-    }
-  }
+    { Telemetry::Accumulate(Telemetry::A11Y_ISIMPLEDOM_USAGE_FLAG, true); }
 
   /**
    * Report that IAccessibleTable has been used.
    */
   inline void IAccessibleTableUsed()
-    { Telemetry::Accumulate(Telemetry::A11Y_IATABLE_USAGE, 1); }
+    { Telemetry::Accumulate(Telemetry::A11Y_IATABLE_USAGE_FLAG, true); }
 
   /**
    * Report that XForms accessibility has been instantiated.
    */
   inline void XFormsAccessibleUsed()
-    { Telemetry::Accumulate(Telemetry::A11Y_XFORMS_USAGE, 1); }
+    { Telemetry::Accumulate(Telemetry::A11Y_XFORMS_USAGE_FLAG, true); }
 
 } // namespace statistics
 } // namespace a11y
 } // namespace mozilla
 
 #endif
 
--- a/accessible/src/base/TextAttrs.cpp
+++ b/accessible/src/base/TextAttrs.cpp
@@ -755,10 +755,19 @@ TextAttrsMgr::TextPosTextAttr::
     {
        nscoord coordValue = styleCoord.GetCoordValue();
        return coordValue > 0 ?
          eTextPosSuper :
          (coordValue < 0 ? eTextPosSub : eTextPosBaseline);
     }
   }
 
+  const nsIContent* content = aFrame->GetContent();
+  if (content && content->IsHTML()) {
+    const nsIAtom* tagName = content->Tag();
+    if (tagName == nsGkAtoms::sup) 
+      return eTextPosSuper;
+    if (tagName == nsGkAtoms::sub) 
+      return eTextPosSub;
+  }
+
   return eTextPosNone;
 }
--- a/accessible/src/base/TextAttrs.h
+++ b/accessible/src/base/TextAttrs.h
@@ -111,23 +111,21 @@ protected:
    * @param aStartHTOffset  [in, out] the start offset
    * @param aEndHTOffset    [in, out] the end offset
    */
   class TextAttr;
   void GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen,
                 PRInt32* aStartHTOffset, PRInt32* aEndHTOffset);
 
 private:
+  nsAccessible* mOffsetAcc;
   nsHyperTextAccessible* mHyperTextAcc;
-
+  PRInt32 mOffsetAccIdx;
   bool mIncludeDefAttrs;
 
-  nsAccessible* mOffsetAcc;
-  PRInt32 mOffsetAccIdx;
-
 protected:
 
   /**
    * Interface class of text attribute class implementations.
    */
   class TextAttr
   {
   public:
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -34,30 +34,30 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsARIAMap.h"
 
-#include "nsIAccessibleRole.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsIContent.h"
 
 using namespace mozilla::a11y;
+using namespace mozilla::a11y::aria;
 
 /**
  *  This list of WAI-defined roles are currently hardcoded.
  *  Eventually we will most likely be loading an RDF resource that contains this information
  *  Using RDF will also allow for role extensibility. See bug 280138.
  *
- *  Definition of nsRoleMapEntry and nsStateMapEntry contains comments explaining this table.
+ *  Definition of nsRoleMapEntry contains comments explaining this table.
  *
  *  When no nsIAccessibleRole enum mapping exists for an ARIA role, the
  *  role will be exposed via the object attribute "xml-roles".
  *  In addition, in MSAA, the unmapped role will also be exposed as a BSTR string role.
  *
  *  There are no nsIAccessibleRole enums for the following landmark roles:
  *    banner, contentinfo, main, navigation, note, search, secondary, seealso, breadcrumbs
  */
@@ -602,102 +602,22 @@ nsRoleMapEntry nsARIAMap::gEmptyRoleMap 
   roles::NOTHING,
   kUseMapRole,
   eNoValue,
   eNoAction,
   eNoLiveAttr,
   kNoReqStates
 };
 
-nsStateMapEntry nsARIAMap::gWAIStateMap[] = {
-  // eARIANone
-  nsStateMapEntry(),
-
-  // eARIAAutoComplete
-  nsStateMapEntry(&nsGkAtoms::aria_autocomplete,
-                  "inline", states::SUPPORTS_AUTOCOMPLETION,
-                  "list", states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION,
-                  "both", states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION),
-
-  // eARIABusy
-  nsStateMapEntry(&nsGkAtoms::aria_busy,
-                  "true", states::BUSY,
-                  "error", states::INVALID),
-
-  // eARIACheckableBool
-  nsStateMapEntry(&nsGkAtoms::aria_checked, kBoolType,
-                  states::CHECKABLE, states::CHECKED, 0, true),
-
-  // eARIACheckableMixed
-  nsStateMapEntry(&nsGkAtoms::aria_checked, kMixedType,
-                  states::CHECKABLE, states::CHECKED, 0, true),
-
-  // eARIACheckedMixed
-  nsStateMapEntry(&nsGkAtoms::aria_checked, kMixedType,
-                  states::CHECKABLE, states::CHECKED, 0),
-
-  // eARIADisabled
-  nsStateMapEntry(&nsGkAtoms::aria_disabled, kBoolType,
-                  0, states::UNAVAILABLE),
-
-  // eARIAExpanded
-  nsStateMapEntry(&nsGkAtoms::aria_expanded, kBoolType,
-                  0, states::EXPANDED, states::COLLAPSED),
-
-  // eARIAHasPopup
-  nsStateMapEntry(&nsGkAtoms::aria_haspopup, kBoolType,
-                  0, states::HASPOPUP),
-
-  // eARIAInvalid
-  nsStateMapEntry(&nsGkAtoms::aria_invalid, kBoolType,
-                  0, states::INVALID),
-
-  // eARIAMultiline
-  nsStateMapEntry(&nsGkAtoms::aria_multiline, kBoolType,
-                  0, states::MULTI_LINE, states::SINGLE_LINE, true),
-
-  // eARIAMultiSelectable
-  nsStateMapEntry(&nsGkAtoms::aria_multiselectable, kBoolType,
-                  0, states::MULTISELECTABLE | states::EXTSELECTABLE),
-
-  // eARIAOrientation
-  nsStateMapEntry(&nsGkAtoms::aria_orientation, eUseFirstState,
-                  "horizontal", states::HORIZONTAL,
-                  "vertical", states::VERTICAL),
-
-  // eARIAPressed
-  nsStateMapEntry(&nsGkAtoms::aria_pressed, kMixedType,
-                  states::CHECKABLE, states::PRESSED),
-
-  // eARIAReadonly
-  nsStateMapEntry(&nsGkAtoms::aria_readonly, kBoolType,
-                  0, states::READONLY),
-
-  // eARIAReadonlyOrEditable
-  nsStateMapEntry(&nsGkAtoms::aria_readonly, kBoolType,
-                  0, states::READONLY, states::EDITABLE, true),
-
-  // eARIARequired
-  nsStateMapEntry(&nsGkAtoms::aria_required, kBoolType,
-                  0, states::REQUIRED),
-
-  // eARIASelectable
-  nsStateMapEntry(&nsGkAtoms::aria_selected, kBoolType,
-                  states::SELECTABLE, states::SELECTED, 0, true),
-
-  // eReadonlyUntilEditable
-  nsStateMapEntry(states::READONLY, states::EDITABLE)
-};
-
 /**
  * Universal (Global) states:
  * The following state rules are applied to any accessible element,
  * whether there is an ARIA role or not:
  */
-eStateMapEntryID nsARIAMap::gWAIUnivStateMap[] = {
+EStateRule nsARIAMap::gWAIUnivStateMap[] = {
   eARIABusy,
   eARIADisabled,
   eARIAExpanded,  // Currently under spec review but precedent exists
   eARIAHasPopup,  // Note this is technically a "property"
   eARIAInvalid,
   eARIARequired,  // XXX not global, Bug 553117
   eARIANone
 };
@@ -741,187 +661,8 @@ nsAttributeCharacteristics nsARIAMap::gW
   {&nsGkAtoms::aria_sort,                               ATTR_VALTOKEN },
   {&nsGkAtoms::aria_valuenow,          ATTR_BYPASSOBJ                 },
   {&nsGkAtoms::aria_valuemin,          ATTR_BYPASSOBJ                 },
   {&nsGkAtoms::aria_valuemax,          ATTR_BYPASSOBJ                 },
   {&nsGkAtoms::aria_valuetext,         ATTR_BYPASSOBJ                 }
 };
 
 PRUint32 nsARIAMap::gWAIUnivAttrMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIUnivAttrMap);
-
-
-////////////////////////////////////////////////////////////////////////////////
-// nsStateMapEntry
-
-nsStateMapEntry::nsStateMapEntry() :
-  mAttributeName(nsnull),
-  mIsToken(false),
-  mPermanentState(0),
-  mValue1(nsnull),
-  mState1(0),
-  mValue2(nsnull),
-  mState2(0),
-  mValue3(nsnull),
-  mState3(0),
-  mDefaultState(0),
-  mDefinedIfAbsent(false)
-{}
-
-nsStateMapEntry::nsStateMapEntry(PRUint64 aDefaultState,
-                                 PRUint64 aExclusingState) :
-  mAttributeName(nsnull),
-  mIsToken(false),
-  mPermanentState(0),
-  mValue1(nsnull),
-  mState1(0),
-  mValue2(nsnull),
-  mState2(0),
-  mValue3(nsnull),
-  mState3(0),
-  mDefaultState(aDefaultState),
-  mDefinedIfAbsent(false),
-  mExcludingState(aExclusingState)
-{
-}
-
-nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName, eStateValueType aType,
-                                 PRUint64 aPermanentState,
-                                 PRUint64 aTrueState,
-                                 PRUint64 aFalseState,
-                                 bool aDefinedIfAbsent) :
-  mAttributeName(aAttrName),
-  mIsToken(true),
-  mPermanentState(aPermanentState),
-  mValue1("false"),
-  mState1(aFalseState),
-  mValue2(nsnull),
-  mState2(0),
-  mValue3(nsnull),
-  mState3(0),
-  mDefaultState(aTrueState),
-  mDefinedIfAbsent(aDefinedIfAbsent),
-  mExcludingState(0)
-{
-  if (aType == kMixedType) {
-    mValue2 = "mixed";
-    mState2 = states::MIXED;
-  }
-}
-
-nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName,
-                                 const char* aValue1, PRUint64 aState1,
-                                 const char* aValue2, PRUint64 aState2,
-                                 const char* aValue3, PRUint64 aState3) :
-  mAttributeName(aAttrName), mIsToken(false), mPermanentState(0),
-  mValue1(aValue1), mState1(aState1),
-  mValue2(aValue2), mState2(aState2),
-  mValue3(aValue3), mState3(aState3),
-  mDefaultState(0), mDefinedIfAbsent(false), mExcludingState(0)
-{
-}
-
-nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName,
-                                 EDefaultStateRule aDefaultStateRule,
-                                 const char* aValue1, PRUint64 aState1,
-                                 const char* aValue2, PRUint64 aState2,
-                                 const char* aValue3, PRUint64 aState3) :
-  mAttributeName(aAttrName), mIsToken(true), mPermanentState(0),
-  mValue1(aValue1), mState1(aState1),
-  mValue2(aValue2), mState2(aState2),
-  mValue3(aValue3), mState3(aState3),
-  mDefaultState(0), mDefinedIfAbsent(true), mExcludingState(0)
-{
-  if (aDefaultStateRule == eUseFirstState)
-    mDefaultState = aState1;
-}
-
-bool
-nsStateMapEntry::MapToStates(nsIContent* aContent, PRUint64* aState,
-                             eStateMapEntryID aStateMapEntryID)
-{
-  // Return true if we should continue.
-  if (aStateMapEntryID == eARIANone)
-    return false;
-
-  const nsStateMapEntry& entry = nsARIAMap::gWAIStateMap[aStateMapEntryID];
-
-  // Non ARIA attribute case. Expose default state until excluding state is
-  // presented.
-  if (!entry.mAttributeName) {
-    if (!(*aState & entry.mExcludingState))
-      *aState |= entry.mDefaultState;
-
-    return true;
-  }
-
-  if (entry.mIsToken) {
-    // If attribute is considered as defined when it's absent then let's act
-    // attribute value is "false" supposedly.
-    bool hasAttr = aContent->HasAttr(kNameSpaceID_None, *entry.mAttributeName);
-    if (entry.mDefinedIfAbsent && !hasAttr) {
-      if (entry.mPermanentState)
-        *aState |= entry.mPermanentState;
-      if (entry.mState1)
-        *aState |= entry.mState1;
-      return true;
-    }
-
-    // We only have attribute state mappings for NMTOKEN (and boolean) based
-    // ARIA attributes. According to spec, a value of "undefined" is to be
-    // treated equivalent to "", or the absence of the attribute. We bail out
-    // for this case here.
-    // Note: If this method happens to be called with a non-token based
-    // attribute, for example: aria-label="" or aria-label="undefined", we will
-    // bail out and not explore a state mapping, which is safe.
-    if (!hasAttr ||
-        aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName,
-                              nsGkAtoms::_empty, eCaseMatters) ||
-        aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName,
-                              nsGkAtoms::_undefined, eCaseMatters)) {
-
-      if (entry.mPermanentState)
-        *aState &= ~entry.mPermanentState;
-      return true;
-    }
-
-    if (entry.mPermanentState)
-      *aState |= entry.mPermanentState;
-  }
-
-  nsAutoString attrValue;
-  if (!aContent->GetAttr(kNameSpaceID_None, *entry.mAttributeName, attrValue))
-    return true;
-
-  // Apply states for matched value. If no values was matched then apply default
-  // states.
-  bool applyDefaultStates = true;
-  if (entry.mValue1) {
-    if (attrValue.EqualsASCII(entry.mValue1)) {
-      applyDefaultStates = false;
-
-      if (entry.mState1)
-        *aState |= entry.mState1;
-    } else if (entry.mValue2) {
-      if (attrValue.EqualsASCII(entry.mValue2)) {
-        applyDefaultStates = false;
-
-        if (entry.mState2)
-          *aState |= entry.mState2;
-
-      } else if (entry.mValue3) {
-        if (attrValue.EqualsASCII(entry.mValue3)) {
-          applyDefaultStates = false;
-
-          if (entry.mState3)
-            *aState |= entry.mState3;
-
-        }
-      }
-    }
-  }
-
-  if (applyDefaultStates) {
-    if (entry.mDefaultState)
-      *aState |= entry.mDefaultState;
-  }
-
-  return true;
-}
--- a/accessible/src/base/nsARIAMap.h
+++ b/accessible/src/base/nsARIAMap.h
@@ -35,16 +35,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsARIAMap_H_
 #define _nsARIAMap_H_
 
+#include "mozilla/a11y/ARIAStateMap.h"
 #include "mozilla/a11y/Role.h"
 #include "prtypes.h"
 
 class nsIAtom;
 class nsIContent;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Value constants
@@ -148,136 +149,22 @@ struct nsAttributeCharacteristics
 // State map entry
 
 /**
  * Used in nsRoleMapEntry.state if no nsIAccessibleStates are automatic for
  * a given role.
  */
 #define kNoReqStates 0
 
-enum eStateValueType
-{
-  kBoolType,
-  kMixedType
-};
-
 enum EDefaultStateRule
 {
   //eNoDefaultState,
   eUseFirstState
 };
 
-/**
- * ID for state map entry, used in nsRoleMapEntry.
- */
-enum eStateMapEntryID
-{
-  eARIANone,
-  eARIAAutoComplete,
-  eARIABusy,
-  eARIACheckableBool,
-  eARIACheckableMixed,
-  eARIACheckedMixed,
-  eARIADisabled,
-  eARIAExpanded,
-  eARIAHasPopup,
-  eARIAInvalid,
-  eARIAMultiline,
-  eARIAMultiSelectable,
-  eARIAOrientation,
-  eARIAPressed,
-  eARIAReadonly,
-  eARIAReadonlyOrEditable,
-  eARIARequired,
-  eARIASelectable,
-  eReadonlyUntilEditable
-};
-
-class nsStateMapEntry
-{
-public:
-  /**
-   * Used to create stub.
-   */
-  nsStateMapEntry();
-
-  /**
-   * Used to expose permanent states presented until accessible has an excluding
-   * state.
-   */
-  nsStateMapEntry(PRUint64 aDefaultState, PRUint64 aExclusingState);
-
-  /**
-   * Used for ARIA attributes having boolean or mixed values.
-   */
-  nsStateMapEntry(nsIAtom** aAttrName, eStateValueType aType,
-                  PRUint64 aPermanentState,
-                  PRUint64 aTrueState,
-                  PRUint64 aFalseState = 0,
-                  bool aDefinedIfAbsent = false);
-
-  /**
-   * Used for ARIA attributes having enumerated values.
-   */
-  nsStateMapEntry(nsIAtom** aAttrName,
-                  const char* aValue1, PRUint64 aState1,
-                  const char* aValue2, PRUint64 aState2,
-                  const char* aValue3 = 0, PRUint64 aState3 = 0);
-
-  /**
-   * Used for ARIA attributes having enumerated values, and where a default
-   * attribute state should be assumed when not supplied by the author.
-   */
-  nsStateMapEntry(nsIAtom** aAttrName, EDefaultStateRule aDefaultStateRule,
-                  const char* aValue1, PRUint64 aState1,
-                  const char* aValue2, PRUint64 aState2,
-                  const char* aValue3 = 0, PRUint64 aState3 = 0);
-
-  /**
-   * Maps ARIA state map pointed by state map entry ID to accessible states.
-   *
-   * @param  aContent         [in] node of the accessible
-   * @param  aState           [in/out] accessible states
-   * @param  aStateMapEntryID [in] state map entry ID
-   * @return                   true if state map entry ID is valid
-   */
-  static bool MapToStates(nsIContent* aContent, PRUint64* aState,
-                            eStateMapEntryID aStateMapEntryID);
-
-private:
-  // ARIA attribute name
-  nsIAtom** mAttributeName;
-
-  // Indicates if attribute is token (can be undefined)
-  bool mIsToken;
-
-  // State applied always if attribute is defined
-  PRUint64 mPermanentState;
-
-  // States applied if attribute value is matched to the stored value
-  const char* mValue1;
-  PRUint64 mState1;
-
-  const char* mValue2;
-  PRUint64 mState2;
-
-  const char* mValue3;
-  PRUint64 mState3;
-
-  // States applied if no stored values above are matched
-  PRUint64 mDefaultState;
-
-  // Permanent and false states are applied if attribute is absent
-  bool mDefinedIfAbsent;
-
-  // If this state is presented in state bits then default state is not exposed.
-  PRUint64 mExcludingState;
-};
-
-
 ////////////////////////////////////////////////////////////////////////////////
 // Role map entry
 
 /**
  * For each ARIA role, this maps the nsIAccessible information.
  */
 struct nsRoleMapEntry
 {
@@ -297,25 +184,25 @@ struct nsRoleMapEntry
   EActionRule actionRule;
 
   // 'live' and 'container-live' object attributes mapping rule: how to expose
   // these object attributes if ARIA 'live' attribute is missed.
   ELiveAttrRule liveAttRule;
 
   // Automatic state mapping rule: always include in nsIAccessibleStates
   PRUint64 state;   // or kNoReqStates if no nsIAccessibleStates are automatic for this role.
-  
+
   // ARIA properties supported for this role
   // (in other words, the aria-foo attribute to nsIAccessibleStates mapping rules)
   // Currently you cannot have unlimited mappings, because
   // a variable sized array would not allow the use of
   // C++'s struct initialization feature.
-  eStateMapEntryID attributeMap1;
-  eStateMapEntryID attributeMap2;
-  eStateMapEntryID attributeMap3;
+  mozilla::a11y::aria::EStateRule attributeMap1;
+  mozilla::a11y::aria::EStateRule attributeMap2;
+  mozilla::a11y::aria::EStateRule attributeMap3;
 };
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // ARIA map
 
 /**
  *  These are currently initialized (hardcoded) in nsARIAMap.cpp, 
@@ -339,40 +226,36 @@ struct nsARIAMap
   /**
    * Empty role map entry. Used by accessibility service to create an accessible
    * if the accessible can't use role of used accessible class. For example,
    * it is used for table cells that aren't contained by table.
    */
   static nsRoleMapEntry gEmptyRoleMap;
 
   /**
-   * State map of ARIA state attributes.
-   */
-  static nsStateMapEntry gWAIStateMap[];
-
-  /**
    * State map of ARIA states applied to any accessible not depending on
    * the role.
    */
-  static eStateMapEntryID gWAIUnivStateMap[];
-  
+  static mozilla::a11y::aria::EStateRule gWAIUnivStateMap[];
+
   /**
    * Map of attribute to attribute characteristics.
    */
   static nsAttributeCharacteristics gWAIUnivAttrMap[];
   static PRUint32 gWAIUnivAttrMapLength;
 
   /**
    * Return accessible state from ARIA universal states applied to the given
    * element.
    */
-  static PRUint64 UniversalStatesFor(nsIContent* aContent)
+  static PRUint64 UniversalStatesFor(mozilla::dom::Element* aElement)
   {
     PRUint64 state = 0;
     PRUint32 index = 0;
-    while (nsStateMapEntry::MapToStates(aContent, &state, gWAIUnivStateMap[index]))
+    while (mozilla::a11y::aria::MapToState(gWAIUnivStateMap[index],
+                                           aElement, &state))
       index++;
 
     return state;
   }
 };
 
 #endif
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -36,17 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccDocManager.h"
 
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsApplicationAccessible.h"
-#include "nsOuterDocAccessible.h"
 #include "nsRootAccessibleWrap.h"
 #include "States.h"
 
 #include "nsCURILoader.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsIChannel.h"
 #include "nsIContentViewer.h"
 #include "nsIDOMDocument.h"
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -74,17 +74,16 @@
 #include "nsIHTMLDocument.h"
 #include "nsImageFrame.h"
 #include "nsILink.h"
 #include "nsIObserverService.h"
 #include "nsLayoutUtils.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsISupportsUtils.h"
 #include "nsObjectFrame.h"
-#include "nsOuterDocAccessible.h"
 #include "nsRootAccessibleWrap.h"
 #include "nsTextFragment.h"
 #include "mozilla/Services.h"
 #include "nsEventStates.h"
 
 #ifdef MOZ_XUL
 #include "nsXULAlertAccessible.h"
 #include "nsXULColorPickerAccessible.h"
@@ -105,16 +104,17 @@
 
 // For embedding plugin accessibles
 #ifdef MOZ_ACCESSIBILITY_ATK
 #include "AtkSocketAccessible.h"
 #endif
 
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
+#include "OuterDocAccessible.h"
 
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -205,19 +205,19 @@ nsAccessibilityService::GetRootDocumentA
   }
   return nsnull;
 }
  
 already_AddRefed<nsAccessible>
 nsAccessibilityService::CreateOuterDocAccessible(nsIContent* aContent,
                                                  nsIPresShell* aPresShell)
 {
-  nsAccessible* accessible = 
-    new nsOuterDocAccessible(aContent, 
-                             nsAccUtils::GetDocAccessibleFor(aPresShell));
+  nsAccessible* accessible =
+    new OuterDocAccessible(aContent,
+                           nsAccUtils::GetDocAccessibleFor(aPresShell));
   NS_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<nsAccessible>
 nsAccessibilityService::CreateHTMLButtonAccessible(nsIContent* aContent,
                                                    nsIPresShell* aPresShell)
 {
@@ -1351,17 +1351,17 @@ nsAccessibilityService::CreateAccessible
     return nsnull;
 
   PRInt32 type;
   nsresult rv = accessibleProvider->GetAccessibleType(&type);
   if (NS_FAILED(rv))
     return nsnull;
 
   if (type == nsIAccessibleProvider::OuterDoc) {
-    nsAccessible* accessible = new nsOuterDocAccessible(aContent, aDoc);
+    nsAccessible* accessible = new OuterDocAccessible(aContent, aDoc);
     NS_IF_ADDREF(accessible);
     return accessible;
   }
 
   nsAccessible* accessible = nsnull;
   switch (type)
   {
 #ifdef MOZ_XUL
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -816,17 +816,17 @@ nsAccessible::ChildAtPoint(PRInt32 aX, P
   if (!accessible)
     return fallbackAnswer;
 
   if (accessible == this) {
     // Manually walk through accessible children and see if the are within this
     // point. Skip offscreen or invisible accessibles. This takes care of cases
     // where layout won't walk into things for us, such as image map areas and
     // sub documents (XXX: subdocuments should be handled by methods of
-    // nsOuterDocAccessibles).
+    // OuterDocAccessibles).
     PRInt32 childCount = GetChildCount();
     for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
       nsAccessible *child = GetChildAt(childIdx);
 
       PRInt32 childX, childY, childWidth, childHeight;
       child->GetBounds(&childX, &childY, &childWidth, &childHeight);
       if (aX >= childX && aX < childX + childWidth &&
           aY >= childY && aY < childY + childHeight &&
@@ -1604,18 +1604,23 @@ nsAccessible::State()
   }
 
   return state;
 }
 
 void
 nsAccessible::ApplyARIAState(PRUint64* aState)
 {
+  if (!mContent->IsElement())
+    return;
+
+  dom::Element* element = mContent->AsElement();
+
   // Test for universal states first
-  *aState |= nsARIAMap::UniversalStatesFor(mContent);
+  *aState |= nsARIAMap::UniversalStatesFor(element);
 
   if (mRoleMapEntry) {
 
     // We only force the readonly bit off if we have a real mapping for the aria
     // role. This preserves the ability for screen readers to use readonly
     // (primarily on the document) as the hint for creating a virtual buffer.
     if (mRoleMapEntry->role != roles::NOTHING)
       *aState &= ~states::READONLY;
@@ -1645,27 +1650,22 @@ nsAccessible::ApplyARIAState(PRUint64* a
       }
     }    
   }
 
   if (!mRoleMapEntry)
     return;
 
   *aState |= mRoleMapEntry->state;
-  if (nsStateMapEntry::MapToStates(mContent, aState,
-                                   mRoleMapEntry->attributeMap1) &&
-      nsStateMapEntry::MapToStates(mContent, aState,
-                                   mRoleMapEntry->attributeMap2)) {
-    nsStateMapEntry::MapToStates(mContent, aState,
-                                 mRoleMapEntry->attributeMap3);
-  }
+
+  if (aria::MapToState(mRoleMapEntry->attributeMap1, element, aState) &&
+      aria::MapToState(mRoleMapEntry->attributeMap2, element, aState))
+    aria::MapToState(mRoleMapEntry->attributeMap3, element, aState);
 }
 
-// Not implemented by this class
-
 /* DOMString getValue (); */
 NS_IMETHODIMP
 nsAccessible::GetValue(nsAString& aValue)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   if (mRoleMapEntry) {
@@ -2820,19 +2820,19 @@ bool
 nsAccessible::IsSelect()
 {
   // If we have an ARIA role attribute present and the role allows multi
   // selectable state, then we need to support SelectAccessible interface. If
   // either attribute (role or multiselectable) change, then we'll destroy this
   // accessible so that we can follow COM identity rules.
 
   return mRoleMapEntry &&
-    (mRoleMapEntry->attributeMap1 == eARIAMultiSelectable ||
-     mRoleMapEntry->attributeMap2 == eARIAMultiSelectable ||
-     mRoleMapEntry->attributeMap3 == eARIAMultiSelectable);
+    (mRoleMapEntry->attributeMap1 == aria::eARIAMultiSelectable ||
+     mRoleMapEntry->attributeMap2 == aria::eARIAMultiSelectable ||
+     mRoleMapEntry->attributeMap3 == aria::eARIAMultiSelectable);
 }
 
 already_AddRefed<nsIArray>
 nsAccessible::SelectedItems()
 {
   nsCOMPtr<nsIMutableArray> selectedItems = do_CreateInstance(NS_ARRAY_CONTRACTID);
   if (!selectedItems)
     return nsnull;
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -59,17 +59,16 @@ class AccEvent;
 class AccGroupInfo;
 class EmbeddedObjCollector;
 class KeyBinding;
 class nsAccessible;
 class nsHyperTextAccessible;
 class nsHTMLImageAccessible;
 class nsHTMLImageMapAccessible;
 class nsHTMLLIAccessible;
-struct nsRoleMapEntry;
 class Relation;
 namespace mozilla {
 namespace a11y {
 class TableAccessible;
 }
 }
 class nsTextAccessible;
 class nsXULTreeAccessible;
--- a/accessible/src/base/nsFormControlAccessible.cpp
+++ b/accessible/src/base/nsFormControlAccessible.cpp
@@ -75,16 +75,32 @@ NS_IMPL_QUERY_INTERFACE_INHERITED1(Progr
 
 template<int Max>
 role
 ProgressMeterAccessible<Max>::NativeRole()
 {
   return roles::PROGRESSBAR;
 }
 
+template<int Max>
+PRUint64
+ProgressMeterAccessible<Max>::NativeState()
+{
+  PRUint64 state = nsFormControlAccessible::NativeState();
+
+  // An undetermined progressbar (i.e. without a value) has a mixed state.
+  nsAutoString attrValue;
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue);
+
+  if (attrValue.IsEmpty())
+    state |= states::MIXED;
+
+  return state;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // ProgressMeterAccessible<Max>: Widgets
 
 template<int Max>
 bool
 ProgressMeterAccessible<Max>::IsWidget() const
 {
   return true;
--- a/accessible/src/base/nsFormControlAccessible.h
+++ b/accessible/src/base/nsFormControlAccessible.h
@@ -58,16 +58,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLEVALUE
 
   // nsIAccessible
   NS_IMETHOD GetValue(nsAString &aValue);
 
   // nsAccessible
   virtual mozilla::a11y::role NativeRole();
+  virtual PRUint64 NativeState();
 
   // Widgets
   virtual bool IsWidget() const;
 };
 
 /**
   * Generic class used for radio buttons.
   */
new file mode 100644
--- /dev/null
+++ b/accessible/src/generic/Makefile.in
@@ -0,0 +1,31 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = accessibility
+LIBRARY_NAME = accessibility_generic_s
+LIBXUL_LIBRARY = 1
+
+
+CPPSRCS = \
+  OuterDocAccessible.cpp \
+  $(NULL)
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+LOCAL_INCLUDES = \
+  -I$(srcdir)/../xpcom \
+  -I$(srcdir)/../base \
+  -I$(srcdir)/../../../layout/generic \
+  -I$(srcdir)/../../../layout/xul/base/src \
+  $(NULL)
rename from accessible/src/base/nsOuterDocAccessible.cpp
rename to accessible/src/generic/OuterDocAccessible.cpp
--- a/accessible/src/base/nsOuterDocAccessible.cpp
+++ b/accessible/src/generic/OuterDocAccessible.cpp
@@ -31,53 +31,58 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "nsOuterDocAccessible.h"
+#include "OuterDocAccessible.h"
 
 #include "nsAccUtils.h"
 #include "nsDocAccessible.h"
 #include "Role.h"
 #include "States.h"
 
+using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsOuterDocAccessible
+// OuterDocAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsOuterDocAccessible::
-  nsOuterDocAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
+OuterDocAccessible::
+  OuterDocAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
   nsAccessibleWrap(aContent, aDoc)
 {
 }
 
+OuterDocAccessible::~OuterDocAccessible()
+{
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED0(nsOuterDocAccessible,
+NS_IMPL_ISUPPORTS_INHERITED0(OuterDocAccessible,
                              nsAccessible)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible public (DON'T add methods here)
 
 role
-nsOuterDocAccessible::NativeRole()
+OuterDocAccessible::NativeRole()
 {
   return roles::INTERNAL_FRAME;
 }
 
 nsAccessible*
-nsOuterDocAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                   EWhichChildAtPoint aWhichChild)
+OuterDocAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                 EWhichChildAtPoint aWhichChild)
 {
   PRInt32 docX = 0, docY = 0, docWidth = 0, docHeight = 0;
   nsresult rv = GetBounds(&docX, &docY, &docWidth, &docHeight);
   NS_ENSURE_SUCCESS(rv, nsnull);
 
   if (aX < docX || aX >= docX + docWidth || aY < docY || aY >= docY + docHeight)
     return nsnull;
 
@@ -87,103 +92,104 @@ nsOuterDocAccessible::ChildAtPoint(PRInt
   NS_ENSURE_TRUE(child, nsnull);
 
   if (aWhichChild == eDeepestChild)
     return child->ChildAtPoint(aX, aY, eDeepestChild);
   return child;
 }
 
 nsresult
-nsOuterDocAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
+OuterDocAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
 {
   nsAutoString tag;
   aAttributes->GetStringProperty(NS_LITERAL_CSTRING("tag"), tag);
   if (!tag.IsEmpty()) {
     // We're overriding the ARIA attributes on an sub document, but we don't want to
     // override the other attributes
     return NS_OK;
   }
   return nsAccessible::GetAttributesInternal(aAttributes);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessible
 
 PRUint8
-nsOuterDocAccessible::ActionCount()
+OuterDocAccessible::ActionCount()
 {
   // Internal frame, which is the doc's parent, should not have a click action.
   return 0;
 }
 
 NS_IMETHODIMP
-nsOuterDocAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+OuterDocAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
 {
   aName.Truncate();
 
   return NS_ERROR_INVALID_ARG;
 }
 
 NS_IMETHODIMP
-nsOuterDocAccessible::GetActionDescription(PRUint8 aIndex, nsAString& aDescription)
+OuterDocAccessible::GetActionDescription(PRUint8 aIndex,
+                                         nsAString& aDescription)
 {
   aDescription.Truncate();
 
   return NS_ERROR_INVALID_ARG;
 }
 
 NS_IMETHODIMP
-nsOuterDocAccessible::DoAction(PRUint8 aIndex)
+OuterDocAccessible::DoAction(PRUint8 aIndex)
 {
   return NS_ERROR_INVALID_ARG;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode public
 
 void
-nsOuterDocAccessible::Shutdown()
+OuterDocAccessible::Shutdown()
 {
   // XXX: sometimes outerdoc accessible is shutdown because of layout style
   // change however the presshell of underlying document isn't destroyed and
   // the document doesn't get pagehide events. Shutdown underlying document if
   // any to avoid hanging document accessible.
   NS_LOG_ACCDOCDESTROY_MSG("A11y outerdoc shutdown")
   NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this)
 
-  nsAccessible *childAcc = mChildren.SafeElementAt(0, nsnull);
+  nsAccessible* childAcc = mChildren.SafeElementAt(0, nsnull);
   if (childAcc) {
     NS_LOG_ACCDOCDESTROY("outerdoc's child document shutdown",
                          childAcc->GetDocumentNode())
     childAcc->Shutdown();
   }
 
   nsAccessibleWrap::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible public
 
 void
-nsOuterDocAccessible::InvalidateChildren()
+OuterDocAccessible::InvalidateChildren()
 {
   // Do not invalidate children because nsAccDocManager is responsible for
   // document accessible lifetime when DOM document is created or destroyed. If
   // DOM document isn't destroyed but its presshell is destroyed (for example,
   // when DOM node of outerdoc accessible is hidden), then outerdoc accessible
   // notifies nsAccDocManager about this. If presshell is created for existing
   // DOM document (for example when DOM node of outerdoc accessible is shown)
   // then allow nsAccDocManager to handle this case since the document
   // accessible is created and appended as a child when it's requested.
 
   SetChildrenFlag(eChildrenUninitialized);
 }
 
 bool
-nsOuterDocAccessible::AppendChild(nsAccessible *aAccessible)
+OuterDocAccessible::AppendChild(nsAccessible* aAccessible)
 {
   // We keep showing the old document for a bit after creating the new one,
   // and while building the new DOM and frame tree. That's done on purpose
   // to avoid weird flashes of default background color.
   // The old viewer will be destroyed after the new one is created.
   // For a11y, it should be safe to shut down the old document now.
   if (mChildren.Length())
     mChildren[0]->Shutdown();
@@ -194,19 +200,19 @@ nsOuterDocAccessible::AppendChild(nsAcce
   NS_LOG_ACCDOCCREATE("append document to outerdoc",
                       aAccessible->GetDocumentNode())
   NS_LOG_ACCDOCCREATE_ACCADDRESS("outerdoc", this)
 
   return true;
 }
 
 bool
-nsOuterDocAccessible::RemoveChild(nsAccessible *aAccessible)
+OuterDocAccessible::RemoveChild(nsAccessible* aAccessible)
 {
-  nsAccessible *child = mChildren.SafeElementAt(0, nsnull);
+  nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
   if (child != aAccessible) {
     NS_ERROR("Wrong child to remove!");
     return false;
   }
 
   NS_LOG_ACCDOCDESTROY_FOR("remove document from outerdoc",
                            child->GetDocumentNode(), child)
   NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this)
@@ -219,17 +225,17 @@ nsOuterDocAccessible::RemoveChild(nsAcce
   return wasRemoved;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible protected
 
 void
-nsOuterDocAccessible::CacheChildren()
+OuterDocAccessible::CacheChildren()
 {
   // Request document accessible for the content document to make sure it's
   // created. It will appended to outerdoc accessible children asynchronously.
   nsIDocument* outerDoc = mContent->GetCurrentDoc();
   if (outerDoc) {
     nsIDocument* innerDoc = outerDoc->GetSubDocumentFor(mContent);
     if (innerDoc)
       GetAccService()->GetDocAccessible(innerDoc);
rename from accessible/src/base/nsOuterDocAccessible.h
rename to accessible/src/generic/OuterDocAccessible.h
--- a/accessible/src/base/nsOuterDocAccessible.h
+++ b/accessible/src/generic/OuterDocAccessible.h
@@ -31,34 +31,38 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#ifndef _nsOuterDocAccessible_H_
-#define _nsOuterDocAccessible_H_
+#ifndef MOZILLA_A11Y_OUTERDOCACCESSIBLE_H_
+#define MOZILLA_A11Y_OUTERDOCACCESSIBLE_H_
 
 #include "nsAccessibleWrap.h"
 
+namespace mozilla {
+namespace a11y {
+
 /**
  * Used for <browser>, <frame>, <iframe>, <page> or editor> elements.
  * 
- * In these variable names, "outer" relates to the nsOuterDocAccessible as
+ * In these variable names, "outer" relates to the OuterDocAccessible as
  * opposed to the nsDocAccessibleWrap which is "inner". The outer node is
  * a something like tags listed above, whereas the inner node corresponds to
  * the inner document root.
  */
 
-class nsOuterDocAccessible : public nsAccessibleWrap
+class OuterDocAccessible : public nsAccessibleWrap
 {
 public:
-  nsOuterDocAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
+  OuterDocAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
+  virtual ~OuterDocAccessible();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD GetActionDescription(PRUint8 aIndex, nsAString& aDescription);
   NS_IMETHOD DoAction(PRUint8 aIndex);
 
@@ -78,9 +82,12 @@ public:
   // ActionAccessible
   virtual PRUint8 ActionCount();
 
 protected:
   // nsAccessible
   virtual void CacheChildren();
 };
 
+} // namespace a11y
+} // namespace mozilla
+
 #endif  
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -427,17 +427,17 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible:
   return NS_ERROR_FAILURE;
 }
 
 void
 nsHTMLTextFieldAccessible::ApplyARIAState(PRUint64* aState)
 {
   nsHyperTextAccessibleWrap::ApplyARIAState(aState);
 
-  nsStateMapEntry::MapToStates(mContent, aState, eARIAAutoComplete);
+  aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState);
 }
 
 PRUint64
 nsHTMLTextFieldAccessible::State()
 {
   PRUint64 state = nsHyperTextAccessibleWrap::State();
   if (state & states::DEFUNCT)
     return state;
--- a/accessible/src/mac/mozAccessible.h
+++ b/accessible/src/mac/mozAccessible.h
@@ -143,19 +143,16 @@ GetObjectOrRepresentedView(id <mozAccess
 // invalidates and removes all our children from our cached array.
 - (void)invalidateChildren;
 
 /** 
  * Append a child if they are already cached.
  */
 - (void)appendChild:(nsAccessible*)aAccessible;
 
-// invalidates the cached parent, used by invalidateChildren.
-- (void)invalidateParent;
-
 // makes ourselves "expired". after this point, we might be around if someone
 // has retained us (e.g., a third-party), but we really contain no information.
 - (void)expire;
 - (BOOL)isExpired;
 
 #ifdef DEBUG
 - (void)printHierarchy;
 - (void)printHierarchyWithLevel:(unsigned)numSpaces;
--- a/accessible/src/mac/mozAccessible.mm
+++ b/accessible/src/mac/mozAccessible.mm
@@ -349,36 +349,33 @@ GetNativeFromGeckoAccessible(nsIAccessib
 }
 
 #pragma mark -
 
 - (id <mozAccessible>)parent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
-  if (mParent)
-    return mParent;
-
   nsAccessible* accessibleParent = mGeckoAccessible->GetUnignoredParent();
   if (accessibleParent) {
     id nativeParent = GetNativeFromGeckoAccessible(accessibleParent);
     if (nativeParent)
-      return mParent = GetClosestInterestingAccessible(nativeParent);
+      return GetClosestInterestingAccessible(nativeParent);
   }
   
   // GetUnignoredParent() returns null when there is no unignored accessible all the way up to
   // the root accessible. so we'll have to return whatever native accessible is above our root accessible 
   // (which might be the owning NSWindow in the application, for example).
   //
   // get the native root accessible, and tell it to return its first parent unignored accessible.
   nsRootAccessible* root = mGeckoAccessible->RootAccessible();
   id nativeParent = GetNativeFromGeckoAccessible(static_cast<nsIAccessible*>(root));
   NSAssert1 (nativeParent, @"!!! we can't find a parent for %@", self);
   
-  return mParent = GetClosestInterestingAccessible(nativeParent);
+  return GetClosestInterestingAccessible(nativeParent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (BOOL)hasRepresentedView
 {
   return NO;
 }
@@ -610,18 +607,16 @@ GetNativeFromGeckoAccessible(nsIAccessib
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (void)invalidateChildren
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
-  [mChildren makeObjectsPerformSelector:@selector(invalidateParent)];
-
   // make room for new children
   [mChildren release];
   mChildren = nil;
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 - (void)appendChild:(nsAccessible*)aAccessible
@@ -630,21 +625,16 @@ GetNativeFromGeckoAccessible(nsIAccessib
   if (!mChildren)
     return;
     
   mozAccessible *curNative = GetNativeFromGeckoAccessible(aAccessible);
   if (curNative)
     [mChildren addObject:GetObjectOrRepresentedView(curNative)];
 }
 
-- (void)invalidateParent
-{
-  mParent = nil;
-}
-
 - (void)expire
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   [self invalidateChildren];
   mIsExpired = YES;
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
--- a/accessible/src/mac/nsRoleMap.h
+++ b/accessible/src/mac/nsRoleMap.h
@@ -137,17 +137,17 @@ static const NSString* AXRoles [] = {
   NSAccessibilityGroupRole,                     // roles::TEXT_CONTAINER       92
   NSAccessibilityButtonRole,                    // roles::TOGGLE_BUTTON        93
   NSAccessibilityTableRole,                     // roles::TREE_TABLE           94
   NSAccessibilityUnknownRole,                   // roles::VIEWPORT             95
   NSAccessibilityGroupRole,                     // roles::HEADER               96
   NSAccessibilityGroupRole,                     // roles::FOOTER               97
   NSAccessibilityGroupRole,                     // roles::PARAGRAPH            98
   @"AXRuler",                                   // roles::RULER                99     10.4+ only, so we re-define the constant.
-  NSAccessibilityComboBoxRole,                  // roles::AUTOCOMPLETE         100
+  NSAccessibilityUnknownRole,                   // roles::AUTOCOMPLETE         100
   NSAccessibilityTextFieldRole,                 // roles::EDITBAR              101
   NSAccessibilityTextFieldRole,                 // roles::ENTRY                102
   NSAccessibilityStaticTextRole,                // roles::CAPTION              103
   NSAccessibilityScrollAreaRole,                // roles::DOCUMENT_FRAME       104
   @"AXHeading",                                 // roles::HEADING              105
   NSAccessibilityGroupRole,                     // roles::PAGE                 106
   NSAccessibilityGroupRole,                     // roles::SECTION              107
   NSAccessibilityUnknownRole,                   // roles::REDUNDANT_OBJECT     108
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -749,17 +749,17 @@ NS_IMETHODIMP nsXULTextFieldAccessible::
   return NS_ERROR_FAILURE;
 }
 
 void
 nsXULTextFieldAccessible::ApplyARIAState(PRUint64* aState)
 {
   nsHyperTextAccessibleWrap::ApplyARIAState(aState);
 
-  nsStateMapEntry::MapToStates(mContent, aState, eARIAAutoComplete);
+  aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState);
 
 }
 
 PRUint64
 nsXULTextFieldAccessible::NativeState()
 {
   PRUint64 state = nsHyperTextAccessibleWrap::NativeState();
 
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -96,17 +96,17 @@ include $(topsrcdir)/config/rules.mk
 		test_aria_role_equation.html \
 		test_aria_roles.html \
 		test_aria_roles.xul \
 		test_aria_token_attrs.html \
 		test_bug420863.html \
 		test_descr.html \
 		test_nsIAccessibleDocument.html \
 		test_nsIAccessibleImage.html \
-		test_nsOuterDocAccessible.html \
+		test_OuterDocAccessible.html \
 		test_role_nsHyperTextAcc.html \
 		test_textboxes.html \
 		test_textboxes.xul \
 		testTextboxes.js \
 		text.js \
 		treeview.css \
 		treeview.js \
 		$(NULL)
--- a/accessible/tests/mochitest/actions/test_select.html
+++ b/accessible/tests/mochitest/actions/test_select.html
@@ -7,16 +7,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="../actions.js"></script>
 
   <script type="application/javascript">
     //gA11yEventDumpToConsole = true; // debugging
--- a/accessible/tests/mochitest/actions/test_tree.xul
+++ b/accessible/tests/mochitest/actions/test_tree.xul
@@ -10,16 +10,18 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../treeview.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
   <script type="application/javascript"
           src="../actions.js" />
 
   <script type="application/javascript">
   <![CDATA[
--- a/accessible/tests/mochitest/actions/test_treegrid.xul
+++ b/accessible/tests/mochitest/actions/test_treegrid.xul
@@ -12,16 +12,18 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../treeview.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
   <script type="application/javascript"
           src="../actions.js" />
 
   <script type="application/javascript">
   <![CDATA[
--- a/accessible/tests/mochitest/attributes/test_text.html
+++ b/accessible/tests/mochitest/attributes/test_text.html
@@ -137,53 +137,44 @@
       attrs = {"color": gComputedStyle.color};
       testTextAttrs(ID, 9, attrs, defAttrs, 8, 11);
 
       // Normal
       attrs = {};
       testTextAttrs(ID, 11, attrs, defAttrs, 11, 18);
 
       //////////////////////////////////////////////////////////////////////////
-      // area6 (CSS vertical-align property, bug 445938)
+      // area6 (CSS vertical-align property, refer to bug 445938 for details
+      // 	and sup and sub elements, refer to bug 735645 for details)
       ID = "area6";
       defAttrs = buildDefaultTextAttrs(ID, "12pt");
       testDefaultTextAttrs(ID, defAttrs);
 
       attrs = {};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 5);
 
-      tempElem = getNode(ID).firstChild.nextSibling;
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      attrs = {"text-position": gComputedStyle.verticalAlign,
-               "font-size": "10pt"};
+      attrs = { "text-position": "super", "font-size": "10pt" };
       testTextAttrs(ID, 5, attrs, defAttrs, 5, 13);
 
       attrs = {};
       testTextAttrs(ID, 13, attrs, defAttrs, 13, 27);
 
-      tempElem = tempElem.nextSibling.nextSibling;
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      attrs = {"text-position": gComputedStyle.verticalAlign};
+      attrs = { "text-position": "super" };
       testTextAttrs(ID, 27, attrs, defAttrs, 27, 35);
 
       attrs = {};
       testTextAttrs(ID, 35, attrs, defAttrs, 35, 39);
 
-      tempElem = tempElem.nextSibling.nextSibling;
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      attrs = {"text-position": gComputedStyle.verticalAlign,
-               "font-size": "10pt"};
+      attrs = { "text-position": "sub", "font-size": "10pt" };
       testTextAttrs(ID, 39, attrs, defAttrs, 39, 50);
 
       attrs = {};
       testTextAttrs(ID, 50, attrs, defAttrs, 50, 55);
 
-      tempElem = tempElem.nextSibling.nextSibling;
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      attrs = {"text-position": gComputedStyle.verticalAlign};
+      attrs = { "text-position": "sub" };
       testTextAttrs(ID, 55, attrs, defAttrs, 55, 64);
 
       attrs = {};
       testTextAttrs(ID, 64, attrs, defAttrs, 64, 69);
 
       attrs = { "text-position": "super" };
       testTextAttrs(ID, 69, attrs, defAttrs, 69, 84);
 
@@ -539,16 +530,21 @@
      title="font-family text attribute should expose actual font used">
     Mozilla Bug 473576
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=523304"
      title="expose text-underline-color and text-line-through-color text attributes">
     Mozilla Bug 523304
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=735645"
+     title="expose sub and sup elements in text attributes">
+    Mozilla Bug 735645
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <p id="area1" style="font-size: smaller">Normal <b>Bold</b> Normal</p>
   <p id="area2" style="font-size: 120%">Normal <b>Bold <i>Italic </i>Bold</b> Normal</p>
   <p id="area3" style="background-color: blue;">
--- a/accessible/tests/mochitest/events/test_aria_alert.html
+++ b/accessible/tests/mochitest/events/test_aria_alert.html
@@ -7,16 +7,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     function showAlert(aID)
     {
       this.DOMNode = document.createElement("div");
--- a/accessible/tests/mochitest/events/test_aria_menu.html
+++ b/accessible/tests/mochitest/events/test_aria_menu.html
@@ -9,16 +9,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     const kViaDisplayStyle = 0;
     const kViaVisibilityStyle = 1;
 
--- a/accessible/tests/mochitest/events/test_aria_statechange.html
+++ b/accessible/tests/mochitest/events/test_aria_statechange.html
@@ -7,16 +7,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
 
 
     /**
--- a/accessible/tests/mochitest/events/test_focus_aria_activedescendant.html
+++ b/accessible/tests/mochitest/events/test_focus_aria_activedescendant.html
@@ -8,16 +8,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     //gA11yEventDumpToConsole = true; // debugging
 
     function changeARIAActiveDescendant(aID, aItemID)
--- a/accessible/tests/mochitest/events/test_focus_autocomplete.xul
+++ b/accessible/tests/mochitest/events/test_focus_autocomplete.xul
@@ -16,16 +16,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript"
           src="../autocomplete.js" />
 
   <script type="application/javascript">
--- a/accessible/tests/mochitest/events/test_focus_canvas.html
+++ b/accessible/tests/mochitest/events/test_focus_canvas.html
@@ -11,16 +11,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     //gA11yEventDumpToConsole = true;
 
     var gQueue = null;
     function doTests()
     {
--- a/accessible/tests/mochitest/events/test_focus_contextmenu.xul
+++ b/accessible/tests/mochitest/events/test_focus_contextmenu.xul
@@ -9,16 +9,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
     //gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true; // debug stuff
 
--- a/accessible/tests/mochitest/events/test_focus_controls.html
+++ b/accessible/tests/mochitest/events/test_focus_controls.html
@@ -11,16 +11,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     //gA11yEventDumpToConsole = true;
 
     var gQueue = null;
     function doTests()
     {
--- a/accessible/tests/mochitest/events/test_focus_dialog.html
+++ b/accessible/tests/mochitest/events/test_focus_dialog.html
@@ -11,16 +11,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     function openCloseDialog(aID)
     {
       this.eventSeq = [
         new focusChecker(getNode(aID))
       ];
--- a/accessible/tests/mochitest/events/test_focus_doc.html
+++ b/accessible/tests/mochitest/events/test_focus_doc.html
@@ -10,16 +10,18 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
       src="../common.js"></script>
   <script type="application/javascript"
     src="../events.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
     <script type="application/javascript"
       src="../states.js"></script>
 
   <script type="application/javascript">
     var gQueue = null;
 
     //var gA11yEventDumpID = "eventdump";
     //gA11yEventDumpToConsole = true;
--- a/accessible/tests/mochitest/events/test_focus_general.xul
+++ b/accessible/tests/mochitest/events/test_focus_general.xul
@@ -9,16 +9,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
     function getColorBtn(aBtnObj)
     {
       var colorpicker = aBtnObj.colorpicker;
--- a/accessible/tests/mochitest/events/test_focus_listcontrols.xul
+++ b/accessible/tests/mochitest/events/test_focus_listcontrols.xul
@@ -9,16 +9,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
     //gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true; // debug stuff
 
--- a/accessible/tests/mochitest/events/test_focus_menu.xul
+++ b/accessible/tests/mochitest/events/test_focus_menu.xul
@@ -9,16 +9,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
     //gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true; // debug stuff
 
--- a/accessible/tests/mochitest/events/test_focus_selects.html
+++ b/accessible/tests/mochitest/events/test_focus_selects.html
@@ -11,16 +11,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     //gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true;
 
     var gQueue = null;
 
--- a/accessible/tests/mochitest/events/test_focus_tabbox.xul
+++ b/accessible/tests/mochitest/events/test_focus_tabbox.xul
@@ -9,16 +9,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
     //gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true; // debug stuff
 
--- a/accessible/tests/mochitest/events/test_focus_tree.xul
+++ b/accessible/tests/mochitest/events/test_focus_tree.xul
@@ -14,16 +14,18 @@
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../treeview.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
 
     ////////////////////////////////////////////////////////////////////////////
--- a/accessible/tests/mochitest/events/test_selection.html
+++ b/accessible/tests/mochitest/events/test_selection.html
@@ -11,16 +11,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     ////////////////////////////////////////////////////////////////////////////
     // Invokers
 
     ////////////////////////////////////////////////////////////////////////////
     // Do tests
--- a/accessible/tests/mochitest/events/test_selection.xul
+++ b/accessible/tests/mochitest/events/test_selection.xul
@@ -11,16 +11,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
     function advanceTab(aTabsID, aDirection, aNextTabID)
     {
       this.eventSeq = [
--- a/accessible/tests/mochitest/events/test_selection_aria.html
+++ b/accessible/tests/mochitest/events/test_selection_aria.html
@@ -11,16 +11,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     ////////////////////////////////////////////////////////////////////////////
     // Invokers
 
     function selectTreeItem(aTreeID, aItemID)
     {
--- a/accessible/tests/mochitest/events/test_statechange.html
+++ b/accessible/tests/mochitest/events/test_statechange.html
@@ -9,16 +9,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     ////////////////////////////////////////////////////////////////////////////
     // Invokers
 
     function makeEditableDoc(aDocNode, aIsEnabled)
     {
--- a/accessible/tests/mochitest/events/test_textattrchange.html
+++ b/accessible/tests/mochitest/events/test_textattrchange.html
@@ -9,16 +9,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="../attributes.js"></script>
 
   <script type="application/javascript">
 
--- a/accessible/tests/mochitest/focus/test_focusedChild.html
+++ b/accessible/tests/mochitest/focus/test_focusedChild.html
@@ -7,16 +7,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     function openWnd()
     {
       this.eventSeq = [ new invokerChecker(EVENT_FOCUS,
--- a/accessible/tests/mochitest/focus/test_takeFocus.html
+++ b/accessible/tests/mochitest/focus/test_takeFocus.html
@@ -7,16 +7,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     ////////////////////////////////////////////////////////////////////////////
     // Invokers
 
--- a/accessible/tests/mochitest/focus/test_takeFocus.xul
+++ b/accessible/tests/mochitest/focus/test_takeFocus.xul
@@ -9,16 +9,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript"
           src="../treeview.js" />
 
   <script type="application/javascript">
--- a/accessible/tests/mochitest/states.js
+++ b/accessible/tests/mochitest/states.js
@@ -1,13 +1,14 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Helper functions for accessible states testing.
 //
 // requires:
 //   common.js
+//   role.js
 //
 ////////////////////////////////////////////////////////////////////////////////
 
 ////////////////////////////////////////////////////////////////////////////////
 // State constants
 
 // const STATE_BUSY is defined in common.js
 const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED;
@@ -66,17 +67,17 @@ const kExtraState = 1;
  * @param aAbsentState       State bits that are not wanted.
  * @param aAbsentExtraState  Extra state bits that are not wanted.
  * @param aTestName          The test name.
  */
 function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
                     aAbsentExtraState, aTestName)
 {
   var [state, extraState] = getStates(aAccOrElmOrID);
-
+  var role = getRole(aAccOrElmOrID);
   var id = prettyName(aAccOrElmOrID) + (aTestName ? " [" + aTestName + "]": "");
 
   // Primary test.
   isState(state & aState, aState, false,
           "wrong state bits for " + id + "!");
 
   if (aExtraState)
     isState(extraState & aExtraState, aExtraState, true,
@@ -130,17 +131,17 @@ function testStates(aAccOrElmOrID, aStat
               "Not expanded " + id + " must be collapsed!");
     } else if (aAbsentState & STATE_COLLAPSED) {
       isState(state & STATE_EXPANDED, STATE_EXPANDED, false,
               "Not collapsed " + id + " must be expanded!");
     }
   }
 
   // checked/mixed/checkable
-  if (state & STATE_CHECKED || state & STATE_MIXED)
+  if (state & STATE_CHECKED || state & STATE_MIXED && role != ROLE_PROGRESSBAR)
     isState(state & STATE_CHECKABLE, STATE_CHECKABLE, false,
             "Checked or mixed element must be checkable!");
 
   if (state & STATE_CHECKED)
     isState(state & STATE_MIXED, 0, false,
             "Checked element cannot be state mixed!");
 
   if (state & STATE_MIXED)
--- a/accessible/tests/mochitest/states/Makefile.in
+++ b/accessible/tests/mochitest/states/Makefile.in
@@ -45,16 +45,17 @@ relativesrcdir  = accessible/states
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_aria.html \
 		test_aria_imgmap.html \
 		test_aria_widgetitems.html \
 		test_buttons.html \
+		test_controls.html \
 		test_controls.xul \
 		test_doc.html \
 		test_docarticle.html \
 		test_editablebody.html \
 		test_expandable.xul \
 		test_frames.html \
 		test_inputs.html \
 		test_link.html \
--- a/accessible/tests/mochitest/states/test_aria_widgetitems.html
+++ b/accessible/tests/mochitest/states/test_aria_widgetitems.html
@@ -8,16 +8,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     function focusARIAItem(aID, aIsSelected)
     {
       this.DOMNode = getNode(aID);
--- a/accessible/tests/mochitest/states/test_buttons.html
+++ b/accessible/tests/mochitest/states/test_buttons.html
@@ -6,16 +6,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
   function doTest()
   {
     // Default state.
     testStates("f1_image", STATE_DEFAULT | STATE_FOCUSABLE);
     testStates("f2_submit", STATE_DEFAULT | STATE_FOCUSABLE);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/states/test_controls.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>HTML control states</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../states.js"></script>
+
+  <script type="application/javascript">
+  function doTest()
+  {
+    // Undetermined progressbar (no value or aria-value attribute): mixed state
+    testStates("progress", STATE_MIXED);
+    // Determined progressbar (has value): shouldn't have mixed state
+    testStates("progress2", 0, 0, STATE_MIXED);
+    // Determined progressbar (has aria-value): shouldn't have mixed state
+    // testStates("progress3", 0, 0, STATE_MIXED);
+    todo(false, "we should respect ARIA");
+
+    SimpleTest.finish();
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  addA11yLoadEvent(doTest);
+  </script>
+</head>
+
+<body>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=670853"
+     title="Bug 670853 - undetermined progressmeters should expose mixed state">
+    Mozilla Bug 670853
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <progress id="progress"></progress>
+  <progress id="progress2" value="1"></progress>
+  <progress id="progress3" aria-valuenow="1"></progress>
+  
+</body>
+</html>
--- a/accessible/tests/mochitest/states/test_controls.xul
+++ b/accessible/tests/mochitest/states/test_controls.xul
@@ -7,16 +7,18 @@
         title="Accessible XUL input control state tests">
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
 
   <script type="application/javascript">
   <![CDATA[
 
     function doTest()
     {
       testStates("checkbox", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
--- a/accessible/tests/mochitest/states/test_doc.html
+++ b/accessible/tests/mochitest/states/test_doc.html
@@ -6,16 +6,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       // Bug 566542: root accesible should expose active state when focused.
       testStates(getRootAccessible(), 0, EXT_STATE_ACTIVE);
 
--- a/accessible/tests/mochitest/states/test_docarticle.html
+++ b/accessible/tests/mochitest/states/test_docarticle.html
@@ -6,16 +6,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       var docAcc = getAccessible(document, [nsIAccessibleDocument]);
       if (docAcc) {
         testStates(docAcc, STATE_READONLY);
--- a/accessible/tests/mochitest/states/test_editablebody.html
+++ b/accessible/tests/mochitest/states/test_editablebody.html
@@ -8,16 +8,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       testStates(document, 0, EXT_STATE_EDITABLE);
       testStates("p", 0, EXT_STATE_EDITABLE);
 
--- a/accessible/tests/mochitest/states/test_expandable.xul
+++ b/accessible/tests/mochitest/states/test_expandable.xul
@@ -19,16 +19,18 @@
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js" />
 
   <script type="application/javascript"
           src="../autocomplete.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
     //gA11yEventDumpToConsole = true; // debuggin
 
--- a/accessible/tests/mochitest/states/test_frames.html
+++ b/accessible/tests/mochitest/states/test_frames.html
@@ -7,16 +7,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       frameDoc = document.getElementById("frame_doc").contentDocument;
       frameDocArticle = document.getElementById("frame_doc_article").contentDocument;
       frameDocCheckbox = document.getElementById("frame_doc_checkbox").contentDocument;
--- a/accessible/tests/mochitest/states/test_inputs.html
+++ b/accessible/tests/mochitest/states/test_inputs.html
@@ -6,16 +6,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
   function doTest()
   {
     ////////////////////////////////////////////////////////////////////////////
     // 'editable' and 'multiline' states.
     testStates("input", 0, EXT_STATE_EDITABLE, 0, EXT_STATE_MULTI_LINE);
@@ -102,16 +104,17 @@
 
     ////////////////////////////////////////////////////////////////////////////
     // autocomplete states
     testStates("autocomplete-default", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-off", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-formoff", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-list", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-list2", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
+    testStates("autocomplete-tel", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     SimpleTest.finish();
   }
 
   SimpleTest.waitForExplicitFinish();
   addA11yLoadEvent(doTest);
   </script>
 </head>
 
@@ -225,11 +228,12 @@
     <input id="autocomplete-formoff">
   </form>
   <datalist id="cities">
     <option>Paris</option>
     <option>San Francisco</option>
   </datalist>
   <input id="autocomplete-list" list="cities">
   <input id="autocomplete-list2" list="cities" autocomplete="off">
+  <input id="autocomplete-tel" type="tel">
 
   </body>
 </html>
--- a/accessible/tests/mochitest/states/test_popup.xul
+++ b/accessible/tests/mochitest/states/test_popup.xul
@@ -7,16 +7,18 @@
         title="XUL popup attribute test">
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
 
   <script type="application/javascript">
   <![CDATA[
     function doTest()
     {
       // label with popup
       testStates("labelWithPopup", STATE_HASPOPUP);
--- a/accessible/tests/mochitest/states/test_selects.html
+++ b/accessible/tests/mochitest/states/test_selects.html
@@ -5,16 +5,18 @@
   <link rel="stylesheet" type="text/css"
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       // combobox
       var combobox = getAccessible("combobox");
       testStates(combobox,
--- a/accessible/tests/mochitest/states/test_stale.html
+++ b/accessible/tests/mochitest/states/test_stale.html
@@ -6,16 +6,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     function addChild(aContainerID)
     {
       this.containerNode = getNode(aContainerID);
--- a/accessible/tests/mochitest/states/test_tree.xul
+++ b/accessible/tests/mochitest/states/test_tree.xul
@@ -12,16 +12,18 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../treeview.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
     ////////////////////////////////////////////////////////////////////////////
     // Test
--- a/accessible/tests/mochitest/table/test_sels_ariagrid.html
+++ b/accessible/tests/mochitest/table/test_sels_ariagrid.html
@@ -9,16 +9,18 @@ https://bugzilla.mozilla.org/show_bug.cg
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../table.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       //////////////////////////////////////////////////////////////////////////
--- a/accessible/tests/mochitest/table/test_sels_table.html
+++ b/accessible/tests/mochitest/table/test_sels_table.html
@@ -7,16 +7,18 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../table.js"></script>
 
   <script type="text/javascript">
 
     function doTest()
     {
--- a/accessible/tests/mochitest/table/test_sels_tree.xul
+++ b/accessible/tests/mochitest/table/test_sels_tree.xul
@@ -12,16 +12,18 @@
   <script type="application/javascript"
           src="../treeview.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
           src="../events.js" />
   <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../table.js" />
 
   <script type="application/javascript">
   <![CDATA[
     ////////////////////////////////////////////////////////////////////////////
     // Test
rename from accessible/tests/mochitest/test_nsOuterDocAccessible.html
rename to accessible/tests/mochitest/test_OuterDocAccessible.html
--- a/accessible/tests/mochitest/tree/test_txtctrl.html
+++ b/accessible/tests/mochitest/tree/test_txtctrl.html
@@ -71,16 +71,29 @@
           {
             role: ROLE_TEXT_LEAF,
             children: []
           }
         ]
       };
 
       testAccessibleTree("txc5", accTree);
+      
+      // input@type="tel", value
+      accTree = {
+        role: ROLE_ENTRY,
+        children: [
+          { // text child
+            role: ROLE_TEXT_LEAF,
+            children: []
+          }
+        ]
+      };
+
+      testAccessibleTree("txc6", accTree);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
@@ -112,11 +125,12 @@
   </div>
   <input id="txc2" value="hello">
   <input id="txc3">
   <textarea id="txc4">
     hello1
     hello2
   </textarea>
   <input id="txc5" type="password" value="hello">
+  <input id="txc6" type="tel" value="4167771234">
 
 </body>
 </html>
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -2,17 +2,16 @@ dnl
 dnl Local autoconf macros used with mozilla
 dnl The contents of this file are under the Public Domain.
 dnl 
 
 builtin(include, build/autoconf/glib.m4)dnl
 builtin(include, build/autoconf/nspr.m4)dnl
 builtin(include, build/autoconf/nss.m4)dnl
 builtin(include, build/autoconf/pkg.m4)dnl
-builtin(include, build/autoconf/freetype2.m4)dnl
 builtin(include, build/autoconf/codeset.m4)dnl
 builtin(include, build/autoconf/altoptions.m4)dnl
 builtin(include, build/autoconf/mozprog.m4)dnl
 builtin(include, build/autoconf/mozheader.m4)dnl
 builtin(include, build/autoconf/mozcommonheader.m4)dnl
 builtin(include, build/autoconf/acwinpaths.m4)dnl
 builtin(include, build/autoconf/lto.m4)dnl
 builtin(include, build/autoconf/gcc-pr49911.m4)dnl
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -302,16 +302,17 @@ pref("editor.singleLine.pasteNewlines", 
 
 // threshold where a tap becomes a drag, in 1/240" reference pixels
 // The names of the preferences are to be in sync with nsEventStateManager.cpp
 pref("ui.dragThresholdX", 25);
 pref("ui.dragThresholdY", 25);
 
 // Layers Acceleration
 pref("layers.acceleration.disabled", false);
+pref("layers.offmainthreadcomposition.enabled", true);
 
 // Web Notifications
 pref("notification.feature.enabled", true);
 
 // IndexedDB
 pref("indexedDB.feature.enabled", true);
 pref("dom.indexedDB.warningQuota", 5);
 
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -40,24 +40,23 @@ XPCOMUtils.defineLazyServiceGetter(Servi
 });
 
 // FIXME Bug 707625
 // until we have a proper security model, add some rights to
 // the pre-installed web applications
 // XXX never grant 'content-camera' to non-gaia apps
 function addPermissions(urls) {
   let permissions = [
-    'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app',
+    'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'pin-app',
     'websettings-read', 'websettings-readwrite',
     'content-camera', 'webcontacts-manage', 'wifi-manage', 'desktop-notification',
     'geolocation'
   ];
   urls.forEach(function(url) {
     url = url.trim();
-    dump("XxXxX adding permissions for " + url);
     let uri = Services.io.newURI(url, null, null);
     let allow = Ci.nsIPermissionManager.ALLOW_ACTION;
 
     permissions.forEach(function(permission) {
       Services.perms.add(uri, permission, allow);
     });
   });
 }
@@ -89,16 +88,17 @@ var shell = {
 
     ['keydown', 'keypress', 'keyup'].forEach((function listenKey(type) {
       window.addEventListener(type, this, false, true);
       window.addEventListener(type, this, true, true);
     }).bind(this));
 
     window.addEventListener('MozApplicationManifest', this);
     window.addEventListener('mozfullscreenchange', this);
+    window.addEventListener('sizemodechange', this);
     this.contentBrowser.addEventListener('load', this, true);
 
     // Until the volume can be set from the content side, set it to a
     // a specific value when the device starts. This way the front-end
     // can display a notification when the volume change and show a volume
     // level modified from this point.
     try {
       Services.audioManager.masterVolume = 0.5;
@@ -126,16 +126,17 @@ var shell = {
     let browser = this.contentBrowser;
     browser.homePage = homeURL;
     browser.goHome();
   },
 
   stop: function shell_stop() {
     window.removeEventListener('MozApplicationManifest', this);
     window.removeEventListener('mozfullscreenchange', this);
+    window.removeEventListener('sizemodechange', this);
   },
 
   toggleDebug: function shell_toggleDebug() {
     this.isDebug = !this.isDebug;
 
     if (this.isDebug) {
       Services.prefs.setBoolPref("layers.acceleration.draw-fps", true);
       Services.prefs.setBoolPref("nglayout.debug.paint_flashing", true);
@@ -222,16 +223,23 @@ var shell = {
 
       case 'mozfullscreenchange':
         // When the screen goes fullscreen make sure to set the focus to the
         // main window so noboby can prevent the ESC key to get out fullscreen
         // mode
         if (document.mozFullScreen)
           Services.fm.focusedWindow = window;
         break;
+      case 'sizemodechange':
+        if (window.windowState == window.STATE_MINIMIZED) {
+          this.contentBrowser.docShell.isActive = false;
+        } else {
+          this.contentBrowser.docShell.isActive = true;
+        }
+        break;
       case 'load':
         this.contentBrowser.removeEventListener('load', this, true);
 
         let chromeWindow = window.QueryInterface(Ci.nsIDOMChromeWindow);
         chromeWindow.browserDOMWindow = new nsBrowserAccess();
 
         this.sendEvent(window, 'ContentStart');
         break;
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -607,16 +607,18 @@ pref("plugins.hide_infobar_for_outdated_
 #ifdef XP_MACOSX
 pref("plugins.use_layers", true);
 pref("plugins.hide_infobar_for_carbon_failure_plugin", false);
 #endif
 
 pref("plugins.update.url", "https://www.mozilla.com/%LOCALE%/plugincheck/");
 pref("plugins.update.notifyUser", false);
 
+pref("plugins.click_to_play", false);
+
 #ifdef XP_WIN
 pref("browser.preferences.instantApply", false);
 #else
 pref("browser.preferences.instantApply", true);
 #endif
 #ifdef XP_MACOSX
 pref("browser.preferences.animateFadeIn", true);
 #else
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -251,16 +251,22 @@ XPCOMUtils.defineLazyGetter(this, "PageM
 * We can avoid adding multiple load event listeners and save some time by adding
 * one listener that calls all real handlers.
 */
 function pageShowEventHandlers(event) {
   // Filter out events that are not about the document load we are interested in
   if (event.originalTarget == content.document) {
     charsetLoadListener(event);
     XULBrowserWindow.asyncUpdateUI();
+
+    // The PluginClickToPlay events are not fired when navigating using the
+    // BF cache. |event.persisted| is true when the page is loaded from the
+    // BF cache, so this code reshows the notification if necessary.
+    if (event.persisted)
+      gPluginHandler.reshowClickToPlayNotification();
   }
 }
 
 function UpdateBackForwardCommands(aWebNavigation) {
   var backBroadcaster = document.getElementById("Browser:Back");
   var forwardBroadcaster = document.getElementById("Browser:Forward");
 
   // Avoid setting attributes on broadcasters if the value hasn't changed!
@@ -1423,16 +1429,17 @@ function HandleAppCommandEvent(evt) {
 function prepareForStartup() {
   gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
 
   gBrowser.addEventListener("PluginNotFound",     gPluginHandler, true);
   gBrowser.addEventListener("PluginCrashed",      gPluginHandler, true);
   gBrowser.addEventListener("PluginBlocklisted",  gPluginHandler, true);
   gBrowser.addEventListener("PluginOutdated",     gPluginHandler, true);
   gBrowser.addEventListener("PluginDisabled",     gPluginHandler, true);
+  gBrowser.addEventListener("PluginClickToPlay",  gPluginHandler, true);
   gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
 #ifdef XP_MACOSX
   gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true);
 #endif
 
   Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false);
 
   window.addEventListener("AppCommand", HandleAppCommandEvent, true);
@@ -5183,18 +5190,23 @@ var TabsProgressListener = {
       // We also want to make changes to page UI for unprivileged about pages.
       BrowserOnAboutPageLoad(aWebProgress.DOMWindow.document);
     }
   },
 
   onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI,
                               aFlags) {
     // Filter out any sub-frame loads
-    if (aBrowser.contentWindow == aWebProgress.DOMWindow)
+    if (aBrowser.contentWindow == aWebProgress.DOMWindow) {
+      // initialize the click-to-play state
+      aBrowser._clickToPlayDoorhangerShown = false;
+      aBrowser._clickToPlayPluginsActivated = false;
+
       FullZoom.onLocationChange(aLocationURI, false, aBrowser);
+    }
   },
 
   onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) {
     if (gPrefService.getBoolPref("accessibility.blockautorefresh")) {
       let brandBundle = document.getElementById("bundle_brand");
       let brandShortName = brandBundle.getString("brandShortName");
       let refreshButtonText =
         gNavigatorBundle.getString("refreshBlocked.goButton");
@@ -7138,30 +7150,50 @@ var gPluginHandler = {
       case "PluginBlocklisted":
       case "PluginOutdated":
 #ifdef XP_MACOSX
       case "npapi-carbon-event-model-failure":
 #endif
         self.pluginUnavailable(plugin, event.type);
         break;
 
+      case "PluginClickToPlay":
+        self._handleClickToPlayEvent(plugin);
+        break;
+
       case "PluginDisabled":
         let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink");
         self.addLinkClickCallback(manageLink, "managePlugins");
         break;
     }
 
     // Hide the in-content UI if it's too big. The crashed plugin handler already did this.
-    if (event.type != "PluginCrashed") {
+    if (event.type != "PluginCrashed" && event.type != "PluginClickToPlay") {
       let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
       if (self.isTooSmall(plugin, overlay))
           overlay.style.visibility = "hidden";
     }
   },
 
+  activatePlugins: function PH_activatePlugins(aContentWindow) {
+    let browser = gBrowser.getBrowserForDocument(aContentWindow.document);
+    browser._clickToPlayPluginsActivated = true;
+    let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                            .getInterface(Ci.nsIDOMWindowUtils);
+    let plugins = cwu.plugins;
+    for (let plugin of plugins) {
+      let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+      if (!objLoadingContent.activated)
+        objLoadingContent.playPlugin();
+    }
+    let notification = PopupNotifications.getNotification("click-to-play-plugins", browser);
+    if (notification)
+      notification.remove();
+  },
+
   newPluginInstalled : function(event) {
     // browser elements are anonymous so we can't just use target.
     var browser = event.originalTarget;
     // clear the plugin list, now that at least one plugin has been installed
     browser.missingPlugins = null;
 
     var notificationBox = gBrowser.getNotificationBox(browser);
     var notification = notificationBox.getNotificationWithValue("missing-plugins");
@@ -7205,16 +7237,63 @@ var gPluginHandler = {
     browser.reload();
   },
 
   // Callback for user clicking the help icon
   openHelpPage: function () {
     openHelpLink("plugin-crashed", false);
   },
 
+  // Event listener for click-to-play plugins.
+  _handleClickToPlayEvent: function PH_handleClickToPlayEvent(aPlugin) {
+    let doc = aPlugin.ownerDocument;
+    let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
+    if (browser._clickToPlayPluginsActivated) {
+      let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
+      objLoadingContent.playPlugin();
+      return;
+    }
+
+    let overlay = doc.getAnonymousElementByAttribute(aPlugin, "class", "mainBox");
+    overlay.addEventListener("click", function(aEvent) {
+      if (aEvent.button == 0 && aEvent.isTrusted)
+        gPluginHandler.activatePlugins(aEvent.target.ownerDocument.defaultView.top);
+    }, true);
+
+    if (!browser._clickToPlayDoorhangerShown)
+      gPluginHandler._showClickToPlayNotification(browser);
+  },
+
+  reshowClickToPlayNotification: function PH_reshowClickToPlayNotification() {
+    if (!Services.prefs.getBoolPref("plugins.click_to_play"))
+      return;
+
+    let browser = gBrowser.selectedBrowser;
+    let contentWindow = browser.contentWindow;
+    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                           .getInterface(Ci.nsIDOMWindowUtils);
+    if (cwu.plugins.length)
+      gPluginHandler._showClickToPlayNotification(browser);
+  },
+
+  _showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser) {
+    aBrowser._clickToPlayDoorhangerShown = true;
+    let contentWindow = aBrowser.contentWindow;
+    let messageString = gNavigatorBundle.getString("activatePluginsMessage.message");
+    let action = {
+      label: gNavigatorBundle.getString("activatePluginsMessage.label"),
+      accessKey: gNavigatorBundle.getString("activatePluginsMessage.accesskey"),
+      callback: function() { gPluginHandler.activatePlugins(contentWindow); }
+    };
+    let options = { dismissed: true };
+    PopupNotifications.show(aBrowser, "click-to-play-plugins",
+                            messageString, "addons-notification-icon",
+                            action, null, options);
+  },
+
   // event listener for missing/blocklisted/outdated/carbonFailure plugins.
   pluginUnavailable: function (plugin, eventType) {
     let browser = gBrowser.getBrowserForDocument(plugin.ownerDocument
                                                        .defaultView.top.document);
     if (!browser.missingPlugins)
       browser.missingPlugins = {};
 
     var pluginInfo = getPluginInfo(plugin);
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -242,16 +242,18 @@ endif
                  moz.png \
                  video.ogg \
                  test_bug435035.html \
                  test_bug462673.html \
                  page_style_sample.html \
                  feed_tab.html \
                  plugin_unknown.html \
                  plugin_test.html \
+                 plugin_test2.html \
+                 plugin_test3.html \
                  plugin_both.html \
                  plugin_both2.html \
                  alltabslistener.html \
                  zoom_test.html \
                  dummy_page.html \
                  browser_tabMatchesInAwesomebar.js \
                  file_bug550565_popup.html \
                  file_bug550565_favicon.ico \
--- a/browser/base/content/test/browser_pluginnotification.js
+++ b/browser/base/content/test/browser_pluginnotification.js
@@ -1,25 +1,30 @@
 var rootDir = getRootDirectory(gTestPath);
 const gTestRoot = rootDir;
 
 var gTestBrowser = null;
 var gNextTest = null;
+var gClickToPlayPluginActualEvents = 0;
+var gClickToPlayPluginExpectedEvents = 6;
 
 function get_test_plugin() {
   var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
   var tags = ph.getPluginTags();
 
   // Find the test plugin
   for (var i = 0; i < tags.length; i++) {
     if (tags[i].name == "Test Plug-in")
       return tags[i];
   }
+  ok(false, "Unable to find plugin");
 }
 
+Components.utils.import("resource://gre/modules/Services.jsm");
+
 // This listens for the next opened tab and checks it is of the right url.
 // opencallback is called when the new tab is fully loaded
 // closecallback is called when the tab is closed
 function TabOpenListener(url, opencallback, closecallback) {
   this.url = url;
   this.opencallback = opencallback;
   this.closecallback = closecallback;
 
@@ -58,31 +63,39 @@ TabOpenListener.prototype = {
       executeSoon(this.closecallback);
       this.closecallback = null;
     }
   }
 };
 
 function test() {
   waitForExplicitFinish();
+  registerCleanupFunction(function() { Services.prefs.clearUserPref("plugins.click_to_play"); });
+  Services.prefs.setBoolPref("plugins.click_to_play", false);
 
   var newTab = gBrowser.addTab();
   gBrowser.selectedTab = newTab;
   gTestBrowser = gBrowser.selectedBrowser;
   gTestBrowser.addEventListener("load", pageLoad, true);
+  gTestBrowser.addEventListener("PluginClickToPlay", handlePluginClickToPlay, true);
   prepareTest(test1, gTestRoot + "plugin_unknown.html");
 }
 
 function finishTest() {
   gTestBrowser.removeEventListener("load", pageLoad, true);
+  gTestBrowser.removeEventListener("PluginClickToPlay", handlePluginClickToPlay, true);
   gBrowser.removeCurrentTab();
   window.focus();
   finish();
 }
 
+function handlePluginClickToPlay() {
+  gClickToPlayPluginActualEvents++;
+}
+
 function pageLoad() {
   // The plugin events are async dispatched and can come after the load event
   // This just allows the events to fire before we then go on to test the states
   executeSoon(gNextTest);
 }
 
 function prepareTest(nextTest, url) {
   gNextTest = nextTest;
@@ -179,10 +192,128 @@ function test7() {
   ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 7, Should not have displayed the blocked plugin notification");
   ok(gTestBrowser.missingPlugins, "Test 7, Should be a missing plugin list");
   ok("application/x-unknown" in gTestBrowser.missingPlugins, "Test 7, Should know about application/x-unknown");
   ok("application/x-test" in gTestBrowser.missingPlugins, "Test 7, Should know about application/x-test");
 
   var plugin = get_test_plugin();
   plugin.disabled = false;
   plugin.blocklisted = false;
-  finishTest();
+  Services.prefs.setBoolPref("plugins.click_to_play", true);
+
+  prepareTest(test8, gTestRoot + "plugin_test.html");
+}
+
+// Tests a page with a working plugin that is click-to-play
+function test8() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 8, Should not have displayed the missing plugin notification");
+  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 8, Should not have displayed the blocked plugin notification");
+  ok(!gTestBrowser.missingPlugins, "Test 8, Should not be a missing plugin list");
+  ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 8, Should have a click-to-play notification");
+
+  prepareTest(test9a, gTestRoot + "plugin_test2.html");
+}
+
+// Tests that activating one click-to-play plugin will activate the other plugins (part 1/1)
+function test9a() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 9a, Should not have displayed the missing plugin notification");
+  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 9a, Should not have displayed the blocked plugin notification");
+  ok(!gTestBrowser.missingPlugins, "Test 9a, Should not be a missing plugin list");
+  ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 9a, Should have a click-to-play notification");
+  var plugin1 = gTestBrowser.contentDocument.getElementById("test");
+  var doc = gTestBrowser.contentDocument;
+  var plugins = [];
+  plugins.push(doc.getElementById("test"));
+  plugins.push(doc.getElementById("test1"));
+  plugins.push(doc.getElementById("test2"));
+  plugins.forEach(function(plugin) {
+    var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
+    ok(rect.width == 200, "Test 9a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
+    ok(rect.height == 200, "Test 9a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
+    var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    ok(!objLoadingContent.activated, "Test 9a, Plugin with id=" + plugin.id + " should not be activated");
+  });
+
+  EventUtils.synthesizeMouse(plugin1, 100, 100, { });
+  setTimeout(test9b, 0);
 }
+
+// Tests that activating one click-to-play plugin will activate the other plugins (part 2/2)
+function test9b() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 9b, Should not have displayed the missing plugin notification");
+  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 9b, Should not have displayed the blocked plugin notification");
+  ok(!gTestBrowser.missingPlugins, "Test 9b, Should not be a missing plugin list");
+  ok(!PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 9b, Click to play notification should be removed now");
+  var doc = gTestBrowser.contentDocument;
+  var plugins = [];
+  plugins.push(doc.getElementById("test"));
+  plugins.push(doc.getElementById("test1"));
+  plugins.push(doc.getElementById("test2"));
+  plugins.forEach(function(plugin) {
+    var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
+    ok(pluginRect.width == 0, "Test 9b, Plugin with id=" + plugin.id + " should have click-to-play overlay with zero width");
+    ok(pluginRect.height == 0, "Test 9b, Plugin with id=" + plugin.id + " should have click-to-play overlay with zero height");
+    var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    ok(objLoadingContent.activated, "Test 9b, Plugin with id=" + plugin.id + " should be activated");
+  });
+
+  prepareTest(test10a, gTestRoot + "plugin_test3.html");
+}
+
+// Tests that activating a hidden click-to-play plugin through the notification works (part 1/2)
+function test10a() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 10a, Should not have displayed the missing plugin notification");
+  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 10a, Should not have displayed the blocked plugin notification");
+  ok(!gTestBrowser.missingPlugins, "Test 10a, Should not be a missing plugin list");
+  var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(popupNotification, "Test 10a, Should have a click-to-play notification");
+  var plugin = gTestBrowser.contentDocument.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(!objLoadingContent.activated, "Test 10c, Plugin should not be activated");
+
+  popupNotification.mainAction.callback();
+  setTimeout(test10b, 0);
+}
+
+// Tests that activating a hidden click-to-play plugin through the notification works (part 2/2)
+function test10b() {
+  var plugin = gTestBrowser.contentDocument.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(objLoadingContent.activated, "Test 10c, Plugin should be activated");
+
+  prepareTest(test11a, gTestRoot + "plugin_test3.html");
+}
+
+// Tests that the going back will reshow the notification for click-to-play plugins (part 1/3)
+function test11a() {
+  var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(popupNotification, "Test 11a, Should have a click-to-play notification");
+
+  prepareTest(test11b, "about:blank");
+}
+
+// Tests that the going back will reshow the notification for click-to-play plugins (part 2/3)
+function test11b() {
+  var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(!popupNotification, "Test 11b, Should not have a click-to-play notification");
+
+  gTestBrowser.addEventListener("pageshow", test11c, false);
+  gTestBrowser.contentWindow.history.back();
+}
+
+// Tests that the going back will reshow the notification for click-to-play plugins (part 3/3)
+function test11c() {
+  gTestBrowser.removeEventListener("pageshow", test11c, false);
+  // Make sure that the event handlers for pageshow can execute before checking for their effects.
+  executeSoon(function() {
+    todo(false, "The following test that checks for the notification fails intermittently, bug 742619.");
+    //var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+    //ok(popupNotification, "Test 11c, Should have a click-to-play notification");
+    is(gClickToPlayPluginActualEvents, gClickToPlayPluginExpectedEvents,
+       "There should be a PluginClickToPlay event for each plugin that was " +
+       "blocked due to the plugins.click_to_play pref");
+    finishTest();
+  });
+}
--- a/browser/base/content/test/plugin_both.html
+++ b/browser/base/content/test/plugin_both.html
@@ -1,6 +1,10 @@
+<!DOCTYPE html>
 <html>
+<head>
+<meta charset="utf-8">
+</head>
 <body>
 <embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown">
 <embed id="test" style="width: 100px; height: 100px" type="application/x-test">
 </body>
 </html>
--- a/browser/base/content/test/plugin_both2.html
+++ b/browser/base/content/test/plugin_both2.html
@@ -1,6 +1,10 @@
+<!DOCTYPE html>
 <html>
+<head>
+<meta charset="utf-8">
+</head>
 <body>
 <embed id="test" style="width: 100px; height: 100px" type="application/x-test">
 <embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown">
 </body>
 </html>
--- a/browser/base/content/test/plugin_test.html
+++ b/browser/base/content/test/plugin_test.html
@@ -1,5 +1,9 @@
+<!DOCTYPE html>
 <html>
+<head>
+<meta charset="utf-8">
+</head>
 <body>
 <embed id="test" style="width: 200px; height: 200px" type="application/x-test">
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/plugin_test2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<embed id="test" style="width: 200px; height: 200px" type="application/x-test">
+<embed id="test1" style="width: 200px; height: 200px" type="application/x-test">
+<embed id="test2" style="width: 200px; height: 200px" type="application/x-test">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/plugin_test3.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<embed id="test" style="width: 0px; height: 0px" type="application/x-test">
+</body>
+</html>
--- a/browser/base/content/test/plugin_unknown.html
+++ b/browser/base/content/test/plugin_unknown.html
@@ -1,5 +1,9 @@
+<!DOCTYPE html>
 <html>
+<head>
+<meta charset="utf-8">
+</head>
 <body>
 <embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown">
 </body>
 </html>
--- a/browser/components/build/nsBrowserCompsCID.h
+++ b/browser/components/build/nsBrowserCompsCID.h
@@ -36,16 +36,22 @@
 
 /////////////////////////////////////////////////////////////////////////////
 
 #define NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "@mozilla.org/profile/migrator;1?app=browser&type="
 
 #ifdef XP_WIN
 #define NS_WINIEPROFILEMIGRATOR_CID \
 { 0xbc15c73d, 0xc05b, 0x497b, { 0xa3, 0x73, 0x4b, 0xae, 0x6c, 0x17, 0x86, 0x31 } }
+
+#define NS_WINIEHISTORYENUMERATOR_CID \
+{ 0x93480624, 0x806e, 0x4756, { 0xb7, 0xcb, 0x0f, 0xb7, 0xdd, 0x74, 0x6a, 0x8f } }
+
+#define NS_IEHISTORYENUMERATOR_CONTRACTID \
+  "@mozilla.org/profile/migrator/iehistoryenumerator;1"
 #endif
 
 #ifdef XP_MACOSX
 #define NS_SAFARIPROFILEMIGRATOR_CID \
 { 0x29e3b139, 0xad19, 0x44f3, { 0xb2, 0xc2, 0xe9, 0xf1, 0x3b, 0xa2, 0xbb, 0xc6 } }
 #endif
 
 #define NS_SHELLSERVICE_CID \
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -46,16 +46,17 @@
 #elif defined(XP_MACOSX)
 #include "nsMacShellService.h"
 #elif defined(MOZ_WIDGET_GTK2)
 #include "nsGNOMEShellService.h"
 #endif
 
 #if defined(XP_WIN) && !defined(__MINGW32__)
 #include "nsIEProfileMigrator.h"
+#include "nsIEHistoryEnumerator.h"
 #elif defined(XP_MACOSX)
 #include "nsSafariProfileMigrator.h"
 #endif
 
 #include "rdf.h"
 #include "nsFeedSniffer.h"
 #include "AboutRedirector.h"
 #include "nsIAboutModule.h"
@@ -73,16 +74,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindows
 #elif defined(XP_MACOSX)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService)
 #elif defined(MOZ_WIDGET_GTK2)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
 #endif
 
 #if defined(XP_WIN) && !defined(__MINGW32__)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEProfileMigrator)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator)
 #elif defined(XP_MACOSX)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSafariProfileMigrator)
 #endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrivateBrowsingServiceWrapper, Init)
 
@@ -91,16 +93,17 @@ NS_DEFINE_NAMED_CID(NS_BROWSERDIRECTORYP
 NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
 #elif defined(MOZ_WIDGET_GTK2)
 NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_FEEDSNIFFER_CID);
 NS_DEFINE_NAMED_CID(NS_BROWSER_ABOUT_REDIRECTOR_CID);
 #if defined(XP_WIN) && !defined(__MINGW32__)
 NS_DEFINE_NAMED_CID(NS_WINIEPROFILEMIGRATOR_CID);
+NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUMERATOR_CID);
 #elif defined(XP_MACOSX)
 NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_SAFARIPROFILEMIGRATOR_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID);
 
 static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
     { &kNS_BROWSERDIRECTORYPROVIDER_CID, false, NULL, DirectoryProviderConstructor },
@@ -108,16 +111,17 @@ static const mozilla::Module::CIDEntry k
     { &kNS_SHELLSERVICE_CID, false, NULL, nsWindowsShellServiceConstructor },
 #elif defined(MOZ_WIDGET_GTK2)
     { &kNS_SHELLSERVICE_CID, false, NULL, nsGNOMEShellServiceConstructor },
 #endif
     { &kNS_FEEDSNIFFER_CID, false, NULL, nsFeedSnifferConstructor },
     { &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, NULL, AboutRedirector::Create },
 #if defined(XP_WIN) && !defined(__MINGW32__)
     { &kNS_WINIEPROFILEMIGRATOR_CID, false, NULL, nsIEProfileMigratorConstructor },
+    { &kNS_WINIEHISTORYENUMERATOR_CID, false, NULL, nsIEHistoryEnumeratorConstructor },
 #elif defined(XP_MACOSX)
     { &kNS_SHELLSERVICE_CID, false, NULL, nsMacShellServiceConstructor },
     { &kNS_SAFARIPROFILEMIGRATOR_CID, false, NULL, nsSafariProfileMigratorConstructor },
 #endif
     { &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID, false, NULL, nsPrivateBrowsingServiceWrapperConstructor },
     { NULL }
 };
 
@@ -142,16 +146,17 @@ static const mozilla::Module::ContractID
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-tabs", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-progress", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #endif
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "home", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #if defined(XP_WIN) && !defined(__MINGW32__)
     { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "ie", &kNS_WINIEPROFILEMIGRATOR_CID },
+    { NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
 #elif defined(XP_MACOSX)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
     { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "safari", &kNS_SAFARIPROFILEMIGRATOR_CID },
 #endif
     { NS_PRIVATE_BROWSING_SERVICE_CONTRACTID, &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID },
     { NULL }
 };
 
--- a/browser/components/migration/src/Makefile.in
+++ b/browser/components/migration/src/Makefile.in
@@ -43,20 +43,20 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= migration
 LIBRARY_NAME	= migration_s
 FORCE_STATIC_LIB = 1
 ifndef MOZ_MEMORY
 USE_STATIC_LIBS = 1
 endif
 
-
 ifeq ($(OS_ARCH)_$(GNU_CXX),WINNT_)
 CPPSRCS += nsIEProfileMigrator.cpp \
            nsBrowserProfileMigratorUtils.cpp \
+           nsIEHistoryEnumerator.cpp \
            $(NULL)
 endif
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += nsSafariProfileMigrator.cpp \
            nsBrowserProfileMigratorUtils.cpp \
            $(NULL)
 endif
--- a/browser/components/migration/src/MigrationUtils.jsm
+++ b/browser/components/migration/src/MigrationUtils.jsm
@@ -134,19 +134,25 @@ let MigratorPrototype = {
   /**
    * DO NOT OVERRIDE - After deCOMing migration, the UI will just call
    * migrate for each resource.
    *
    * @see nsIBrowserProfileMigrator
    */
   migrate: function MP_migrate(aItems, aStartup, aProfile) {
     // Not using aStartup because it's going away soon.
-    if (MigrationUtils.isStartupMigration && !this.startupOnlyMigrator)
+    if (MigrationUtils.isStartupMigration && !this.startupOnlyMigrator) {
       MigrationUtils.profileStartup.doStartup();
 
+      // Notify glue we are about to do initial migration, otherwise it may try
+      // to restore default bookmarks overwriting the imported ones.
+      Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIObserver)
+        .observe(null, "initial-migration", null);
+    }
+
     let resources = this._getMaybeCachedResources(aProfile);
     if (resources.length == 0)
       throw new Error("migrate called for a non-existent source");
 
     if (aItems != Ci.nsIBrowserProfileMigrator.ALL)
       resources = [r for each (r in resources) if (aItems & r.type)];
 
     // TODO: use Map (for the items) and Set (for the resources)
new file mode 100644
--- /dev/null
+++ b/browser/components/migration/src/nsIEHistoryEnumerator.cpp
@@ -0,0 +1,139 @@
+/* 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 "nsIEHistoryEnumerator.h"
+
+#include <urlhist.h>
+#include <shlguid.h>
+
+#include "nsStringAPI.h"
+#include "nsNetUtil.h"
+#include "nsIVariant.h"
+#include "nsCOMArray.h"
+#include "nsArrayEnumerator.h"
+
+namespace {
+
+  PRTime FileTimeToPRTime(FILETIME* filetime)
+  {
+    SYSTEMTIME st;
+    ::FileTimeToSystemTime(filetime, &st);
+    PRExplodedTime prt;
+    prt.tm_year = st.wYear;
+    // SYSTEMTIME's day-of-month parameter is 1-based,
+    // PRExplodedTime's is 0-based.
+    prt.tm_month = st.wMonth - 1;
+    prt.tm_mday = st.wDay;
+    prt.tm_hour = st.wHour;
+    prt.tm_min = st.wMinute;
+    prt.tm_sec = st.wSecond;
+    prt.tm_usec = st.wMilliseconds * 1000;
+    prt.tm_wday = 0;
+    prt.tm_yday = 0;
+    prt.tm_params.tp_gmt_offset = 0;
+    prt.tm_params.tp_dst_offset = 0;
+    return PR_ImplodeTime(&prt);
+  }
+
+} // Anonymous namespace.
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsIEHistoryEnumerator
+
+NS_IMPL_ISUPPORTS1(nsIEHistoryEnumerator, nsISimpleEnumerator)
+
+nsIEHistoryEnumerator::nsIEHistoryEnumerator()
+{
+  ::CoInitialize(NULL);  
+}
+
+nsIEHistoryEnumerator::~nsIEHistoryEnumerator()
+{
+  ::CoUninitialize();
+}
+
+void
+nsIEHistoryEnumerator::EnsureInitialized()
+{
+  if (mURLEnumerator)
+    return;
+
+  HRESULT hr = ::CoCreateInstance(CLSID_CUrlHistory,
+                                  NULL,
+                                  CLSCTX_INPROC_SERVER,
+                                  IID_IUrlHistoryStg2,
+                                  getter_AddRefs(mIEHistory));
+  if (FAILED(hr))
+    return;
+
+  hr = mIEHistory->EnumUrls(getter_AddRefs(mURLEnumerator));
+  if (FAILED(hr))
+    return;
+}
+
+NS_IMETHODIMP
+nsIEHistoryEnumerator::HasMoreElements(bool* _retval NS_OUTPARAM)
+{
+  *_retval = false;
+
+  EnsureInitialized();
+  MOZ_ASSERT(mURLEnumerator, "Should have instanced an IE History URLEnumerator");
+  if (!mURLEnumerator)
+    return NS_OK;
+
+  STATURL statURL;
+  ULONG fetched;
+
+  // First argument is not implemented, so doesn't matter what we pass.
+  HRESULT hr = mURLEnumerator->Next(1, &statURL, &fetched);
+  if (FAILED(hr) || fetched != 1UL) {
+    // Reached the last entry.
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  if (statURL.pwcsUrl) {
+    nsDependentString url(statURL.pwcsUrl);
+    nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
+    ::CoTaskMemFree(statURL.pwcsUrl);
+    if (NS_FAILED(rv)) {
+      // Got a corrupt or invalid URI, continue to the next entry.
+      return HasMoreElements(_retval);
+    }
+  }
+
+  nsDependentString title(statURL.pwcsTitle);
+
+  PRTime lastVisited = FileTimeToPRTime(&(statURL.ftLastVisited));
+
+  mCachedNextEntry = do_CreateInstance("@mozilla.org/hash-property-bag;1");
+  MOZ_ASSERT(mCachedNextEntry, "Should have instanced a new property bag");
+  if (mCachedNextEntry) {
+    mCachedNextEntry->SetPropertyAsInterface(NS_LITERAL_STRING("uri"), uri);
+    mCachedNextEntry->SetPropertyAsAString(NS_LITERAL_STRING("title"), title);
+    mCachedNextEntry->SetPropertyAsInt64(NS_LITERAL_STRING("time"), lastVisited);
+
+    *_retval = true;
+  }
+
+  if (statURL.pwcsTitle)
+    ::CoTaskMemFree(statURL.pwcsTitle);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsIEHistoryEnumerator::GetNext(nsISupports** _retval NS_OUTPARAM)
+{
+  *_retval = nsnull;
+
+  if (!mCachedNextEntry)
+    return NS_ERROR_FAILURE;
+
+  NS_ADDREF(*_retval = mCachedNextEntry);
+  // Release the cached entry, so it can't be returned twice.
+  mCachedNextEntry = nsnull;
+
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/migration/src/nsIEHistoryEnumerator.h
@@ -0,0 +1,36 @@
+/* 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 iehistoryenumerator___h___
+#define iehistoryenumerator___h___
+
+#include <urlhist.h>
+
+#include "nsISimpleEnumerator.h"
+#include "nsIWritablePropertyBag2.h"
+#include "nsAutoPtr.h"
+
+class nsIEHistoryEnumerator : public nsISimpleEnumerator
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISIMPLEENUMERATOR
+
+  nsIEHistoryEnumerator();
+
+private:
+  ~nsIEHistoryEnumerator();
+
+  /**
+   * Initializes the history reader, if needed.
+   */
+  void EnsureInitialized();
+
+  nsRefPtr<IUrlHistoryStg2> mIEHistory;
+  nsRefPtr<IEnumSTATURL> mURLEnumerator;
+
+  nsRefPtr<nsIWritablePropertyBag2> mCachedNextEntry;
+};
+
+#endif
--- a/browser/components/places/tests/unit/test_browserGlue_prefs.js
+++ b/browser/components/places/tests/unit/test_browserGlue_prefs.js
@@ -69,29 +69,29 @@ let gTests = [
     // Sanity check: we should not have any bookmark on the toolbar.
     let itemId =
       PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
     do_check_eq(itemId, -1);
 
     // Set preferences.
     Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true);
 
-    // Force nsBrowserGlue::_initPlaces().
-    print("Simulate Places init");
     waitForImportAndSmartBookmarks(function () {
       // Check bookmarks.html has been imported, and a smart bookmark has been
       // created.
       itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId,
                                                     SMART_BOOKMARKS_ON_TOOLBAR);
       do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), "example");
       // Check preferences have been reverted.
       do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML));
 
       run_next_test();
     });
+    // Force nsBrowserGlue::_initPlaces().
+    do_log_info("Simulate Places init");
     bg.QueryInterface(Ci.nsIObserver).observe(null,
                                               TOPIC_BROWSERGLUE_TEST,
                                               TOPICDATA_FORCE_PLACES_INIT);
   },
 
   function test_import_noSmartBookmarks()
   {
     do_log_info("import from bookmarks.html, but don't create smart bookmarks \
@@ -102,29 +102,29 @@ let gTests = [
     let itemId =
       PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
     do_check_eq(itemId, -1);
 
     // Set preferences.
     Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, -1);
     Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true);
 
-    // Force nsBrowserGlue::_initPlaces().
-    print("Simulate Places init");
     waitForImportAndSmartBookmarks(function () {
       // Check bookmarks.html has been imported, but smart bookmarks have not
       // been created.
       itemId =
         PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
       do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), "example");
       // Check preferences have been reverted.
       do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML));
 
       run_next_test();
     });
+    // Force nsBrowserGlue::_initPlaces().
+    do_log_info("Simulate Places init");
     bg.QueryInterface(Ci.nsIObserver).observe(null,
                                               TOPIC_BROWSERGLUE_TEST,
                                               TOPICDATA_FORCE_PLACES_INIT);
   },
 
   function test_import_autoExport_updatedSmartBookmarks()
   {
     do_log_info("Import from bookmarks.html, but don't create smart bookmarks \
@@ -136,30 +136,30 @@ let gTests = [
       PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
     do_check_eq(itemId, -1);
 
     // Set preferences.
     Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 999);
     Services.prefs.setBoolPref(PREF_AUTO_EXPORT_HTML, true);
     Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true);
 
-    // Force nsBrowserGlue::_initPlaces()
-    print("Simulate Places init");
     waitForImportAndSmartBookmarks(function () {
       // Check bookmarks.html has been imported, but smart bookmarks have not
       // been created.
       itemId =
         PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
       do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), "example");
       do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML));
       // Check preferences have been reverted.
       Services.prefs.setBoolPref(PREF_AUTO_EXPORT_HTML, false);
 
       run_next_test();
     });
+    // Force nsBrowserGlue::_initPlaces()
+    do_log_info("Simulate Places init");
     bg.QueryInterface(Ci.nsIObserver).observe(null,
                                               TOPIC_BROWSERGLUE_TEST,
                                               TOPICDATA_FORCE_PLACES_INIT);
   },
 
   function test_import_autoExport_oldSmartBookmarks()
   {
     do_log_info("Import from bookmarks.html, and create smart bookmarks if \
@@ -171,31 +171,31 @@ let gTests = [
       PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
     do_check_eq(itemId, -1);
 
     // Set preferences.
     Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 0);
     Services.prefs.setBoolPref(PREF_AUTO_EXPORT_HTML, true);
     Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true);
 
-    // Force nsBrowserGlue::_initPlaces()
-    print("Simulate Places init");
     waitForImportAndSmartBookmarks(function () {
       // Check bookmarks.html has been imported, but smart bookmarks have not
       // been created.
       itemId =
         PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId,
                                              SMART_BOOKMARKS_ON_TOOLBAR);
       do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), "example");
       do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML));
       // Check preferences have been reverted.
       Services.prefs.setBoolPref(PREF_AUTO_EXPORT_HTML, false);
 
       run_next_test();
     });
+    // Force nsBrowserGlue::_initPlaces()
+    do_log_info("Simulate Places init");
     bg.QueryInterface(Ci.nsIObserver).observe(null,
                                               TOPIC_BROWSERGLUE_TEST,
                                               TOPICDATA_FORCE_PLACES_INIT);
   },
 
   function test_restore()
   {
     do_log_info("restore from default bookmarks.html if \
@@ -205,29 +205,29 @@ let gTests = [
     // Sanity check: we should not have any bookmark on the toolbar.
     let itemId =
       PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
     do_check_eq(itemId, -1);
 
     // Set preferences.
     Services.prefs.setBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS, true);
 
-    // Force nsBrowserGlue::_initPlaces()
-    print("Simulate Places init");
     waitForImportAndSmartBookmarks(function () {
       // Check bookmarks.html has been restored.
       itemId =
         PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId,
                                              SMART_BOOKMARKS_ON_TOOLBAR);
       do_check_true(itemId > 0);
       // Check preferences have been reverted.
       do_check_false(Services.prefs.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS));
 
       run_next_test();
     });
+    // Force nsBrowserGlue::_initPlaces()
+    do_log_info("Simulate Places init");
     bg.QueryInterface(Ci.nsIObserver).observe(null,
                                               TOPIC_BROWSERGLUE_TEST,
                                               TOPICDATA_FORCE_PLACES_INIT);
 
   },
 
   function test_restore_import()
   {
@@ -239,30 +239,30 @@ let gTests = [
     let itemId =
       PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
     do_check_eq(itemId, -1);
 
     // Set preferences.
     Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true);
     Services.prefs.setBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS, true);
 
-    // Force nsBrowserGlue::_initPlaces()
-    print("Simulate Places init");
     waitForImportAndSmartBookmarks(function () {
       // Check bookmarks.html has been restored.
       itemId =
         PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId,
                                              SMART_BOOKMARKS_ON_TOOLBAR);
       do_check_true(itemId > 0);
       // Check preferences have been reverted.
       do_check_false(Services.prefs.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS));
       do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML));
 
       run_next_test();
     });
+    // Force nsBrowserGlue::_initPlaces()
+    do_log_info("Simulate Places init");
     bg.QueryInterface(Ci.nsIObserver).observe(null,
                                               TOPIC_BROWSERGLUE_TEST,
                                               TOPICDATA_FORCE_PLACES_INIT);
   }
 
 ];
 
 do_register_cleanup(function () {
--- a/browser/devtools/debugger/DebuggerUI.jsm
+++ b/browser/devtools/debugger/DebuggerUI.jsm
@@ -487,30 +487,31 @@ DebuggerUI.prototype = {
    * local file.
    * XXX: it may be better to use nsITraceableChannel to get to the sources
    * without relying on caching when we can (not for eval, etc.):
    * http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
    */
   _onLoadSource: function DebuggerUI__onLoadSource(aEvent) {
     let gBrowser = this.aWindow.gBrowser;
 
-    let url = aEvent.detail;
+    let url = aEvent.detail.url;
+    let showOptions = aEvent.detail.options;
     let scheme = Services.io.extractScheme(url);
     switch (scheme) {
       case "file":
       case "chrome":
       case "resource":
         try {
           NetUtil.asyncFetch(url, function onFetch(aStream, aStatus) {
             if (!Components.isSuccessCode(aStatus)) {
               return this.logError(url, aStatus);
             }
             let source = NetUtil.readInputStreamToString(aStream, aStream.available());
             aStream.close();
-            this._onSourceLoaded(url, source);
+            this._onSourceLoaded(url, source, showOptions);
           }.bind(this));
         } catch (ex) {
           return this.logError(url, ex.name);
         }
         break;
 
       default:
         let channel = Services.io.newChannel(url, null, null);
@@ -524,17 +525,18 @@ DebuggerUI.prototype = {
           onDataAvailable: function (aRequest, aContext, aStream, aOffset, aCount) {
             chunks.push(NetUtil.readInputStreamToString(aStream, aCount));
           },
           onStopRequest: function (aRequest, aContext, aStatusCode) {
             if (!Components.isSuccessCode(aStatusCode)) {
               return this.logError(url, aStatusCode);
             }
 
-            this._onSourceLoaded(url, chunks.join(""), channel.contentType);
+            this._onSourceLoaded(url, chunks.join(""), channel.contentType,
+                                 showOptions);
           }.bind(this)
         };
 
         channel.loadFlags = channel.LOAD_FROM_CACHE;
         channel.asyncOpen(streamListener, null);
         break;
     }
   },
@@ -550,40 +552,43 @@ DebuggerUI.prototype = {
   logError: function DebuggerUI_logError(aUrl, aStatus) {
     let view = this.getDebugger(gBrowser.selectedTab).DebuggerView;
     Components.utils.reportError(view.getFormatStr("loadingError", [ aUrl, aStatus ]));
   },
 
   /**
    * Called when source has been loaded.
    *
+   * @private
    * @param string aSourceUrl
    *        The URL of the source script.
    * @param string aSourceText
    *        The text of the source script.
    * @param string aContentType
    *        The content type of the source script.
+   * @param object [aOptions]
+   *        Additional options for showing the script (optional). Supported
+   *        options:
+   *        - targetLine: place the editor at the given line number.
    */
   _onSourceLoaded: function DebuggerUI__onSourceLoaded(aSourceUrl,
                                                        aSourceText,
-                                                       aContentType) {
+                                                       aContentType,
+                                                       aOptions) {
     let dbg = this.getDebugger(this.aWindow.gBrowser.selectedTab);
-    dbg.debuggerWindow.SourceScripts.setEditorMode(aSourceUrl, aContentType);
-    dbg.editor.setText(aSourceText);
-    dbg.editor.resetUndo();
     let doc = dbg.frame.contentDocument;
     let scripts = doc.getElementById("scripts");
     let elt = scripts.getElementsByAttribute("value", aSourceUrl)[0];
     let script = elt.getUserData("sourceScript");
     script.loaded = true;
     script.text = aSourceText;
     script.contentType = aContentType;
     elt.setUserData("sourceScript", script, null);
-    dbg._updateEditorBreakpoints();
-    dbg.debuggerWindow.StackFrames.updateEditor();
+
+    dbg.debuggerWindow.SourceScripts._onShowScript(script, aOptions);
   }
 };
 
 /**
  * Various debugger UI preferences (currently just the pane height).
  */
 let DebuggerUIPreferences = {
 
--- a/browser/devtools/debugger/debugger.js
+++ b/browser/devtools/debugger/debugger.js
@@ -267,23 +267,23 @@ var StackFrames = {
     if (aDepth !== null) {
       DebuggerView.Stackframes.highlightFrame(this.selectedFrame, true);
     }
 
     let frame = this.activeThread.cachedFrames[aDepth];
     if (!frame) {
       return;
     }
+
     // Move the editor's caret to the proper line.
     if (DebuggerView.Scripts.isSelected(frame.where.url) && frame.where.line) {
       window.editor.setCaretPosition(frame.where.line - 1);
       window.editor.setDebugLocation(frame.where.line - 1);
     } else if (DebuggerView.Scripts.contains(frame.where.url)) {
       DebuggerView.Scripts.selectScript(frame.where.url);
-      SourceScripts.onChange({ target: DebuggerView.Scripts._scripts });
       window.editor.setCaretPosition(frame.where.line - 1);
     } else {
       window.editor.setDebugLocation(-1);
     }
 
     // Display the local variables.
     let localScope = DebuggerView.Properties.localScope;
     localScope.empty();
@@ -518,18 +518,17 @@ var SourceScripts = {
    * Handler for changes on the selected source script.
    */
   onChange: function SS_onChange(aEvent) {
     let scripts = aEvent.target;
     if (!scripts.selectedItem) {
       return;
     }
     let script = scripts.selectedItem.getUserData("sourceScript");
-    this.setEditorMode(script.url, script.contentType);
-    this._showScript(script);
+    this.showScript(script);
   },
 
   /**
    * Sets the proper editor mode (JS or HTML) according to the specified
    * content type, or by determining the type from the URL.
    *
    * @param string aUrl
    *        The script URL.
@@ -623,38 +622,74 @@ var SourceScripts = {
   /**
    * Add the specified script to the list and display it in the editor if the
    * editor is empty.
    */
   _addScript: function SS_addScript(aScript) {
     DebuggerView.Scripts.addScript(this._getScriptLabel(aScript.url), aScript);
 
     if (window.editor.getCharCount() == 0) {
-      this._showScript(aScript);
+      this.showScript(aScript);
     }
   },
 
   /**
    * Load the editor with the script text if available, otherwise fire an event
    * to load and display the script text.
+   *
+   * @param object aScript
+   *        The script object coming from the active thread.
+   * @param object [aOptions]
+   *        Additional options for showing the script (optional). Supported
+   *        options:
+   *        - targetLine: place the editor at the given line number.
    */
-  _showScript: function SS_showScript(aScript) {
+  showScript: function SS_showScript(aScript, aOptions) {
     if (!aScript.loaded) {
       // Notify the chrome code that we need to load a script file.
       var evt = document.createEvent("CustomEvent");
-      evt.initCustomEvent("Debugger:LoadSource", true, false, aScript.url);
+      evt.initCustomEvent("Debugger:LoadSource", true, false,
+                          {url: aScript.url, options: aOptions});
       document.documentElement.dispatchEvent(evt);
+      window.editor.setMode(SourceEditor.MODES.TEXT);
       window.editor.setText(DebuggerView.getStr("loadingText"));
+      window.editor.resetUndo();
     } else {
-      window.editor.setText(aScript.text);
-      window.updateEditorBreakpoints();
-      StackFrames.updateEditor();
+      this._onShowScript(aScript, aOptions);
+    }
+  },
+
+  /**
+   * Display the script source once it loads.
+   *
+   * @private
+   * @param object aScript
+   *        The script object coming from the active thread.
+   * @param object [aOptions]
+   *        Additional options for showing the script (optional). Supported
+   *        options:
+   *        - targetLine: place the editor at the given line number.
+   */
+  _onShowScript: function SS__onShowScript(aScript, aOptions) {
+    aOptions = aOptions || {};
+    this.setEditorMode(aScript.url, aScript.contentType);
+    window.editor.setText(aScript.text);
+    window.updateEditorBreakpoints();
+    StackFrames.updateEditor();
+    if (aOptions.targetLine) {
+      window.editor.setCaretPosition(aOptions.targetLine - 1);
     }
     window.editor.resetUndo();
-  }
+
+    // Notify the chrome code that we shown script file.
+    let evt = document.createEvent("CustomEvent");
+    evt.initCustomEvent("Debugger:ScriptShown", true, false,
+                        {url: aScript.url});
+    document.documentElement.dispatchEvent(evt);
+  },
 };
 
 SourceScripts.onScripts = SourceScripts.onScripts.bind(SourceScripts);
 SourceScripts.onNewScript = SourceScripts.onNewScript.bind(SourceScripts);
 SourceScripts.onScriptsCleared = SourceScripts.onScriptsCleared.bind(SourceScripts);
 SourceScripts.onChange = SourceScripts.onChange.bind(SourceScripts);
 
 window.addEventListener("DOMContentLoaded", initDebugger, false);
--- a/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js
@@ -16,53 +16,70 @@ let gScripts = null;
 let gEditor = null;
 let gBreakpoints = null;
 
 function test()
 {
   let tempScope = {};
   Cu.import("resource:///modules/source-editor.jsm", tempScope);
   let SourceEditor = tempScope.SourceEditor;
+  let scriptShown = false;
+  let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.debuggerWindow;
+    gPane.activeThread.addOneTimeListener("framesadded", function() {
+      framesAdded = true;
+      runTest();
+    });
 
-    gPane.activeThread.addOneTimeListener("framesadded", function() {
-      Services.tm.currentThread.dispatch({ run: onScriptsAdded }, 0);
-    });
     gDebuggee.firstCall();
   });
 
-  function onScriptsAdded()
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    let url = aEvent.detail.url;
+    if (url.indexOf("-02.js") != -1) {
+      scriptShown = true;
+      window.removeEventListener(aEvent.type, _onEvent);
+      runTest();
+    }
+  });
+
+  function runTest()
+  {
+    if (scriptShown && framesAdded) {
+      Services.tm.currentThread.dispatch({ run: onScriptShown }, 0);
+    }
+  }
+
+  function onScriptShown()
   {
     gScripts = gDebugger.DebuggerView.Scripts;
 
     is(gDebugger.StackFrames.activeThread.state, "paused",
       "Should only be getting stack frames while paused.");
 
     is(gScripts._scripts.itemCount, 2, "Found the expected number of scripts.");
 
     gEditor = gDebugger.editor;
 
     isnot(gEditor.getText().indexOf("debugger"), -1,
           "The correct script was loaded initially.");
     isnot(gScripts.selected, gScripts.scriptLocations()[0],
-          "the correct sccript is selected");
+          "the correct script is selected");
 
     gBreakpoints = gPane.breakpoints;
     is(Object.keys(gBreakpoints), 0, "no breakpoints");
     ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
 
     is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
 
-
-    info("add the first breakpoint");
     gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
                              onEditorBreakpointAddFirst);
     let location = {url: gScripts.selected, line: 6};
     executeSoon(function() {
       gPane.addBreakpoint(location, onBreakpointAddFirst);
     });
   }
 
--- a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js
@@ -14,30 +14,49 @@ let gDebugger = null;
 
 function test()
 {
   let tempScope = {};
   Cu.import("resource:///modules/source-editor.jsm", tempScope);
   let SourceEditor = tempScope.SourceEditor;
 
   let contextMenu = null;
+  let scriptShown = false;
+  let framesAdded = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.debuggerWindow;
 
     gPane.activeThread.addOneTimeListener("framesadded", function() {
-      Services.tm.currentThread.dispatch({ run: onScriptsAdded }, 0);
+      framesAdded = true;
+      runTest();
     });
     gDebuggee.firstCall();
   });
 
-  function onScriptsAdded()
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    let url = aEvent.detail.url;
+    if (url.indexOf("-02.js") != -1) {
+      scriptShown = true;
+      window.removeEventListener(aEvent.type, _onEvent);
+      runTest();
+    }
+  });
+
+  function runTest()
+  {
+    if (scriptShown && framesAdded) {
+      Services.tm.currentThread.dispatch({ run: onScriptShown }, 0);
+    }
+  }
+
+  function onScriptShown()
   {
     let scripts = gDebugger.DebuggerView.Scripts._scripts;
 
     is(gDebugger.StackFrames.activeThread.state, "paused",
       "Should only be getting stack frames while paused.");
 
     is(scripts.itemCount, 2, "Found the expected number of scripts.");
 
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
@@ -20,25 +20,37 @@ function test()
     gDebugger = gPane.debuggerWindow;
 
     testFrameParameters();
   });
 }
 
 function testFrameParameters()
 {
+  dump("Started testFrameParameters!\n");
+
   gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
+    dump("Entered Debugger:FetchedParameters!\n");
+
     gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
+      dump("After currentThread.dispatch!\n");
+
       var frames = gDebugger.DebuggerView.Stackframes._frames,
           childNodes = frames.childNodes,
           localScope = gDebugger.DebuggerView.Properties.localScope,
           localNodes = localScope.querySelector(".details").childNodes;
 
+      dump("Got our variables:\n");
+      dump("frames     - " + frames.constructor + "\n");
+      dump("childNodes - " + childNodes.constructor + "\n");
+      dump("localScope - " + localScope.constructor + "\n");
+      dump("localNodes - " + localNodes.constructor + "\n");
+
       is(gDebugger.StackFrames.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 3,
         "Should have three frames.");
 
       is(localNodes.length, 8,
         "The localScope should contain all the created variable elements.");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
@@ -20,24 +20,35 @@ function test()
     gDebugger = gPane.debuggerWindow;
 
     testFrameParameters();
   });
 }
 
 function testFrameParameters()
 {
+  dump("Started testFrameParameters!\n");
+
   gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
+    dump("Entered Debugger:FetchedParameters!\n");
+
     gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
+      dump("After currentThread.dispatch!\n");
+
       var frames = gDebugger.DebuggerView.Stackframes._frames,
           localScope = gDebugger.DebuggerView.Properties.localScope,
           localNodes = localScope.querySelector(".details").childNodes;
 
+      dump("Got our variables:\n");
+      dump("frames     - " + frames.constructor + "\n");
+      dump("localScope - " + localScope.constructor + "\n");
+      dump("localNodes - " + localNodes.constructor + "\n");
+
       is(gDebugger.StackFrames.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 3,
         "Should have three frames.");
 
       is(localNodes.length, 8,
         "The localScope should contain all the created variable elements.");
@@ -82,19 +93,19 @@ function testFrameParameters()
                         .textContent, 5,
           "Should have the right argument length.");
 
         resumeAndFinish();
       }, 100);
     }}, 0);
   }, false);
 
-  EventUtils.synthesizeMouseAtCenter(content.document.querySelector("button"),
-                                     {},
-                                     content.window);
+  EventUtils.sendMouseEvent({ type: "click" },
+    content.document.querySelector("button"),
+    content.window);
 }
 
 function resumeAndFinish() {
   gPane.activeThread.addOneTimeListener("framescleared", function() {
     Services.tm.currentThread.dispatch({ run: function() {
       var frames = gDebugger.DebuggerView.Stackframes._frames;
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 0,
--- a/browser/devtools/debugger/test/browser_dbg_stack-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-05.js
@@ -10,82 +10,101 @@
 const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
 
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
 function test() {
+  let scriptShown = false;
+  let framesAdded = false;
+
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.debuggerWindow;
 
-    testRecurse();
+    gPane.activeThread.addOneTimeListener("framesadded", function() {
+      framesAdded = true;
+      runTest();
+    });
+
+    gDebuggee.firstCall();
   });
+
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    let url = aEvent.detail.url;
+    if (url.indexOf("-02.js") != -1) {
+      scriptShown = true;
+      window.removeEventListener(aEvent.type, _onEvent);
+      runTest();
+    }
+  });
+
+  function runTest()
+  {
+    if (scriptShown && framesAdded) {
+      Services.tm.currentThread.dispatch({ run: testRecurse }, 0);
+    }
+  }
 }
 
-function testRecurse() {
-  gPane.activeThread.addOneTimeListener("framesadded", function() {
-    Services.tm.currentThread.dispatch({ run: function() {
-      let frames = gDebugger.DebuggerView.Stackframes._frames;
-      let childNodes = frames.childNodes;
+function testRecurse()
+{
+  let frames = gDebugger.DebuggerView.Stackframes._frames;
+  let childNodes = frames.childNodes;
 
-      is(frames.querySelectorAll(".dbg-stackframe").length, 4,
-        "Correct number of frames.");
+  is(frames.querySelectorAll(".dbg-stackframe").length, 4,
+    "Correct number of frames.");
 
-      is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
-        "All children should be frames.");
+  is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
+    "All children should be frames.");
 
-      ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
-        "First frame should be selected by default.");
+  ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
+    "First frame should be selected by default.");
 
-      ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
-        "Third frame should not be selected.");
+  ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
+    "Third frame should not be selected.");
 
-      is(gDebugger.editor.getDebugLocation(), 5,
-         "editor debugger location is correct.");
+  is(gDebugger.editor.getDebugLocation(), 5,
+     "editor debugger location is correct.");
 
-      EventUtils.sendMouseEvent({ type: "click" },
-        frames.querySelector("#stackframe-2"),
-        gDebugger);
-
-      ok(!frames.querySelector("#stackframe-0").classList.contains("selected"),
-         "First frame should not be selected after click.");
+  EventUtils.sendMouseEvent({ type: "click" },
+    frames.querySelector("#stackframe-2"),
+    gDebugger);
 
-      ok(frames.querySelector("#stackframe-2").classList.contains("selected"),
-         "Third frame should be selected after click.");
+  ok(!frames.querySelector("#stackframe-0").classList.contains("selected"),
+     "First frame should not be selected after click.");
 
-      is(gDebugger.editor.getDebugLocation(), 4,
-         "editor debugger location is correct after click.");
+  ok(frames.querySelector("#stackframe-2").classList.contains("selected"),
+     "Third frame should be selected after click.");
 
-      EventUtils.sendMouseEvent({ type: "click" },
-        frames.querySelector("#stackframe-0 .dbg-stackframe-name"),
-        gDebugger);
+  is(gDebugger.editor.getDebugLocation(), 4,
+     "editor debugger location is correct after click.");
 
-      ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
-         "First frame should be selected after click inside the first frame.");
+  EventUtils.sendMouseEvent({ type: "click" },
+    frames.querySelector("#stackframe-0 .dbg-stackframe-name"),
+    gDebugger);
 
-      ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
-         "Third frame should not be selected after click inside the first frame.");
+  ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
+     "First frame should be selected after click inside the first frame.");
 
-      is(gDebugger.editor.getDebugLocation(), 5,
-         "editor debugger location is correct (frame 0 again).");
+  ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
+     "Third frame should not be selected after click inside the first frame.");
 
-      gDebugger.StackFrames.activeThread.resume(function() {
-        is(gDebugger.editor.getDebugLocation(), -1,
-           "editor debugger location is correct after resume.");
-        closeDebuggerAndFinish(gTab);
-      });
-    }}, 0);
+  is(gDebugger.editor.getDebugLocation(), 5,
+     "editor debugger location is correct (frame 0 again).");
+
+  gDebugger.StackFrames.activeThread.resume(function() {
+    is(gDebugger.editor.getDebugLocation(), -1,
+       "editor debugger location is correct after resume.");
+    closeDebuggerAndFinish(gTab);
   });
-
-  gDebuggee.firstCall();
 }
 
 registerCleanupFunction(function() {
   removeTab(gTab);
   gPane = null;
   gTab = null;
   gDebuggee = null;
   gDebugger = null;
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -934,37 +934,16 @@ InspectorUI.prototype = {
 
       // Add event handlers bound to this.
       this.boundRuleViewChanged = this.ruleViewChanged.bind(this);
       this.ruleView.element.addEventListener("CssRuleViewChanged",
                                              this.boundRuleViewChanged);
       this.cssRuleViewBoundCSSLinkClicked = this.ruleViewCSSLinkClicked.bind(this);
       this.ruleView.element.addEventListener("CssRuleViewCSSLinkClicked",
                                              this.cssRuleViewBoundCSSLinkClicked);
-      this.cssRuleViewBoundMouseDown = this.ruleViewMouseDown.bind(this);
-      this.ruleView.element.addEventListener("mousedown",
-                                             this.cssRuleViewBoundMouseDown);
-      this.cssRuleViewBoundMouseUp = this.ruleViewMouseUp.bind(this);
-      this.ruleView.element.addEventListener("mouseup",
-                                             this.cssRuleViewBoundMouseUp);
-      this.cssRuleViewBoundMouseMove = this.ruleViewMouseMove.bind(this);
-      this.cssRuleViewBoundMenuUpdate = this.ruleViewMenuUpdate.bind(this);
-
-      this.cssRuleViewBoundCopy = this.ruleViewCopy.bind(this);
-      iframe.addEventListener("copy", this.cssRuleViewBoundCopy);
-
-      this.cssRuleViewBoundCopyRule = this.ruleViewCopyRule.bind(this);
-      this.cssRuleViewBoundCopyDeclaration =
-        this.ruleViewCopyDeclaration.bind(this);
-      this.cssRuleViewBoundCopyProperty = this.ruleViewCopyProperty.bind(this);
-      this.cssRuleViewBoundCopyPropertyValue =
-        this.ruleViewCopyPropertyValue.bind(this);
-
-      // Add the rule view's context menu.
-      this.ruleViewAddContextMenu();
 
       doc.documentElement.appendChild(this.ruleView.element);
       this.ruleView.highlight(this.selection);
       Services.obs.notifyObservers(null,
         INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, null);
     }.bind(this);
 
     iframe.addEventListener("load", boundLoadListener, true);
@@ -1046,373 +1025,33 @@ InspectorUI.prototype = {
         href = rule.elementStyle.element.ownerDocument.location.href;
       }
       let viewSourceUtils = this.chromeWin.gViewSourceUtils;
       viewSourceUtils.viewSource(href, null, doc, line);
     }
   },
 
   /**
-   * This is the mousedown handler for the rule view. We use it to track whether
-   * text is currently getting selected.
-   * .
-   * @param aEvent The event object
-   */
-  ruleViewMouseDown: function IUI_ruleViewMouseDown(aEvent)
-  {
-    this.ruleView.element.addEventListener("mousemove",
-      this.cssRuleViewBoundMouseMove);
-  },
-
-  /**
-   * This is the mouseup handler for the rule view. We use it to track whether
-   * text is currently getting selected.
-   * .
-   * @param aEvent The event object
-   */
-  ruleViewMouseUp: function IUI_ruleViewMouseUp(aEvent)
-  {
-    this.ruleView.element.removeEventListener("mousemove",
-      this.cssRuleViewBoundMouseMove);
-    this.ruleView._selectionMode = false;
-  },
-
-  /**
-   * This is the mousemove handler for the rule view. We use it to track whether
-   * text is currently getting selected.
-   * .
-   * @param aEvent The event object
-   */
-  ruleViewMouseMove: function IUI_ruleViewMouseMove(aEvent)
-  {
-    this.ruleView._selectionMode = true;
-  },
-
-  /**
-   * Add a context menu to the rule view.
-   */
-  ruleViewAddContextMenu: function IUI_ruleViewAddContextMenu()
-  {
-    let iframe = this.getToolIframe(this.ruleViewObject);
-    let popupSet = this.chromeDoc.getElementById("mainPopupSet");
-    let menu = this.chromeDoc.createElement("menupopup");
-    menu.addEventListener("popupshowing", this.cssRuleViewBoundMenuUpdate);
-    menu.id = "rule-view-context-menu";
-
-    // Copy selection
-    let label = styleInspectorStrings
-      .GetStringFromName("rule.contextmenu.copyselection");
-    let accessKey = styleInspectorStrings
-      .GetStringFromName("rule.contextmenu.copyselection.accesskey");
-    let item = this.chromeDoc.createElement("menuitem");
-    item.id = "rule-view-copy";
-    item.setAttribute("label", label);
-    item.setAttribute("accesskey", accessKey);
-    item.addEventListener("command", this.cssRuleViewBoundCopy);
-    menu.appendChild(item);
-
-    // Copy rule
-    label = styleInspectorStrings.
-      GetStringFromName("rule.contextmenu.copyrule");
-    accessKey = styleInspectorStrings.
-      GetStringFromName("rule.contextmenu.copyrule.accesskey");
-    item = this.chromeDoc.createElement("menuitem");
-    item.id = "rule-view-copy-rule";
-    item.setAttribute("label", label);
-    item.setAttribute("accesskey", accessKey);
-    item.addEventListener("command", this.cssRuleViewBoundCopyRule);
-    menu.appendChild(item);
-
-    // Copy declaration
-    label = styleInspectorStrings.
-      GetStringFromName("rule.contextmenu.copydeclaration");
-    accessKey = styleInspectorStrings.
-      GetStringFromName("rule.contextmenu.copydeclaration.accesskey");
-    item = this.chromeDoc.createElement("menuitem");
-    item.id = "rule-view-copy-declaration";
-    item.setAttribute("label", label);
-    item.setAttribute("accesskey", accessKey);
-    item.addEventListener("command", this.cssRuleViewBoundCopyDeclaration);
-    menu.appendChild(item);
-
-    // Copy property name
-    label = styleInspectorStrings.
-      GetStringFromName("rule.contextmenu.copyproperty");
-    accessKey = styleInspectorStrings.
-      GetStringFromName("rule.contextmenu.copyproperty.accesskey");
-    item = this.chromeDoc.createElement("menuitem");
-    item.id = "rule-view-copy-property";
-    item.setAttribute("label", label);
-    item.setAttribute("accesskey", accessKey);
-    item.addEventListener("command", this.cssRuleViewBoundCopyProperty);
-    menu.appendChild(item);
-
-    // Copy property value
-    label = styleInspectorStrings.
-      GetStringFromName("rule.contextmenu.copypropertyvalue");
-    accessKey = styleInspectorStrings.
-      GetStringFromName("rule.contextmenu.copypropertyvalue.accesskey");
-    item = this.chromeDoc.createElement("menuitem");
-    item.id = "rule-view-copy-property-value";
-    item.setAttribute("label", label);
-    item.setAttribute("accesskey", accessKey);
-    item.addEventListener("command", this.cssRuleViewBoundCopyPropertyValue);
-    menu.appendChild(item);
-
-    popupSet.appendChild(menu);
-
-    iframe.setAttribute("context", menu.id);
-  },
-
-  /**
-   * Update the rule view's context menu by disabling irrelevant menuitems and
-   * enabling relevant ones.
-   *
-   * @param aEvent The event object
-   */
-  ruleViewMenuUpdate: function IUI_ruleViewMenuUpdate(aEvent)
-  {
-    let iframe = this.getToolIframe(this.ruleViewObject);
-    let win = iframe.contentWindow;
-
-    // Copy selection.
-    let disable = win.getSelection().isCollapsed;
-    let menuitem = this.chromeDoc.getElementById("rule-view-copy");
-    menuitem.disabled = disable;
-
-    // Copy property, copy property name & copy property value.
-    let node = this.chromeDoc.popupNode;
-    if (!node.classList.contains("ruleview-property") &&
-        !node.classList.contains("ruleview-computed")) {
-      while (node = node.parentElement) {
-        if (node.classList.contains("ruleview-property") ||
-          node.classList.contains("ruleview-computed")) {
-          break;
-        }
-      }
-    }
-    let disablePropertyItems = !node || (node &&
-      !node.classList.contains("ruleview-property") &&
-      !node.classList.contains("ruleview-computed"));
-
-    menuitem = this.chromeDoc.querySelector("#rule-view-copy-declaration");
-    menuitem.disabled = disablePropertyItems;
-    menuitem = this.chromeDoc.querySelector("#rule-view-copy-property");
-    menuitem.disabled = disablePropertyItems;
-    menuitem = this.chromeDoc.querySelector("#rule-view-copy-property-value");
-    menuitem.disabled = disablePropertyItems;
-  },
-
-  /**
-   * Copy selected text from the rule view.
-   *
-   * @param aEvent The event object
-   */
-  ruleViewCopy: function IUI_ruleViewCopy(aEvent)
-  {
-    let iframe = this.getToolIframe(this.ruleViewObject);
-    let win = iframe.contentWindow;
-    let text = win.getSelection().toString();
-
-    // Remove any double newlines.
-    text = text.replace(/(\r?\n)\r?\n/g, "$1");
-
-    // Remove "inline"
-    let inline = styleInspectorStrings.GetStringFromName("rule.sourceInline");
-    let rx = new RegExp("^" + inline + "\\r?\\n?", "g");
-    text = text.replace(rx, "");
-
-    // Remove file:line
-    text = text.replace(/[\w\.]+:\d+(\r?\n)/g, "$1");
-
-    // Remove inherited from: line
-    let inheritedFrom = styleInspectorStrings
-      .GetStringFromName("rule.inheritedSource");
-    inheritedFrom = inheritedFrom.replace(/\s%S\s\(%S\)/g, "");
-    rx = new RegExp("(\r?\n)" + inheritedFrom + ".*", "g");
-    text = text.replace(rx, "$1");
-
-    clipboardHelper.copyString(text);
-
-    if (aEvent) {
-      aEvent.preventDefault();
-    }
-  },
-
-  /**
-   * Copy a rule from the rule view.
-   *
-   * @param aEvent The event object
-   */
-  ruleViewCopyRule: function IUI_ruleViewCopyRule(aEvent)
-  {
-    let node = this.chromeDoc.popupNode;
-    if (node.className != "ruleview-code") {
-      if (node.className == "ruleview-rule-source") {
-        node = node.nextElementSibling;
-      } else {
-        while (node = node.parentElement) {
-          if (node.className == "ruleview-code") {
-            break;
-          }
-        }
-      }
-    }
-
-    if (node.className == "ruleview-code") {
-      // We need to strip expanded properties from the node because we use
-      // node.textContent below, which also gets text from hidden nodes. The
-      // simplest way to do this is to clone the node and remove them from the
-      // clone.
-      node = node.cloneNode();
-      let computed = node.querySelector(".ruleview-computedlist");
-      if (computed) {
-        computed.parentNode.removeChild(computed);
-      }
-      let autosizer = node.querySelector(".autosizer");
-      if (autosizer) {
-        autosizer.parentNode.removeChild(autosizer);
-      }
-    }
-
-    let text = node.textContent;
-
-    // Format the rule
-    if (osString == "WINNT") {
-      text = text.replace(/{/g, "{\r\n    ");
-      text = text.replace(/;/g, ";\r\n    ");
-      text = text.replace(/\s*}/g, "\r\n}");
-    } else {
-      text = text.replace(/{/g, "{\n    ");
-      text = text.replace(/;/g, ";\n    ");
-      text = text.replace(/\s*}/g, "\n}");
-    }
-
-    clipboardHelper.copyString(text);
-  },
-
-  /**
-   * Copy a declaration from the rule view.
-   *
-   * @param aEvent The event object
-   */
-  ruleViewCopyDeclaration: function IUI_ruleViewCopyDeclaration(aEvent)
-  {
-    let node = this.chromeDoc.popupNode;
-    if (!node.classList.contains("ruleview-property") &&
-        !node.classList.contains("ruleview-computed")) {
-      while (node = node.parentElement) {
-        if (node.classList.contains("ruleview-property") ||
-            node.classList.contains("ruleview-computed")) {
-          break;
-        }
-      }
-    }
-
-    // We need to strip expanded properties from the node because we use
-    // node.textContent below, which also gets text from hidden nodes. The
-    // simplest way to do this is to clone the node and remove them from the
-    // clone.
-    node = node.cloneNode();
-    let computed = node.querySelector(".ruleview-computedlist");
-    if (computed) {
-      computed.parentNode.removeChild(computed);
-    }
-    clipboardHelper.copyString(node.textContent);
-  },
-
-  /**
-   * Copy a property name from the rule view.
-   *
-   * @param aEvent The event object
-   */
-  ruleViewCopyProperty: function IUI_ruleViewCopyProperty(aEvent)
-  {
-    let node = this.chromeDoc.popupNode;
-
-    if (!node.classList.contains("ruleview-propertyname")) {
-      node = node.querySelector(".ruleview-propertyname");
-    }
-
-    if (node) {
-      clipboardHelper.copyString(node.textContent);
-    }
-  },
-
-  /**
-   * Copy a property value from the rule view.
-   *
-   * @param aEvent The event object
-   */
-  ruleViewCopyPropertyValue: function IUI_ruleViewCopyPropertyValue(aEvent)
-  {
-    let node = this.chromeDoc.popupNode;
-
-    if (!node.classList.contains("ruleview-propertyvalue")) {
-      node = node.querySelector(".ruleview-propertyvalue");
-    }
-
-    if (node) {
-      clipboardHelper.copyString(node.textContent);
-    }
-  },
-
-  /**
    * Destroy the rule view.
    */
   destroyRuleView: function IUI_destroyRuleView()
   {
-    let iframe = this.getToolIframe(this.ruleViewObject);
-    iframe.removeEventListener("copy", this.cssRuleViewBoundCopy);
-    iframe.parentNode.removeChild(iframe);
-
     if (this.ruleView) {
-      let menu = this.chromeDoc.querySelector("#rule-view-context-menu");
-      if (menu) {
-        // Copy
-        let menuitem = this.chromeDoc.querySelector("#rule-view-copy");
-        menuitem.removeEventListener("command", this.cssRuleViewBoundCopy);
-
-        // Copy rule
-        menuitem = this.chromeDoc.querySelector("#rule-view-copy-rule");
-        menuitem.removeEventListener("command", this.cssRuleViewBoundCopyRule);
-
-        // Copy property
-        menuitem = this.chromeDoc.querySelector("#rule-view-copy-declaration");
-        menuitem.removeEventListener("command",
-                                     this.cssRuleViewBoundCopyDeclaration);
-
-        // Copy property name
-        menuitem = this.chromeDoc.querySelector("#rule-view-copy-property");
-        menuitem.removeEventListener("command",
-                                     this.cssRuleViewBoundCopyProperty);
-
-        // Copy property value
-        menuitem = this.chromeDoc.querySelector("#rule-view-copy-property-value");
-        menuitem.removeEventListener("command",
-                                     this.cssRuleViewBoundCopyPropertyValue);
-
-        menu.removeEventListener("popupshowing", this.cssRuleViewBoundMenuUpdate);
-        menu.parentNode.removeChild(menu);
-      }
-
       this.ruleView.element.removeEventListener("CssRuleViewChanged",
                                                 this.boundRuleViewChanged);
       this.ruleView.element.removeEventListener("CssRuleViewCSSLinkClicked",
                                                 this.cssRuleViewBoundCSSLinkClicked);
-      this.ruleView.element.removeEventListener("mousedown",
-                                                this.cssRuleViewBoundMouseDown);
-      this.ruleView.element.removeEventListener("mouseup",
-                                                this.cssRuleViewBoundMouseUp);
-      this.ruleView.element.removeEventListener("mousemove",
-                                                this.cssRuleViewBoundMouseMove);
-      delete boundRuleViewChanged;
-      this.ruleView.clear();
+      delete this.boundRuleViewChanged;
+      delete this.cssRuleViewBoundCSSLinkClicked;
+      this.ruleView.destroy();
       delete this.ruleView;
     }
+
+    let iframe = this.getToolIframe(this.ruleViewObject);
+    iframe.parentNode.removeChild(iframe);
   },
 
   /////////////////////////////////////////////////////////////////////////
   //// Utility Methods
 
   /**
    * inspect the given node, highlighting it on the page and selecting the
    * correct row in the tree panel
@@ -2626,17 +2265,8 @@ XPCOMUtils.defineLazyGetter(this, "Style
 XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
   return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
 });
 
 XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
   return Cc["@mozilla.org/widget/clipboardhelper;1"].
     getService(Ci.nsIClipboardHelper);
 });
-
-XPCOMUtils.defineLazyGetter(this, "styleInspectorStrings", function() {
-  return Services.strings.createBundle(
-    "chrome://browser/locale/devtools/styleinspector.properties");
-});
-
-XPCOMUtils.defineLazyGetter(this, "osString", function() {
-  return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
-});
--- a/browser/devtools/highlighter/test/browser_inspector_duplicate_ruleview.js
+++ b/browser/devtools/highlighter/test/browser_inspector_duplicate_ruleview.js
@@ -85,17 +85,19 @@ function inspectorFocusTab1()
 
   // Make sure the inspector is open.
   ok(InspectorUI.inspecting, "Inspector is highlighting");
   ok(!InspectorUI.treePanel.isOpen(), "Inspector Tree Panel is not open");
   is(InspectorUI.store.length, 1, "Inspector.store.length = 1");
   is(InspectorUI.selection, div, "selection matches the div element");
   ok(InspectorUI.isSidebarOpen, "sidebar is open");
   ok(InspectorUI.isRuleViewOpen(), "rule view is open");
-  is(InspectorUI.ruleView.doc.documentElement.children.length, 1, "RuleView elements.length == 1");
+
+  // The rule view element plus its popupSet
+  is(InspectorUI.ruleView.doc.documentElement.children.length, 2, "RuleView elements.length == 2");
 
   requestLongerTimeout(4);
   executeSoon(function() {
     InspectorUI.closeInspectorUI();
     gBrowser.removeCurrentTab(); // tab 1
     gBrowser.removeCurrentTab(); // tab 2
     finish();
   });
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_653427_confirm_close.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_653427_confirm_close.js
@@ -35,16 +35,17 @@ function test()
     confirmEx: function() {
       return promptButton;
     }
   };
 
   testNew();
   testSavedFile();
 
+  gBrowser.selectedTab = gBrowser.addTab();
   content.location = "data:text/html,<p>test scratchpad save file prompt on closing";
 }
 
 function testNew()
 {
   openScratchpad(function(win) {
     win.Scratchpad.close(function() {
       ok(win.closed, "new scratchpad window should close without prompting")
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_669612_unsaved.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_669612_unsaved.js
@@ -19,16 +19,17 @@ function test()
 {
   waitForExplicitFinish();
   
   testListeners();
   testRestoreNotFromFile();
   testRestoreFromFileSaved();
   testRestoreFromFileUnsaved();
 
+  gBrowser.selectedTab = gBrowser.addTab();
   content.location = "data:text/html,<p>test star* UI for unsaved file changes";
 }
 
 function testListeners()
 {
   openScratchpad(function(aWin, aScratchpad) {
     aScratchpad.setText("new text");
     ok(!isStar(aWin), "no star if scratchpad isn't from a file");
--- a/browser/devtools/styleinspector/CssRuleView.jsm
+++ b/browser/devtools/styleinspector/CssRuleView.jsm
@@ -59,16 +59,17 @@ const FOCUS_BACKWARD = Ci.nsIFocusManage
 // Used to split on css line separators
 const CSS_LINE_RE = /(?:[^;\(]*(?:\([^\)]*?\))?[^;\(]*)*;?/g;
 
 // Used to parse a single property line.
 const CSS_PROP_RE = /\s*([^:\s]*)\s*:\s*(.*?)\s*(?:! (important))?;?$/;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/devtools/CssLogic.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 var EXPORTED_SYMBOLS = ["CssRuleView",
                         "_ElementStyle",
                         "_editableField",
                         "_getInplaceEditorForSpan"];
 
 /**
  * Our model looks like this:
@@ -694,22 +695,65 @@ TextProperty.prototype = {
 function CssRuleView(aDoc, aStore)
 {
   this.doc = aDoc;
   this.store = aStore;
   this.element = this.doc.createElementNS(XUL_NS, "vbox");
   this.element.setAttribute("tabindex", "0");
   this.element.classList.add("ruleview");
   this.element.flex = 1;
+  this._selectionMode = false;
+
+  this._boundMouseDown = this._onMouseDown.bind(this);
+  this.element.addEventListener("mousedown",
+                                this._boundMouseDown);
+  this._boundMouseUp = this._onMouseUp.bind(this);
+  this.element.addEventListener("mouseup",
+                                this._boundMouseUp);
+  this._boundMouseMove = this._onMouseMove.bind(this);
+
+  this._boundCopy = this._onCopy.bind(this);
+  this.element.addEventListener("copy", this._boundCopy);
+
+  this._createContextMenu();
 }
 
 CssRuleView.prototype = {
   // The element that we're inspecting.
   _viewedElement: null,
 
+  destroy: function CssRuleView_destroy()
+  {
+    this.clear();
+
+    this.element.removeEventListener("copy", this._boundCopy);
+    this._copyItem.removeEventListener("command", this._boundCopy);
+    delete this._boundCopy;
+
+    this._ruleItem.removeEventListener("command", this._boundCopyRule);
+    delete this._boundCopyRule;
+
+    this._declarationItem.removeEventListener("command", this._boundCopyDeclaration);
+    delete this._boundCopyDeclaration;
+
+    this._propertyItem.removeEventListener("command", this._boundCopyProperty);
+    delete this._boundCopyProperty;
+
+    this._propertyValueItem.removeEventListener("command", this._boundCopyPropertyValue);
+    delete this._boundCopyPropertyValue;
+
+    this._contextMenu.removeEventListener("popupshowing", this._boundMenuUpdate);
+    delete this._boundMenuUpdate;
+    delete this._contextMenu;
+
+    if (this.element.parentNode) {
+      this.element.parentNode.removeChild(this.element);
+    }
+  },
+
   /**
    * Update the highlighted element.
    *
    * @param {nsIDOMElement} aElement
    *        The node whose style rules we'll inspect.
    */
   highlight: function CssRuleView_highlight(aElement)
   {
@@ -757,17 +801,17 @@ CssRuleView.prototype = {
   /**
    * Update the rules for the currently highlighted element.
    */
   nodeChanged: function CssRuleView_nodeChanged()
   {
     this._clearRules();
     this._elementStyle.populate();
     this._createEditors();
-  },  
+  },
 
   /**
    * Clear the rules.
    */
   _clearRules: function CssRuleView_clearRules()
   {
     while (this.element.hasChildNodes()) {
       this.element.removeChild(this.element.lastChild);
@@ -808,16 +852,272 @@ CssRuleView.prototype = {
   {
     for each (let rule in this._elementStyle.rules) {
       // Don't hold a reference to this editor beyond the one held
       // by the node.
       let editor = new RuleEditor(this, rule);
       this.element.appendChild(editor.element);
     }
   },
+
+  /**
+   * Add a context menu to the rule view.
+   */
+  _createContextMenu: function CssRuleView_createContextMenu()
+  {
+    let popupSet = this.doc.createElement("popupset");
+    this.doc.documentElement.appendChild(popupSet);
+
+    let menu = this.doc.createElement("menupopup");
+    menu.id = "rule-view-context-menu";
+
+    this._boundMenuUpdate = this._onMenuUpdate.bind(this);
+    menu.addEventListener("popupshowing", this._boundMenuUpdate);
+
+    // Copy selection
+    this._copyItem = createMenuItem(menu, {
+      label: "rule.contextmenu.copyselection",
+      accesskey: "rule.contextmenu.copyselection.accesskey",
+      command: this._boundCopy
+    });
+
+    // Copy rule
+    this._boundCopyRule = this._onCopyRule.bind(this);
+    this._ruleItem = createMenuItem(menu, {
+      label: "rule.contextmenu.copyrule",
+      accesskey: "rule.contextmenu.copyrule.accesskey",
+      command: this._boundCopyRule
+    });
+
+    // Copy declaration
+    this._boundCopyDeclaration = this._onCopyDeclaration.bind(this);
+    this._declarationItem = createMenuItem(menu, {
+      label: "rule.contextmenu.copydeclaration",
+      accesskey: "rule.contextmenu.copydeclaration.accesskey",
+      command: this._boundCopyDeclaration
+    });
+
+    this._boundCopyProperty = this._onCopyProperty.bind(this);
+    this._propertyItem = createMenuItem(menu, {
+      label: "rule.contextmenu.copyproperty",
+      accesskey: "rule.contextmenu.copyproperty.accesskey",
+      command: this._boundCopyProperty
+    });
+
+    this._boundCopyPropertyValue = this._onCopyPropertyValue.bind(this);
+    this._propertyValueItem = createMenuItem(menu,{
+      label: "rule.contextmenu.copypropertyvalue",
+      accesskey: "rule.contextmenu.copypropertyvalue.accesskey",
+      command: this._boundCopyPropertyValue
+    });
+
+    popupSet.appendChild(menu);
+    this.element.setAttribute("context", menu.id);
+
+    this._contextMenu = menu;
+  },
+
+  /**
+   * Update the rule view's context menu by disabling irrelevant menuitems and
+   * enabling relevant ones.
+   *
+   * @param aEvent The event object
+   */
+  _onMenuUpdate: function CssRuleView_onMenuUpdate(aEvent)
+  {
+    // Copy selection.
+    let disable = this.doc.defaultView.getSelection().isCollapsed;
+    this._copyItem.disabled = disable;
+
+    // Copy property, copy property name & copy property value.
+    let node = this.doc.popupNode;
+    if (!node.classList.contains("ruleview-property") &&
+        !node.classList.contains("ruleview-computed")) {
+      while (node = node.parentElement) {
+        if (node.classList.contains("ruleview-property") ||
+          node.classList.contains("ruleview-computed")) {
+          break;
+        }
+      }
+    }
+    let disablePropertyItems = !node || (node &&
+      !node.classList.contains("ruleview-property") &&
+      !node.classList.contains("ruleview-computed"));
+
+    this._declarationItem.disabled = disablePropertyItems;
+    this._propertyItem.disabled = disablePropertyItems;
+    this._propertyValueItem.disabled = disablePropertyItems;
+
+    dump("Done updating menu!\n");
+  },
+
+  _onMouseDown: function CssRuleView_onMouseDown()
+  {
+    this.element.addEventListener("mousemove", this._boundMouseMove);
+  },
+
+  _onMouseUp: function CssRuleView_onMouseUp()
+  {
+    this.element.removeEventListener("mousemove", this._boundMouseMove);
+    this._selectionMode = false;
+  },
+
+  _onMouseMove: function CssRuleView_onMouseMove()
+  {
+    this._selectionMode = true;
+  },
+
+  /**
+   * Copy selected text from the rule view.
+   *
+   * @param aEvent The event object
+   */
+  _onCopy: function CssRuleView_onCopy(aEvent)
+  {
+    let win = this.doc.defaultView;
+    let text = win.getSelection().toString();
+
+    // Remove any double newlines.
+    text = text.replace(/(\r?\n)\r?\n/g, "$1");
+
+    // Remove "inline"
+    let inline = _strings.GetStringFromName("rule.sourceInline");
+    let rx = new RegExp("^" + inline + "\\r?\\n?", "g");
+    text = text.replace(rx, "");
+
+    // Remove file:line
+    text = text.replace(/[\w\.]+:\d+(\r?\n)/g, "$1");
+
+    // Remove inherited from: line
+    let inheritedFrom = _strings.
+      GetStringFromName("rule.inheritedSource");
+    inheritedFrom = inheritedFrom.replace(/\s%S\s\(%S\)/g, "");
+    rx = new RegExp("(\r?\n)" + inheritedFrom + ".*", "g");
+    text = text.replace(rx, "$1");
+
+    clipboardHelper.copyString(text);
+
+    if (aEvent) {
+      aEvent.preventDefault();
+    }
+  },
+
+  /**
+   * Copy a rule from the rule view.
+   *
+   * @param aEvent The event object
+   */
+  _onCopyRule: function CssRuleView_onCopyRule(aEvent)
+  {
+    let node = this.doc.popupNode;
+    if (node.className != "ruleview-code") {
+      if (node.className == "ruleview-rule-source") {
+        node = node.nextElementSibling;
+      } else {
+        while (node = node.parentElement) {
+          if (node.className == "ruleview-code") {
+            break;
+          }
+        }
+      }
+    }
+
+    if (node.className == "ruleview-code") {
+      // We need to strip expanded properties from the node because we use
+      // node.textContent below, which also gets text from hidden nodes. The
+      // simplest way to do this is to clone the node and remove them from the
+      // clone.
+      node = node.cloneNode();
+      let computed = node.querySelector(".ruleview-computedlist");
+      if (computed) {
+        computed.parentNode.removeChild(computed);
+      }
+    }
+
+    let text = node.textContent;
+
+    // Format the rule
+    if (osString == "WINNT") {
+      text = text.replace(/{/g, "{\r\n    ");
+      text = text.replace(/;/g, ";\r\n    ");
+      text = text.replace(/\s*}/g, "\r\n}");
+    } else {
+      text = text.replace(/{/g, "{\n    ");
+      text = text.replace(/;/g, ";\n    ");
+      text = text.replace(/\s*}/g, "\n}");
+    }
+
+    clipboardHelper.copyString(text);
+  },
+
+  /**
+   * Copy a declaration from the rule view.
+   *
+   * @param aEvent The event object
+   */
+  _onCopyDeclaration: function CssRuleView_onCopyDeclaration(aEvent)
+  {
+    let node = this.doc.popupNode;
+    if (!node.classList.contains("ruleview-property") &&
+        !node.classList.contains("ruleview-computed")) {
+      while (node = node.parentElement) {
+        if (node.classList.contains("ruleview-property") ||
+            node.classList.contains("ruleview-computed")) {
+          break;
+        }
+      }
+    }
+
+    // We need to strip expanded properties from the node because we use
+    // node.textContent below, which also gets text from hidden nodes. The
+    // simplest way to do this is to clone the node and remove them from the
+    // clone.
+    node = node.cloneNode();
+    let computed = node.querySelector(".ruleview-computedlist");
+    if (computed) {
+      computed.parentNode.removeChild(computed);
+    }
+    clipboardHelper.copyString(node.textContent);
+  },
+
+  /**
+   * Copy a property name from the rule view.
+   *
+   * @param aEvent The event object
+   */
+  _onCopyProperty: function CssRuleView_onCopyProperty(aEvent)
+  {
+    let node = this.doc.popupNode;
+
+    if (!node.classList.contains("ruleview-propertyname")) {
+      node = node.querySelector(".ruleview-propertyname");
+    }
+
+    if (node) {
+      clipboardHelper.copyString(node.textContent);
+    }
+  },
+
+ /**
+   * Copy a property value from the rule view.
+   *
+   * @param aEvent The event object
+   */
+  _onCopyPropertyValue: function CssRuleView_onCopyPropertyValue(aEvent)
+  {
+    let node = this.doc.popupNode;
+
+    if (!node.classList.contains("ruleview-propertyvalue")) {
+      node = node.querySelector(".ruleview-propertyvalue");
+    }
+
+    if (node) {
+      clipboardHelper.copyString(node.textContent);
+    }
+  }
 };
 
 /**
  * Create a RuleEditor.
  *
  * @param CssRuleView aRuleView
  *        The CssRuleView containg the document holding this rule editor and the
  *        _selectionMode flag.
@@ -1564,16 +1864,28 @@ function createChild(aParent, aTag, aAtt
         elt.setAttribute(attr, aAttributes[attr]);
       }
     }
   }
   aParent.appendChild(elt);
   return elt;
 }
 
+function createMenuItem(aMenu, aAttributes)
+{
+  let item = aMenu.ownerDocument.createElementNS(XUL_NS, "menuitem");
+  item.setAttribute("label", _strings.GetStringFromName(aAttributes.label));
+  item.setAttribute("accesskey", _strings.GetStringFromName(aAttributes.accesskey));
+  item.addEventListener("command", aAttributes.command);
+
+  aMenu.appendChild(item);
+
+  return item;
+}
+
 /**
  * Append a text node to an element.
  */
 function appendText(aParent, aText)
 {
   aParent.appendChild(aParent.ownerDocument.createTextNode(aText));
 }
 
@@ -1593,8 +1905,23 @@ function copyTextStyles(aFrom, aTo)
 /**
  * Trigger a focus change similar to pressing tab/shift-tab.
  */
 function moveFocus(aWin, aDirection)
 {
   let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
   fm.moveFocus(aWin, null, aDirection, 0);
 }
+
+XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
+  return Cc["@mozilla.org/widget/clipboardhelper;1"].
+    getService(Ci.nsIClipboardHelper);
+});
+
+XPCOMUtils.defineLazyGetter(this, "_strings", function() {
+  return Services.strings.createBundle(
+    "chrome://browser/locale/devtools/styleinspector.properties");
+});
+
+XPCOMUtils.defineLazyGetter(this, "osString", function() {
+  return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
+});
+
--- a/browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js
@@ -65,17 +65,17 @@ function inspectorUIOpen()
 }
 
 function testClip()
 {
   Services.obs.removeObserver(testClip,
     InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, false);
 
   executeSoon(function() {
-    info("Checking that InspectorUI.ruleViewCopyRule() returns " +
+    info("Checking that _onCopyRule() returns " +
          "the correct clipboard value");
     let expectedPattern = "element {[\\r\\n]+" +
       "    margin: 10em;[\\r\\n]+" +
       "    font-size: 14pt;[\\r\\n]+" +
       "    font-family: helvetica,sans-serif;[\\r\\n]+" +
       "    color: rgb\\(170, 170, 170\\);[\\r\\n]+" +
       "}[\\r\\n]*";
     info("Expected pattern: " + expectedPattern);
@@ -101,86 +101,86 @@ function checkCopyRule() {
   is(propName, "font-family", "checking property name");
   is(propValue, "helvetica,sans-serif", "checking property value");
 
   // We need the context menu to open in the correct place in order for
   // popupNode to be propertly set.
   EventUtils.synthesizeMouse(prop, 1, 1, { type: "contextmenu", button: 2 },
     ruleView.contentWindow);
 
-  InspectorUI.ruleViewCopyRule();
+  InspectorUI.ruleView._boundCopyRule();
 }
 
 function checkCopyProperty()
 {
-  info("Checking that InspectorUI.cssRuleViewBoundCopyDeclaration() returns " +
+  info("Checking that _onCopyDeclaration() returns " +
        "the correct clipboard value");
   let expectedPattern = "font-family: helvetica,sans-serif;";
   info("Expected pattern: " + expectedPattern);
 
   SimpleTest.waitForClipboard(function IUI_boundCopyPropCheck() {
       return checkClipboardData(expectedPattern);
     },
-    InspectorUI.cssRuleViewBoundCopyDeclaration,
+    InspectorUI.ruleView._boundCopyDeclaration,
     checkCopyPropertyName, checkCopyPropertyName);
 }
 
 function checkCopyPropertyName()
 {
-  info("Checking that InspectorUI.cssRuleViewBoundCopyProperty() returns " +
+  info("Checking that _onCopyProperty() returns " +
        "the correct clipboard value");
   let expectedPattern = "font-family";
   info("Expected pattern: " + expectedPattern);
 
   SimpleTest.waitForClipboard(function IUI_boundCopyPropNameCheck() {
       return checkClipboardData(expectedPattern);
     },
-    InspectorUI.cssRuleViewBoundCopyProperty,
+    InspectorUI.ruleView._boundCopyProperty,
     checkCopyPropertyValue, checkCopyPropertyValue);
 }
 
 function checkCopyPropertyValue()
 {
-  info("Checking that InspectorUI.cssRuleViewBoundCopyPropertyValue() " +
+  info("Checking that _onCopyPropertyValue() " +
        " returns the correct clipboard value");
   let expectedPattern = "helvetica,sans-serif";
   info("Expected pattern: " + expectedPattern);
 
   SimpleTest.waitForClipboard(function IUI_boundCopyPropValueCheck() {
       return checkClipboardData(expectedPattern);
     },
-    InspectorUI.cssRuleViewBoundCopyPropertyValue,
+    InspectorUI.ruleView._boundCopyPropertyValue,
     checkCopySelection, checkCopySelection);
 }
 
 function checkCopySelection()
 {
   let ruleView = document.querySelector("#devtools-sidebar-iframe-ruleview");
   let contentDoc = ruleView.contentDocument;
   let props = contentDoc.querySelectorAll(".ruleview-property");
 
   let range = document.createRange();
   range.setStart(props[0], 0);
   range.setEnd(props[4], 8);
   ruleView.contentWindow.getSelection().addRange(range);
 
-  info("Checking that InspectorUI.cssRuleViewBoundCopy()  returns the correct" +
+  info("Checking that _onCopy()  returns the correct" +
        "clipboard value");
   let expectedPattern = "    margin: 10em;[\\r\\n]+" +
                         "    font-size: 14pt;[\\r\\n]+" +
                         "    font-family: helvetica,sans-serif;[\\r\\n]+" +
                         "    color: rgb\\(170, 170, 170\\);[\\r\\n]+" +
                         "}[\\r\\n]+" +
                         "html {[\\r\\n]+" +
                         "    color: rgb\\(0, 0, 0\\);[\\r\\n]*";
   info("Expected pattern: " + expectedPattern);
 
   SimpleTest.waitForClipboard(function IUI_boundCopyCheck() {
       return checkClipboardData(expectedPattern);
-    },InspectorUI.cssRuleViewBoundCopy, finishup, finishup);
+    },InspectorUI.ruleView._boundCopy, finishup, finishup);
 }
 
 function checkClipboardData(aExpectedPattern)
 {
   let actual = SpecialPowers.getClipboardData("text/unicode");
   let expectedRegExp = new RegExp(aExpectedPattern, "g");
   return expectedRegExp.test(actual);
 }
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -110,16 +110,19 @@ crashedpluginsMessage.title=The %S plugi
 crashedpluginsMessage.reloadButton.label=Reload page
 crashedpluginsMessage.reloadButton.accesskey=R
 crashedpluginsMessage.submitButton.label=Submit a crash report
 crashedpluginsMessage.submitButton.accesskey=S
 crashedpluginsMessage.learnMore=Learn Moreā€¦
 carbonFailurePluginsMessage.message=This page asks to use a plugin that can only run in 32-bit mode
 carbonFailurePluginsMessage.restartButton.label=Restart in 32-bit mode
 carbonFailurePluginsMessage.restartButton.accesskey=R
+activatePluginsMessage.message=Would you like to activate the plugins on this page?
+activatePluginsMessage.label=Activate plugins
+activatePluginsMessage.accesskey=A
 
 # Sanitize
 # LOCALIZATION NOTE (sanitizeDialog2.everything.title): When "Time range to
 # clear" is set to "Everything", the Clear Recent History dialog's title is
 # changed to this.  See UI mockup and comment 11 at bug 480169 -->
 sanitizeDialog2.everything.title=Clear All History
 sanitizeButtonOK=Clear Now
 # LOCALIZATION NOTE (sanitizeEverythingWarning2): Warning that appears when
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1186,17 +1186,18 @@ toolbar[iconsize="small"] #feed-button {
   list-style-image: url(chrome://browser/skin/Geolocation-64.png);
 }
 
 .popup-notification-icon[popupid="xpinstall-disabled"],
 .popup-notification-icon[popupid="addon-progress"],
 .popup-notification-icon[popupid="addon-install-cancelled"],
 .popup-notification-icon[popupid="addon-install-blocked"],
 .popup-notification-icon[popupid="addon-install-failed"],
-.popup-notification-icon[popupid="addon-install-complete"] {
+.popup-notification-icon[popupid="addon-install-complete"],
+.popup-notification-icon[popupid="click-to-play-plugins"] {
   list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
   width: 32px;
   height: 32px;
 }
 
 .addon-progress-description {
   width: 350px;
   max-width: 350px;
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -2373,17 +2373,18 @@ toolbarbutton.chevron > .toolbarbutton-m
   list-style-image: url(chrome://browser/skin/Geolocation-64.png);
 }
 
 .popup-notification-icon[popupid="xpinstall-disabled"],
 .popup-notification-icon[popupid="addon-progress"],
 .popup-notification-icon[popupid="addon-install-cancelled"],
 .popup-notification-icon[popupid="addon-install-blocked"],
 .popup-notification-icon[popupid="addon-install-failed"],
-.popup-notification-icon[popupid="addon-install-complete"] {
+.popup-notification-icon[popupid="addon-install-complete"],
+.popup-notification-icon[popupid="click-to-play-plugins"] {
   list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
   width: 32px;
   height: 32px;
 }
 
 .addon-progress-description {
   width: 350px;
   max-width: 350px;
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -2244,17 +2244,18 @@ toolbarbutton.bookmark-item[dragover="tr
   list-style-image: url(chrome://browser/skin/Geolocation-64.png);
 }
 
 .popup-notification-icon[popupid="xpinstall-disabled"],
 .popup-notification-icon[popupid="addon-progress"],
 .popup-notification-icon[popupid="addon-install-cancelled"],
 .popup-notification-icon[popupid="addon-install-blocked"],
 .popup-notification-icon[popupid="addon-install-failed"],
-.popup-notification-icon[popupid="addon-install-complete"] {
+.popup-notification-icon[popupid="addon-install-complete"],
+.popup-notification-icon[popupid="click-to-play-plugins"] {
   list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
   width: 32px;
   height: 32px;
 }
 
 .addon-progress-description {
   width: 350px;
   max-width: 350px;
deleted file mode 100644
--- a/build/autoconf/freetype2.m4
+++ /dev/null
@@ -1,137 +0,0 @@
-# Configure paths for FreeType2
-# Marcelo Magallon 2001-10-26, based on gtk.m4 by Owen Taylor
-
-dnl AM_CHECK_FT2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
-dnl Test for FreeType2, and define FT2_CFLAGS and FT2_LIBS
-dnl
-AC_DEFUN([AC_CHECK_FT2],
-[dnl
-dnl Get the cflags and libraries from the freetype-config script
-dnl
-AC_ARG_WITH(freetype-prefix,
-[  --with-ft-prefix=PFX    Prefix where FreeType is installed (optional)],
-            ft_config_prefix="$withval", ft_config_prefix="")
-AC_ARG_WITH(freetype-exec-prefix,
-[  --with-ft-exec-prefix=PFX
-                          Exec prefix where FreeType is installed (optional)],
-            ft_config_exec_prefix="$withval", ft_config_exec_prefix="")
-AC_ARG_ENABLE(freetypetest,
-[  --disable-freetypetest
-                          Do not try to compile and run a test FreeType program],
-            [], enable_fttest=yes)
-
-if test x$ft_config_exec_prefix != x ; then
-  ft_config_args="$ft_config_args --exec-prefix=$ft_config_exec_prefix"
-  if test x${FT2_CONFIG+set} != xset ; then
-    FT2_CONFIG=$ft_config_exec_prefix/bin/freetype-config
-  fi
-fi
-if test x$ft_config_prefix != x ; then
-  ft_config_args="$ft_config_args --prefix=$ft_config_prefix"
-  if test x${FT2_CONFIG+set} != xset ; then
-    FT2_CONFIG=$ft_config_prefix/bin/freetype-config
-  fi
-fi
-AC_PATH_PROG(FT2_CONFIG, freetype-config, no)
-
-min_ft_version=ifelse([$1], ,6.1.0,$1)
-AC_MSG_CHECKING(for FreeType - version >= $min_ft_version)
-no_ft=""
-if test "$FT2_CONFIG" = "no" ; then
-  no_ft=yes
-else
-  FT2_CFLAGS=`$FT2_CONFIG $ft_config_args --cflags`
-  FT2_LIBS=`$FT2_CONFIG $ft_config_args --libs`
-  ft_config_major_version=`$FT2_CONFIG $ft_config_args --version | \
-         sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
-  ft_config_minor_version=`$FT2_CONFIG $ft_config_args --version | \
-         sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
-  ft_config_micro_version=`$FT2_CONFIG $ft_config_args --version | \
-         sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
-  ft_min_major_version=`echo $min_ft_version | \
-         sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
-  ft_min_minor_version=`echo $min_ft_version | \
-         sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
-  ft_min_micro_version=`echo $min_ft_version | \
-         sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
-  if test "x$enable_fttest" = "xyes" ; then
-    ft_config_is_lt=no
-    if test $ft_config_major_version -lt $ft_min_major_version ; then
-      ft_config_is_lt=yes
-    else
-      if test $ft_config_major_version -eq $ft_min_major_version ; then
-        if test $ft_config_minor_version -lt $ft_min_minor_version ; then
-          ft_config_is_lt=yes
-        else
-          if test $ft_config_minor_version -eq $ft_min_minor_version ; then
-            if test $ft_config_micro_version -lt $ft_min_micro_version ; then
-              ft_config_is_lt=yes
-            fi
-          fi
-        fi
-      fi
-    fi
-    if test "x$ft_config_is_lt" = "xyes" ; then
-      ifelse([$3], , :, [$3])
-      AC_MSG_RESULT(no)
-    else
-      ac_save_CFLAGS="$CFLAGS"
-      ac_save_LIBS="$LIBS"
-      CFLAGS="$CFLAGS $FT2_CFLAGS"
-      LIBS="$FT2_LIBS $LIBS"
-dnl
-dnl Sanity checks for the results of freetype-config to some extent
-dnl
-      AC_TRY_RUN([
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include <stdio.h>
-#include <stdlib.h>
-
-int
-main()
-{
-  FT_Library library;
-  FT_Error error;
-
-  error = FT_Init_FreeType(&library);
-
-  if (error)
-    return 1;
-  else
-  {
-    FT_Done_FreeType(library);
-    return 0;
-  }
-}
-],, no_ft=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
-      CFLAGS="$ac_save_CFLAGS"
-      LIBS="$ac_save_LIBS"
-    fi             # test $ft_config_version -lt $ft_min_version
-  fi               # test "x$enable_fttest" = "xyes"
-fi                 # test "$FT2_CONFIG" = "no"
-if test "x$ft_config_is_lt" != "xyes" ; then
-  if test "x$no_ft" = x ; then
-     AC_MSG_RESULT(yes)
-     ifelse([$2], , :, [$2])
-  else
-     AC_MSG_RESULT(no)
-     if test "$FT2_CONFIG" = "no" ; then
-       echo "*** The freetype-config script installed by FreeType 2 could not be found."
-       echo "*** If FreeType 2 was installed in PREFIX, make sure PREFIX/bin is in"
-       echo "*** your path, or set the FT2_CONFIG environment variable to the"
-       echo "*** full path to freetype-config."
-     else
-       echo "*** The FreeType test program failed to run.  If your system uses"
-       echo "*** shared libraries and they are installed outside the normal"
-       echo "*** system library path, make sure the variable LD_LIBRARY_PATH"
-       echo "*** (or whatever is appropiate for your system) is correctly set."
-     fi
-     FT2_CFLAGS=""
-     FT2_LIBS=""
-     ifelse([$3], , :, [$3])
-  fi
-  AC_SUBST(FT2_CFLAGS)
-  AC_SUBST(FT2_LIBS)
-fi
-])
--- a/build/macosx/universal/flight.mk
+++ b/build/macosx/universal/flight.mk
@@ -62,17 +62,16 @@ INSTALLER_DIR = camino/installer
 MOZ_PKG_APPNAME = camino
 APPNAME = Camino.app
 BUILDCONFIG_BASE = Contents/MacOS/chrome
 else # } {
 MOZ_PKG_APPNAME = $(MOZ_APP_NAME)
 APPNAME = $(MOZ_MACBUNDLE_NAME)
 INSTALLER_DIR = $(MOZ_BUILD_APP)/installer
 ifeq ($(MOZ_BUILD_APP),xulrunner) # {
-INSTALLER_DIR = xulrunner/installer/mac
 APPNAME = XUL.framework
 APP_CONTENTS = Versions/Current
 endif # } xulrunner
 BUILDCONFIG_BASE = $(APP_CONTENTS)/chrome
 endif # } !camino
 
 ifeq ($(MOZ_CHROME_FILE_FORMAT),jar)
 BUILDCONFIG = $(BUILDCONFIG_BASE)/toolkit.jar
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -2,36 +2,44 @@ import subprocess
 from devicemanager import DeviceManager, DMError, _pop_last_line
 import re
 import os
 import sys
 import tempfile
 
 class DeviceManagerADB(DeviceManager):
 
-  def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = None):
+  def __init__(self, host=None, port=20701, retrylimit=5, packageName='fennec',
+               adbPath='adb', deviceSerial=None):
     self.host = host
     self.port = port
     self.retrylimit = retrylimit
     self.retries = 0
     self._sock = None
     self.useRunAs = False
     self.haveRoot = False
     self.useDDCopy = False
     self.useZip = False
     self.packageName = None
     self.tempDir = None
 
-    if packageName:
-      self.packageName = packageName
-    else:
+    # the path to adb, or 'adb' to assume that it's on the PATH
+    self.adbPath = adbPath
+
+    # The serial number of the device to use with adb, used in cases
+    # where multiple devices are being managed by the same adb instance.
+    self.deviceSerial = deviceSerial
+
+    if packageName == 'fennec':
       if os.getenv('USER'):
         self.packageName = 'org.mozilla.fennec_' + os.getenv('USER')
       else:
         self.packageName = 'org.mozilla.fennec_'
+    elif packageName:
+      self.packageName = packageName
 
     # verify that we can run the adb command. can't continue otherwise
     self.verifyADB()
 
     # try to connect to the device over tcp/ip if we have a hostname
     if self.host:
       self.connectRemoteADB()
 
@@ -91,17 +99,21 @@ class DeviceManagerADB(DeviceManager):
     # prepend cwd and env to command if necessary
     if cwd:
       cmdline = "cd %s; %s" % (cwd, cmdline)
     if env:
       envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems()))
       cmdline = envstr + "; " + cmdline
 
     # all output should be in stdout
-    proc = subprocess.Popen(["adb", "shell", cmdline],
+    args=[self.adbPath]
+    if self.deviceSerial:
+        args.extend(['-s', self.deviceSerial])
+    args.extend(["shell", cmdline])
+    proc = subprocess.Popen(args,
                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     (stdout, stderr) = proc.communicate()
     outputfile.write(stdout.rstrip('\n'))
 
     lastline = _pop_last_line(outputfile)
     if lastline:
       m = re.search('([0-9]+)', lastline)
       if m:
@@ -144,17 +156,19 @@ class DeviceManagerADB(DeviceManager):
       return False
 
   # external function
   # returns:
   #  success: directory name
   #  failure: None
   def mkDir(self, name):
     try:
-      self.checkCmdAs(["shell", "mkdir", name])
+      result = self.runCmdAs(["shell", "mkdir", name]).stdout.read()
+      if 'read-only file system' in result.lower():
+        return None
       self.chmodDir(name)
       return name
     except:
       return None
 
   # make directory structure on the device
   # external function
   # returns:
@@ -518,20 +532,24 @@ class DeviceManagerADB(DeviceManager):
   #  success: path for device root
   #  failure: None
   def getDeviceRoot(self):
     # /mnt/sdcard/tests is preferred to /data/local/tests, but this can be
     # over-ridden by creating /data/local/tests
     testRoot = "/data/local/tests"
     if (self.dirExists(testRoot)):
       return testRoot
+
     root = "/mnt/sdcard"
-    if (not self.dirExists(root)):
-      root = "/data/local"
-    testRoot = root + "/tests"
+    if self.dirExists(root):
+      testRoot = root + "/tests"
+      if self.mkDir(testRoot):
+        return testRoot
+
+    testRoot = "/data/local/tests"
     if (not self.dirExists(testRoot)):
       self.mkDir(testRoot)
     return testRoot
 
   # Gets the temporary directory we are using on this device
   # base on our device root, ensuring also that it exists.
   #
   # internal function
@@ -666,36 +684,42 @@ class DeviceManagerADB(DeviceManager):
     if (directive == "systime" or directive == "all"):
       ret["systime"] = self.runCmd(["shell", "date"]).stdout.read()
     print ret
     return ret
 
   def runCmd(self, args):
     # If we are not root but have run-as, and we're trying to execute 
     # a shell command then using run-as is the best we can do
+    finalArgs = [self.adbPath]
+    if self.deviceSerial:
+      finalArgs.extend(['-s', self.deviceSerial])
     if (not self.haveRoot and self.useRunAs and args[0] == "shell" and args[1] != "run-as"):
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
-    args.insert(0, "adb")
-    return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    finalArgs.extend(args)
+    return subprocess.Popen(finalArgs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
   def runCmdAs(self, args):
     if self.useRunAs:
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
     return self.runCmd(args)
 
   def checkCmd(self, args):
     # If we are not root but have run-as, and we're trying to execute 
     # a shell command then using run-as is the best we can do
+    finalArgs = [self.adbPath]
+    if self.deviceSerial:
+      finalArgs.extend(['-s', self.deviceSerial])
     if (not self.haveRoot and self.useRunAs and args[0] == "shell" and args[1] != "run-as"):
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
-    args.insert(0, "adb")
-    return subprocess.check_call(args)
+    finalArgs.extend(args)
+    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)
 
   def chmodDir(self, remoteDir):
@@ -710,24 +734,45 @@ class DeviceManagerADB(DeviceManager):
       self.checkCmdAs(["shell", "chmod", "777", remoteDir])
       print "chmod " + remoteDir
     else:
       self.checkCmdAs(["shell", "chmod", "777", remoteDir.strip()])
       print "chmod " + remoteDir.strip()
 
   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:
       self.checkCmd(["version"])
     except os.error, err:
       raise DMError("unable to execute ADB (%s): ensure Android SDK is installed and adb is in your $PATH" % err)
     except subprocess.CalledProcessError:
       raise DMError("unable to execute ADB: ensure Android SDK is installed and adb is in your $PATH")
 
   def verifyDevice(self):
+    # If there is a device serial number, see if adb is connected to it
+    if self.deviceSerial:
+      deviceStatus = None
+      proc = subprocess.Popen([self.adbPath, "devices"],
+                              stdout=subprocess.PIPE,
+                              stderr=subprocess.STDOUT)
+      for line in proc.stdout:
+        m = re.match('(.+)?\s+(.+)$', line)
+        if m:
+          if self.deviceSerial == m.group(1):
+            deviceStatus = m.group(2)
+      if deviceStatus == None:
+        raise DMError("device not found: %s" % self.deviceSerial)
+      elif deviceStatus != "device":
+        raise DMError("bad status for device %s: %s" % (self.deviceSerial,
+                                                        deviceStatus))
+
     # Check to see if we can connect to device and run a simple command
     try:
       self.checkCmd(["shell", "echo"])
     except subprocess.CalledProcessError:
       raise DMError("unable to connect to device: is it plugged in?")
 
   def verifyRoot(self):
     # a test to see if we have root privs
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -193,16 +193,54 @@ GetPrincipalDomainOrigin(nsIPrincipal* a
 }
 
 static nsIScriptContext *
 GetScriptContext(JSContext *cx)
 {
     return GetScriptContextFromJSContext(cx);
 }
 
+// Callbacks for the JS engine to use to push/pop context principals.
+static JSBool
+PushPrincipalCallback(JSContext *cx, JSPrincipals *principals)
+{
+    // We should already be in the compartment of the given principal.
+    MOZ_ASSERT(principals ==
+               JS_GetCompartmentPrincipals((js::GetContextCompartment(cx))));
+
+    // Get the security manager.
+    nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
+    if (!ssm) {
+        return true;
+    }
+
+    // Push the principal.
+    JSStackFrame *fp = NULL;
+    nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp),
+                                            nsJSPrincipals::get(principals));
+    if (NS_FAILED(rv)) {
+        JS_ReportOutOfMemory(cx);
+        return false;
+    }
+
+    return true;
+}
+
+static JSBool
+PopPrincipalCallback(JSContext *cx)
+{
+    nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
+    if (ssm) {
+        ssm->PopContextPrincipal(cx);
+    }
+
+    return true;
+}
+
+
 inline void SetPendingException(JSContext *cx, const char *aMsg)
 {
     JSAutoRequest ar(cx);
     JS_ReportError(cx, "%s", aMsg);
 }
 
 inline void SetPendingException(JSContext *cx, const PRUnichar *aMsg)
 {
@@ -3386,17 +3424,19 @@ nsresult nsScriptSecurityManager::Init()
 
     rv = runtimeService->GetRuntime(&sRuntime);
     NS_ENSURE_SUCCESS(rv, rv);
 
     static const JSSecurityCallbacks securityCallbacks = {
         CheckObjectAccess,
         nsJSPrincipals::Subsume,
         ObjectPrincipalFinder,
-        ContentSecurityPolicyPermitsJSAction
+        ContentSecurityPolicyPermitsJSAction,
+        PushPrincipalCallback,
+        PopPrincipalCallback
     };
 
     MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
     JS_SetSecurityCallbacks(sRuntime, &securityCallbacks);
     JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy);
 
     JS_SetTrustedPrincipals(sRuntime, system);
 
--- a/client.mk
+++ b/client.mk
@@ -363,18 +363,17 @@ ifdef MOZ_PREFLIGHT
 	for mkfile in $(MOZ_PREFLIGHT); do \
 	  $(MAKE) -f $(TOPSRCDIR)/$$mkfile preflight TOPSRCDIR=$(TOPSRCDIR) OBJDIR=$(OBJDIR) MOZ_OBJDIR=$(MOZ_OBJDIR); \
 	done
 endif
 
 ####################################
 # Build it
 
-realbuild::  $(OBJDIR)/Makefile $(OBJDIR)/config.status
-	@$(PYTHON) $(TOPSRCDIR)/js/src/config/check-sync-dirs.py $(TOPSRCDIR)/js/src/config $(TOPSRCDIR)/config
+realbuild::  $(OBJDIR)/Makefile $(OBJDIR)/config.status check-sync-dirs-config
 	$(MOZ_MAKE)
 
 ####################################
 # Other targets
 
 # Pass these target onto the real build system
 $(OBJDIR_TARGETS):: $(OBJDIR)/Makefile $(OBJDIR)/config.status
 	$(MOZ_MAKE) $@
@@ -422,16 +421,22 @@ cleansrcdir:
 	else \
 	  echo "Removing object files from srcdir..."; \
 	  rm -fr `find . -type d \( -name .deps -print -o -name CVS \
 	          -o -exec test ! -d {}/CVS \; \) -prune \
 	          -o \( -name '*.[ao]' -o -name '*.so' \) -type f -print`; \
 	   build/autoconf/clean-config.sh; \
 	fi;
 
+## Sanity check $X and js/src/$X are in sync
+.PHONY: check-sync-dirs
+check-sync-dirs: check-sync-dirs-build check-sync-dirs-config
+check-sync-dirs-%:
+	@$(PYTHON) $(TOPSRCDIR)/js/src/config/check-sync-dirs.py $(TOPSRCDIR)/js/src/$* $(TOPSRCDIR)/$*
+
 echo-variable-%:
 	@echo $($*)
 
 # This makefile doesn't support parallel execution. It does pass
 # MOZ_MAKE_FLAGS to sub-make processes, so they will correctly execute
 # in parallel.
 .NOTPARALLEL:
 
--- a/config/expandlibs_gen.py
+++ b/config/expandlibs_gen.py
@@ -42,16 +42,21 @@ import sys
 import os
 import expandlibs_config as conf
 from expandlibs import LibDescriptor, isObject
 
 def generate(args):
     desc = LibDescriptor()
     for arg in args:
         if isObject(arg):
-            desc['OBJS'].append(os.path.abspath(arg))
-        elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX and \
-             (os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX)):
-            desc['LIBS'].append(os.path.abspath(arg))
+            if os.path.exists(arg):
+                desc['OBJS'].append(os.path.abspath(arg))
+            else:
+                raise Exception("File not found: %s" % arg)
+        elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX:
+            if os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
+                desc['LIBS'].append(os.path.abspath(arg))
+            else:
+                raise Exception("File not found: %s" % arg)
     return desc
 
 if __name__ == '__main__':
     print generate(sys.argv[1:])
--- a/config/tests/unit-expandlibs.py
+++ b/config/tests/unit-expandlibs.py
@@ -140,16 +140,19 @@ class TestExpandLibsGen(TestCaseWithTmpD
                  [Lib('a'), Obj('b'), Lib('c'), Obj('d'), Obj('e'), Lib('f')]]
         self.touch(files[:-1])
         self.touch([files[-1] + config.LIBS_DESC_SUFFIX])
 
         desc = generate(files)
         self.assertEqual(desc['OBJS'], [self.tmpfile(Obj(s)) for s in ['b', 'd', 'e']])
         self.assertEqual(desc['LIBS'], [self.tmpfile(Lib(s)) for s in ['a', 'c', 'f']])
 
+        self.assertRaises(Exception, generate, files + [self.tmpfile(Obj('z'))])
+        self.assertRaises(Exception, generate, files + [self.tmpfile(Lib('y'))])
+
 class TestExpandInit(TestCaseWithTmpDir):
     def init(self):
         ''' Initializes test environment for library expansion tests'''
         super(TestExpandInit, self).init()
         # Create 2 fake libraries, each containing 3 objects, and the second
         # including the first one and another library.
         os.mkdir(self.tmpfile('libx'))
         os.mkdir(self.tmpfile('liby'))
--- a/configure.in
+++ b/configure.in
@@ -3375,17 +3375,17 @@ else
             [XSS_LIBS="-lXss $XEXT_LIBS $XLIBS"
              AC_DEFINE(HAVE_LIBXSS)],, $XEXT_LIBS $XLIBS))
 
 	LDFLAGS="$_SAVE_LDFLAGS"
 
     dnl ========================================================
     dnl = Check for freetype2 and its functionality
     dnl ========================================================
-    AC_CHECK_FT2(6.1.0, [_HAVE_FREETYPE2=1], [_HAVE_FREETYPE2=])
+    PKG_CHECK_MODULES(FT2, freetype2 >= 6.1.0, _HAVE_FREETYPE2=1, _HAVE_FREETYPE2=)
 
     if test "$_HAVE_FREETYPE2"; then
     	_SAVE_LIBS="$LIBS"
     	_SAVE_CFLAGS="$CFLAGS"
     	LIBS="$LIBS $FT2_LIBS"
     	CFLAGS="$CFLAGS $FT2_CFLAGS"
 
         AC_CACHE_CHECK(for FT_Bitmap_Size.y_ppem,
@@ -7209,23 +7209,16 @@ else
     rm crtdll.obj
 
     export DLLFLAGS
     ;;
   *)
     AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
     ;;
   esac
-
-  if test "$OS_ARCH" != "WINNT"; then
-    dnl NB: this must be kept in sync with jemalloc.h
-    AC_DEFINE(HAVE_JEMALLOC_VALLOC)
-  fi
-  AC_DEFINE(HAVE_JEMALLOC_POSIX_MEMALIGN)
-  AC_DEFINE(HAVE_JEMALLOC_MEMALIGN)
 fi # MOZ_MEMORY
 AC_SUBST(MOZ_MEMORY)
 AC_SUBST(MOZ_GLUE_LDFLAGS)
 AC_SUBST(MOZ_GLUE_PROGRAM_LDFLAGS)
 AC_SUBST(WIN32_CRT_LIBS)
 dnl Need to set this for make because NSS doesn't have configure
 AC_SUBST(DLLFLAGS)
 
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -795,19 +795,24 @@ public:
 
   /**
    * Get the inline style rule, if any, for this content node
    */
   virtual mozilla::css::StyleRule* GetInlineStyleRule() = 0;
 
   /**
    * Set the inline style rule for this node.  This will send an
-   * appropriate AttributeChanged notification if aNotify is true.
+   * appropriate AttributeChanged notification if aNotify is true.  If
+   * a serialized form of aStyleRule is available, a pointer to it
+   * should be passed in aSerialized.  Otherwise, aSerialized should
+   * be null.
    */
-  NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, bool aNotify) = 0;
+  NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule,
+                                const nsAString* aSerialized,
+                                bool aNotify) = 0;
 
   /**
    * Is the attribute named stored in the mapped attributes?
    *
    * // XXXbz we use this method in HasAttributeDependentStyle, so svg
    *    returns true here even though it stores nothing in the mapped
    *    attributes.
    */
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1637,17 +1637,17 @@ public:
   // only appear at the top of the DOM tree, we have a specialized measurement
   // function which returns multiple sizes.
   virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const;
   // DocSizeOfIncludingThis doesn't need to be overridden by sub-classes
   // because nsIDocument inherits from nsINode;  see the comment above the
   // declaration of nsINode::SizeOfIncludingThis.
   virtual void DocSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const;
 
-  PRBool MayHaveDOMMutationObservers()
+  bool MayHaveDOMMutationObservers()
   {
     return mMayHaveDOMMutationObservers;
   }
 
   void SetMayHaveDOMMutationObservers()
   {
     mMayHaveDOMMutationObservers = true;
   }
--- a/content/base/src/nsDOMMutationObserver.cpp
+++ b/content/base/src/nsDOMMutationObserver.cpp
@@ -380,16 +380,22 @@ nsMutationReceiver::ContentRemoved(nsIDo
     m->mPreviousSibling = aPreviousSibling;
     m->mNextSibling = parent->GetChildAt(aIndexInContainer);
   }
   // We need to schedule always, so that after microtask mTransientReceivers
   // can be cleared correctly.
   Observer()->ScheduleForRun();
 }
 
+void nsMutationReceiver::NodeWillBeDestroyed(const nsINode *aNode)
+{
+  NS_ASSERTION(!mParent, "Shouldn't have mParent here!");
+  Disconnect(true);
+}
+
 // Observer
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMutationObserver)
 
 DOMCI_DATA(MozMutationObserver, nsDOMMutationObserver)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMMutationObserver)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozMutationObserver)
--- a/content/base/src/nsDOMMutationObserver.h
+++ b/content/base/src/nsDOMMutationObserver.h
@@ -260,44 +260,22 @@ public:
 
   void Disconnect(bool aRemoveFromObserver);
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMUTATION_OBSERVER_IID)
   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsMutationReceiver)
 
-  virtual void AttributeWillChange(nsIDocument* aDocument,
-                                   mozilla::dom::Element* aElement,
-                                   PRInt32 aNameSpaceID,
-                                   nsIAtom* aAttribute,
-                                   PRInt32 aModType);
-  virtual void CharacterDataWillChange(nsIDocument *aDocument,
-                                       nsIContent* aContent,
-                                       CharacterDataChangeInfo* aInfo);
-  virtual void ContentAppended(nsIDocument *aDocument,
-                               nsIContent* aContainer,
-                               nsIContent* aFirstNewContent,
-                               PRInt32     aNewIndexInContainer);
-  virtual void ContentInserted(nsIDocument *aDocument,
-                               nsIContent* aContainer,
-                               nsIContent* aChild,
-                               PRInt32 aIndexInContainer);
-  virtual void ContentRemoved(nsIDocument *aDocument,
-                              nsIContent* aContainer,
-                              nsIContent* aChild,
-                              PRInt32 aIndexInContainer,
-                              nsIContent* aPreviousSibling);
-
-  virtual void NodeWillBeDestroyed(const nsINode *aNode)
-  {
-    NS_ASSERTION(!mParent, "Shouldn't have mParent here!");
-    Disconnect(true);
-  }
-  
+  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
+  NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
+  NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsMutationReceiver, NS_MUTATION_OBSERVER_IID)
 
 class nsDOMMutationObserver : public nsIDOMMozMutationObserver,
                               public nsIJSNativeInitializer
 {
 public:
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3148,18 +3148,20 @@ nsDocument::TryChannelCharset(nsIChannel
   if(kCharsetFromChannel <= aCharsetSource) {
     return true;
   }
 
   if (aChannel) {
     nsCAutoString charsetVal;
     nsresult rv = aChannel->GetContentCharset(charsetVal);
     if (NS_SUCCEEDED(rv)) {
-      rv = nsCharsetAlias::GetPreferred(charsetVal, aCharset);
+      nsCAutoString preferred;
+      rv = nsCharsetAlias::GetPreferred(charsetVal, preferred);
       if(NS_SUCCEEDED(rv)) {
+        aCharset = preferred;
         aCharsetSource = kCharsetFromChannel;
         return true;
       } else if (aExecutor && !charsetVal.IsEmpty()) {
         aExecutor->ComplainAboutBogusProtocolCharset(this);
       }
     }
   }
   return false;
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -975,16 +975,17 @@ nsGenericDOMDataNode::SetSMILOverrideSty
 css::StyleRule*
 nsGenericDOMDataNode::GetInlineStyleRule()
 {
   return nsnull;
 }
 
 NS_IMETHODIMP
 nsGenericDOMDataNode::SetInlineStyleRule(css::StyleRule* aStyleRule,
+                                         const nsAString* aSerialized,
                                          bool aNotify)
 {
   NS_NOTREACHED("How come we're setting inline style on a non-element?");
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP_(bool)
 nsGenericDOMDataNode::IsAttributeMapped(const nsIAtom* aAttribute) const
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -243,17 +243,18 @@ public:
   virtual nsIContent *GetBindingParent() const;
   virtual bool IsNodeOfType(PRUint32 aFlags) const;
   virtual bool IsLink(nsIURI** aURI) const;
 
   virtual nsIAtom* DoGetID() const;
   virtual const nsAttrValue* DoGetClasses() const;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
   virtual mozilla::css::StyleRule* GetInlineStyleRule();
-  NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, bool aNotify);
+  NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule,
+                                const nsAString* aSerialized, bool aNotify);
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
   virtual nsIAtom *GetClassAttributeName() const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
   {
     *aResult = CloneDataNode(aNodeInfo, true);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -3604,16 +3604,17 @@ nsGenericElement::SetSMILOverrideStyleRu
 css::StyleRule*
 nsGenericElement::GetInlineStyleRule()
 {
   return nsnull;
 }
 
 NS_IMETHODIMP
 nsGenericElement::SetInlineStyleRule(css::StyleRule* aStyleRule,
+                                     const nsAString* aSerialized,
                                      bool aNotify)
 {
   NS_NOTYETIMPLEMENTED("nsGenericElement::SetInlineStyleRule");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP_(bool)
 nsGenericElement::IsAttributeMapped(const nsIAtom* aAttribute) const
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -363,17 +363,19 @@ public:
   virtual void DumpContent(FILE* out, PRInt32 aIndent, bool aDumpAll) const;
   void List(FILE* out, PRInt32 aIndent, const nsCString& aPrefix) const;
   void ListAttributes(FILE* out) const;
 #endif
 
   virtual const nsAttrValue* DoGetClasses() const;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
   virtual mozilla::css::StyleRule* GetInlineStyleRule();
-  NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, bool aNotify);
+  NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule,
+                                const nsAString* aSerialized,
+                                bool aNotify);
   NS_IMETHOD_(bool)
     IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
   /*
    * Attribute Mapping Helpers
    */
   struct MappedAttributeEntry {
@@ -1041,16 +1043,35 @@ nsresult                                
   DOMCI_DATA(_interface, _class)                                        \
   nsXPCClassInfo* _class::GetClassInfo()                                \
   {                                                                     \
     return static_cast<nsXPCClassInfo*>(                                \
       NS_GetDOMClassInfoInstance(eDOMClassInfo_##_interface##_id));     \
   }
 
 /**
+ * A macro to implement the getter and setter for a given string
+ * valued content property. The method uses the generic GetAttr and
+ * SetAttr methods.  We use the 5-argument form of SetAttr, because
+ * some consumers only implement that one, hiding superclass
+ * 4-argument forms.
+ */
+#define NS_IMPL_STRING_ATTR(_class, _method, _atom)                     \
+  NS_IMETHODIMP                                                         \
+  _class::Get##_method(nsAString& aValue)                               \
+  {                                                                     \
+    return GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue);        \
+  }                                                                     \
+  NS_IMETHODIMP                                                         \
+  _class::Set##_method(const nsAString& aValue)                         \
+  {                                                                     \
+    return SetAttr(kNameSpaceID_None, nsGkAtoms::_atom, nsnull, aValue, true); \
+  }
+
+/**
  * Tearoff class to implement nsITouchEventReceiver
  */
 class nsTouchEventReceiverTearoff : public nsITouchEventReceiver
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_FORWARD_NSITOUCHEVENTRECEIVER(mElement->)
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -2032,16 +2032,17 @@ GK_ATOM(containerBusy, "container-busy")
 GK_ATOM(containerLive, "container-live")
 GK_ATOM(containerLiveRole, "container-live-role")
 GK_ATOM(containerRelevant, "container-relevant")
 GK_ATOM(cycles, "cycles")
 GK_ATOM(datatable, "datatable")
 GK_ATOM(droppable, "droppable")
 GK_ATOM(eventFromInput, "event-from-input")
 GK_ATOM(InlineBlockFrame, "InlineBlockFrame")
+GK_ATOM(inlinevalue, "inline")
 GK_ATOM(invalid, "invalid")
 GK_ATOM(item, "item")
 GK_ATOM(itemset, "itemset")
 GK_ATOM(lineNumber, "line-number")
 GK_ATOM(linkedPanel, "linkedpanel")
 GK_ATOM(live, "live")
 GK_ATOM(marginBottom, "margin-bottom")
 GK_ATOM(marginLeft, "margin-left")
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -158,16 +158,17 @@ nsStyledElementNotElementCSSInlineStyle:
   }
 
   return nsGenericElement::AfterSetAttr(aNamespaceID, aAttribute, aValue,
                                         aNotify);
 }
 
 NS_IMETHODIMP
 nsStyledElementNotElementCSSInlineStyle::SetInlineStyleRule(css::StyleRule* aStyleRule,
+                                                            const nsAString* aSerialized,
                                                             bool aNotify)
 {
   SetMayHaveStyle();
   bool modification = false;
   nsAttrValue oldValue;
 
   bool hasListeners = aNotify &&
     nsContentUtils::HasMutationListeners(this,
@@ -188,17 +189,17 @@ nsStyledElementNotElementCSSInlineStyle:
     if (modification) {
       oldValue.SetTo(oldValueStr);
     }
   }
   else if (aNotify && IsInDoc()) {
     modification = !!mAttrsAndChildren.GetAttr(nsGkAtoms::style);
   }
 
-  nsAttrValue attrValue(aStyleRule, nsnull);
+  nsAttrValue attrValue(aStyleRule, aSerialized);
 
   // XXXbz do we ever end up with ADDITION here?  I doubt it.
   PRUint8 modType = modification ?
     static_cast<PRUint8>(nsIDOMMutationEvent::MODIFICATION) :
     static_cast<PRUint8>(nsIDOMMutationEvent::ADDITION);
 
   return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nsnull,
                           oldValue, attrValue, modType, hasListeners,
--- a/content/base/src/nsStyledElement.h
+++ b/content/base/src/nsStyledElement.h
@@ -69,17 +69,19 @@ protected:
 public:
   // nsIContent interface methods
   virtual nsIAtom* GetClassAttributeName() const;
   virtual nsIAtom* GetIDAttributeName() const;
   virtual nsIAtom* DoGetID() const;
   virtual const nsAttrValue* DoGetClasses() const;
 
   virtual mozilla::css::StyleRule* GetInlineStyleRule();
-  NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, bool aNotify);
+  NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule,
+                                const nsAString* aSerialized,
+                                bool aNotify);
 
   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify);
   virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                                 const nsAttrValue* aValue, bool aNotify);
 
   nsIDOMCSSStyleDeclaration* GetStyle(nsresult* retval);
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/test_bug737966.js
@@ -0,0 +1,20 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* If charset parameter is invalid, the encoding should be detected as UTF-8 */
+
+function run_test()
+{
+  let body = '<?xml version="1.0"><html>%c3%80</html>';
+  let result = '<?xml version="1.0"><html>\u00c0</html>';
+
+  let xhr = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1'].
+            createInstance(Components.interfaces.nsIXMLHttpRequest);
+  xhr.open('GET',
+           'data:text/xml;charset=abc,' + body,
+           false);
+  xhr.send(null);
+
+  do_check_eq(xhr.responseText, result);
+}
--- a/content/base/test/unit/xpcshell.ini
+++ b/content/base/test/unit/xpcshell.ini
@@ -1,11 +1,12 @@
 [DEFAULT]
 head = head_utilities.js
 tail = 
 
 [test_bug553888.js]
 [test_bug558431.js]
+[test_bug737966.js]
 [test_csputils.js]
 [test_error_codes.js]
 [test_thirdpartyutil.js]
 [test_xhr_standalone.js]
 [test_xmlserializer.js]
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -3117,28 +3117,30 @@ NS_IMETHODIMP
 WebGLContext::Hint(WebGLenum target, WebGLenum mode)
 {
     if (!IsContextStable())
         return NS_OK;
 
     bool isValid = false;
 
     switch (target) {
+        case LOCAL_GL_GENERATE_MIPMAP_HINT:
+            isValid = true;
+            break;
         case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
             if (mEnabledExtensions[WebGL_OES_standard_derivatives]) 
                 isValid = true;
             break;
     }
 
-    if (isValid) {
-        gl->fHint(target, mode);
-        return NS_OK;
-    }
-
-    return ErrorInvalidEnum("hint: invalid hint");
+    if (!isValid)
+        return ErrorInvalidEnum("hint: invalid hint");
+
+    gl->fHint(target, mode);
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::IsBuffer(nsIWebGLBuffer *bobj, WebGLboolean *retval)
 {
     if (!IsContextStable())
     {
         *retval = false;
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -891,17 +891,18 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa
       newEvent = new nsMozTouchEvent(false, msg, nsnull,
                                      static_cast<nsMozTouchEvent*>(mEvent)->streamId);
       NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
       isInputEvent = true;
       break;
     }
     case NS_TOUCH_EVENT:
     {
-      newEvent = new nsTouchEvent(false, msg, nsnull);
+      nsTouchEvent *oldTouchEvent = static_cast<nsTouchEvent*>(mEvent);
+      newEvent = new nsTouchEvent(false, oldTouchEvent);
       NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
       isInputEvent = true;
       break;
     }
     default:
     {
       NS_WARNING("Unknown event type!!!");
       return NS_ERROR_FAILURE;
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -285,26 +285,19 @@ nsEventListenerManager::AddEventListener
     if (window) {
       // If aType is NS_MUTATION_SUBTREEMODIFIED, we need to listen all
       // mutations. nsContentUtils::HasMutationListeners relies on this.
       window->SetMutationListeners((aType == NS_MUTATION_SUBTREEMODIFIED) ?
                                    kAllMutationBits :
                                    MutationBitForEventType(aType));
     }
   } else if (aTypeAtom == nsGkAtoms::ondeviceorientation) {
-     nsPIDOMWindow* window = GetInnerWindowForTarget();
-     if (window)
-       window->EnableDeviceSensor(SENSOR_ORIENTATION);
+    EnableDevice(NS_DEVICE_ORIENTATION);
   } else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
-    nsPIDOMWindow* window = GetInnerWindowForTarget();
-    if (window) {
-      window->EnableDeviceSensor(SENSOR_ACCELERATION);
-      window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
-      window->EnableDeviceSensor(SENSOR_GYROSCOPE);
-    }
+    EnableDevice(NS_DEVICE_MOTION);
   } else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) ||
              (aTypeAtom == nsGkAtoms::ontouchstart ||
               aTypeAtom == nsGkAtoms::ontouchend ||
               aTypeAtom == nsGkAtoms::ontouchmove ||
               aTypeAtom == nsGkAtoms::ontouchenter ||
               aTypeAtom == nsGkAtoms::ontouchleave ||
               aTypeAtom == nsGkAtoms::ontouchcancel)) {
     mMayHaveTouchEventListener = true;
@@ -336,22 +329,50 @@ nsEventListenerManager::IsDeviceType(PRU
       return true;
     default:
       break;
   }
   return false;
 }
 
 void
-nsEventListenerManager::DisableDevice(PRUint32 aType)
+nsEventListenerManager::EnableDevice(PRUint32 aType)
 {
-  nsPIDOMWindow* window = GetInnerWindowForTarget();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget);
   if (!window) {
     return;
   }
+
+  NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window");
+
+  switch (aType) {
+    case NS_DEVICE_ORIENTATION:
+      window->EnableDeviceSensor(SENSOR_ORIENTATION);
+      break;
+    case NS_DEVICE_MOTION:
+      window->EnableDeviceSensor(SENSOR_ACCELERATION);
+      window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
+      window->EnableDeviceSensor(SENSOR_GYROSCOPE);
+      break;
+    default:
+      NS_WARNING("Enabling an unknown device sensor.");
+      break;
+  }
+}
+
+void
+nsEventListenerManager::DisableDevice(PRUint32 aType)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget);
+  if (!window) {
+    return;
+  }
+
+  NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window");
+
   switch (aType) {
     case NS_DEVICE_ORIENTATION:
       window->DisableDeviceSensor(SENSOR_ORIENTATION);
       break;
     case NS_DEVICE_MOTION:
       window->DisableDeviceSensor(SENSOR_ACCELERATION);
       window->DisableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
       window->DisableDeviceSensor(SENSOR_GYROSCOPE);
@@ -372,38 +393,39 @@ nsEventListenerManager::RemoveEventListe
     return;
   }
 
   nsListenerStruct* ls;
   aFlags &= ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
 
   PRUint32 count = mListeners.Length();
   PRUint32 typeCount = 0;
+  bool deviceType = IsDeviceType(aType);
 
   for (PRUint32 i = 0; i < count; ++i) {
     ls = &mListeners.ElementAt(i);
     if (EVENT_TYPE_EQUALS(ls, aType, aUserType)) {
       ++typeCount;
       if (ls->mListener == aListener &&
           (ls->mFlags & ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED) == aFlags) {
         nsRefPtr<nsEventListenerManager> kungFuDeathGrip = this;
         mListeners.RemoveElementAt(i);
         --count;
         mNoListenerForEvent = NS_EVENT_TYPE_NULL;
         mNoListenerForEventAtom = nsnull;
 
-        if (!IsDeviceType(aType)) {
+        if (deviceType) {
           return;
         }
         --typeCount;
       }
     }
   }
 
-  if (typeCount == 0) {
+  if (deviceType && typeCount == 0) {
     DisableDevice(aType);
   }
 }
 
 static inline bool
 ListenerCanHandle(nsListenerStruct* aLs, nsEvent* aEvent)
 {
   // This is slightly different from EVENT_TYPE_EQUALS in that it returns
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -279,16 +279,17 @@ protected:
   nsresult SetJSEventListener(nsIScriptContext *aContext,
                               JSObject* aScopeGlobal,
                               nsIAtom* aName,
                               JSObject *aHandler,
                               bool aPermitUntrustedEvents,
                               nsListenerStruct **aListenerStruct);
 
   bool IsDeviceType(PRUint32 aType);
+  void EnableDevice(PRUint32 aType);
   void DisableDevice(PRUint32 aType);
 
 public:
   /**
    * Set the "inline" event listener for aEventName to |v|.  This
    * might actually remove the event listener, depending on the value
    * of |v|.
    */
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -109,16 +109,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug667919-1.html \
 		test_bug667919-2.html \
 		test_bug667612.html \
 		empty.js \
 		test_bug689564.html \
 		test_bug698929.html \
 		test_eventctors.html \
 		test_bug635465.html \
+		test_bug741666.html \
 		$(NULL)
 
 #bug 585630
 ifneq (mobile,$(MOZ_BUILD_APP))
 _TEST_FILES += \
 		test_dragstart.html \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_bug741666.html
@@ -0,0 +1,176 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=741666
+-->
+<head>
+  <title>Test for Bug 741666</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741666">Mozilla Bug 741666</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+
+/** Test for Bug 306008 - Touch events with a reference held should retain their touch lists **/
+
+let tests = [], testTarget, parent;
+
+let touch = {
+  id: 0,
+  point: {x: 0, y: 0},
+  radius: {x: 0, y: 0},
+  rotation: 0,
+  force: 0.5,
+  target: null
+}
+
+function nextTest() {
+  if (tests.length)
+    SimpleTest.executeSoon(tests.shift());
+}
+
+function checkEvent(aFakeEvent, aTouches) {
+  return function(aEvent, aTrusted) {
+    is(aFakeEvent.ctrlKey, aEvent.ctrlKey, "Correct ctrlKey");
+    is(aFakeEvent.altKey, aEvent.altKey, "Correct altKey");
+    is(aFakeEvent.shiftKey, aEvent.shiftKey, "Correct shiftKey");
+    is(aFakeEvent.metaKey, aEvent.metaKey, "Correct metaKey");
+    is(aEvent.isTrusted, aTrusted, "Event is trusted");
+    checkTouches(aFakeEvent[aTouches], aEvent[aTouches]);
+  }
+}
+
+function checkTouches(aTouches1, aTouches2) {
+  is(aTouches1.length, aTouches2.length, "Correct touches length");
+  for (var i = 0; i < aTouches1.length; i++) {
+    checkTouch(aTouches1[i], aTouches2[i]);
+  }
+}
+
+function checkTouch(aFakeTouch, aTouch) {
+  is(aFakeTouch.identifier, aTouch.identifier, "Touch has correct identifier");
+  is(aFakeTouch.target, aTouch.target, "Touch has correct target");
+  is(aFakeTouch.page.x, aTouch.pageX, "Touch has correct pageX");
+  is(aFakeTouch.page.y, aTouch.pageY, "Touch has correct pageY");
+  is(aFakeTouch.page.x + Math.round(window.mozInnerScreenX), aTouch.screenX, "Touch has correct screenX");
+  is(aFakeTouch.page.y + Math.round(window.mozInnerScreenY), aTouch.screenY, "Touch has correct screenY");
+  is(aFakeTouch.page.x, aTouch.clientX, "Touch has correct clientX");
+  is(aFakeTouch.page.y, aTouch.clientY, "Touch has correct clientY");
+  is(aFakeTouch.radius.x, aTouch.radiusX, "Touch has correct radiusX");
+  is(aFakeTouch.radius.y, aTouch.radiusY, "Touch has correct radiusY");
+  is(aFakeTouch.rotationAngle, aTouch.rotationAngle, "Touch has correct rotationAngle");
+  is(aFakeTouch.force, aTouch.force, "Touch has correct force");
+}
+
+function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
+  var ids = [], xs=[], ys=[], rxs = [], rys = [],
+      rotations = [], forces = [];
+
+  for each (var touchType in ["touches", "changedTouches", "targetTouches"]) {
+    for (var i = 0; i < aEvent[touchType].length; i++) {
+      if (ids.indexOf(aEvent[touchType][i].identifier) == -1) {
+        ids.push(aEvent[touchType][i].identifier);
+        xs.push(aEvent[touchType][i].page.x);
+        ys.push(aEvent[touchType][i].page.y);
+        rxs.push(aEvent[touchType][i].radius.x);
+        rys.push(aEvent[touchType][i].radius.y);
+        rotations.push(aEvent[touchType][i].rotationAngle);
+        forces.push(aEvent[touchType][i].force);
+      }
+    }
+  }
+  return windowUtils.sendTouchEvent(aType,
+                                    ids, xs, ys, rxs, rys,
+                                    rotations, forces,
+                                    ids.length, aModifiers, 0);
+}
+
+function touchEvent(aOptions) {
+  if (!aOptions) {
+    aOptions = {};
+  }
+  this.ctrlKey = aOptions.ctrlKey || false;
+  this.altKey = aOptions.altKey || false;
+  this.shiftKey = aOptions.shiftKey || false;
+  this.metaKey = aOptions.metaKey || false;
+  this.touches = aOptions.touches || [];
+  this.targetTouches = aOptions.targetTouches || [];
+  this.changedTouches = aOptions.changedTouches || [];
+}
+
+function testtouch(aOptions) {
+  if (!aOptions)
+    aOptions = {};
+  this.identifier = aOptions.identifier || 0;
+  this.target = aOptions.target || 0;
+  this.page = aOptions.page || {x: 0, y: 0};
+  this.radius = aOptions.radius || {x: 0, y: 0};
+  this.rotationAngle = aOptions.rotationAngle || 0;
+  this.force = aOptions.force || 1;
+}
+
+function testPreventDefault(name) {
+  let cwu = SpecialPowers.getDOMWindowUtils(window);
+  let target = document.getElementById("testTarget");
+  let bcr = target.getBoundingClientRect();
+
+  let touch1 = new testtouch({
+    page: {x: Math.round(bcr.left + bcr.width/2),
+           y: Math.round(bcr.top  + bcr.height/2)},
+    target: target
+  });
+
+  let event = new touchEvent({
+    touches: [touch1],
+    targetTouches: [touch1],
+    changedTouches: [touch1]
+  });
+
+  // test touchstart event fires correctly
+  var checkTouches = checkEvent(event, "touches");
+  var checkTargetTouches = checkEvent(event, "targetTouches");
+
+  /* This is the heart of the test. Verify that the touch event
+     looks correct both in and outside of a setTimeout */
+  window.addEventListener("touchstart", function(firedEvent) {
+    checkTouches(firedEvent, true);
+    setTimeout(function() {
+      checkTouches(firedEvent, true);
+      checkTargetTouches(firedEvent, true);
+
+      event.touches = [];
+      event.targetTouches = [];
+      sendTouchEvent(cwu, "touchend", event, 0);
+
+      nextTest();
+    }, 0);
+  }, false);
+  sendTouchEvent(cwu, "touchstart", event, 0);
+}
+
+function doTest() {
+  tests.push(testPreventDefault);
+
+  tests.push(function() {
+    SimpleTest.finish();
+  });
+
+  nextTest();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(doTest);
+
+</script>
+</pre>
+<div id="parent">
+  <span id="testTarget" style="padding: 5px; border: 1px solid black;">testTarget</span>
+</div>
+</body>
+</html>
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -309,33 +309,35 @@ nsGenericHTMLElement::DOMQueryInterface(
 nsresult
 nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst) const
 {
   nsresult rv;
   PRInt32 i, count = GetAttrCount();
   for (i = 0; i < count; ++i) {
     const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
     const nsAttrValue *value = mAttrsAndChildren.AttrAt(i);
+
+    nsAutoString valStr;
+    value->ToString(valStr);
+
     if (name->Equals(nsGkAtoms::style, kNameSpaceID_None) &&
         value->Type() == nsAttrValue::eCSSStyleRule) {
       // We can't just set this as a string, because that will fail
       // to reparse the string into style data until the node is
       // inserted into the document.  Clone the Rule instead.
       nsRefPtr<mozilla::css::Rule> ruleClone = value->GetCSSStyleRuleValue()->Clone();
       nsRefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(ruleClone);
       NS_ENSURE_TRUE(styleRule, NS_ERROR_UNEXPECTED);
 
-      rv = aDst->SetInlineStyleRule(styleRule, false);
+      rv = aDst->SetInlineStyleRule(styleRule, &valStr, false);
       NS_ENSURE_SUCCESS(rv, rv);
 
       continue;
     }
 
-    nsAutoString valStr;
-    value->ToString(valStr);
     rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
                        name->GetPrefix(), valStr, false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
@@ -2257,23 +2259,16 @@ nsGenericHTMLElement::MapScrollingAttrib
       }
     }
   }
 }
 
 //----------------------------------------------------------------------
 
 nsresult
-nsGenericHTMLElement::GetAttrHelper(nsIAtom* aAttr, nsAString& aValue)
-{
-  GetAttr(kNameSpaceID_None, aAttr, aValue);
-  return NS_OK;
-}
-
-nsresult
 nsGenericHTMLElement::SetAttrHelper(nsIAtom* aAttr, const nsAString& aValue)
 {
   return SetAttr(kNameSpaceID_None, aAttr, aValue, true);
 }
 
 nsresult
 nsGenericHTMLElement::SetBoolAttr(nsIAtom* aAttr, bool aValue)
 {
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -604,28 +604,16 @@ protected:
 
   virtual nsEventListenerManager*
     GetEventListenerManagerForAttr(nsIAtom* aAttrName, bool* aDefer);
 
   virtual const nsAttrName* InternalGetExistingAttrNameFromQName(const nsAString& aStr) const;
 
   /**
    * Helper method for NS_IMPL_STRING_ATTR macro.
-   * Gets the value of an attribute, returns empty string if
-   * attribute isn't set. Only works for attributes in null namespace.
-   *
-   * @param aAttr    name of attribute.
-   * @param aDefault default-value to return if attribute isn't set.
-   * @param aResult  result value [out]
-   * @result always NS_OK
-   */
-  NS_HIDDEN_(nsresult) GetAttrHelper(nsIAtom* aAttr, nsAString& aValue);
-
-  /**
-   * Helper method for NS_IMPL_STRING_ATTR macro.
    * Sets the value of an attribute, returns specified default value if the
    * attribute isn't set. Only works for attributes in null namespace.
    *
    * @param aAttr    name of attribute.
    * @param aDefault default-value to return if attribute isn't set.
    * @param aResult  result value [out]
    */
   NS_HIDDEN_(nsresult) SetAttrHelper(nsIAtom* aAttr, const nsAString& aValue);
@@ -1002,33 +990,16 @@ protected:
 // same bit.  --bz
 
 // Make sure we have enough space for those bits
 PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32);
 
 //----------------------------------------------------------------------
 
 /**
- * A macro to implement the getter and setter for a given string
- * valued content property. The method uses the generic GetAttr and
- * SetAttr methods.
- */
-#define NS_IMPL_STRING_ATTR(_class, _method, _atom)                  \
-  NS_IMETHODIMP                                                      \
-  _class::Get##_method(nsAString& aValue)                            \
-  {                                                                  \
-    return GetAttrHelper(nsGkAtoms::_atom, aValue);                  \
-  }                                                                  \
-  NS_IMETHODIMP                                                      \
-  _class::Set##_method(const nsAString& aValue)                      \
-  {                                                                  \
-    return SetAttrHelper(nsGkAtoms::_atom, aValue);                  \
-  }
-
-/**
  * This macro is similar to NS_IMPL_STRING_ATTR except that the getter method
  * falls back to an alternative method if the content attribute isn't set.
  */
 #define NS_IMPL_STRING_ATTR_WITH_FALLBACK(_class, _method, _atom, _fallback) \
   NS_IMETHODIMP                                                              \
   _class::Get##_method(nsAString& aValue)                                    \
   {                                                                          \
     if (!GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue)) {             \
--- a/content/html/content/src/nsHTMLScriptElement.cpp
+++ b/content/html/content/src/nsHTMLScriptElement.cpp
@@ -238,16 +238,17 @@ nsHTMLScriptElement::SetText(const nsASt
 
 
 NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Charset, charset)
 NS_IMPL_BOOL_ATTR(nsHTMLScriptElement, Defer, defer)
 NS_IMPL_URI_ATTR(nsHTMLScriptElement, Src, src)
 NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Type, type)
 NS_IMPL_STRING_ATTR(nsHTMLScriptElement, HtmlFor, _for)
 NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Event, event)
+NS_IMPL_STRING_ATTR(nsHTMLScriptElement, CrossOrigin, crossorigin)
 
 nsresult
 nsHTMLScriptElement::GetAsync(bool* aValue)
 {
   if (mForceAsync) {
     *aValue = true;
     return NS_OK;
   }
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -294,16 +294,18 @@ include $(topsrcdir)/config/rules.mk
 		file_fullscreen-esc-exit-inner.html \
 		file_fullscreen-rollback.html \
 		file_fullscreen-svg-element.html \
 		test_li_attributes_reflection.html \
 		test_ol_attributes_reflection.html \
 		test_bug651956.html \
 		test_bug694503.html \
 		test_object_plugin_nav.html \
+		test_bug742030.html \
+		test_bug742549.html \
 		$(NULL)
 
 _BROWSER_TEST_FILES = \
 		browser_bug649778.js \
 		file_bug649778.html \
 		file_bug649778.html^headers^ \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug742030.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=742030
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 742030</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742030">Mozilla Bug 742030</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 742030 **/
+const str = "  color:   #ff0000  ";
+var span = document.createElement("span");
+span.setAttribute("style", str);
+is(span.getAttribute("style"), str, "Should have set properly");
+var span2 = span.cloneNode(false);
+is(span2.getAttribute("style"), str, "Should have cloned properly");
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug742549.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=742549
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 742549</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="reflect.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742549">Mozilla Bug 742549</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 742549 **/
+var els = [ document.createElement("script"),
+            document.createElementNS("http://www.w3.org/2000/svg", "script") ]
+
+for (var i = 0; i < els.length; ++i) {
+  reflectString({
+    element: els[i],
+    attribute: { content: "crossorigin", idl: "crossOrigin" },
+    otherValues: [ "anonymous", "use-credentials" ]
+  })
+}
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -3119,32 +3119,16 @@ nsHTMLDocument::ExecCommand(const nsAStr
     rv = cmdMgr->DoCommand(cmdToDispatch.get(), cmdParams, window);
   }
 
   *_retval = NS_SUCCEEDED(rv);
 
   return rv;
 }
 
-/* TODO: don't let this call do anything if the page is not done loading */
-/* boolean execCommandShowHelp(in DOMString commandID); */
-NS_IMETHODIMP
-nsHTMLDocument::ExecCommandShowHelp(const nsAString & commandID,
-                                    bool *_retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = false;
-
-  // if editing is not on, bail
-  if (!IsEditingOnAfterFlush())
-    return NS_ERROR_FAILURE;
-
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 /* boolean queryCommandEnabled(in DOMString commandID); */
 NS_IMETHODIMP
 nsHTMLDocument::QueryCommandEnabled(const nsAString & commandID,
                                     bool *_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = false;
 
@@ -3301,30 +3285,16 @@ nsHTMLDocument::QueryCommandSupported(co
   // commandID is supported if it can be converted to a Midas command
   nsCAutoString cmdToDispatch;
   if (ConvertToMidasInternalCommand(commandID, cmdToDispatch))
     *_retval = true;
 
   return NS_OK;
 }
 
-/* DOMString queryCommandText(in DOMString commandID); */
-NS_IMETHODIMP
-nsHTMLDocument::QueryCommandText(const nsAString & commandID,
-                                 nsAString & _retval)
-{
-  _retval.SetLength(0);
-
-  // if editing is not on, bail
-  if (!IsEditingOnAfterFlush())
-    return NS_ERROR_FAILURE;
-
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 /* DOMString queryCommandValue(in DOMString commandID); */
 NS_IMETHODIMP
 nsHTMLDocument::QueryCommandValue(const nsAString & commandID,
                                   nsAString &_retval)
 {
   _retval.SetLength(0);
 
   // if editing is not on, bail
--- a/content/html/document/test/Makefile.in
+++ b/content/html/document/test/Makefile.in
@@ -101,16 +101,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug497242.xhtml \
 		test_bug499092.html \
 		bug499092.xml \
 		bug499092.html \
 		test_bug512367.html \
 		test_bug571981.html \
 		test_bug677495.html \
 		test_bug677495-1.html \
+		test_bug742261.html \
 		$(NULL)
 
 ifneq (mobile,$(MOZ_BUILD_APP))
 _BROWSER_TEST_FILES = \
 		browser_bug592641.js \
 		bug592641_img.jpg \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/content/html/document/test/test_bug742261.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=742261
+-->
+<title>Test for Bug 742261</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<body>
+<script>
+is(document.execCommandShowHelp, undefined,
+   "execCommandShowHelp shouldn't exist");
+is(document.queryCommandText, undefined,
+   "queryCommandText shouldn't exist");
+</script>
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -510,17 +510,17 @@ bool nsWebMReader::DecodeAudioPacket(nes
         NS_WARNING("Int overflow converting WebM audio total_duration");
         return false;
       }
       
       CheckedInt64 time = total_duration + tstamp_usecs;
       if (!time.valid()) {
         NS_WARNING("Int overflow adding total_duration and tstamp_usecs");
         nestegg_free_packet(aPacket);
-        return PR_FALSE;
+        return false;
       };
 
       total_frames += frames;
       mAudioQueue.Push(new AudioData(aOffset,
                                      time.value(),
                                      duration.value(),
                                      frames,
                                      buffer.forget(),
--- a/content/svg/content/src/nsSVGScriptElement.cpp
+++ b/content/svg/content/src/nsSVGScriptElement.cpp
@@ -172,28 +172,19 @@ nsSVGScriptElement::Clone(nsINodeInfo *a
 
   return NS_OK;
 }
 
 //----------------------------------------------------------------------
 // nsIDOMSVGScriptElement methods
 
 /* attribute DOMString type; */
-NS_IMETHODIMP
-nsSVGScriptElement::GetType(nsAString & aType)
-{
-  GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
-
-  return NS_OK;
-}
-NS_IMETHODIMP
-nsSVGScriptElement::SetType(const nsAString & aType)
-{
-  return SetAttr(kNameSpaceID_None, nsGkAtoms::type, aType, true); 
-}
+NS_IMPL_STRING_ATTR(nsSVGScriptElement, Type, type)
+/* attribute DOMString crossOrigin */
+NS_IMPL_STRING_ATTR(nsSVGScriptElement, CrossOrigin, crossorigin)
 
 //----------------------------------------------------------------------
 // nsIDOMSVGURIReference methods
 
 /* readonly attribute nsIDOMSVGAnimatedString href; */
 NS_IMETHODIMP
 nsSVGScriptElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
 {
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -97,17 +97,17 @@
 
 // Helper classes
 
 /***********************************************************************/
 //
 // The JS class for XBLBinding
 //
 static void
-XBLFinalize(JSContext *cx, JSObject *obj)
+XBLFinalize(JSFreeOp *fop, JSObject *obj)
 {
   nsXBLDocumentInfo* docInfo =
     static_cast<nsXBLDocumentInfo*>(::JS_GetPrivate(obj));
   NS_RELEASE(docInfo);
   
   nsXBLJSClass* c = static_cast<nsXBLJSClass*>(::JS_GetClass(obj));
   c->Drop();
 }
--- a/content/xbl/src/nsXBLContentSink.cpp
+++ b/content/xbl/src/nsXBLContentSink.cpp
@@ -901,19 +901,16 @@ nsXBLContentSink::CreateElement(const PR
   // Note that this needs to match the code in nsXBLPrototypeBinding::ReadContentNode.
 
   *aAppendContent = true;
   nsRefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement();
   if (!prototype)
     return NS_ERROR_OUT_OF_MEMORY;
 
   prototype->mNodeInfo = aNodeInfo;
-  // XXX - we need to do exactly what the XUL content-sink does (eg,
-  // look for 'type', 'version' etc attributes)
-  prototype->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
 
   AddAttributesToXULPrototype(aAtts, aAttsCount, prototype);
 
   Element* result;
   nsresult rv = nsXULElement::Create(prototype, mDocument, false, &result);
   *aResult = result;
   return rv;
 #endif
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -167,17 +167,17 @@ nsXBLDocGlobalObject_checkAccess(JSConte
     translated = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
   }
 
   return nsXBLDocGlobalObject::
     doCheckAccess(cx, obj, id, translated);
 }
 
 static void
-nsXBLDocGlobalObject_finalize(JSContext *cx, JSObject *obj)
+nsXBLDocGlobalObject_finalize(JSFreeOp *fop, JSObject *obj)
 {
   nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(obj);
 
   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
 
   if (sgo)
     sgo->OnFinalize(obj);
 
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -1874,17 +1874,16 @@ nsXBLPrototypeBinding::ReadContentNode(n
 #ifdef MOZ_XUL
   if (namespaceID == kNameSpaceID_XUL) {
     nsIURI* documentURI = aDocument->GetDocumentURI();
 
     nsRefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement();
     NS_ENSURE_TRUE(prototype, NS_ERROR_OUT_OF_MEMORY);
 
     prototype->mNodeInfo = nodeInfo;
-    prototype->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
 
     nsCOMPtr<Element> result;
     nsresult rv =
       nsXULElement::Create(prototype, aDocument, false, getter_AddRefs(result));
     NS_ENSURE_SUCCESS(rv, rv);
     content = result;
 
     nsXULPrototypeAttribute* attrs = nsnull;
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -409,18 +409,16 @@ nsresult
 nsXULElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
 {
     *aResult = nsnull;
 
     // If we have a prototype, so will our clone.
     nsRefPtr<nsXULElement> element;
     if (mPrototype) {
         element = nsXULElement::Create(mPrototype, aNodeInfo, true);
-        NS_ASSERTION(nsIProgrammingLanguage::JAVASCRIPT == mPrototype->mScriptTypeID,
-                     "Didn't get the default language from proto?");
     }
     else {
         nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
         element = new nsXULElement(ni.forget());
     }
 
     if (!element) {
         return NS_ERROR_OUT_OF_MEMORY;
@@ -1088,29 +1086,22 @@ nsXULElement::AfterSetAttr(PRInt32 aName
 {
     if (aNamespaceID == kNameSpaceID_None) {
         // XXX UnsetAttr handles more attributes than we do. See bug 233642.
 
         // Add popup and event listeners. We can't call AddListenerFor since
         // the attribute isn't set yet.
         MaybeAddPopupListener(aName);
         if (nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL) && aValue) {
-            // If mPrototype->mScriptTypeID != nsIProgrammingLanguage::JAVASCRIPT, it means
-            // we are resolving an overlay with a different default script
-            // language.  We can't defer compilation of those handlers as
-            // we will have lost the script language (storing it on each
-            // nsXULPrototypeAttribute is expensive!)
-            bool defer = mPrototype == nsnull ||
-                           mPrototype->mScriptTypeID == nsIProgrammingLanguage::JAVASCRIPT;
             if (aValue->Type() == nsAttrValue::eString) {
-                AddScriptEventListener(aName, aValue->GetStringValue(), defer);
+                AddScriptEventListener(aName, aValue->GetStringValue(), true);
             } else {
                 nsAutoString body;
                 aValue->ToString(body);
-                AddScriptEventListener(aName, body, defer);
+                AddScriptEventListener(aName, body, true);
             }
         }
 
         // Hide chrome if needed
         if (mNodeInfo->Equals(nsGkAtoms::window) && aValue) {
             if (aName == nsGkAtoms::hidechrome) {
                 HideWindowChrome(
                   aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
@@ -2501,21 +2492,16 @@ nsXULElement::RecompileScriptEventListen
         }
 
         nsAutoString value;
         GetAttr(kNameSpaceID_None, attr, value);
         AddScriptEventListener(attr, value, true);
     }
 
     if (mPrototype) {
-        // If we have a prototype, the node we are binding to should
-        // have the same script-type - otherwise we will compile the
-        // event handlers incorrectly.
-        NS_ASSERTION(mPrototype->mScriptTypeID == nsIProgrammingLanguage::JAVASCRIPT,
-                     "Prototype and node confused about default language?");
 
         count = mPrototype->mNumAttributes;
         for (i = 0; i < count; ++i) {
             const nsAttrName &name = mPrototype->mAttributes[i].mName;
 
             // Eventlistenener-attributes are always in the null namespace
             if (!name.IsAtom()) {
                 continue;
@@ -2574,17 +2560,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(nsXULPrototypeNode)
     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
         nsXULPrototypeElement *elem =
             static_cast<nsXULPrototypeElement*>(tmp);
         if (elem->mHoldsScriptObject) {
             PRUint32 i;
             for (i = 0; i < elem->mNumAttributes; ++i) {
                 JSObject* handler = elem->mAttributes[i].mEventHandler;
-                NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(elem->mScriptTypeID,
+                NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(nsIProgrammingLanguage::JAVASCRIPT,
                                                         handler,
                                                         "mAttributes[i].mEventHandler")
             }
         }
     }
     else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
         nsXULPrototypeScript *script =
             static_cast<nsXULPrototypeScript*>(tmp);
@@ -2617,19 +2603,16 @@ nsXULPrototypeElement::Serialize(nsIObje
                                  nsIScriptGlobalObject* aGlobal,
                                  const nsCOMArray<nsINodeInfo> *aNodeInfos)
 {
     nsresult rv;
 
     // Write basic prototype data
     rv = aStream->Write32(mType);
 
-    // Write script language
-    rv |= aStream->Write32(mScriptTypeID);
-
     // Write Node Info
     PRInt32 index = aNodeInfos->IndexOf(mNodeInfo);
     NS_ASSERTION(index >= 0, "unknown nsINodeInfo index");
     rv |= aStream->Write32(index);
 
     // Write Attributes
     rv |= aStream->Write32(mNumAttributes);
 
@@ -2700,21 +2683,16 @@ nsresult
 nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
                                    nsIScriptGlobalObject* aGlobal,
                                    nsIURI* aDocumentURI,
                                    const nsCOMArray<nsINodeInfo> *aNodeInfos)
 {
     NS_PRECONDITION(aNodeInfos, "missing nodeinfo array");
     nsresult rv;
 
-    // Read script language
-    PRUint32 scriptId = 0;
-    rv = aStream->Read32(&scriptId);
-    mScriptTypeID = scriptId;
-
     // Read Node Info
     PRUint32 number;
     rv |= aStream->Read32(&number);
     mNodeInfo = aNodeInfos->SafeObjectAt(number);
     if (!mNodeInfo)
         return NS_ERROR_UNEXPECTED;
 
     // Read Attributes
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -243,18 +243,17 @@ class nsXULPrototypeElement : public nsX
 public:
     nsXULPrototypeElement()
         : nsXULPrototypeNode(eType_Element),
           mNumAttributes(0),
           mAttributes(nsnull),
           mHasIdAttribute(false),
           mHasClassAttribute(false),
           mHasStyleAttribute(false),
-          mHoldsScriptObject(false),
-          mScriptTypeID(nsIProgrammingLanguage::UNKNOWN)
+          mHoldsScriptObject(false)
     {
     }
 
     virtual ~nsXULPrototypeElement()
     {
         Unlink();
     }
 
@@ -292,21 +291,16 @@ public:
     PRUint32                 mNumAttributes;
     nsXULPrototypeAttribute* mAttributes;         // [OWNER]
     
     bool                     mHasIdAttribute:1;
     bool                     mHasClassAttribute:1;
     bool                     mHasStyleAttribute:1;
     bool                     mHoldsScriptObject:1;
 
-    // The language ID can not be set on a per-node basis, but is tracked
-    // so that the language ID from the originating root can be used
-    // (eg, when a node from an overlay ends up in our document, that node
-    // must use its original script language, not our document's default.
-    PRUint16                 mScriptTypeID;
 };
 
 class nsXULDocument;
 
 class nsXULPrototypeScript : public nsXULPrototypeNode
 {
 public:
     nsXULPrototypeScript(PRUint32 aLangID, PRUint32 aLineNo, PRUint32 version);
--- a/content/xul/document/src/nsXULContentSink.cpp
+++ b/content/xul/document/src/nsXULContentSink.cpp
@@ -176,17 +176,17 @@ XULContentSinkImpl::ContextStack::GetTop
     nsresult rv = NS_OK;
     nsRefPtr<nsXULPrototypeNode> node;
     rv = GetTopNode(node);
     if (NS_FAILED(rv)) return rv;
     switch (node->mType) {
         case nsXULPrototypeNode::eType_Element: {
             nsXULPrototypeElement *parent =
                 reinterpret_cast<nsXULPrototypeElement*>(node.get());
-            *aScriptType = parent->mScriptTypeID;
+            *aScriptType = nsIProgrammingLanguage::JAVASCRIPT;
             break;
         }
         case nsXULPrototypeNode::eType_Script: {
             nsXULPrototypeScript *parent =
                 reinterpret_cast<nsXULPrototypeScript*>(node.get());
             *aScriptType = parent->mScriptObject.mLangID;
             break;
         }
@@ -782,65 +782,16 @@ XULContentSinkImpl::ReportError(const PR
   
   rv = HandleEndElement(parsererror.get());
   NS_ENSURE_SUCCESS(rv,rv);
 
   return rv;
 }
 
 nsresult
-XULContentSinkImpl::SetElementScriptType(nsXULPrototypeElement* element,
-                                         const PRUnichar** aAttributes, 
-                                         const PRUint32 aAttrLen)
-{
-    // First check if the attributes specify an explicit script type.
-    nsresult rv = NS_OK;
-    PRUint32 i;
-    bool found = false;
-    for (i=0;i<aAttrLen;i++) {
-        const nsDependentString key(aAttributes[i*2]);
-        if (key.EqualsLiteral("script-type")) {
-            const nsDependentString value(aAttributes[i*2+1]);
-            if (!value.IsEmpty()) {
-                nsCOMPtr<nsIScriptRuntime> runtime;
-                rv = NS_GetScriptRuntime(value, getter_AddRefs(runtime));
-                if (NS_SUCCEEDED(rv))
-                    element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
-                else {
-                    // probably just a bad language name (typo, etc)
-                    NS_WARNING("Failed to load the node's script language!");
-                    // Leave the default language as unknown - we don't want js
-                    // trying to execute this stuff.
-                    NS_ASSERTION(element->mScriptTypeID == nsIProgrammingLanguage::UNKNOWN,
-                                 "Default script type should be unknown");
-                }
-                found = true;
-                break;
-            }
-        }
-    }
-    // If not specified, look at the context stack and use the element
-    // there.
-    if (!found) {
-        if (mContextStack.Depth() == 0) {
-            // This is the root element - default to JS
-            element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
-        } else {
-            // Ask the top-node for its script type (which has already
-            // had this function called for it - so no need to recurse
-            // until we find it)
-            PRUint32 scriptId = 0;
-            rv = mContextStack.GetTopNodeScriptType(&scriptId);
-            element->mScriptTypeID = scriptId;
-        }
-    }
-    return rv;
-}
-
-nsresult
 XULContentSinkImpl::OpenRoot(const PRUnichar** aAttributes, 
                              const PRUint32 aAttrLen, 
                              nsINodeInfo *aNodeInfo)
 {
     NS_ASSERTION(mState == eInProlog, "how'd we get here?");
     if (mState != eInProlog)
         return NS_ERROR_UNEXPECTED;
 
@@ -868,20 +819,16 @@ XULContentSinkImpl::OpenRoot(const PRUni
                     NS_ConvertUTF16toUTF8(anodeC).get(),
                     -1)); // XXX pass in line number
         }
 #endif
 
         return rv;
     }
 
-    // Set the correct script-type for the element.
-    rv = SetElementScriptType(element, aAttributes, aAttrLen);
-    if (NS_FAILED(rv)) return rv;
-
     // Push the element onto the context stack, so that child
     // containers will hook up to us as their parent.
     rv = mContextStack.Push(element, mState);
     if (NS_FAILED(rv)) {
         element->Release();
         return rv;
     }
 
@@ -931,36 +878,29 @@ XULContentSinkImpl::OpenTag(const PRUnic
     // Add the attributes
     rv = AddAttributes(aAttributes, aAttrLen, element);
     if (NS_FAILED(rv)) return rv;
 
     children->AppendElement(element);
 
     if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) || 
         aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XUL)) {
-        // Do scripty things now.  Set a script language for the element,
-        // even though it is ignored (the nsPrototypeScriptElement
-        // has its own script-type).
-        element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
+        // Do scripty things now
         rv = OpenScript(aAttributes, aLineNumber);
         NS_ENSURE_SUCCESS(rv, rv);
 
         NS_ASSERTION(mState == eInScript || mState == eInDocumentElement,
                      "Unexpected state");
         if (mState == eInScript) {
             // OpenScript has pushed the nsPrototypeScriptElement onto the 
             // stack, so we're done.
             return NS_OK;
         }
     }
 
-    // Set the correct script-type for the element.
-    rv = SetElementScriptType(element, aAttributes, aAttrLen);
-    if (NS_FAILED(rv)) return rv;
-
     // Push the element onto the context stack, so that child
     // containers will hook up to us as their parent.
     rv = mContextStack.Push(element, mState);
     if (NS_FAILED(rv)) return rv;
 
     mState = eInDocumentElement;
     return NS_OK;
 }
--- a/content/xul/document/src/nsXULContentSink.h
+++ b/content/xul/document/src/nsXULContentSink.h
@@ -112,20 +112,16 @@ protected:
     // eInDocumentElement then we didn't create a prototype script (e.g. the
     // script had an unknown type), and the caller should create a prototype
     // element.
     nsresult OpenScript(const PRUnichar** aAttributes,
                         const PRUint32 aLineNumber);
 
     static bool IsDataInBuffer(PRUnichar* aBuffer, PRInt32 aLength);
 
-    nsresult SetElementScriptType(nsXULPrototypeElement* element,
-                                  const PRUnichar** aAttributes,
-                                  const PRUint32 aAttrLen);
-
     // Text management
     nsresult FlushText(bool aCreateTextNode = true);
     nsresult AddText(const PRUnichar* aText, PRInt32 aLength);
 
 
     nsRefPtr<nsNodeInfoManager> mNodeInfoManager;
 
     nsresult NormalizeAttributeString(const PRUnichar *aExpatName,
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -115,17 +115,17 @@ protected:
 };
 
 nsIPrincipal* nsXULPrototypeDocument::gSystemPrincipal;
 nsXULPDGlobalObject* nsXULPrototypeDocument::gSystemGlobal;
 PRUint32 nsXULPrototypeDocument::gRefCnt;
 
 
 void
-nsXULPDGlobalObject_finalize(JSContext *cx, JSObject *obj)
+nsXULPDGlobalObject_finalize(JSFreeOp *fop, JSObject *obj)
 {
     nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(obj);
 
     nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
 
     if (sgo) {
         sgo->OnFinalize(obj);
     }
--- a/dom/base/BrowserElementAPI.js
+++ b/dom/base/BrowserElementAPI.js
@@ -127,24 +127,37 @@ BrowserElementAPI.prototype = {
    * <iframe mozbrowser>.
    */
   _initBrowserWindow: function BA_initBrowserWindow(win, isTopLevel) {
     // XPCNativeWrapper.unwrap gets us the object that content sees; this is
     // the object object that we must define properties on.  Otherwise, the
     // properties will be visible only to chrome!
     var unwrappedWin = XPCNativeWrapper.unwrap(win);
 
-    Object.defineProperty(unwrappedWin, 'top', {
+    // This property should exist only on the x-ray wrapped object, not on the
+    // unwrapped object, so we define it on |win|, not |unwrappedWin|.
+    Object.defineProperty(win, 'browserFrameTop', {
       get: function() {
         if (isTopLevel) {
           return win;
         }
-        // Call the mozbrowser-aware |top| method we presumably defined on our
-        // parent.
-        return XPCNativeWrapper.unwrap(win.parent).top;
+
+        if ('browserFrameTop' in win.parent) {
+          return win.parent.browserFrameTop;
+        }
+
+        // This shouldn't happen, but let's at least throw a semi-meaningful
+        // error message if it does.
+        throw new Error('Internal error in window.browserFrameTop.');
+      }
+    });
+
+    Object.defineProperty(unwrappedWin, 'top', {
+      get: function() {
+        return win.browserFrameTop;
       }
     });
 
     Object.defineProperty(unwrappedWin, 'parent', {
       get: function() {
         if (isTopLevel) {
           return win;
         }
--- a/dom/base/DOMRequest.cpp
+++ b/dom/base/DOMRequest.cpp
@@ -126,17 +126,17 @@ DOMRequest::FireEvent(const nsAString& a
   }
 
   nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
   nsresult rv = event->InitEvent(aType, false, false);
   if (NS_FAILED(rv)) {
     return;
   }
 
-  rv = event->SetTrusted(PR_TRUE);
+  rv = event->SetTrusted(true);
   if (NS_FAILED(rv)) {
     return;
   }
 
   bool dummy;
   DispatchEvent(event, &dummy);
 }
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1351,18 +1351,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(Storage, nsStorage2SH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_NEWRESOLVE |
                            nsIXPCScriptable::WANT_GETPROPERTY |
                            nsIXPCScriptable::WANT_SETPROPERTY |
                            nsIXPCScriptable::WANT_DELPROPERTY |
                            nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |
                            nsIXPCScriptable::WANT_NEWENUMERATE)
-  NS_DEFINE_CLASSINFO_DATA(StorageList, nsStorageListSH,
-                           ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(StorageItem, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(StorageEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(StorageEventObsolete, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(DOMParser, nsDOMGenericSH,
@@ -3916,20 +3914,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(StorageObsolete, nsIDOMStorageObsolete)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageObsolete)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Storage, nsIDOMStorage)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorage)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(StorageList, nsIDOMStorageList)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageList)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(StorageItem, nsIDOMStorageItem)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageItem)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMToString)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(StorageEvent, nsIDOMStorageEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
@@ -4794,17 +4788,17 @@ nsDOMClassInfo::Convert(nsIXPConnectWrap
                         bool *_retval)
 {
   NS_WARNING("nsDOMClassInfo::Convert Don't call me!");
 
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
-nsDOMClassInfo::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+nsDOMClassInfo::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
                          JSObject *obj)
 {
   NS_WARNING("nsDOMClassInfo::Finalize Don't call me!");
 
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
@@ -7398,17 +7392,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       *objp = obj;
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
                      JSObject *obj)
 {
   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
   NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED);
 
   sgo->OnFinalize(obj);
 
   return NS_OK;
@@ -8935,17 +8929,17 @@ nsHTMLDocumentSH::DocumentAllNewResolve(
 
   return ok;
 }
 
 // Finalize hook used by document related JS objects, but also by
 // sGlobalScopePolluterClass!
 
 void
-nsHTMLDocumentSH::ReleaseDocument(JSContext *cx, JSObject *obj)
+nsHTMLDocumentSH::ReleaseDocument(JSFreeOp *fop, JSObject *obj)
 {
   nsIHTMLDocument *doc = (nsIHTMLDocument *)::JS_GetPrivate(obj);
 
   NS_IF_RELEASE(doc);
 }
 
 JSBool
 nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp)
@@ -10625,28 +10619,16 @@ nsStorage2SH::NewEnumerate(nsIXPConnectW
                     "Bad call from the JS engine");
   delete keys;
 
   *statep = JSVAL_NULL;
 
   return NS_OK;
 }
 
-// StorageList scriptable helper
-
-nsISupports*
-nsStorageListSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                              nsWrapperCache **aCache, nsresult *aResult)
-{
-  nsDOMStorageList* storagelist = static_cast<nsDOMStorageList*>(aNative);
-
-  return storagelist->GetNamedItem(aName, aResult);
-}
-
-
 // nsIDOMEventListener::HandleEvent() 'this' converter helper
 
 NS_INTERFACE_MAP_BEGIN(nsEventListenerThisTranslator)
   NS_INTERFACE_MAP_ENTRY(nsIXPCFunctionThisTranslator)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 
@@ -10735,17 +10717,17 @@ nsDOMConstructorSH::NewResolve(nsIXPConn
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Now re-lookup the ID to see if we should report back that we resolved the
   // looked-for constant. Note that we don't have to worry about infinitely
   // recurring back here because the Xray wrapper's holder object doesn't call
   // NewResolve hooks.
   JSBool found;
   if (!JS_HasPropertyById(cx, nativePropsObj, id, &found)) {
-    *_retval = PR_FALSE;
+    *_retval = false;
     return NS_OK;
   }
 
   if (found) {
     *objp = obj;
   }
   return NS_OK;
 }
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -411,17 +411,17 @@ public:
 #endif
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsid id, jsval *vp, bool *_retval);
   NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                        JSObject *obj, bool *_retval);
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, PRUint32 flags,
                         JSObject **objp, bool *_retval);
-  NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+  NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
                       JSObject *obj);
   NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                          JSObject * obj, JSObject * *_retval);
 
   static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
                                               jsid id, unsigned flags,
                                               JSObject **objp);
   static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj,
@@ -793,17 +793,17 @@ protected:
                                        nsDocument *doc,
                                        nsContentList **nodeList);
 
 public:
   static JSBool DocumentAllGetProperty(JSContext *cx, JSObject *obj, jsid id,
                                        jsval *vp);
   static JSBool DocumentAllNewResolve(JSContext *cx, JSObject *obj, jsid id,
                                       unsigned flags, JSObject **objp);
-  static v