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 id23447
push userdanderson@mozilla.com
push dateTue, 11 Sep 2012 17:34:27 +0000
treeherdermozilla-central@fdfaef738a00 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge from mozilla-central.
accessible/src/base/Makefile.in
accessible/src/base/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 void ReleaseDocument(JSContext *cx, JSObject *obj);
+  static void ReleaseDocument(JSFreeOp *fop, JSObject *obj);
   static JSBool CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp);
   static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj,
                                              jsid id, jsval *vp);
   static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSObject *obj,
                                             jsid id, unsigned flags,
                                             JSObject **objp);
   static JSBool DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj,
                                           jsid id, unsigned flags,
@@ -1422,46 +1422,16 @@ protected:
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsStorage2SH(aData);
   }
 };
 
-class nsStorageListSH : public nsNamedArraySH
-{
-protected:
-  nsStorageListSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
-  {
-  }
-
-  virtual ~nsStorageListSH()
-  {
-  }
-
-  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult)
-  {
-    return nsnull;
-  }
-  // Override nsNamedArraySH::GetNamedItem()
-  virtual nsISupports* GetNamedItem(nsISupports *aNative,
-                                    const nsAString& aName,
-                                    nsWrapperCache **cache,
-                                    nsresult *aResult);
-
-public:
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsStorageListSH(aData);
-  }
-};
-
-
 // Event handler 'this' translator class, this is called by XPConnect
 // when a "function interface" (nsIDOMEventListener) is called, this
 // class extracts 'this' fomr the first argument to the called
 // function (nsIDOMEventListener::HandleEvent(in nsIDOMEvent)), this
 // class will pass back nsIDOMEvent::currentTarget to be used as
 // 'this'.
 
 class nsEventListenerThisTranslator : public nsIXPCFunctionThisTranslator
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses