Merge cedar with mozilla-central.
authorMounir Lamouri <mounir.lamouri@gmail.com>
Fri, 22 Apr 2011 15:25:11 +0200
changeset 68429 49dd65bf80921d737d93b26efa10a5921aa4be7c
parent 68428 1ebe64a0f85f20112c304864e811cbc82a0902a5 (current diff)
parent 68421 f0a03fc3247dc9a7246705e5303788c8cc87eece (diff)
child 68430 ee7fef67c37068ed4eb85a5e6068c8637259711e
push idunknown
push userunknown
push dateunknown
milestone6.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 cedar with mozilla-central.
browser/app/profile/firefox.js
content/base/src/nsDocument.cpp
content/base/src/nsGenericElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/xul/content/src/nsXULElement.cpp
dom/base/nsGlobalWindow.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -890,16 +890,17 @@ pref("toolbar.customization.usesheet", f
 
 // The default for this pref reflects whether the build is capable of IPC.
 // (Turning it on in a no-IPC build will have no effect.)
 #ifdef XP_MACOSX
 // i386 ipc preferences
 pref("dom.ipc.plugins.enabled.i386", false);
 pref("dom.ipc.plugins.enabled.i386.flash player.plugin", true);
 pref("dom.ipc.plugins.enabled.i386.javaplugin2_npapi.plugin", true);
+pref("dom.ipc.plugins.enabled.i386.javaappletplugin.plugin", true);
 // x86_64 ipc preferences
 pref("dom.ipc.plugins.enabled.x86_64", true);
 #else
 pref("dom.ipc.plugins.enabled", true);
 #endif
 
 #ifdef XP_WIN
 pref("browser.taskbar.previews.enable", false);
--- a/browser/base/content/test/browser_bug553455.js
+++ b/browser/base/content/test/browser_bug553455.js
@@ -700,98 +700,16 @@ function test_renotify_installed() {
   var triggers = encodeURIComponent(JSON.stringify({
     "XPI": "unsigned.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_cancel_restart() {
-  // If the XPI is already cached then the HTTP observer won't see the request
-  var cacheService = Cc["@mozilla.org/network/cache-service;1"].
-                     getService(Ci.nsICacheService);
-  try {
-    cacheService.evictEntries(Components.interfaces.nsICache.STORE_ANYWHERE);
-  } catch(ex) {}
-
-  // Must be registered before any request starts
-  var observerService = Cc["@mozilla.org/network/http-activity-distributor;1"].
-                        getService(Ci.nsIHttpActivityDistributor);
-  observerService.addObserver({
-    observeActivity: function(aChannel, aType, aSubtype, aTimestamp, aSizeData,
-                              aStringData) {
-      aChannel.QueryInterface(Ci.nsIChannel);
-
-      // Wait for the first event for the download
-      if (aChannel.URI.spec != TESTROOT + "unsigned.xpi" ||
-        aType != Ci.nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION ||
-        aSubtype != Ci.nsIHttpActivityObserver.ACTIVITY_SUBTYPE_REQUEST_HEADER)
-        return;
-
-      observerService.removeObserver(this);
-
-      info("Replacing channel");
-      aChannel.QueryInterface(Ci.nsITraceableChannel);
-      var listener = aChannel.setNewListener({
-        onStartRequest: function(aRequest, aContext) {
-          listener.onStartRequest(aRequest, aContext);
-        },
-
-        onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
-          listener.onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
-        },
-
-        onStopRequest: function(aRequest, aContext, aStatusCode) {
-          listener.onStopRequest(aRequest, aContext, aStatusCode);
-
-          // Request should have been cancelled
-          is(aStatusCode, Components.results.NS_BINDING_ABORTED, "Should have seen a cancelled request");
-
-          // Notification should have changed to cancelled
-          let notification = PopupNotifications.panel.childNodes[0];
-          is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
-
-          // Wait for the install confirmation dialog
-          wait_for_install_dialog(function(aWindow) {
-            // Wait for the complete notification
-            wait_for_notification(function(aPanel) {
-              let notification = aPanel.childNodes[0];
-              is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
-              is(notification.button.label, "Restart Now", "Should have seen the right button");
-              is(notification.getAttribute("label"),
-                 "XPI Test will be installed after you restart " + gApp + ".",
-                 "Should have seen the right message");
-
-              AddonManager.getAllInstalls(function(aInstalls) {
-                is(aInstalls.length, 1, "Should be one pending install");
-                aInstalls[0].cancel();
-
-                Services.perms.remove("example.com", "install");
-                wait_for_notification_close(runNextTest);
-                gBrowser.removeTab(gBrowser.selectedTab);
-              });
-            });
-
-            aWindow.document.documentElement.acceptDialog();
-          });
-
-          // Restart the download
-          info("Restarting download");
-          EventUtils.synthesizeMouse(notification.button, 20, 10, {});
-
-          // Should be back to a progress notification
-          ok(PopupNotifications.isPanelOpen, "Notification should still be open");
-          is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
-          notification = PopupNotifications.panel.childNodes[0];
-          is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-        }
-      });
-    }
-  });
-
   // Wait for the progress notification
   wait_for_notification(function(aPanel) {
     let notification = aPanel.childNodes[0];
     is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
 
     // Close the notification
     let anchor = document.getElementById("addons-notification-icon");
     EventUtils.synthesizeMouseAtCenter(anchor, {});
@@ -801,18 +719,54 @@ function test_cancel_restart() {
     ok(PopupNotifications.isPanelOpen, "Notification should still be open");
     is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
     isnot(notification, aPanel.childNodes[0], "Should have reconstructed the notification UI");
     notification = aPanel.childNodes[0];
     is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
     let button = document.getAnonymousElementByAttribute(notification, "anonid", "cancel");
 
     // Cancel the download
-    info("Cancelling download");
     EventUtils.synthesizeMouse(button, 2, 2, {});
+
+    // Notification should have changed to cancelled
+    notification = aPanel.childNodes[0];
+    is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
+
+    // Wait for the install confirmation dialog
+    wait_for_install_dialog(function(aWindow) {
+      // Wait for the complete notification
+      wait_for_notification(function(aPanel) {
+        let notification = aPanel.childNodes[0];
+        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
+        is(notification.button.label, "Restart Now", "Should have seen the right button");
+        is(notification.getAttribute("label"),
+           "XPI Test will be installed after you restart " + gApp + ".",
+           "Should have seen the right message");
+
+        AddonManager.getAllInstalls(function(aInstalls) {
+          is(aInstalls.length, 1, "Should be one pending install");
+          aInstalls[0].cancel();
+
+          Services.perms.remove("example.com", "install");
+          wait_for_notification_close(runNextTest);
+          gBrowser.removeTab(gBrowser.selectedTab);
+        });
+      });
+
+      aWindow.document.documentElement.acceptDialog();
+    });
+
+    // Restart the download
+    EventUtils.synthesizeMouse(notification.button, 20, 10, {});
+
+    // Should be back to a progress notification
+    ok(PopupNotifications.isPanelOpen, "Notification should still be open");
+    is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
+    notification = aPanel.childNodes[0];
+    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
   });
 
   var pm = Services.perms;
   pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(JSON.stringify({
     "XPI": "unsigned.xpi"
   }));
--- a/browser/locales/en-US/installer/custom.properties
+++ b/browser/locales/en-US/installer/custom.properties
@@ -48,17 +48,16 @@
 # being used as an accesskey.
 
 # You can use \n to create a newline in the string but only when the string
 # from en-US contains a \n.
 
 REG_APP_DESC=$BrandShortName delivers safe, easy web browsing. A familiar user interface, enhanced security features including protection from online identity theft, and integrated search let you get the most out of the web.
 CONTEXT_OPTIONS=$BrandShortName &Options
 CONTEXT_SAFE_MODE=$BrandShortName &Safe Mode
-SAFE_MODE=Safe Mode
 OPTIONS_PAGE_TITLE=Setup Type
 OPTIONS_PAGE_SUBTITLE=Choose setup options
 SHORTCUTS_PAGE_TITLE=Set Up Shortcuts
 SHORTCUTS_PAGE_SUBTITLE=Create Program Icons
 SUMMARY_PAGE_TITLE=Summary
 SUMMARY_PAGE_SUBTITLE=Ready to start installing $BrandShortName
 SUMMARY_INSTALLED_TO=$BrandShortName will be installed to the following location:
 SUMMARY_REBOOT_REQUIRED_INSTALL=A restart of your computer may be required to complete the installation.
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -702,16 +702,18 @@ ANDROID_PLATFORM  = @ANDROID_PLATFORM@
 ANDROID_SDK       = @ANDROID_SDK@
 ANDROID_PLATFORM_TOOLS = @ANDROID_PLATFORM_TOOLS@
 ANDROID_VERSION   = @ANDROID_VERSION@
 
 ANDROID_PACKAGE_NAME = @ANDROID_PACKAGE_NAME@
 
 JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
 
+MOZ_INSTRUMENT_EVENT_LOOP = @MOZ_INSTRUMENT_EVENT_LOOP@
+
 # We only want to do the pymake sanity on Windows, other os's can cope
 ifeq ($(HOST_OS_ARCH),WINNT)
 # Ensure invariants between GNU Make and pymake
 # Checked here since we want the sane error in a file that
 # actually can be found regardless of path-style.
 ifeq (_:,$(.PYMAKE)_$(findstring :,$(srcdir)))
 $(error Windows-style srcdir being used with GNU make. Did you mean to run $(topsrcdir)/build/pymake/make.py instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake])
 endif
--- a/configure.in
+++ b/configure.in
@@ -5018,16 +5018,17 @@ photon)
 	MOZ_ENABLE_PHOTON=1
 	AC_DEFINE(MOZ_WIDGET_PHOTON)
     ;;
 
 cairo-windows)
     MOZ_WIDGET_TOOLKIT=windows
     MOZ_WEBGL=1
     MOZ_PDF_PRINTING=1
+    MOZ_INSTRUMENT_EVENT_LOOP=1
     ;;
 
 cairo-gtk2|cairo-gtk2-x11)
     MOZ_WIDGET_TOOLKIT=gtk2
     MOZ_ENABLE_GTK2=1
     MOZ_ENABLE_XREMOTE=1
     MOZ_WEBGL=1
     MOZ_WEBGL_GLX=1
@@ -5035,16 +5036,17 @@ cairo-gtk2|cairo-gtk2-x11)
     AC_DEFINE(MOZ_X11)
     MOZ_X11=1
     USE_FC_FREETYPE=1
 
     TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
     TK_LIBS='$(MOZ_GTK2_LIBS)'
     AC_DEFINE(MOZ_WIDGET_GTK2)
     MOZ_PDF_PRINTING=1
+    MOZ_INSTRUMENT_EVENT_LOOP=1
     ;;
 
 cairo-gtk2-dfb)
     MOZ_WIDGET_TOOLKIT=gtk2
     MOZ_ENABLE_GTK2=1
     MOZ_WEBGL=
 
     AC_DEFINE(MOZ_DFB)
@@ -5094,16 +5096,17 @@ cairo-cocoa)
     TK_LIBS='-framework QuartzCore -framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook -framework OpenGL'
     TK_CFLAGS="-DNO_X11"
     LDFLAGS="$LDFLAGS -framework Cocoa -lobjc"
     CFLAGS="$CFLAGS $TK_CFLAGS"
     CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
     LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
     MOZ_FS_LAYOUT=bundle
     MOZ_WEBGL=1
+    MOZ_INSTRUMENT_EVENT_LOOP=1
     ;;
 
 cairo-android)
     AC_DEFINE(MOZ_WIDGET_ANDROID)
     MOZ_WIDGET_TOOLKIT=android
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS)'
     MOZ_WEBGL=1
@@ -5117,16 +5120,20 @@ if test "$MOZ_PDF_PRINTING"; then
    PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
    AC_DEFINE(MOZ_PDF_PRINTING)
 fi
 
 if test "$MOZ_ENABLE_XREMOTE"; then
     AC_DEFINE(MOZ_ENABLE_XREMOTE)
 fi
 
+if test "$MOZ_INSTRUMENT_EVENT_LOOP"; then
+   AC_DEFINE(MOZ_INSTRUMENT_EVENT_LOOP)
+fi
+
 if test "$COMPILE_ENVIRONMENT"; then
   if test "$MOZ_ENABLE_GTK2"; then
     if test "$MOZ_X11"; then
       GDK_PACKAGES=gdk-x11-2.0
     elif test "$MOZ_DFB"; then
       PKG_CHECK_MODULES(MOZ_DFB, directfb >= 1.1.0)
       GDK_PACKAGES=directfb
     fi
@@ -8987,16 +8994,17 @@ AC_SUBST(MOZ_OGG)
 AC_SUBST(MOZ_ALSA_LIBS)
 AC_SUBST(VPX_AS)
 AC_SUBST(VPX_ASFLAGS)
 AC_SUBST(VPX_DASH_C_FLAG)
 AC_SUBST(VPX_AS_CONVERSION)
 AC_SUBST(VPX_ASM_SUFFIX)
 AC_SUBST(VPX_X86_ASM)
 AC_SUBST(VPX_ARM_ASM)
+AC_SUBST(MOZ_INSTRUMENT_EVENT_LOOP)
 AC_SUBST(LIBJPEG_TURBO_AS)
 AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
 AC_SUBST(LIBJPEG_TURBO_X86_ASM)
 AC_SUBST(LIBJPEG_TURBO_X64_ASM)
 
 if test "$USING_HCC"; then
    CC='${topsrcdir}/build/hcc'
    CC="$CC '$_OLDCC'"
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/646184.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+
+function boom()
+{
+  var f = document.getElementById("f");
+  var w = f.contentWindow;
+  f.parentNode.removeChild(f);
+  w.localStorage;
+}
+
+</script>
+</head>
+<body onload="boom();"><iframe id="f" src="data:text/html,1"></iframe></body>
+</html>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -81,11 +81,12 @@ load 590395-1.html
 load 595606-1.html
 load 595606-2.html
 load 606729-1.html
 load 593302-1.html
 load 593302-2.html
 load 610571-1.html
 load 604262-1.html
 load 628599-1.html
-load 642022-1.html
 load 637214-1.svg
 load 637214-2.svg
+load 642022-1.html
+asserts(1) load 646184.html # Bug 651842
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5914,31 +5914,16 @@ nsDocument::GetXmlVersion(nsAString& aXm
 
 NS_IMETHODIMP
 nsDocument::SetXmlVersion(const nsAString& aXmlVersion)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsDocument::GetStrictErrorChecking(PRBool *aStrictErrorChecking)
-{
-  // This attribute is true by default, and we don't really support it being false.
-  *aStrictErrorChecking = PR_TRUE;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocument::SetStrictErrorChecking(PRBool aStrictErrorChecking)
-{
-  // We don't really support non-strict error checking, so just no-op for now.
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsDocument::GetDocumentURI(nsAString& aDocumentURI)
 {
   if (mDocumentURI) {
     nsCAutoString uri;
     mDocumentURI->GetSpec(uri);
     CopyUTF8toUTF16(uri, aDocumentURI);
   } else {
     SetDOMStringToNull(aDocumentURI);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -5461,17 +5461,16 @@ ParseSelectorList(nsINode* aNode,
                   nsCSSSelectorList** aSelectorList)
 {
   NS_ENSURE_ARG(aNode);
 
   nsIDocument* doc = aNode->GetOwnerDoc();
   NS_ENSURE_STATE(doc);
 
   nsCSSParser parser(doc->CSSLoader());
-  NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
 
   nsCSSSelectorList* selectorList;
   nsresult rv = parser.ParseSelectorString(aSelectorString,
                                            doc->GetDocumentURI(),
                                            0, // XXXbz get the line number!
                                            &selectorList);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -327,26 +327,25 @@ nsStyledElementNotElementCSSInlineStyle:
         static const char textCssStr[] = "text/css";
         isCSS = (styleType.EqualsIgnoreCase(textCssStr, sizeof(textCssStr) - 1));
       }
     }
 
     if (isCSS) {
       css::Loader* cssLoader = doc->CSSLoader();
       nsCSSParser cssParser(cssLoader);
-      if (cssParser) {
-        nsCOMPtr<nsIURI> baseURI = GetBaseURI();
+
+      nsCOMPtr<nsIURI> baseURI = GetBaseURI();
 
-        nsRefPtr<css::StyleRule> rule;
-        cssParser.ParseStyleAttribute(aValue, doc->GetDocumentURI(),
-                                      baseURI,
-                                      NodePrincipal(),
-                                      getter_AddRefs(rule));
-        if (rule) {
-          aResult.SetTo(rule, &aValue);
-          return;
-        }
+      nsRefPtr<css::StyleRule> rule;
+      cssParser.ParseStyleAttribute(aValue, doc->GetDocumentURI(),
+                                    baseURI,
+                                    NodePrincipal(),
+                                    getter_AddRefs(rule));
+      if (rule) {
+        aResult.SetTo(rule, &aValue);
+        return;
       }
     }
   }
 
   aResult.SetTo(aValue);
 }
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -2205,17 +2205,16 @@ CreateFontStyleRule(const nsAString& aFo
     nsIDocument* document = aNode->GetOwnerDoc();
 
     nsIURI* docURL = document->GetDocumentURI();
     nsIURI* baseURL = document->GetDocBaseURI();
 
     // Pass the CSS Loader object to the parser, to allow parser error reports
     // to include the outer window ID.
     nsCSSParser parser(document->CSSLoader());
-    NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
 
     nsresult rv = parser.ParseStyleAttribute(EmptyString(), docURL, baseURL,
                                              principal, getter_AddRefs(rule));
     if (NS_FAILED(rv))
         return rv;
 
     rv = parser.ParseProperty(eCSSProperty_font, aFont, docURL, baseURL,
                               principal, rule->GetDeclaration(), &changed,
@@ -3675,17 +3674,16 @@ nsCanvasRenderingContext2D::DrawWindow(n
     nscolor bgColor;
 
     nsIDocument* elementDoc = mCanvasElement ?
                               HTMLCanvasElement()->GetOwnerDoc() : nsnull;
 
     // Pass the CSS Loader object to the parser, to allow parser error reports
     // to include the outer window ID.
     nsCSSParser parser(elementDoc ? elementDoc->CSSLoader() : nsnull);
-    NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
     nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor),
                                           nsnull, 0, &bgColor);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsIPresShell* presShell = presContext->PresShell();
     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
     nsRect r(nsPresContext::CSSPixelsToAppUnits(aX),
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1363,28 +1363,16 @@ nsHTMLDocument::SetXmlVersion(const nsAS
   if (!IsHTML()) {
     return nsDocument::SetXmlVersion(aXmlVersion);
   }
 
   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 }
 
 NS_IMETHODIMP
-nsHTMLDocument::GetStrictErrorChecking(PRBool* aStrictErrorChecking)
-{
-  return nsDocument::GetStrictErrorChecking(aStrictErrorChecking);
-}
-
-NS_IMETHODIMP
-nsHTMLDocument::SetStrictErrorChecking(PRBool aStrictErrorChecking)
-{
-  return nsDocument::SetStrictErrorChecking(aStrictErrorChecking);
-}
-
-NS_IMETHODIMP
 nsHTMLDocument::GetDocumentURI(nsAString& aDocumentURI)
 {
   return nsDocument::GetDocumentURI(aDocumentURI);
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::SetDocumentURI(const nsAString& aDocumentURI)
 {
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -1164,19 +1164,16 @@ private:
 
 MappedAttrParser::MappedAttrParser(css::Loader* aLoader,
                                    nsIURI* aDocURI,
                                    already_AddRefed<nsIURI> aBaseURI,
                                    nsIPrincipal* aNodePrincipal)
   : mParser(aLoader), mDocURI(aDocURI), mBaseURI(aBaseURI),
     mNodePrincipal(aNodePrincipal), mDecl(nsnull)
 {
-  // mParser should successfully construct, now that we have infallible malloc.
-  NS_ABORT_IF_FALSE(mParser, "parser failed to initialize?");
-
   // SVG and CSS differ slightly in their interpretation of some of
   // the attributes.  SVG allows attributes of the form: font-size="5"
   // (style="font-size: 5" if using a style attribute)
   // where CSS requires units: font-size="5pt" (style="font-size: 5pt")
   // Set a flag to pass information to the parser so that we can use
   // the CSS parser to parse the font-size attribute.  Note that this
   // does *not* affect the use of CSS stylesheets, which will still
   // require units.
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2871,17 +2871,16 @@ nsXULPrototypeElement::SetAttrAt(PRUint3
         return NS_OK;
     }
     else if (mAttributes[aPos].mName.Equals(nsGkAtoms::style)) {
         mHasStyleAttribute = PR_TRUE;
         // Parse the element's 'style' attribute
         nsRefPtr<css::StyleRule> rule;
 
         nsCSSParser parser;
-        NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
 
         // XXX Get correct Base URI (need GetBaseURI on *prototype* element)
         parser.ParseStyleAttribute(aValue, aDocumentURI, aDocumentURI,
                                    // This is basically duplicating what
                                    // nsINode::NodePrincipal() does
                                    mNodeInfo->NodeInfoManager()->
                                      DocumentPrincipal(),
                                    getter_AddRefs(rule));
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -505,16 +505,18 @@
 #include "mozilla/dom/indexedDB/IDBObjectStore.h"
 #include "mozilla/dom/indexedDB/IDBTransaction.h"
 #include "mozilla/dom/indexedDB/IDBCursor.h"
 #include "mozilla/dom/indexedDB/IDBKeyRange.h"
 #include "mozilla/dom/indexedDB/IDBIndex.h"
 #include "nsIIDBDatabaseException.h"
 #include "nsIDOMEventException.h"
 
+#include "nsIDOMMediaQueryList.h"
+
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
   "chrome://global/locale/dom/dom.properties";
 
 // NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
@@ -1497,16 +1499,19 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
 #ifdef MOZ_CSS_ANIMATIONS
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframesRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
+
+  NS_DEFINE_CLASSINFO_DATA(MediaQueryList, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
 };
 
 // Objects that should be constructable through |new Name();|
 struct nsContractIDMapData
 {
   PRInt32 mDOMClassInfoID;
   const char *mContractID;
 };
@@ -4253,16 +4258,20 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframesRule, nsIDOMMozCSSKeyframesRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframesRule)
   DOM_CLASSINFO_MAP_END
 #endif
 
+  DOM_CLASSINFO_MAP_BEGIN(MediaQueryList, nsIDOMMediaQueryList)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMediaQueryList)
+  DOM_CLASSINFO_MAP_END
+
 #ifdef NS_DEBUG
   {
     PRUint32 i = NS_ARRAY_LENGTH(sClassInfoData);
 
     if (i != eDOMClassInfoIDCount) {
       NS_ERROR("The number of items in sClassInfoData doesn't match the "
                "number of nsIDOMClassInfo ID's, this is bad! Fix it!");
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -512,8 +512,10 @@ DOMCI_CLASS(IDBVersionChangeRequest)
 DOMCI_CLASS(IDBDatabaseException)
 
 DOMCI_CLASS(EventException)
 
 #ifdef MOZ_CSS_ANIMATIONS
 DOMCI_CLASS(MozCSSKeyframeRule)
 DOMCI_CLASS(MozCSSKeyframesRule)
 #endif
+
+DOMCI_CLASS(MediaQueryList)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -81,16 +81,17 @@
 #include "nsGeolocation.h"
 #include "nsDesktopNotification.h"
 #include "nsContentCID.h"
 #include "nsLayoutStatics.h"
 #include "nsCycleCollector.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsDOMThreadService.h"
 #include "nsAutoJSValHolder.h"
+#include "nsDOMMediaQueryList.h"
 
 // Interfaces Needed
 #include "nsIFrame.h"
 #include "nsCanvasFrame.h"
 #include "nsIWidget.h"
 #include "nsIBaseWindow.h"
 #include "nsAccelerometer.h"
 #include "nsIContent.h"
@@ -3919,16 +3920,42 @@ nsGlobalWindow::GetMozAnimationStartTime
   }
 
   // If all else fails, just be compatible with Date.now()
   *aTime = JS_Now() / PR_USEC_PER_MSEC;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
+                           nsIDOMMediaQueryList** aResult)
+{
+  // FIXME: This whole forward-to-outer and then get a pres
+  // shell/context off the docshell dance is sort of silly; it'd make
+  // more sense to forward to the inner, but it's what everyone else
+  // (GetSelection, GetScrollXY, etc.) does around here.
+  FORWARD_TO_OUTER(MatchMedia, (aMediaQueryList, aResult),
+                   NS_ERROR_NOT_INITIALIZED);
+
+  *aResult = nsnull;
+
+  if (!mDocShell)
+    return NS_OK;
+
+  nsRefPtr<nsPresContext> presContext;
+  mDocShell->GetPresContext(getter_AddRefs(presContext));
+
+  if (!presContext)
+    return NS_OK;
+
+  presContext->MatchMedia(aMediaQueryList, aResult);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsGlobalWindow::SetScreenX(PRInt32 aScreenX)
 {
   FORWARD_TO_OUTER(SetScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED);
 
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * prevent setting window.screenX by exiting early
    */
@@ -8012,17 +8039,19 @@ nsGlobalWindow::GetSessionStorage(nsIDOM
       }
     }
   }
 
   if (!mSessionStorage) {
     *aSessionStorage = nsnull;
 
     nsString documentURI;
-    mDocument->GetDocumentURI(documentURI);
+    if (mDocument) {
+      mDocument->GetDocumentURI(documentURI);
+    }
 
     nsresult rv = docShell->GetSessionStorageForPrincipal(principal,
                                                           documentURI,
                                                           PR_TRUE,
                                                           getter_AddRefs(mSessionStorage));
     NS_ENSURE_SUCCESS(rv, rv);
 
 #ifdef PR_LOGGING
@@ -8096,17 +8125,19 @@ nsGlobalWindow::GetLocalStorage(nsIDOMSt
     if (!principal)
       return NS_OK;
 
     nsCOMPtr<nsIDOMStorageManager> storageManager =
       do_GetService("@mozilla.org/dom/storagemanager;1", &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsString documentURI;
-    mDocument->GetDocumentURI(documentURI);
+    if (mDocument) {
+      mDocument->GetDocumentURI(documentURI);
+    }
 
     rv = storageManager->GetLocalStorageForPrincipal(principal,
                                                      documentURI,
                                                      getter_AddRefs(mLocalStorage));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   NS_ADDREF(*aLocalStorage = mLocalStorage);
--- a/dom/interfaces/base/Makefile.in
+++ b/dom/interfaces/base/Makefile.in
@@ -62,16 +62,17 @@ XPIDLSRCS =					\
 	nsIContentPrefService.idl		\
 	nsIContentURIGrouper.idl		\
 	nsIDOMClientInformation.idl		\
 	nsIDOMConstructor.idl			\
 	nsIDOMCRMFObject.idl			\
 	nsIDOMCrypto.idl			\
 	nsIDOMHistory.idl			\
 	nsIDOMLocation.idl			\
+	nsIDOMMediaQueryList.idl		\
 	nsIDOMMimeType.idl			\
 	nsIDOMMimeTypeArray.idl			\
 	nsIDOMNavigator.idl			\
 	nsIDOMPkcs11.idl			\
 	nsIDOMPlugin.idl			\
 	nsIDOMPluginArray.idl			\
 	nsIDOMScreen.idl			\
 	nsIDOMWindowInternal.idl		\
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/base/nsIDOMMediaQueryList.idl
@@ -0,0 +1,58 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "domstubs.idl"
+
+interface nsIDOMMediaQueryListListener;
+
+/* see http://dev.w3.org/csswg/cssom-view/#the-mediaquerylist-interface */
+
+[scriptable, uuid(e0e49c52-915b-40f9-9cba-6026305cdf3e)]
+interface nsIDOMMediaQueryList : nsISupports
+{
+  readonly attribute DOMString media;
+  readonly attribute boolean matches;
+
+  void addListener(in nsIDOMMediaQueryListListener listener);
+  void removeListener(in nsIDOMMediaQueryListListener listener);
+};
+
+[scriptable, function, uuid(279a5cbd-5c15-475d-847b-e0de1624eb77)]
+interface nsIDOMMediaQueryListListener : nsISupports
+{
+  void handleChange(in nsIDOMMediaQueryList mql);
+};
--- a/dom/interfaces/base/nsIDOMWindowInternal.idl
+++ b/dom/interfaces/base/nsIDOMWindowInternal.idl
@@ -39,18 +39,19 @@
 
 #include "nsIDOMWindow2.idl"
 
 interface nsIPrompt;
 interface nsIControllers;
 interface nsIDOMLocation;
 interface nsIVariant;
 interface nsIAnimationFrameListener;
+interface nsIDOMMediaQueryList;
 
-[scriptable, uuid(9d6a1157-0719-46a7-b49f-7ffeaa0b5c86)]
+[scriptable, uuid(04eafa93-efbe-4254-9d65-91c344fa7ff2)]
 interface nsIDOMWindowInternal : nsIDOMWindow2
 {
   readonly attribute nsIDOMWindowInternal        window;
 
   /* [replaceable] self */
   readonly attribute nsIDOMWindowInternal        self;
 
   readonly attribute nsIDOMNavigator             navigator;
@@ -227,16 +228,21 @@ interface nsIDOMWindowInternal : nsIDOMW
    */
   void
     mozRequestAnimationFrame([optional] in nsIAnimationFrameListener aListener);
 
   /**
    * The current animation start time in milliseconds since the epoch.
    */
   readonly attribute long long mozAnimationStartTime;
+
+  /**
+   * http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface
+   */
+  nsIDOMMediaQueryList matchMedia(in DOMString media_query_list);
 };
 
 [scriptable, uuid(8fc58f56-f769-4368-a098-edd08550cf1a)]
 interface nsIDOMMozURLProperty : nsISupports
 {
   DOMString createObjectURL(in nsIDOMBlob blob);
   void revokeObjectURL(in DOMString URL);
 };
--- a/dom/interfaces/core/nsIDOMDocument.idl
+++ b/dom/interfaces/core/nsIDOMDocument.idl
@@ -47,17 +47,17 @@
  * cannot exist outside the context of a Document, the nsIDOMDocument 
  * interface also contains the factory methods needed to create these 
  * objects.
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[scriptable, uuid(1ae51729-c57c-43cd-91f4-2ffee5c5d493)]
+[scriptable, uuid(2d305b95-a030-4d24-a12c-7fabf61a8c3c)]
 interface nsIDOMDocument : nsIDOMNode
 {
   readonly attribute nsIDOMDocumentType         doctype;
   readonly attribute nsIDOMDOMImplementation    implementation;
   readonly attribute nsIDOMElement              documentElement;
   nsIDOMElement                 createElement(in DOMString tagName)
                                   raises(DOMException);
   nsIDOMDocumentFragment        createDocumentFragment();
@@ -97,17 +97,15 @@ interface nsIDOMDocument : nsIDOMNode
   readonly attribute DOMString       xmlEncoding;
   // Introduced in DOM Level 3:
            attribute boolean         xmlStandalone;
                                         // raises(DOMException) on setting
   // Introduced in DOM Level 3:
            attribute DOMString       xmlVersion;
                                         // raises(DOMException) on setting
   // Introduced in DOM Level 3:
-           attribute boolean         strictErrorChecking;
-  // Introduced in DOM Level 3:
            attribute DOMString       documentURI;
   // Introduced in DOM Level 3:
   nsIDOMNode         adoptNode(in nsIDOMNode source)
                                         raises(DOMException);
   // Introduced in DOM Level 3:
   void               normalizeDocument();
 };
--- a/dom/interfaces/core/nsIDOMXMLDocument.idl
+++ b/dom/interfaces/core/nsIDOMXMLDocument.idl
@@ -33,17 +33,17 @@
  * 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 "nsIDOMDocument.idl"
 
-[scriptable, uuid(38708cf6-d055-4618-9d8f-a8731834d63f)]
+[scriptable, uuid(f493687c-ea80-471b-965b-11467ebea24b)]
 interface nsIDOMXMLDocument : nsIDOMDocument
 {
   // DOM Level 3 Load & Save, DocumentLS
   // http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS
   /**
    * Whether to load synchronously or asynchronously.
    * The default is async==true.
    */
--- a/dom/interfaces/css/nsIDOMCSS2Properties.idl
+++ b/dom/interfaces/css/nsIDOMCSS2Properties.idl
@@ -45,22 +45,19 @@
  * The nsIDOMCSS2Properties interface is a datatype for additional
  * reflection of data already provided in nsIDOMCSSStyleDeclaration in
  * the Document Object Model.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Style
  */
 
-[scriptable, uuid(cd0e6cfe-7278-49b2-a1d6-c2b87b6eb7e0)]
+[scriptable, uuid(f28df617-ac8b-48e0-8094-c4642ab43940)]
 interface nsIDOMCSS2Properties : nsISupports
 {
-           attribute DOMString        azimuth;
-                                        // raises(DOMException) on setting
-
            attribute DOMString        background;
                                         // raises(DOMException) on setting
 
            attribute DOMString        backgroundAttachment;
                                         // raises(DOMException) on setting
 
            attribute DOMString        backgroundColor;
                                         // raises(DOMException) on setting
@@ -177,37 +174,25 @@ interface nsIDOMCSS2Properties : nsISupp
                                         // raises(DOMException) on setting
 
            attribute DOMString        counterIncrement;
                                         // raises(DOMException) on setting
 
            attribute DOMString        counterReset;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        cue;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        cueAfter;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        cueBefore;
-                                        // raises(DOMException) on setting
-
            attribute DOMString        cursor;
                                         // raises(DOMException) on setting
 
            attribute DOMString        direction;
                                         // raises(DOMException) on setting
 
            attribute DOMString        display;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        elevation;
-                                        // raises(DOMException) on setting
-
            attribute DOMString        emptyCells;
                                         // raises(DOMException) on setting
 
            attribute DOMString        cssFloat;
                                         // raises(DOMException) on setting
 
            attribute DOMString        font;
                                         // raises(DOMException) on setting
@@ -330,64 +315,28 @@ interface nsIDOMCSS2Properties : nsISupp
                                         // raises(DOMException) on setting
 
            attribute DOMString        pageBreakBefore;
                                         // raises(DOMException) on setting
 
            attribute DOMString        pageBreakInside;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        pause;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        pauseAfter;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        pauseBefore;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        pitch;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        pitchRange;
-                                        // raises(DOMException) on setting
-
            attribute DOMString        position;
                                         // raises(DOMException) on setting
 
            attribute DOMString        quotes;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        richness;
-                                        // raises(DOMException) on setting
-
            attribute DOMString        right;
                                         // raises(DOMException) on setting
 
            attribute DOMString        size;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        speak;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        speakHeader;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        speakNumeral;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        speakPunctuation;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        speechRate;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        stress;
-                                        // raises(DOMException) on setting
-
            attribute DOMString        tableLayout;
                                         // raises(DOMException) on setting
 
            attribute DOMString        textAlign;
                                         // raises(DOMException) on setting
 
            attribute DOMString        textDecoration;
                                         // raises(DOMException) on setting
@@ -408,22 +357,16 @@ interface nsIDOMCSS2Properties : nsISupp
                                         // raises(DOMException) on setting
 
            attribute DOMString        verticalAlign;
                                         // raises(DOMException) on setting
 
            attribute DOMString        visibility;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        voiceFamily;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        volume;
-                                        // raises(DOMException) on setting
-
            attribute DOMString        whiteSpace;
                                         // raises(DOMException) on setting
 
            attribute DOMString        widows;
                                         // raises(DOMException) on setting
 
            attribute DOMString        width;
                                         // raises(DOMException) on setting
--- a/dom/interfaces/html/nsIDOMHTMLDocument.idl
+++ b/dom/interfaces/html/nsIDOMHTMLDocument.idl
@@ -45,17 +45,17 @@
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
-[scriptable, uuid(42de381d-1535-4223-b7d9-a9d7c250f9a7)]
+[scriptable, uuid(2d7a0f2e-6b1c-4e93-bbea-122eb0a8a513)]
 interface nsIDOMHTMLDocument : nsIDOMDocument
 {
            attribute DOMString            title;
   readonly attribute DOMString            referrer;
   // domain is readonly per spec, but it's settable in
   // nsIDOMNSHTMLDocument
   [noscript] readonly attribute DOMString domain;
   readonly attribute DOMString            URL;
--- a/dom/interfaces/svg/nsIDOMSVGDocument.idl
+++ b/dom/interfaces/svg/nsIDOMSVGDocument.idl
@@ -34,17 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMDocument.idl"
 
 interface nsIDOMSVGSVGElement;
 
-[scriptable, uuid(b0cb0f05-6fd4-4f2c-8a6c-aac63bc90cad)]
+[scriptable, uuid(dcac0765-b258-4e0b-9862-6470eb9876ba)]
 interface nsIDOMSVGDocument : nsIDOMDocument
                          /* , nsIDOMDocumentEvent */
 {
   readonly attribute DOMString title;
   readonly attribute DOMString referrer;
   readonly attribute DOMString domain;
   readonly attribute DOMString URL;
   readonly attribute nsIDOMSVGSVGElement rootElement;
--- a/dom/locales/en-US/chrome/layout/css.properties
+++ b/dom/locales/en-US/chrome/layout/css.properties
@@ -50,16 +50,17 @@ PECharsetRuleEOF=charset string in @char
 PECharsetRuleNotString=Expected charset string but found '%1$S'.
 PEGatherMediaEOF=end of media list in @import or @media rule
 PEGatherMediaNotComma=Expected ',' in media list but found '%1$S'.
 PEGatherMediaNotIdent=Expected identifier in media list but found '%1$S'.
 PEImportNotURI=Expected URI in @import rule but found '%1$S'.
 PEImportBadURI=Invalid URI in @import rule: '%1$S'.
 PEImportUnexpected=Found unexpected '%1$S' within @import.
 PEGroupRuleEOF=end of @media or @-moz-document rule
+PEGroupRuleNestedAtRule=%1$S rule not allowed within @media or @-moz-document rule.
 PEMozDocRuleBadFunc=Expected url(), url-prefix(), or domain() in @-moz-document rule but found '%1$S'.
 PEMozDocRuleNotURI=Expected URI in @-moz-document rule but found '%1$S'.
 PEAtNSPrefixEOF=namespace prefix in @namespace rule
 PEAtNSURIEOF=namespace URI in @namespace rule
 PEAtNSUnexpected=Unexpected token within @namespace: '%1$S'.
 PEKeyframeNameEOF=name of @keyframes rule.
 PEKeyframeBadName=Expected identifier for name of @keyframes rule.
 PEKeyframeBrace=Expected opening { of @keyframes rule.
--- a/editor/libeditor/text/tests/test_bug600570.html
+++ b/editor/libeditor/text/tests/test_bug600570.html
@@ -10,17 +10,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.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=600570">Mozilla Bug 600570</a>
 <p id="display"></p>
 <div id="content">
-<textarea>
+<textarea spellcheck="false">
 aaa
 [bbb]</textarea>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 600570 **/
 
@@ -40,27 +40,29 @@ SimpleTest.waitForFocus(function() {
   SimpleTest.waitForClipboard("aaa\n",
     function() {
       synthesizeKey("X", {accelKey: true});
     },
     function() {
       t.addEventListener("input", function() {
         t.removeEventListener("input", arguments.callee, false);
 
-        is(t.value, "[aaa\nbbb]", "The value of the textarea should be correct");
-        synthesizeKey("A", {accelKey: true});
-        is(t.selectionStart, 0, "Select all should set the selection start to the beginning of textarea");
-        is(t.selectionEnd, 9, "Select all should set the selection end to the end of textarea");
+        setTimeout(function() { // Avoid the assertion in bug 649797
+          is(t.value, "[aaa\nbbb]", "The value of the textarea should be correct");
+          synthesizeKey("A", {accelKey: true});
+          is(t.selectionStart, 0, "Select all should set the selection start to the beginning of textarea");
+          is(t.selectionEnd, 9, "Select all should set the selection end to the end of textarea");
 
-        var afterPaste = snapshotWindow(window);
+          var afterPaste = snapshotWindow(window);
 
-        var res = compareSnapshots(afterSetValue, afterPaste, true);
-        ok(res[0], "Pasting and setting the value directly should result in the same rendering");
+          var res = compareSnapshots(afterSetValue, afterPaste, true);
+          ok(res[0], "Pasting and setting the value directly should result in the same rendering");
 
-        SimpleTest.finish();
+          SimpleTest.finish();
+        }, 0);
       }, false);
       synthesizeKey("VK_RIGHT", {});
       synthesizeKey("V", {accelKey: true});
     },
     function() {
       SimpleTest.finish();
     }
   );
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -383,17 +383,17 @@ CPPSRCS += 	checks.cc \
 		platform.cc \
 		utils.cc \
 		$(NONE)
 
 #
 # END enclude sources for V8 dtoa
 #############################################
 
-ifeq (,$(filter-out powerpc sparc,$(TARGET_CPU)))
+ifeq (,$(filter arm %86 x86_64,$(TARGET_CPU)))
 
 VPATH +=	$(srcdir)/assembler \
 		$(srcdir)/assembler/wtf \
 		$(srcdir)/yarr/pcre \
 		$(NULL)
 
 CPPSRCS += 	pcre_compile.cpp \
                 pcre_exec.cpp \
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -95,16 +95,17 @@
 #include "nsObjectFrame.h"
 #include "nsTransitionManager.h"
 #ifdef MOZ_CSS_ANIMATIONS
 #include "nsAnimationManager.h"
 #endif
 #include "mozilla/dom/Element.h"
 #include "nsIFrameMessageManager.h"
 #include "FrameLayerBuilder.h"
+#include "nsDOMMediaQueryList.h"
 
 #ifdef MOZ_SMIL
 #include "nsSMILAnimationController.h"
 #endif // MOZ_SMIL
 
 #ifdef IBMBIDI
 #include "nsBidiPresUtils.h"
 #endif // IBMBIDI
@@ -249,23 +250,28 @@ nsPresContext::nsPresContext(nsIDocument
     mNeverAnimate = PR_TRUE;
   } else {
     mImageAnimationMode = imgIContainer::kNormalAnimMode;
     mNeverAnimate = PR_FALSE;
   }
   NS_ASSERTION(mDocument, "Null document");
   mUserFontSet = nsnull;
   mUserFontSetDirty = PR_TRUE;
+
+  PR_INIT_CLIST(&mDOMMediaQueryLists);
 }
 
 nsPresContext::~nsPresContext()
 {
   NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
   SetShell(nsnull);
 
+  NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
+                    "must not have media query lists left");
+
   // Disconnect the refresh driver *after* the transition manager, which
   // needs it.
   if (mRefreshDriver && mRefreshDriver->PresContext() == this) {
     mRefreshDriver->Disconnect();
   }
 
   if (mEventManager) {
     // unclear if these are needed, but can't hurt
@@ -1638,21 +1644,66 @@ void
 nsPresContext::MediaFeatureValuesChanged(PRBool aCallerWillRebuildStyleData)
 {
   mPendingMediaFeatureValuesChanged = PR_FALSE;
   if (mShell &&
       mShell->StyleSet()->MediumFeaturesChanged(this) &&
       !aCallerWillRebuildStyleData) {
     RebuildAllStyleData(nsChangeHint(0));
   }
+
+  if (!nsContentUtils::IsSafeToRunScript()) {
+    NS_ABORT_IF_FALSE(mDocument->IsBeingUsedAsImage(),
+                      "How did we get here?  Are we failing to notify "
+                      "listeners that we should notify?");
+    return;
+  }
+
+  // Media query list listeners should be notified from a queued task
+  // (in HTML5 terms), although we also want to notify them on certain
+  // flushes.  (We're already running off an event.)
+  //
+  // Note that we do this after the new style from media queries in
+  // style sheets has been computed.
+
+  if (!PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists)) {
+    // We build a list of all the notifications we're going to send
+    // before we send any of them.  (The spec says the notifications
+    // should be a queued task, so any removals that happen during the
+    // notifications shouldn't affect what gets notified.)  Furthermore,
+    // we hold strong pointers to everything we're going to make
+    // notification calls to, since each notification involves calling
+    // arbitrary script that might otherwise destroy these objects, or,
+    // for that matter, |this|.
+    //
+    // Note that we intentionally send the notifications to media query
+    // list in the order they were created and, for each list, to the
+    // listeners in the order added.
+    nsDOMMediaQueryList::NotifyList notifyList;
+    for (PRCList *l = PR_LIST_HEAD(&mDOMMediaQueryLists);
+         l != &mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
+      nsDOMMediaQueryList *mql = static_cast<nsDOMMediaQueryList*>(l);
+      mql->MediumFeaturesChanged(notifyList);
+    }
+
+    for (PRUint32 i = 0, i_end = notifyList.Length(); i != i_end; ++i) {
+      nsDOMMediaQueryList::HandleChangeData &d = notifyList[i];
+      d.listener->HandleChange(d.mql);
+    }
+
+    // NOTE:  When |notifyList| goes out of scope, our destructor could run.
+  }
 }
 
 void
 nsPresContext::PostMediaFeatureValuesChangedEvent()
 {
+  // FIXME: We should probably replace this event with use of
+  // nsRefreshDriver::AddStyleFlushObserver (except the pres shell would
+  // need to track whether it's been added).
   if (!mPendingMediaFeatureValuesChanged) {
     nsCOMPtr<nsIRunnable> ev =
       NS_NewRunnableMethod(this, &nsPresContext::HandleMediaFeatureValuesChangedEvent);
     if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev))) {
       mPendingMediaFeatureValuesChanged = PR_TRUE;
     }
   }
 }
@@ -1663,16 +1714,29 @@ nsPresContext::HandleMediaFeatureValuesC
   // Null-check mShell in case the shell has been destroyed (and the
   // event is the only thing holding the pres context alive).
   if (mPendingMediaFeatureValuesChanged && mShell) {
     MediaFeatureValuesChanged(PR_FALSE);
   }
 }
 
 void
+nsPresContext::MatchMedia(const nsAString& aMediaQueryList,
+                          nsIDOMMediaQueryList** aResult)
+{
+  nsRefPtr<nsDOMMediaQueryList> result =
+    new nsDOMMediaQueryList(this, aMediaQueryList);
+
+  // Insert the new item at the end of the linked list.
+  PR_INSERT_BEFORE(result, &mDOMMediaQueryLists);
+
+  result.forget(aResult);
+}
+
+void
 nsPresContext::SetPaginatedScrolling(PRBool aPaginated)
 {
   if (mType == eContext_PrintPreview || mType == eContext_PageLayout)
     mCanPaginatedScroll = aPaginated;
 }
 
 void
 nsPresContext::SetPrintSettings(nsIPrintSettings *aPrintSettings)
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -68,16 +68,17 @@
 #include "nsRegion.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
 #include "nsContentUtils.h"
 #include "nsIWidget.h"
 #include "mozilla/TimeStamp.h"
 #include "nsIContent.h"
+#include "prclist.h"
 
 class nsImageLoader;
 #ifdef IBMBIDI
 class nsBidiPresUtils;
 #endif // IBMBIDI
 
 struct nsRect;
 
@@ -102,16 +103,17 @@ class nsUserFontSet;
 struct nsFontFaceRuleContainer;
 class nsObjectFrame;
 class nsTransitionManager;
 #ifdef MOZ_CSS_ANIMATIONS
 class nsAnimationManager;
 #endif
 class nsRefreshDriver;
 class imgIContainer;
+class nsIDOMMediaQueryList;
 
 #ifdef MOZ_REFLOW_PERF
 class nsRenderingContext;
 #endif
 
 enum nsWidgetType {
   eWidgetType_Button  	= 1,
   eWidgetType_Checkbox	= 2,
@@ -265,16 +267,22 @@ public:
   void PostMediaFeatureValuesChangedEvent();
   NS_HIDDEN_(void) HandleMediaFeatureValuesChangedEvent();
   void FlushPendingMediaFeatureValuesChanged() {
     if (mPendingMediaFeatureValuesChanged)
       MediaFeatureValuesChanged(PR_FALSE);
   }
 
   /**
+   * Support for window.matchMedia()
+   */
+  void MatchMedia(const nsAString& aMediaQueryList,
+                  nsIDOMMediaQueryList** aResult);
+
+  /**
    * Access compatibility mode for this context.  This is the same as
    * our document's compatibility mode.
    */
   nsCompatibility CompatibilityMode() const {
     return Document()->GetCompatibilityMode();
   }
   /**
    * Notify the context that the document's compatibility mode has changed
@@ -1072,16 +1080,18 @@ protected:
   // charset rather than explicitly specified as a lang attribute).
   nsIAtom*              mLanguage;      // [STRONG]
 
   nsRefPtrHashtable<nsVoidPtrHashKey, nsImageLoader>
                         mImageLoaders[IMAGE_LOAD_TYPE_COUNT];
 
   nsWeakPtr             mContainer;
 
+  PRCList               mDOMMediaQueryLists;
+
   PRInt32               mMinFontSize;   // Min font size, defaults to 0
   float                 mTextZoom;      // Text zoom, defaults to 1.0
   float                 mFullZoom;      // Page zoom, defaults to 1.0
 
   PRInt32               mCurAppUnitsPerDevPixel;
   PRInt32               mAutoQualityMinFontSizePixelsPref;
 
   nsCOMPtr<nsITheme> mTheme;
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -134,59 +134,67 @@ nsRefreshDriver::RestoreNormalRefresh()
 {
   mTestControllingRefreshes = false;
   Notify(nsnull); // will call UpdateMostRecentRefresh()
 }
 
 TimeStamp
 nsRefreshDriver::MostRecentRefresh() const
 {
-  const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted();
+  const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted(false);
 
   return mMostRecentRefresh;
 }
 
 PRInt64
 nsRefreshDriver::MostRecentRefreshEpochTime() const
 {
-  const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted();
+  const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted(false);
 
   return mMostRecentRefreshEpochTime;
 }
 
 PRBool
 nsRefreshDriver::AddRefreshObserver(nsARefreshObserver *aObserver,
                                     mozFlushType aFlushType)
 {
   ObserverArray& array = ArrayFor(aFlushType);
   PRBool success = array.AppendElement(aObserver) != nsnull;
 
-  EnsureTimerStarted();
+  EnsureTimerStarted(false);
 
   return success;
 }
 
 PRBool
 nsRefreshDriver::RemoveRefreshObserver(nsARefreshObserver *aObserver,
                                        mozFlushType aFlushType)
 {
   ObserverArray& array = ArrayFor(aFlushType);
   return array.RemoveElement(aObserver);
 }
 
 void
-nsRefreshDriver::EnsureTimerStarted()
+nsRefreshDriver::EnsureTimerStarted(bool aAdjustingTimer)
 {
   if (mTimer || mFrozen || !mPresContext) {
     // It's already been started, or we don't want to start it now or
     // we've been disconnected.
     return;
   }
 
-  UpdateMostRecentRefresh();
+  if (!aAdjustingTimer) {
+    // If we didn't already have a timer and aAdjustingTimer is false,
+    // then we just got our first observer (or an explicit call to
+    // MostRecentRefresh by a caller who's likely to add an observer
+    // shortly).  This means we should fake a most-recent-refresh time
+    // of now so that said observer gets a reasonable refresh time, so
+    // things behave as though the timer had always been running.
+    UpdateMostRecentRefresh();
+  }
 
   mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
   if (!mTimer) {
     return;
   }
 
   PRInt32 timerType = GetRefreshTimerType();
   mTimerIsPrecise = (timerType == nsITimer::TYPE_REPEATING_PRECISE);
@@ -390,17 +398,17 @@ nsRefreshDriver::Notify(nsITimer *aTimer
     // to be one-shot.  Stopping and restarting in the case when we need to
     // switch from precise to slack timers or vice versa is unfortunately
     // required.
 
     // Note that the EnsureTimerStarted() call here is ok because
     // EnsureTimerStarted makes sure to not start the timer if it shouldn't be
     // started.
     StopTimer();
-    EnsureTimerStarted();
+    EnsureTimerStarted(true);
   }
 
   return NS_OK;
 }
 
 void
 nsRefreshDriver::Freeze()
 {
@@ -410,31 +418,35 @@ nsRefreshDriver::Freeze()
 }
 
 void
 nsRefreshDriver::Thaw()
 {
   NS_ASSERTION(mFrozen, "Thaw called on an unfrozen refresh driver");
   mFrozen = false;
   if (ObserverCount()) {
+    // FIXME: This isn't quite right, since our EnsureTimerStarted call
+    // updates our mMostRecentRefresh, but the DoRefresh call won't run
+    // and notify our observers until we get back to the event loop.
+    // Thus MostRecentRefresh() will lie between now and the DoRefresh.
     NS_DispatchToCurrentThread(NS_NewRunnableMethod(this, &nsRefreshDriver::DoRefresh));
-    EnsureTimerStarted();
+    EnsureTimerStarted(false);
   }
 }
 
 void
 nsRefreshDriver::SetThrottled(bool aThrottled)
 {
   if (aThrottled != mThrottled) {
     mThrottled = aThrottled;
     if (mTimer) {
       // We want to switch our timer type here, so just stop and
       // restart the timer.
       StopTimer();
-      EnsureTimerStarted();
+      EnsureTimerStarted(true);
     }
   }
 }
 
 void
 nsRefreshDriver::DoRefresh()
 {
   // Don't do a refresh unless we're in a state where we should be refreshing.
@@ -455,30 +467,30 @@ nsRefreshDriver::IsRefreshObserver(nsARe
 
 PRBool
 nsRefreshDriver::ScheduleBeforePaintEvent(nsIDocument* aDocument)
 {
   NS_ASSERTION(mBeforePaintTargets.IndexOf(aDocument) ==
                mBeforePaintTargets.NoIndex,
                "Shouldn't have a paint event posted for this document");
   PRBool appended = mBeforePaintTargets.AppendElement(aDocument) != nsnull;
-  EnsureTimerStarted();
+  EnsureTimerStarted(false);
   return appended;
 }
 
 void
 nsRefreshDriver::ScheduleAnimationFrameListeners(nsIDocument* aDocument)
 {
   NS_ASSERTION(mAnimationFrameListenerDocs.IndexOf(aDocument) ==
                mAnimationFrameListenerDocs.NoIndex,
                "Don't schedule the same document multiple times");
   mAnimationFrameListenerDocs.AppendElement(aDocument);
   // No need to worry about restarting our timer in precise mode if it's
   // already running; that will happen automatically when it fires.
-  EnsureTimerStarted();
+  EnsureTimerStarted(false);
 }
 
 void
 nsRefreshDriver::RevokeBeforePaintEvent(nsIDocument* aDocument)
 {
   mBeforePaintTargets.RemoveElement(aDocument);
 }
 
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -130,27 +130,27 @@ public:
 
   /**
    * Add / remove presshells that we should flush style and layout on
    */
   PRBool AddStyleFlushObserver(nsIPresShell* aShell) {
     NS_ASSERTION(!mStyleFlushObservers.Contains(aShell),
 		 "Double-adding style flush observer");
     PRBool appended = mStyleFlushObservers.AppendElement(aShell) != nsnull;
-    EnsureTimerStarted();
+    EnsureTimerStarted(false);
     return appended;
   }
   void RemoveStyleFlushObserver(nsIPresShell* aShell) {
     mStyleFlushObservers.RemoveElement(aShell);
   }
   PRBool AddLayoutFlushObserver(nsIPresShell* aShell) {
     NS_ASSERTION(!IsLayoutFlushObserver(aShell),
 		 "Double-adding layout flush observer");
     PRBool appended = mLayoutFlushObservers.AppendElement(aShell) != nsnull;
-    EnsureTimerStarted();
+    EnsureTimerStarted(false);
     return appended;
   }
   void RemoveLayoutFlushObserver(nsIPresShell* aShell) {
     mLayoutFlushObservers.RemoveElement(aShell);
   }
   PRBool IsLayoutFlushObserver(nsIPresShell* aShell) {
     return mLayoutFlushObservers.Contains(aShell);
   }
@@ -214,17 +214,17 @@ public:
    */
   PRBool IsRefreshObserver(nsARefreshObserver *aObserver,
 			   mozFlushType aFlushType);
 #endif
 
 private:
   typedef nsTObserverArray<nsARefreshObserver*> ObserverArray;
 
-  void EnsureTimerStarted();
+  void EnsureTimerStarted(bool aAdjustingTimer);
   void StopTimer();
   PRUint32 ObserverCount() const;
   void UpdateMostRecentRefresh();
   ObserverArray& ArrayFor(mozFlushType aFlushType);
   // Trigger a refresh immediately, if haven't been disconnected or frozen.
   void DoRefresh();
 
   PRInt32 GetRefreshTimerInterval() const;
--- a/layout/generic/nsLineBox.cpp
+++ b/layout/generic/nsLineBox.cpp
@@ -655,18 +655,16 @@ nsLineIterator::CheckLineOrder(PRInt32  
 
   if (!line->mFirstChild) { // empty line
     *aIsReordered = PR_FALSE;
     *aFirstVisual = nsnull;
     *aLastVisual = nsnull;
     return NS_OK;
   }
   
-  nsPresContext* presContext = line->mFirstChild->PresContext();
-
   nsIFrame* leftmostFrame;
   nsIFrame* rightmostFrame;
   *aIsReordered = nsBidiPresUtils::CheckLineOrder(line->mFirstChild, line->GetChildCount(), &leftmostFrame, &rightmostFrame);
 
   // map leftmost/rightmost to first/last according to paragraph direction
   *aFirstVisual = mRightToLeft ? rightmostFrame : leftmostFrame;
   *aLastVisual = mRightToLeft ? leftmostFrame : rightmostFrame;
 
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1967,29 +1967,31 @@ nsPluginInstanceOwner::NotifyPaintWaiter
   if (!mWaitingForPaint && !IsUpToDate() && aBuilder->ShouldSyncDecodeImages()) {
     nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, PR_FALSE);
     // Run this event as soon as it's safe to do so, since listeners need to
     // receive it immediately
     mWaitingForPaint = nsContentUtils::AddScriptRunner(event);
   }
 }
 
+#ifdef XP_MACOSX
 static void DrawPlugin(ImageContainer* aContainer, void* aPluginInstanceOwner)
 {
   nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetOwner();
   if (frame) {
     frame->UpdateImageLayer(aContainer, gfxRect(0,0,0,0));
   }
 }
 
 static void OnDestroyImage(void* aPluginInstanceOwner)
 {
   nsPluginInstanceOwner* owner = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner);
   NS_IF_RELEASE(owner);
 }
+#endif // XP_MACOSX
 
 void
 nsObjectFrame::UpdateImageLayer(ImageContainer* aContainer, const gfxRect& aRect)
 {
   if (!mInstanceOwner) {
     return;
   }
 
@@ -2778,26 +2780,28 @@ public:
 
 private:  
   nsCOMPtr<nsITimer> mTimer;
   nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
 };
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsStopPluginRunnable, nsRunnable, nsITimerCallback)
 
+#if defined(XP_MACOSX) || defined (XP_WIN)
 static const char*
 GetMIMEType(nsIPluginInstance *aPluginInstance)
 {
   if (aPluginInstance) {
     const char* mime = nsnull;
     if (NS_SUCCEEDED(aPluginInstance->GetMIMEType(&mime)) && mime)
       return mime;
   }
   return "";
 }
+#endif // XP_MACOSX || XP_WIN
 
 static PRBool
 DoDelayedStop(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop)
 {
 #if (MOZ_PLATFORM_MAEMO==5)
   // Don't delay stop on Maemo/Hildon (bug 530739).
   if (aDelayedStop && aInstanceOwner->MatchPluginName("Shockwave Flash"))
     return PR_FALSE;
--- a/layout/mathml/nsMathMLmunderFrame.cpp
+++ b/layout/mathml/nsMathMLmunderFrame.cpp
@@ -277,18 +277,16 @@ nsMathMLmunderFrame::Place(nsRenderingCo
 
   ////////////////////
   // Place Children
 
   aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
   nsFontMetrics* fm = aRenderingContext.FontMetrics();
 
-  nscoord xHeight = fm->XHeight();
-
   nscoord ruleThickness;
   GetRuleThickness (aRenderingContext, fm, ruleThickness);
 
   // there are 2 different types of placement depending on 
   // whether we want an accented under or not
 
   nscoord correction = 0;
   GetItalicCorrection (bmBase, correction);
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -478,24 +478,16 @@ Declaration::GetValue(nsCSSProperty aPro
         aValue.Append(PRUnichar(','));
         aValue.Append(PRUnichar(' '));
       }
 
       aValue.Append(PRUnichar(' '));
       AppendValueToString(eCSSProperty_background_color, aValue);
       break;
     }
-    case eCSSProperty_cue: {
-      if (AppendValueToString(eCSSProperty_cue_before, aValue)) {
-        aValue.Append(PRUnichar(' '));
-        if (!AppendValueToString(eCSSProperty_cue_after, aValue))
-          aValue.Truncate();
-      }
-      break;
-    }
     case eCSSProperty_font: {
       // systemFont might not be present; the others are guaranteed to be
       // based on the shorthand check at the beginning of the function
       const nsCSSValue *systemFont =
         data->ValueFor(eCSSProperty__x_system_font);
       const nsCSSValue &style =
         *data->ValueFor(eCSSProperty_font_style);
       const nsCSSValue &variant =
@@ -583,24 +575,16 @@ Declaration::GetValue(nsCSSProperty aPro
       const nsCSSValue &xValue =
         *data->ValueFor(eCSSProperty_overflow_x);
       const nsCSSValue &yValue =
         *data->ValueFor(eCSSProperty_overflow_y);
       if (xValue == yValue)
         xValue.AppendToString(eCSSProperty_overflow_x, aValue);
       break;
     }
-    case eCSSProperty_pause: {
-      if (AppendValueToString(eCSSProperty_pause_before, aValue)) {
-        aValue.Append(PRUnichar(' '));
-        if (!AppendValueToString(eCSSProperty_pause_after, aValue))
-          aValue.Truncate();
-      }
-      break;
-    }
     case eCSSProperty_transition: {
       const nsCSSValue &transProp =
         *data->ValueFor(eCSSProperty_transition_property);
       const nsCSSValue &transDuration =
         *data->ValueFor(eCSSProperty_transition_duration);
       const nsCSSValue &transTiming =
         *data->ValueFor(eCSSProperty_transition_timing_function);
       const nsCSSValue &transDelay =
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1163,17 +1163,16 @@ Loader::PrepareSheet(nsCSSStyleSheet* aS
 
   if (!aMediaString.IsEmpty()) {
     NS_ASSERTION(!aMediaList,
                  "must not provide both aMediaString and aMediaList");
     mediaList = new nsMediaList();
     NS_ENSURE_TRUE(mediaList, NS_ERROR_OUT_OF_MEMORY);
 
     nsCSSParser mediumParser(this);
-    NS_ENSURE_TRUE(mediumParser, NS_ERROR_OUT_OF_MEMORY);
 
     // We have aMediaString only when linked from link elements, style
     // elements, or PIs, so pass PR_TRUE.
     rv = mediumParser.ParseMediaList(aMediaString, nsnull, 0, mediaList,
                                      PR_TRUE);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
@@ -1570,21 +1569,16 @@ Loader::ParseSheet(nsIUnicharInputStream
   nsCAutoString spec__("N/A");
   if (aLoadData->mURI) aLoadData->mURI->GetSpec(spec__);
   NS_TIME_FUNCTION_FMT("Parsing stylesheet (url: %s)", spec__.get());
 #endif
 
   aCompleted = PR_FALSE;
 
   nsCSSParser parser(this, aLoadData->mSheet);
-  if (!parser) {
-    LOG_ERROR(("  Failed to get CSS parser"));
-    SheetComplete(aLoadData, NS_ERROR_OUT_OF_MEMORY);
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
 
   // Push our load data on the stack so any kids can pick it up
   mParsingDatas.AppendElement(aLoadData);
   nsIURI* sheetURI = aLoadData->mSheet->GetSheetURI();
   nsIURI* baseURI = aLoadData->mSheet->GetBaseURI();
   nsresult rv = parser.Parse(aStream, sheetURI, baseURI,
                              aLoadData->mSheet->Principal(),
                              aLoadData->mLineNumber,
--- a/layout/style/Makefile.in
+++ b/layout/style/Makefile.in
@@ -66,16 +66,17 @@ EXPORTS		= \
 		nsCSSPseudoClasses.h \
 		nsCSSPseudoElementList.h \
 		nsCSSPseudoElements.h \
 		nsCSSRuleProcessor.h \
 		nsCSSStyleSheet.h \
 		nsCSSValue.h \
 		nsDOMCSSAttrDeclaration.h \
 		nsDOMCSSDeclaration.h \
+		nsDOMMediaQueryList.h \
 		nsICSSDeclaration.h \
 		nsICSSLoaderObserver.h \
 		nsICSSPseudoComparator.h \
 		nsICSSRule.h \
 		nsICSSRuleList.h \
 		nsICSSStyleRuleDOMWrapper.h \
 		nsIStyleRule.h \
 		nsIStyleRuleProcessor.h \
@@ -122,16 +123,17 @@ CPPSRCS		= \
 		nsCSSStyleSheet.cpp \
 		nsCSSValue.cpp \
 		nsComputedDOMStyle.cpp \
 		nsDOMCSSAttrDeclaration.cpp \
 		nsDOMCSSDeclaration.cpp \
 		nsDOMCSSRGBColor.cpp \
 		nsDOMCSSRect.cpp \
 		nsDOMCSSValueList.cpp \
+		nsDOMMediaQueryList.cpp \
 		nsFontFaceLoader.cpp \
 		nsHTMLCSSStyleSheet.cpp \
 		nsHTMLStyleSheet.cpp \
 		nsLayoutStylesheetCache.cpp \
 		nsMediaFeatures.cpp \
 		nsNthIndexCache.cpp \
 		nsROCSSPrimitiveValue.cpp \
 		nsRuleData.cpp \
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -175,35 +175,32 @@ CSS_KEY(-moz-trad-chinese-informal, _moz
 CSS_KEY(-moz-urdu, _moz_urdu)
 CSS_KEY(-moz-use-system-font, _moz_use_system_font)
 CSS_KEY(-moz-use-text-color, _moz_use_text_color)
 CSS_KEY(-moz-visitedhyperlinktext, _moz_visitedhyperlinktext)
 CSS_KEY(-moz-window, _moz_window)
 CSS_KEY(-moz-workspace, _moz_workspace)
 CSS_KEY(-moz-zoom-in, _moz_zoom_in)
 CSS_KEY(-moz-zoom-out, _moz_zoom_out)
-CSS_KEY(above, above)
 CSS_KEY(absolute, absolute)
 CSS_KEY(active, active)
 CSS_KEY(activeborder, activeborder)
 CSS_KEY(activecaption, activecaption)
 CSS_KEY(alias, alias)
 CSS_KEY(all, all)
 CSS_KEY(all-scroll, all_scroll)
 CSS_KEY(alternate, alternate)
 CSS_KEY(always, always)
 CSS_KEY(appworkspace, appworkspace)
 CSS_KEY(armenian, armenian)
 CSS_KEY(auto, auto)
 CSS_KEY(avoid, avoid)
 CSS_KEY(background, background)
 CSS_KEY(backwards, backwards)
 CSS_KEY(baseline, baseline)
-CSS_KEY(behind, behind)
-CSS_KEY(below, below)
 CSS_KEY(bidi-override, bidi_override)
 CSS_KEY(blink, blink)
 CSS_KEY(block, block)
 CSS_KEY(block-axis, block_axis)
 CSS_KEY(bold, bold)
 CSS_KEY(bolder, bolder)
 CSS_KEY(border-box, border_box)
 CSS_KEY(both, both)
@@ -216,26 +213,23 @@ CSS_KEY(buttonface, buttonface)
 CSS_KEY(buttonhighlight, buttonhighlight)
 CSS_KEY(buttonshadow, buttonshadow)
 CSS_KEY(buttontext, buttontext)
 CSS_KEY(capitalize, capitalize)
 CSS_KEY(caption, caption)
 CSS_KEY(captiontext, captiontext)
 CSS_KEY(cell, cell)
 CSS_KEY(center, center)
-CSS_KEY(center-left, center_left)
-CSS_KEY(center-right, center_right)
 CSS_KEY(ch, ch)
 CSS_KEY(circle, circle)
 CSS_KEY(cjk-ideographic, cjk_ideographic)
 CSS_KEY(close-quote, close_quote)
 CSS_KEY(closest-corner, closest_corner)
 CSS_KEY(closest-side, closest_side)
 CSS_KEY(cm, cm)
-CSS_KEY(code, code)
 CSS_KEY(col-resize, col_resize)
 CSS_KEY(collapse, collapse)
 CSS_KEY(condensed, condensed)
 CSS_KEY(contain, contain)
 CSS_KEY(content-box, content_box)
 CSS_KEY(context-menu, context_menu)
 CSS_KEY(continuous, continuous)
 CSS_KEY(copy, copy)
@@ -245,17 +239,16 @@ CSS_KEY(cross, cross)
 CSS_KEY(crosshair, crosshair)
 CSS_KEY(currentcolor, currentcolor)
 CSS_KEY(dashed, dashed)
 CSS_KEY(decimal, decimal)
 CSS_KEY(decimal-leading-zero, decimal_leading_zero)
 CSS_KEY(default, default)
 CSS_KEY(deg, deg)
 CSS_KEY(dialog, dialog)
-CSS_KEY(digits, digits)
 CSS_KEY(disabled, disabled)
 CSS_KEY(disc, disc)
 CSS_KEY(dotted, dotted)
 CSS_KEY(double, double)
 CSS_KEY(e-resize, e_resize)
 CSS_KEY(each-box, each_box)
 CSS_KEY(ease, ease)
 CSS_KEY(ease-in, ease_in)
@@ -268,35 +261,29 @@ CSS_KEY(em, em)
 CSS_KEY(embed, embed)
 CSS_KEY(enabled, enabled)
 CSS_KEY(end, end)
 CSS_KEY(ex, ex)
 CSS_KEY(expanded, expanded)
 CSS_KEY(extra-condensed, extra_condensed)
 CSS_KEY(extra-expanded, extra_expanded)
 CSS_KEY(ew-resize, ew_resize)
-CSS_KEY(far-left, far_left)
-CSS_KEY(far-right, far_right)
 CSS_KEY(farthest-side, farthest_side)
 CSS_KEY(farthest-corner, farthest_corner)
-CSS_KEY(fast, fast)
-CSS_KEY(faster, faster)
 CSS_KEY(fill, fill)
 CSS_KEY(fixed, fixed)
 CSS_KEY(forwards, forwards)
 CSS_KEY(georgian, georgian)
 CSS_KEY(grad, grad)
 CSS_KEY(graytext, graytext)
 CSS_KEY(groove, groove)
 CSS_KEY(hebrew, hebrew)
 CSS_KEY(help, help)
 CSS_KEY(hidden, hidden)
 CSS_KEY(hide, hide)
-CSS_KEY(high, high)
-CSS_KEY(higher, higher)
 CSS_KEY(highlight, highlight)
 CSS_KEY(highlighttext, highlighttext)
 CSS_KEY(hiragana, hiragana)
 CSS_KEY(hiragana-iroha, hiragana_iroha)
 CSS_KEY(horizontal, horizontal)
 CSS_KEY(hz, hz)
 CSS_KEY(icon, icon)
 CSS_KEY(ignore, ignore)
@@ -323,27 +310,21 @@ CSS_KEY(italic, italic)
 CSS_KEY(justify, justify)
 CSS_KEY(katakana, katakana)
 CSS_KEY(katakana-iroha, katakana_iroha)
 CSS_KEY(khz, khz)
 CSS_KEY(landscape, landscape)
 CSS_KEY(large, large)
 CSS_KEY(larger, larger)
 CSS_KEY(left, left)
-CSS_KEY(left-side, left_side)
-CSS_KEY(leftwards, leftwards)
-CSS_KEY(level, level)
 CSS_KEY(lighter, lighter)
 CSS_KEY(line-through, line_through)
 CSS_KEY(linear, linear)
 CSS_KEY(list-item, list_item)
 CSS_KEY(logical, logical)
-CSS_KEY(loud, loud)
-CSS_KEY(low, low)
-CSS_KEY(lower, lower)
 CSS_KEY(lower-alpha, lower_alpha)
 CSS_KEY(lower-greek, lower_greek)
 CSS_KEY(lower-latin, lower_latin)
 CSS_KEY(lower-roman, lower_roman)
 CSS_KEY(lowercase, lowercase)
 CSS_KEY(ltr, ltr)
 CSS_KEY(margin-box, margin_box)
 CSS_KEY(matrix, matrix)
@@ -367,17 +348,16 @@ CSS_KEY(no-repeat, no_repeat)
 CSS_KEY(none, none)
 CSS_KEY(normal, normal)
 CSS_KEY(not-allowed, not_allowed)
 CSS_KEY(nowrap, nowrap)
 CSS_KEY(ns-resize, ns_resize)
 CSS_KEY(nw-resize, nw_resize)
 CSS_KEY(nwse-resize, nwse_resize)
 CSS_KEY(oblique, oblique)
-CSS_KEY(once, once)
 CSS_KEY(open-quote, open_quote)
 CSS_KEY(outset, outset)
 CSS_KEY(outside, outside)
 CSS_KEY(overline, overline)
 CSS_KEY(padding-box, padding_box)
 CSS_KEY(painted, painted)
 CSS_KEY(paused, paused)
 CSS_KEY(pc, pc)
@@ -396,18 +376,16 @@ CSS_KEY(read-only, read_only)
 CSS_KEY(read-write, read_write)
 CSS_KEY(relative, relative)
 CSS_KEY(repeat, repeat)
 CSS_KEY(repeat-x, repeat_x)
 CSS_KEY(repeat-y, repeat_y)
 CSS_KEY(reverse, reverse)
 CSS_KEY(ridge, ridge)
 CSS_KEY(right, right)
-CSS_KEY(right-side, right_side)
-CSS_KEY(rightwards, rightwards)
 CSS_KEY(rotate, rotate)
 CSS_KEY(round, round)
 CSS_KEY(row-resize, row_resize)
 CSS_KEY(rtl, rtl)
 CSS_KEY(running, running)
 CSS_KEY(s, s)
 CSS_KEY(s-resize, s_resize)
 CSS_KEY(scale, scale)
@@ -421,29 +399,25 @@ CSS_KEY(select-after, select_after)
 CSS_KEY(select-all, select_all)
 CSS_KEY(select-before, select_before)
 CSS_KEY(select-menu, select_menu)
 CSS_KEY(select-same, select_same)
 CSS_KEY(semi-condensed, semi_condensed)
 CSS_KEY(semi-expanded, semi_expanded)
 CSS_KEY(separate, separate)
 CSS_KEY(show, show)
-CSS_KEY(silent, silent)
 CSS_KEY(skew, skew)
 CSS_KEY(skewx, skewx)
 CSS_KEY(skewy, skewy)
-CSS_KEY(slow, slow)
-CSS_KEY(slower, slower)
 CSS_KEY(small, small)
 CSS_KEY(small-caps, small_caps)
 CSS_KEY(small-caption, small_caption)
 CSS_KEY(smaller, smaller)
 CSS_KEY(soft, soft)
 CSS_KEY(solid, solid)
-CSS_KEY(spell-out, spell_out)
 CSS_KEY(square, square)
 CSS_KEY(start, start)
 CSS_KEY(static, static)
 CSS_KEY(status-bar, status_bar)
 CSS_KEY(step-end, step_end)
 CSS_KEY(step-start, step_start)
 CSS_KEY(stretch, stretch)
 CSS_KEY(stretch-to-fit, stretch_to_fit)
@@ -494,24 +468,18 @@ CSS_KEY(visiblestroke, visiblestroke)
 CSS_KEY(w-resize, w_resize)
 CSS_KEY(wait, wait)
 CSS_KEY(wavy, wavy)
 CSS_KEY(wider, wider)
 CSS_KEY(window, window)
 CSS_KEY(windowframe, windowframe)
 CSS_KEY(windowtext, windowtext)
 CSS_KEY(write-only, write_only)
-CSS_KEY(x-fast, x_fast)
-CSS_KEY(x-high, x_high)
 CSS_KEY(x-large, x_large)
-CSS_KEY(x-loud, x_loud)
-CSS_KEY(x-low, x_low)
-CSS_KEY(x-slow, x_slow)
 CSS_KEY(x-small, x_small)
-CSS_KEY(x-soft, x_soft)
 CSS_KEY(xx-large, xx_large)
 CSS_KEY(xx-small, xx_small)
 
 // Appearance keywords for widget styles
 CSS_KEY(radio, radio)
 CSS_KEY(checkbox, checkbox)
 CSS_KEY(button-bevel, button_bevel)
 CSS_KEY(toolbox, toolbox)
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -448,17 +448,16 @@ protected:
 
 #ifdef MOZ_XUL
   PRBool ParseTreePseudoElement(nsAtomList **aPseudoElementArgs);
 #endif
 
   void InitBoxPropsAsPhysical(const nsCSSProperty *aSourceProperties);
 
   // Property specific parsing routines
-  PRBool ParseAzimuth(nsCSSValue& aValue);
   PRBool ParseBackground();
 
   struct BackgroundParseState {
     nsCSSValue&  mColor;
     nsCSSValueList* mImage;
     nsCSSValueList* mRepeat;
     nsCSSValueList* mAttachment;
     nsCSSValueList* mClip;
@@ -501,33 +500,31 @@ protected:
                                            PRBool *aHadFinalWS);
   PRBool ParseCalcTerm(nsCSSValue& aValue, PRInt32& aVariantMask);
   PRBool RequireWhitespace();
 
   // for 'clip' and '-moz-image-region'
   PRBool ParseRect(nsCSSProperty aPropID);
   PRBool ParseContent();
   PRBool ParseCounterData(nsCSSProperty aPropID);
-  PRBool ParseCue();
   PRBool ParseCursor();
   PRBool ParseFont();
   PRBool ParseFontWeight(nsCSSValue& aValue);
   PRBool ParseOneFamily(nsAString& aValue);
   PRBool ParseFamily(nsCSSValue& aValue);
   PRBool ParseFontSrc(nsCSSValue& aValue);
   PRBool ParseFontSrcFormat(nsTArray<nsCSSValue>& values);
   PRBool ParseFontRanges(nsCSSValue& aValue);
   PRBool ParseListStyle();
   PRBool ParseMargin();
   PRBool ParseMarks(nsCSSValue& aValue);
   PRBool ParseMozTransform();
   PRBool ParseOutline();
   PRBool ParseOverflow();
   PRBool ParsePadding();
-  PRBool ParsePause();
   PRBool ParseQuotes();
   PRBool ParseSize();
   PRBool ParseTextDecoration(nsCSSValue& aValue);
 
   PRBool ParseShadowItem(nsCSSValue& aValue, PRBool aIsBoxShadow);
   PRBool ParseShadowList(nsCSSProperty aProperty);
   PRBool ParseTransitionProperty();
   PRBool ParseTransitionTimingFunctionValues(nsCSSValue& aValue);
@@ -2062,16 +2059,18 @@ CSSParserImpl::ParseGroupRule(css::Group
       REPORT_UNEXPECTED_EOF(PEGroupRuleEOF);
       break;
     }
     if (mToken.IsSymbol('}')) { // done!
       UngetToken();
       break;
     }
     if (eCSSToken_AtKeyword == mToken.mType) {
+      REPORT_UNEXPECTED_TOKEN(PEGroupRuleNestedAtRule);
+      OUTPUT_ERROR();
       SkipAtRule(PR_TRUE); // group rules cannot contain @rules
       continue;
     }
     UngetToken();
     ParseRuleSet(AppendRuleToSheet, this, PR_TRUE);
   }
   PopGroup();
 
@@ -5518,18 +5517,16 @@ CSSParserImpl::ParsePropertyByFunction(n
     return ParseRect(eCSSProperty_clip);
   case eCSSProperty__moz_column_rule:
     return ParseBorderSide(kColumnRuleIDs, PR_FALSE);
   case eCSSProperty_content:
     return ParseContent();
   case eCSSProperty_counter_increment:
   case eCSSProperty_counter_reset:
     return ParseCounterData(aPropID);
-  case eCSSProperty_cue:
-    return ParseCue();
   case eCSSProperty_cursor:
     return ParseCursor();
   case eCSSProperty_font:
     return ParseFont();
   case eCSSProperty_image_region:
     return ParseRect(eCSSProperty_image_region);
   case eCSSProperty_list_style:
     return ParseListStyle();
@@ -5560,18 +5557,16 @@ CSSParserImpl::ParsePropertyByFunction(n
     return ParseDirectionalBoxProperty(eCSSProperty_padding_left,
                                        NS_BOXPROP_SOURCE_PHYSICAL);
   case eCSSProperty_padding_right:
     return ParseDirectionalBoxProperty(eCSSProperty_padding_right,
                                        NS_BOXPROP_SOURCE_PHYSICAL);
   case eCSSProperty_padding_start:
     return ParseDirectionalBoxProperty(eCSSProperty_padding_start,
                                        NS_BOXPROP_SOURCE_LOGICAL);
-  case eCSSProperty_pause:
-    return ParsePause();
   case eCSSProperty_quotes:
     return ParseQuotes();
   case eCSSProperty_size:
     return ParseSize();
   case eCSSProperty__moz_transform:
     return ParseMozTransform();
   case eCSSProperty__moz_transform_origin:
     return ParseMozTransformOrigin();
@@ -5619,20 +5614,17 @@ CSSParserImpl::ParseSingleValueProperty(
 
   if (aPropID < 0 || aPropID >= eCSSProperty_COUNT_no_shorthands) {
     NS_ABORT_IF_FALSE(PR_FALSE, "not a single value property");
     return PR_FALSE;
   }
 
   if (nsCSSProps::PropHasFlags(aPropID, CSS_PROPERTY_VALUE_PARSER_FUNCTION)) {
     switch (aPropID) {
-      case eCSSProperty_azimuth:
-        return ParseAzimuth(aValue);
       case eCSSProperty_font_family:
-      case eCSSProperty_voice_family:
         return ParseFamily(aValue);
       case eCSSProperty_font_weight:
         return ParseFontWeight(aValue);
       case eCSSProperty_marks:
         return ParseMarks(aValue);
       case eCSSProperty_text_decoration:
         return ParseTextDecoration(aValue);
       default:
@@ -5771,46 +5763,16 @@ CSSParserImpl::InitBoxPropsAsPhysical(co
 {
   nsCSSValue physical(NS_BOXPROP_SOURCE_PHYSICAL, eCSSUnit_Enumerated);
   for (const nsCSSProperty *prop = aSourceProperties;
        *prop != eCSSProperty_UNKNOWN; ++prop) {
     AppendValue(*prop, physical);
   }
 }
 
-PRBool
-CSSParserImpl::ParseAzimuth(nsCSSValue& aValue)
-{
-  if (ParseVariant(aValue, VARIANT_HK | VARIANT_ANGLE,
-                   nsCSSProps::kAzimuthKTable)) {
-    if (eCSSUnit_Enumerated == aValue.GetUnit()) {
-      PRInt32 intValue = aValue.GetIntValue();
-      if ((NS_STYLE_AZIMUTH_LEFT_SIDE <= intValue) &&
-          (intValue <= NS_STYLE_AZIMUTH_BEHIND)) {  // look for optional modifier
-        nsCSSValue  modifier;
-        if (ParseEnum(modifier, nsCSSProps::kAzimuthKTable)) {
-          PRInt32 enumValue = modifier.GetIntValue();
-          if (((intValue == NS_STYLE_AZIMUTH_BEHIND) &&
-               (NS_STYLE_AZIMUTH_LEFT_SIDE <= enumValue) && (enumValue <= NS_STYLE_AZIMUTH_RIGHT_SIDE)) ||
-              ((enumValue == NS_STYLE_AZIMUTH_BEHIND) &&
-               (NS_STYLE_AZIMUTH_LEFT_SIDE <= intValue) && (intValue <= NS_STYLE_AZIMUTH_RIGHT_SIDE))) {
-            aValue.SetIntValue(intValue | enumValue, eCSSUnit_Enumerated);
-            return PR_TRUE;
-          }
-          // Put the unknown identifier back and return
-          UngetToken();
-          return PR_FALSE;
-        }
-      }
-    }
-    return PR_TRUE;
-  }
-  return PR_FALSE;
-}
-
 static nsCSSValue
 BoxPositionMaskToCSSValue(PRInt32 aMask, PRBool isX)
 {
   PRInt32 val = NS_STYLE_BG_POSITION_CENTER;
   if (isX) {
     if (aMask & BG_LEFT) {
       val = NS_STYLE_BG_POSITION_LEFT;
     }
@@ -6997,42 +6959,16 @@ CSSParserImpl::ParseCounterData(nsCSSPro
       cur = cur->mNext;
     }
   }
   AppendValue(aPropID, value);
   return PR_TRUE;
 }
 
 PRBool
-CSSParserImpl::ParseCue()
-{
-  nsCSSValue before;
-  if (ParseSingleValueProperty(before, eCSSProperty_cue_before)) {
-    if (eCSSUnit_Inherit != before.GetUnit() &&
-        eCSSUnit_Initial != before.GetUnit()) {
-      nsCSSValue after;
-      if (ParseSingleValueProperty(after, eCSSProperty_cue_after)) {
-        if (ExpectEndProperty()) {
-          AppendValue(eCSSProperty_cue_before, before);
-          AppendValue(eCSSProperty_cue_after, after);
-          return PR_TRUE;
-        }
-        return PR_FALSE;
-      }
-    }
-    if (ExpectEndProperty()) {
-      AppendValue(eCSSProperty_cue_before, before);
-      AppendValue(eCSSProperty_cue_after, before);
-      return PR_TRUE;
-    }
-  }
-  return PR_FALSE;
-}
-
-PRBool
 CSSParserImpl::ParseCursor()
 {
   nsCSSValue value;
   if (ParseVariant(value, VARIANT_INHERIT, nsnull)) {
     // 'inherit' and 'initial' must be alone
     if (!ExpectEndProperty()) {
       return PR_FALSE;
     }
@@ -7944,41 +7880,16 @@ CSSParserImpl::ParsePadding()
   };
 
   // do this now, in case 4 values weren't specified
   InitBoxPropsAsPhysical(kPaddingSources);
   return ParseBoxProperties(kPaddingSideIDs);
 }
 
 PRBool
-CSSParserImpl::ParsePause()
-{
-  nsCSSValue  before;
-  if (ParseSingleValueProperty(before, eCSSProperty_pause_before)) {
-    if (eCSSUnit_Inherit != before.GetUnit() && eCSSUnit_Initial != before.GetUnit()) {
-      nsCSSValue after;
-      if (ParseSingleValueProperty(after, eCSSProperty_pause_after)) {
-        if (ExpectEndProperty()) {
-          AppendValue(eCSSProperty_pause_before, before);
-          AppendValue(eCSSProperty_pause_after, after);
-          return PR_TRUE;
-        }
-        return PR_FALSE;
-      }
-    }
-    if (ExpectEndProperty()) {
-      AppendValue(eCSSProperty_pause_before, before);
-      AppendValue(eCSSProperty_pause_after, before);
-      return PR_TRUE;
-    }
-  }
-  return PR_FALSE;
-}
-
-PRBool
 CSSParserImpl::ParseQuotes()
 {
   nsCSSValue value;
   if (!ParseVariant(value, VARIANT_HOS, nsnull)) {
     return PR_FALSE;
   }
   if (value.GetUnit() != eCSSUnit_String) {
     if (!ExpectEndProperty()) {
--- a/layout/style/nsCSSParser.h
+++ b/layout/style/nsCSSParser.h
@@ -76,21 +76,16 @@ public:
   static void Shutdown();
 
 private:
   // not to be implemented
   nsCSSParser(nsCSSParser const&);
   nsCSSParser& operator=(nsCSSParser const&);
 
 public:
-  // If this is false, memory allocation failed in the constructor
-  // and all other methods will crash.
-  operator bool() const
-  { return !!mImpl; }
-
   // Set a style sheet for the parser to fill in. The style sheet must
   // implement the nsCSSStyleSheet interface.  Null can be passed in to clear
   // out an existing stylesheet reference.
   nsresult SetStyleSheet(nsCSSStyleSheet* aSheet);
 
   // Set whether or not to emulate Nav quirks
   nsresult SetQuirkMode(PRBool aQuirkMode);
 
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -451,24 +451,16 @@ CSS_PROP_DISPLAY(
     CSS_PROP_DOMPROP_PREFIXED(AnimationTimingFunction),
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
     VARIANT_KEYWORD | VARIANT_TIMING_FUNCTION, // used by list parsing
     kTransitionTimingFunctionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 #endif
-CSS_PROP_BACKENDONLY(
-    azimuth,
-    azimuth,
-    Azimuth,
-    CSS_PROPERTY_PARSE_VALUE |
-        CSS_PROPERTY_VALUE_PARSER_FUNCTION,
-    0,
-    kAzimuthKTable)
 CSS_PROP_SHORTHAND(
     background,
     background,
     Background,
     CSS_PROPERTY_PARSE_FUNCTION)
 CSS_PROP_BACKGROUND(
     background-attachment,
     background_attachment,
@@ -1327,35 +1319,16 @@ CSS_PROP_CONTENT(
     counter-reset,
     counter_reset,
     CounterReset,
     CSS_PROPERTY_PARSE_FUNCTION,
     0,
     nsnull,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None) // XXX bug 137285
-CSS_PROP_SHORTHAND(
-    cue,
-    cue,
-    Cue,
-    CSS_PROPERTY_PARSE_FUNCTION)
-CSS_PROP_BACKENDONLY(
-    cue-after,
-    cue_after,
-    CueAfter,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HUO,
-    nsnull)
-CSS_PROP_BACKENDONLY(
-    cue-before,
-    cue_before,
-    CueBefore,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HUO,
-    nsnull)
 CSS_PROP_USERINTERFACE(
     cursor,
     cursor,
     Cursor,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_START_IMAGE_LOADS |
         CSS_PROPERTY_IMAGE_IS_IN_ARRAY_0,
@@ -1376,23 +1349,16 @@ CSS_PROP_DISPLAY(
     display,
     display,
     Display,
     CSS_PROPERTY_PARSE_VALUE,
     VARIANT_HK,
     kDisplayKTable,
     offsetof(nsStyleDisplay, mDisplay),
     eStyleAnimType_EnumU8)
-CSS_PROP_BACKENDONLY(
-    elevation,
-    elevation,
-    Elevation,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HK | VARIANT_ANGLE,
-    kElevationKTable)
 CSS_PROP_TABLEBORDER(
     empty-cells,
     empty_cells,
     EmptyCells,
     CSS_PROPERTY_PARSE_VALUE,
     VARIANT_HK,
     kEmptyCellsKTable,
     CSS_PROP_NO_OFFSET,
@@ -2086,49 +2052,16 @@ CSS_PROP_DISPLAY(
     eStyleAnimType_None) // temp fix for bug 24000
 CSS_PROP_BACKENDONLY(
     page-break-inside,
     page_break_inside,
     PageBreakInside,
     CSS_PROPERTY_PARSE_VALUE,
     VARIANT_HK,
     kPageBreakInsideKTable)
-CSS_PROP_SHORTHAND(
-    pause,
-    pause,
-    Pause,
-    CSS_PROPERTY_PARSE_FUNCTION)
-CSS_PROP_BACKENDONLY(
-    pause-after,
-    pause_after,
-    PauseAfter,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HTP,
-    nsnull)
-CSS_PROP_BACKENDONLY(
-    pause-before,
-    pause_before,
-    PauseBefore,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HTP,
-    nsnull)
-CSS_PROP_BACKENDONLY(
-    pitch,
-    pitch,
-    Pitch,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HKF,
-    kPitchKTable)
-CSS_PROP_BACKENDONLY(
-    pitch-range,
-    pitch_range,
-    PitchRange,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HN,
-    nsnull)
 CSS_PROP_VISIBILITY(
     pointer-events,
     pointer_events,
     PointerEvents,
     CSS_PROPERTY_PARSE_VALUE,
     VARIANT_HK,
     kPointerEventsKTable,
     offsetof(nsStyleVisibility, mPointerEvents),
@@ -2155,23 +2088,16 @@ CSS_PROP_DISPLAY(
     resize,
     resize,
     Resize,
     CSS_PROPERTY_PARSE_VALUE,
     VARIANT_HK,
     kResizeKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
-CSS_PROP_BACKENDONLY(
-    richness,
-    richness,
-    Richness,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HN,
-    nsnull)
 CSS_PROP_POSITION(
     right,
     right,
     Right,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_STORES_CALC,
     VARIANT_AHLP | VARIANT_CALC,
     nsnull,
@@ -2179,58 +2105,16 @@ CSS_PROP_POSITION(
     eStyleAnimType_Sides_Right)
 CSS_PROP_BACKENDONLY(
     size,
     size,
     Size,
     CSS_PROPERTY_PARSE_FUNCTION,
     0,
     kPageSizeKTable)
-CSS_PROP_BACKENDONLY(
-    speak,
-    speak,
-    Speak,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HK,
-    kSpeakKTable)
-CSS_PROP_BACKENDONLY(
-    speak-header,
-    speak_header,
-    SpeakHeader,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HK,
-    kSpeakHeaderKTable)
-CSS_PROP_BACKENDONLY(
-    speak-numeral,
-    speak_numeral,
-    SpeakNumeral,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HK,
-    kSpeakNumeralKTable)
-CSS_PROP_BACKENDONLY(
-    speak-punctuation,
-    speak_punctuation,
-    SpeakPunctuation,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HK,
-    kSpeakPunctuationKTable)
-CSS_PROP_BACKENDONLY(
-    speech-rate,
-    speech_rate,
-    SpeechRate,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HN | VARIANT_KEYWORD,
-    kSpeechRateKTable)
-CSS_PROP_BACKENDONLY(
-    stress,
-    stress,
-    Stress,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HN,
-    nsnull)
 CSS_PROP_TABLE(
     table-layout,
     table_layout,
     TableLayout,
     CSS_PROPERTY_PARSE_VALUE,
     VARIANT_HK,
     kTableLayoutKTable,
     CSS_PROP_NO_OFFSET,
@@ -2447,31 +2331,16 @@ CSS_PROP_VISIBILITY(
     visibility,
     visibility,
     Visibility,
     CSS_PROPERTY_PARSE_VALUE,
     VARIANT_HK,
     kVisibilityKTable,
     offsetof(nsStyleVisibility, mVisible),
     eStyleAnimType_EnumU8)  // reflow for collapse
-CSS_PROP_BACKENDONLY(
-    voice-family,
-    voice_family,
-    VoiceFamily,
-    CSS_PROPERTY_PARSE_VALUE |
-        CSS_PROPERTY_VALUE_PARSER_FUNCTION,
-    0,
-    nsnull)
-CSS_PROP_BACKENDONLY(
-    volume,
-    volume,
-    Volume,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HPN | VARIANT_KEYWORD,
-    kVolumeKTable)
 CSS_PROP_TEXT(
     white-space,
     white_space,
     WhiteSpace,
     CSS_PROPERTY_PARSE_VALUE,
     VARIANT_HK,
     kWhitespaceKTable,
     CSS_PROP_NO_OFFSET,
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -577,33 +577,16 @@ const PRInt32 nsCSSProps::kAppearanceKTa
   eCSSKeyword__moz_window_button_minimize,    NS_THEME_WINDOW_BUTTON_MINIMIZE,
   eCSSKeyword__moz_window_button_maximize,    NS_THEME_WINDOW_BUTTON_MAXIMIZE,
   eCSSKeyword__moz_window_button_restore,     NS_THEME_WINDOW_BUTTON_RESTORE,
   eCSSKeyword__moz_window_button_box,         NS_THEME_WINDOW_BUTTON_BOX,
   eCSSKeyword__moz_window_button_box_maximized, NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED,
   eCSSKeyword_UNKNOWN,-1
 };
 
-// Keyword id tables for variant/enum parsing
-const PRInt32 nsCSSProps::kAzimuthKTable[] = {
-  eCSSKeyword_left_side,    NS_STYLE_AZIMUTH_LEFT_SIDE,
-  eCSSKeyword_far_left,     NS_STYLE_AZIMUTH_FAR_LEFT,
-  eCSSKeyword_left,         NS_STYLE_AZIMUTH_LEFT,
-  eCSSKeyword_center_left,  NS_STYLE_AZIMUTH_CENTER_LEFT,
-  eCSSKeyword_center,       NS_STYLE_AZIMUTH_CENTER,
-  eCSSKeyword_center_right, NS_STYLE_AZIMUTH_CENTER_RIGHT,
-  eCSSKeyword_right,        NS_STYLE_AZIMUTH_RIGHT,
-  eCSSKeyword_far_right,    NS_STYLE_AZIMUTH_FAR_RIGHT,
-  eCSSKeyword_right_side,   NS_STYLE_AZIMUTH_RIGHT_SIDE,
-  eCSSKeyword_behind,       NS_STYLE_AZIMUTH_BEHIND,
-  eCSSKeyword_leftwards,    NS_STYLE_AZIMUTH_LEFTWARDS,
-  eCSSKeyword_rightwards,   NS_STYLE_AZIMUTH_RIGHTWARDS,
-  eCSSKeyword_UNKNOWN,-1
-};
-
 const PRInt32 nsCSSProps::kBackgroundAttachmentKTable[] = {
   eCSSKeyword_fixed, NS_STYLE_BG_ATTACHMENT_FIXED,
   eCSSKeyword_scroll, NS_STYLE_BG_ATTACHMENT_SCROLL,
   eCSSKeyword_UNKNOWN,-1
 };
 
 const PRInt32 nsCSSProps::kBackgroundInlinePolicyKTable[] = {
   eCSSKeyword_each_box,     NS_STYLE_BG_INLINE_POLICY_EACH_BOX,
@@ -882,25 +865,16 @@ const PRInt32 nsCSSProps::kDisplayKTable
   eCSSKeyword__moz_inline_stack,  NS_STYLE_DISPLAY_INLINE_STACK,
   eCSSKeyword__moz_deck,          NS_STYLE_DISPLAY_DECK,
   eCSSKeyword__moz_popup,         NS_STYLE_DISPLAY_POPUP,
   eCSSKeyword__moz_groupbox,      NS_STYLE_DISPLAY_GROUPBOX,
 #endif
   eCSSKeyword_UNKNOWN,-1
 };
 
-const PRInt32 nsCSSProps::kElevationKTable[] = {
-  eCSSKeyword_below,  NS_STYLE_ELEVATION_BELOW,
-  eCSSKeyword_level,  NS_STYLE_ELEVATION_LEVEL,
-  eCSSKeyword_above,  NS_STYLE_ELEVATION_ABOVE,
-  eCSSKeyword_higher, NS_STYLE_ELEVATION_HIGHER,
-  eCSSKeyword_lower,  NS_STYLE_ELEVATION_LOWER,
-  eCSSKeyword_UNKNOWN,-1
-};
-
 const PRInt32 nsCSSProps::kEmptyCellsKTable[] = {
   eCSSKeyword_show,                 NS_STYLE_TABLE_EMPTY_CELLS_SHOW,
   eCSSKeyword_hide,                 NS_STYLE_TABLE_EMPTY_CELLS_HIDE,
   eCSSKeyword__moz_show_background, NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND,
   eCSSKeyword_UNKNOWN,-1
 };
 
 const PRInt32 nsCSSProps::kFloatKTable[] = {
@@ -1133,25 +1107,16 @@ const PRInt32 nsCSSProps::kPageMarksKTab
 };
 
 const PRInt32 nsCSSProps::kPageSizeKTable[] = {
   eCSSKeyword_landscape, NS_STYLE_PAGE_SIZE_LANDSCAPE,
   eCSSKeyword_portrait, NS_STYLE_PAGE_SIZE_PORTRAIT,
   eCSSKeyword_UNKNOWN,-1
 };
 
-const PRInt32 nsCSSProps::kPitchKTable[] = {
-  eCSSKeyword_x_low, NS_STYLE_PITCH_X_LOW,
-  eCSSKeyword_low, NS_STYLE_PITCH_LOW,
-  eCSSKeyword_medium, NS_STYLE_PITCH_MEDIUM,
-  eCSSKeyword_high, NS_STYLE_PITCH_HIGH,
-  eCSSKeyword_x_high, NS_STYLE_PITCH_X_HIGH,
-  eCSSKeyword_UNKNOWN,-1
-};
-
 const PRInt32 nsCSSProps::kPointerEventsKTable[] = {
   eCSSKeyword_none, NS_STYLE_POINTER_EVENTS_NONE,
   eCSSKeyword_visiblepainted, NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED,
   eCSSKeyword_visiblefill, NS_STYLE_POINTER_EVENTS_VISIBLEFILL,
   eCSSKeyword_visiblestroke, NS_STYLE_POINTER_EVENTS_VISIBLESTROKE,
   eCSSKeyword_visible, NS_STYLE_POINTER_EVENTS_VISIBLE,
   eCSSKeyword_painted, NS_STYLE_POINTER_EVENTS_PAINTED,
   eCSSKeyword_fill, NS_STYLE_POINTER_EVENTS_FILL,
@@ -1189,52 +1154,16 @@ const PRInt32 nsCSSProps::kRadialGradien
 const PRInt32 nsCSSProps::kResizeKTable[] = {
   eCSSKeyword_none,       NS_STYLE_RESIZE_NONE,
   eCSSKeyword_both,       NS_STYLE_RESIZE_BOTH,
   eCSSKeyword_horizontal, NS_STYLE_RESIZE_HORIZONTAL,
   eCSSKeyword_vertical,   NS_STYLE_RESIZE_VERTICAL,
   eCSSKeyword_UNKNOWN,-1
 };
 
-const PRInt32 nsCSSProps::kSpeakKTable[] = {
-  eCSSKeyword_none,      NS_STYLE_SPEAK_NONE,
-  eCSSKeyword_normal,    NS_STYLE_SPEAK_NORMAL,
-  eCSSKeyword_spell_out, NS_STYLE_SPEAK_SPELL_OUT,
-  eCSSKeyword_UNKNOWN,-1
-};
-
-const PRInt32 nsCSSProps::kSpeakHeaderKTable[] = {
-  eCSSKeyword_once, NS_STYLE_SPEAK_HEADER_ONCE,
-  eCSSKeyword_always, NS_STYLE_SPEAK_HEADER_ALWAYS,
-  eCSSKeyword_UNKNOWN,-1
-};
-
-const PRInt32 nsCSSProps::kSpeakNumeralKTable[] = {
-  eCSSKeyword_digits, NS_STYLE_SPEAK_NUMERAL_DIGITS,
-  eCSSKeyword_continuous, NS_STYLE_SPEAK_NUMERAL_CONTINUOUS,
-  eCSSKeyword_UNKNOWN,-1
-};
-
-const PRInt32 nsCSSProps::kSpeakPunctuationKTable[] = {
-  eCSSKeyword_none, NS_STYLE_SPEAK_PUNCTUATION_NONE,
-  eCSSKeyword_code, NS_STYLE_SPEAK_PUNCTUATION_CODE,
-  eCSSKeyword_UNKNOWN,-1
-};
-
-const PRInt32 nsCSSProps::kSpeechRateKTable[] = {
-  eCSSKeyword_x_slow, NS_STYLE_SPEECH_RATE_X_SLOW,
-  eCSSKeyword_slow, NS_STYLE_SPEECH_RATE_SLOW,
-  eCSSKeyword_medium, NS_STYLE_SPEECH_RATE_MEDIUM,
-  eCSSKeyword_fast, NS_STYLE_SPEECH_RATE_FAST,
-  eCSSKeyword_x_fast, NS_STYLE_SPEECH_RATE_X_FAST,
-  eCSSKeyword_faster, NS_STYLE_SPEECH_RATE_FASTER,
-  eCSSKeyword_slower, NS_STYLE_SPEECH_RATE_SLOWER,
-  eCSSKeyword_UNKNOWN,-1
-};
-
 const PRInt32 nsCSSProps::kStackSizingKTable[] = {
   eCSSKeyword_ignore, NS_STYLE_STACK_SIZING_IGNORE,
   eCSSKeyword_stretch_to_fit, NS_STYLE_STACK_SIZING_STRETCH_TO_FIT,
   eCSSKeyword_UNKNOWN,-1
 };
 
 const PRInt32 nsCSSProps::kTableLayoutKTable[] = {
   eCSSKeyword_auto, NS_STYLE_TABLE_LAYOUT_AUTO,
@@ -1357,26 +1286,16 @@ const PRInt32 nsCSSProps::kVerticalAlign
 
 const PRInt32 nsCSSProps::kVisibilityKTable[] = {
   eCSSKeyword_visible, NS_STYLE_VISIBILITY_VISIBLE,
   eCSSKeyword_hidden, NS_STYLE_VISIBILITY_HIDDEN,
   eCSSKeyword_collapse, NS_STYLE_VISIBILITY_COLLAPSE,
   eCSSKeyword_UNKNOWN,-1
 };
 
-const PRInt32 nsCSSProps::kVolumeKTable[] = {
-  eCSSKeyword_silent, NS_STYLE_VOLUME_SILENT,
-  eCSSKeyword_x_soft, NS_STYLE_VOLUME_X_SOFT,
-  eCSSKeyword_soft, NS_STYLE_VOLUME_SOFT,
-  eCSSKeyword_medium, NS_STYLE_VOLUME_MEDIUM,
-  eCSSKeyword_loud, NS_STYLE_VOLUME_LOUD,
-  eCSSKeyword_x_loud, NS_STYLE_VOLUME_X_LOUD,
-  eCSSKeyword_UNKNOWN,-1
-};
-
 const PRInt32 nsCSSProps::kWhitespaceKTable[] = {
   eCSSKeyword_normal, NS_STYLE_WHITESPACE_NORMAL,
   eCSSKeyword_pre, NS_STYLE_WHITESPACE_PRE,
   eCSSKeyword_nowrap, NS_STYLE_WHITESPACE_NOWRAP,
   eCSSKeyword_pre_wrap, NS_STYLE_WHITESPACE_PRE_WRAP,
   eCSSKeyword_pre_line, NS_STYLE_WHITESPACE_PRE_LINE,
   eCSSKeyword_UNKNOWN,-1
 };
@@ -1941,22 +1860,16 @@ static const nsCSSProperty gBorderStartW
 static const nsCSSProperty gBorderEndWidthSubpropTable[] = {
   // nsCSSParser::ParseDirectionalBoxProperty depends on this order
   eCSSProperty_border_end_width_value,
   eCSSProperty_border_right_width_ltr_source,
   eCSSProperty_border_left_width_rtl_source,
   eCSSProperty_UNKNOWN
 };
 
-static const nsCSSProperty gCueSubpropTable[] = {
-  eCSSProperty_cue_after,
-  eCSSProperty_cue_before,
-  eCSSProperty_UNKNOWN
-};
-
 static const nsCSSProperty gFontSubpropTable[] = {
   eCSSProperty_font_family,
   eCSSProperty_font_style,
   eCSSProperty_font_variant,
   eCSSProperty_font_weight,
   eCSSProperty_font_size,
   eCSSProperty_line_height,
   eCSSProperty_font_size_adjust, // XXX Added LDB.
@@ -2086,22 +1999,16 @@ static const nsCSSProperty gPaddingStart
 static const nsCSSProperty gPaddingEndSubpropTable[] = {
   // nsCSSParser::ParseDirectionalBoxProperty depends on this order
   eCSSProperty_padding_end_value,
   eCSSProperty_padding_right_ltr_source,
   eCSSProperty_padding_left_rtl_source,
   eCSSProperty_UNKNOWN
 };
 
-static const nsCSSProperty gPauseSubpropTable[] = {
-  eCSSProperty_pause_after,
-  eCSSProperty_pause_before,
-  eCSSProperty_UNKNOWN
-};
-
 static const nsCSSProperty gTransitionSubpropTable[] = {
   eCSSProperty_transition_property,
   eCSSProperty_transition_duration,
   eCSSProperty_transition_timing_function,
   eCSSProperty_transition_delay,
   eCSSProperty_UNKNOWN
 };
 
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -883,17 +883,17 @@ MediaRule::DeleteRule(PRUint32 aIndex)
 }
 
 // GroupRule interface
 /* virtual */ PRBool
 MediaRule::UseForPresentation(nsPresContext* aPresContext,
                                    nsMediaQueryResultCacheKey& aKey)
 {
   if (mMedia) {
-    return mMedia->Matches(aPresContext, aKey);
+    return mMedia->Matches(aPresContext, &aKey);
   }
   return PR_TRUE;
 }
 
 } // namespace css
 } // namespace mozilla
 
 // Must be outside namespace
@@ -1890,17 +1890,16 @@ nsCSSKeyframeRule::GetKeyText(nsAString&
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText)
 {
   nsCSSParser parser;
-  NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
 
   nsTArray<float> newSelectors;
   // FIXME: pass filename and line number
   if (parser.ParseKeyframeSelectorString(aKeyText, nsnull, 0, newSelectors)) {
     newSelectors.SwapElements(mKeys);
   } else {
     // for now, we don't do anything if the parse fails
   }
@@ -2054,17 +2053,16 @@ nsCSSKeyframesRule::GetCssRules(nsIDOMCS
 
 NS_IMETHODIMP
 nsCSSKeyframesRule::InsertRule(const nsAString& aRule)
 {
   // The spec is confusing, and I think we should just append the rule,
   // which also turns out to match WebKit:
   // http://lists.w3.org/Archives/Public/www-style/2011Apr/0034.html
   nsCSSParser parser;
-  NS_ENSURE_TRUE(parser, NS_OK);
 
   // FIXME: pass filename and line number
   nsRefPtr<nsCSSKeyframeRule> rule =
     parser.ParseKeyframeRule(aRule, nsnull, 0);
   if (rule) {
     mRules.AppendObject(rule);
     mSheet->SetModifiedByChildRule();
   }
@@ -2073,17 +2071,16 @@ nsCSSKeyframesRule::InsertRule(const nsA
 }
 
 static const PRUint32 RULE_NOT_FOUND = PRUint32(-1);
 
 PRUint32
 nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey)
 {
   nsCSSParser parser;
-  NS_ENSURE_TRUE(parser, RULE_NOT_FOUND);
 
   nsTArray<float> keys;
   // FIXME: pass filename and line number
   if (parser.ParseKeyframeSelectorString(aKey, nsnull, 0, keys)) {
     // The spec isn't clear, but we'll match on the key list, which
     // mostly matches what WebKit does, except we'll do last-match
     // instead of first-match, and handling parsing differences better.
     // http://lists.w3.org/Archives/Public/www-style/2011Apr/0036.html
--- a/layout/style/nsCSSStyleSheet.cpp
+++ b/layout/style/nsCSSStyleSheet.cpp
@@ -500,32 +500,34 @@ nsMediaQuery::Clone() const
   NS_ENSURE_TRUE(result &&
                    result->mExpressions.Length() == mExpressions.Length(),
                  nsnull);
   return result.forget();
 }
 
 PRBool
 nsMediaQuery::Matches(nsPresContext* aPresContext,
-                      nsMediaQueryResultCacheKey& aKey) const
+                      nsMediaQueryResultCacheKey* aKey) const
 {
   if (mHadUnknownExpression)
     return PR_FALSE;
 
   PRBool match =
     mMediaType == aPresContext->Medium() || mMediaType == nsGkAtoms::all;
   for (PRUint32 i = 0, i_end = mExpressions.Length(); match && i < i_end; ++i) {
     const nsMediaExpression &expr = mExpressions[i];
     nsCSSValue actual;
     nsresult rv =
       (expr.mFeature->mGetter)(aPresContext, expr.mFeature, actual);
     NS_ENSURE_SUCCESS(rv, PR_FALSE); // any better ideas?
 
     match = expr.Matches(aPresContext, actual);
-    aKey.AddExpression(&expr, match);
+    if (aKey) {
+      aKey->AddExpression(&expr, match);
+    }
   }
 
   return match == !mNegated;
 }
 
 DOMCI_DATA(MediaList, nsMediaList)
 
 NS_INTERFACE_MAP_BEGIN(nsMediaList)
@@ -572,32 +574,31 @@ nsMediaList::GetText(nsAString& aMediaTe
 }
 
 // XXXbz this is so ill-defined in the spec, it's not clear quite what
 // it should be doing....
 nsresult
 nsMediaList::SetText(const nsAString& aMediaText)
 {
   nsCSSParser parser;
-  NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
 
   PRBool htmlMode = PR_FALSE;
   if (mStyleSheet) {
     nsCOMPtr<nsIDOMNode> node;
     mStyleSheet->GetOwnerNode(getter_AddRefs(node));
     htmlMode = !!node;
   }
 
-  return parser.ParseMediaList(nsString(aMediaText), nsnull, 0,
+  return parser.ParseMediaList(aMediaText, nsnull, 0,
                                this, htmlMode);
 }
 
 PRBool
 nsMediaList::Matches(nsPresContext* aPresContext,
-                     nsMediaQueryResultCacheKey& aKey)
+                     nsMediaQueryResultCacheKey* aKey)
 {
   for (PRInt32 i = 0, i_end = mArray.Length(); i < i_end; ++i) {
     if (mArray[i]->Matches(aPresContext, aKey)) {
       return PR_TRUE;
     }
   }
   return mIsEmpty;
 }
@@ -1159,17 +1160,17 @@ nsCSSStyleSheet::GetType(nsString& aType
   aType.AssignLiteral("text/css");
 }
 
 PRBool
 nsCSSStyleSheet::UseForPresentation(nsPresContext* aPresContext,
                                     nsMediaQueryResultCacheKey& aKey) const
 {
   if (mMedia) {
-    return mMedia->Matches(aPresContext, aKey);
+    return mMedia->Matches(aPresContext, &aKey);
   }
   return PR_TRUE;
 }
 
 
 void
 nsCSSStyleSheet::SetMedia(nsMediaList* aMedia)
 {
@@ -1776,18 +1777,16 @@ nsCSSStyleSheet::InsertRuleInternal(cons
   // kills the document
   nsRefPtr<css::Loader> loader;
   if (mDocument) {
     loader = mDocument->CSSLoader();
     NS_ASSERTION(loader, "Document with no CSS loader!");
   }
 
   nsCSSParser css(loader, this);
-  if (!css)
-    return NS_ERROR_OUT_OF_MEMORY;
 
   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE);
 
   nsCOMArray<nsICSSRule> rules;
   result = css.ParseRule(aRule, mInner->mSheetURI, mInner->mBaseURI,
                          mInner->mPrincipal, rules);
   if (NS_FAILED(result))
     return result;
@@ -1986,19 +1985,16 @@ nsCSSStyleSheet::InsertRuleIntoGroup(con
   // kills the document
   nsRefPtr<css::Loader> loader;
   if (mDocument) {
     loader = mDocument->CSSLoader();
     NS_ASSERTION(loader, "Document with no CSS loader!");
   }
 
   nsCSSParser css(loader, this);
-  if (!css) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
 
   // parse and grab the rule
   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE);
 
   result = WillDirty();
   NS_ENSURE_SUCCESS(result, result);
 
   nsCOMArray<nsICSSRule> rules;
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -801,24 +801,16 @@ nsCSSValue::AppendToString(nsCSSProperty
         intValue &= ~NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL;
         nsStyleUtil::AppendBitmaskCSSValue(
           aProperty, intValue,
           NS_STYLE_TEXT_DECORATION_UNDERLINE,
           NS_STYLE_TEXT_DECORATION_PREF_ANCHORS,
           aResult);
       }
     }
-    else if (eCSSProperty_azimuth == aProperty) {
-      PRInt32 intValue = GetIntValue();
-      AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, (intValue & ~NS_STYLE_AZIMUTH_BEHIND)), aResult);
-      if ((NS_STYLE_AZIMUTH_BEHIND & intValue) != 0) {
-        aResult.Append(PRUnichar(' '));
-        AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, NS_STYLE_AZIMUTH_BEHIND), aResult);
-      }
-    }
     else if (eCSSProperty_marks == aProperty) {
       PRInt32 intValue = GetIntValue();
       if (intValue == NS_STYLE_PAGE_MARKS_NONE) {
         AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue),
                            aResult);
       } else {
         nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
                                            NS_STYLE_PAGE_MARKS_CROP,
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -4135,17 +4135,16 @@ nsComputedDOMStyle::GetQueryableProperty
    * Properties commented out with // are not yet implemented            *
    * Properties commented out with //// are shorthands and not queryable *
   \* ******************************************************************* */
   static const ComputedStyleMapEntry map[] = {
     /* ****************************** *\
      * Implementations of CSS2 styles *
     \* ****************************** */
 
-    // COMPUTED_STYLE_MAP_ENTRY(azimuth,                    Azimuth),
     //// COMPUTED_STYLE_MAP_ENTRY(background,               Background),
     COMPUTED_STYLE_MAP_ENTRY(background_attachment,         BackgroundAttachment),
     COMPUTED_STYLE_MAP_ENTRY(background_color,              BackgroundColor),
     COMPUTED_STYLE_MAP_ENTRY(background_image,              BackgroundImage),
     COMPUTED_STYLE_MAP_ENTRY(background_position,           BackgroundPosition),
     COMPUTED_STYLE_MAP_ENTRY(background_repeat,             BackgroundRepeat),
     //// COMPUTED_STYLE_MAP_ENTRY(border,                   Border),
     //// COMPUTED_STYLE_MAP_ENTRY(border_bottom,            BorderBottom),
@@ -4172,23 +4171,19 @@ nsComputedDOMStyle::GetQueryableProperty
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(bottom,                 Bottom),
     COMPUTED_STYLE_MAP_ENTRY(caption_side,                  CaptionSide),
     COMPUTED_STYLE_MAP_ENTRY(clear,                         Clear),
     COMPUTED_STYLE_MAP_ENTRY(clip,                          Clip),
     COMPUTED_STYLE_MAP_ENTRY(color,                         Color),
     COMPUTED_STYLE_MAP_ENTRY(content,                       Content),
     COMPUTED_STYLE_MAP_ENTRY(counter_increment,             CounterIncrement),
     COMPUTED_STYLE_MAP_ENTRY(counter_reset,                 CounterReset),
-    //// COMPUTED_STYLE_MAP_ENTRY(cue,                      Cue),
-    // COMPUTED_STYLE_MAP_ENTRY(cue_after,                  CueAfter),
-    // COMPUTED_STYLE_MAP_ENTRY(cue_before,                 CueBefore),
     COMPUTED_STYLE_MAP_ENTRY(cursor,                        Cursor),
     COMPUTED_STYLE_MAP_ENTRY(direction,                     Direction),
     COMPUTED_STYLE_MAP_ENTRY(display,                       Display),
-    // COMPUTED_STYLE_MAP_ENTRY(elevation,                  Elevation),
     COMPUTED_STYLE_MAP_ENTRY(empty_cells,                   EmptyCells),
     COMPUTED_STYLE_MAP_ENTRY(float,                         CssFloat),
     //// COMPUTED_STYLE_MAP_ENTRY(font,                     Font),
     COMPUTED_STYLE_MAP_ENTRY(font_family,                   FontFamily),
     COMPUTED_STYLE_MAP_ENTRY(font_size,                     FontSize),
     COMPUTED_STYLE_MAP_ENTRY(font_size_adjust,              FontSizeAdjust),
     COMPUTED_STYLE_MAP_ENTRY(font_stretch,                  FontStretch),
     COMPUTED_STYLE_MAP_ENTRY(font_style,                    FontStyle),
@@ -4228,45 +4223,31 @@ nsComputedDOMStyle::GetQueryableProperty
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(padding_bottom,         PaddingBottom),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(padding_left,           PaddingLeft),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(padding_right,          PaddingRight),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(padding_top,            PaddingTop),
     // COMPUTED_STYLE_MAP_ENTRY(page,                       Page),
     COMPUTED_STYLE_MAP_ENTRY(page_break_after,              PageBreakAfter),
     COMPUTED_STYLE_MAP_ENTRY(page_break_before,             PageBreakBefore),
     // COMPUTED_STYLE_MAP_ENTRY(page_break_inside,          PageBreakInside),
-    //// COMPUTED_STYLE_MAP_ENTRY(pause,                    Pause),
-    // COMPUTED_STYLE_MAP_ENTRY(pause_after,                PauseAfter),
-    // COMPUTED_STYLE_MAP_ENTRY(pause_before,               PauseBefore),
-    // COMPUTED_STYLE_MAP_ENTRY(pitch,                      Pitch),
-    // COMPUTED_STYLE_MAP_ENTRY(pitch_range,                PitchRange),
     COMPUTED_STYLE_MAP_ENTRY(pointer_events,                PointerEvents),
     COMPUTED_STYLE_MAP_ENTRY(position,                      Position),
     COMPUTED_STYLE_MAP_ENTRY(quotes,                        Quotes),
-    // COMPUTED_STYLE_MAP_ENTRY(richness,                   Richness),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(right,                  Right),
     //// COMPUTED_STYLE_MAP_ENTRY(size,                     Size),
-    // COMPUTED_STYLE_MAP_ENTRY(speak,                      Speak),
-    // COMPUTED_STYLE_MAP_ENTRY(speak_header,               SpeakHeader),
-    // COMPUTED_STYLE_MAP_ENTRY(speak_numeral,              SpeakNumeral),
-    // COMPUTED_STYLE_MAP_ENTRY(speak_punctuation,          SpeakPunctuation),
-    // COMPUTED_STYLE_MAP_ENTRY(speech_rate,                SpeechRate),
-    // COMPUTED_STYLE_MAP_ENTRY(stress,                     Stress),
     COMPUTED_STYLE_MAP_ENTRY(table_layout,                  TableLayout),
     COMPUTED_STYLE_MAP_ENTRY(text_align,                    TextAlign),
     COMPUTED_STYLE_MAP_ENTRY(text_decoration,               TextDecoration),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(text_indent,            TextIndent),
     COMPUTED_STYLE_MAP_ENTRY(text_shadow,                   TextShadow),
     COMPUTED_STYLE_MAP_ENTRY(text_transform,                TextTransform),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(top,                    Top),
     COMPUTED_STYLE_MAP_ENTRY(unicode_bidi,                  UnicodeBidi),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(vertical_align,         VerticalAlign),
     COMPUTED_STYLE_MAP_ENTRY(visibility,                    Visibility),
-    // COMPUTED_STYLE_MAP_ENTRY(voice_family,               VoiceFamily),
-    // COMPUTED_STYLE_MAP_ENTRY(volume,                     Volume),
     COMPUTED_STYLE_MAP_ENTRY(white_space,                   WhiteSpace),
     // COMPUTED_STYLE_MAP_ENTRY(widows,                     Widows),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(width,                  Width),
     COMPUTED_STYLE_MAP_ENTRY(word_spacing,                  WordSpacing),
     COMPUTED_STYLE_MAP_ENTRY(z_index,                       ZIndex),
 
     /* ******************************* *\
      * Implementations of -moz- styles *
new file mode 100644
--- /dev/null
+++ b/layout/style/nsDOMMediaQueryList.cpp
@@ -0,0 +1,164 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsDOMMediaQueryList.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* implements DOM interface for querying and observing media queries */
+
+#include "nsDOMMediaQueryList.h"
+#include "nsPresContext.h"
+#include "nsIMediaList.h"
+#include "nsCSSParser.h"
+
+nsDOMMediaQueryList::nsDOMMediaQueryList(nsPresContext *aPresContext,
+                                         const nsAString &aMediaQueryList)
+  : mPresContext(aPresContext),
+    mMediaList(new nsMediaList),
+    mMatchesValid(PR_FALSE)
+{
+  PR_INIT_CLIST(this);
+
+  nsCSSParser parser;
+  parser.ParseMediaList(aMediaQueryList, nsnull, 0, mMediaList, PR_FALSE);
+}
+
+nsDOMMediaQueryList::~nsDOMMediaQueryList()
+{
+  if (mPresContext) {
+    PR_REMOVE_LINK(this);
+  }
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMediaQueryList)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMMediaQueryList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPresContext)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mListeners)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMMediaQueryList)
+if (tmp->mPresContext) {
+  PR_REMOVE_LINK(tmp);
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPresContext)
+}
+NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mListeners)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+DOMCI_DATA(MediaQueryList, nsDOMMediaQueryList)
+
+NS_INTERFACE_MAP_BEGIN(nsDOMMediaQueryList)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMMediaQueryList)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMMediaQueryList)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MediaQueryList)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMMediaQueryList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMMediaQueryList)
+
+NS_IMETHODIMP
+nsDOMMediaQueryList::GetMedia(nsAString &aMedia)
+{
+  mMediaList->GetText(aMedia);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMMediaQueryList::GetMatches(PRBool *aMatches)
+{
+  if (!mMatchesValid) {
+    NS_ABORT_IF_FALSE(mListeners.Length() == 0,
+                      "when listeners present, must keep mMatches current");
+    RecomputeMatches();
+  }
+
+  *aMatches = mMatches;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMMediaQueryList::AddListener(nsIDOMMediaQueryListListener *aListener)
+{
+  if (!mMatchesValid) {
+    NS_ABORT_IF_FALSE(mListeners.Length() == 0,
+                      "when listeners present, must keep mMatches current");
+    RecomputeMatches();
+  }
+
+  if (!mListeners.Contains(aListener)) {
+    mListeners.AppendElement(aListener);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMMediaQueryList::RemoveListener(nsIDOMMediaQueryListListener *aListener)
+{
+  mListeners.RemoveElement(aListener);
+  NS_ABORT_IF_FALSE(!mListeners.Contains(aListener),
+                    "duplicate occurrence of listeners");
+  return NS_OK;
+}
+
+void
+nsDOMMediaQueryList::RecomputeMatches()
+{
+  if (!mPresContext) {
+    return;
+  }
+
+  mMatches = mMediaList->Matches(mPresContext, nsnull);
+  mMatchesValid = PR_TRUE;
+}
+
+void
+nsDOMMediaQueryList::MediumFeaturesChanged(NotifyList &aListenersToNotify)
+{
+  mMatchesValid = PR_FALSE;
+
+  if (mListeners.Length()) {
+    PRPackedBool oldMatches = mMatches;
+    RecomputeMatches();
+    if (mMatches != oldMatches) {
+      for (PRUint32 i = 0, i_end = mListeners.Length(); i != i_end; ++i) {
+        HandleChangeData *d = aListenersToNotify.AppendElement();
+        if (d) {
+          d->mql = this;
+          d->listener = mListeners[i];
+        }
+      }
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/layout/style/nsDOMMediaQueryList.h
@@ -0,0 +1,106 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsDOMMediaQueryList.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* implements DOM interface for querying and observing media queries */
+
+#ifndef nsDOMMediaQueryList_h_
+#define nsDOMMediaQueryList_h_
+
+#include "nsIDOMMediaQueryList.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
+#include "nsTArray.h"
+#include "prclist.h"
+
+class nsPresContext;
+class nsMediaList;
+
+class nsDOMMediaQueryList : public nsIDOMMediaQueryList,
+                            public PRCList
+{
+public:
+  // The caller who constructs is responsible for calling Evaluate
+  // before calling any other methods.
+  nsDOMMediaQueryList(nsPresContext *aPresContext,
+                      const nsAString &aMediaQueryList);
+private:
+  ~nsDOMMediaQueryList();
+
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMMediaQueryList)
+
+  NS_DECL_NSIDOMMEDIAQUERYLIST
+
+  struct HandleChangeData {
+    nsRefPtr<nsDOMMediaQueryList> mql;
+    nsCOMPtr<nsIDOMMediaQueryListListener> listener;
+  };
+
+  typedef FallibleTArray< nsCOMPtr<nsIDOMMediaQueryListListener> > ListenerList;
+  typedef FallibleTArray<HandleChangeData> NotifyList;
+
+  // Appends listeners that need notification to aListenersToNotify
+  void MediumFeaturesChanged(NotifyList &aListenersToNotify);
+
+private:
+  void RecomputeMatches();
+
+  // We only need a pointer to the pres context to support lazy
+  // reevaluation following dynamic changes.  However, this lazy
+  // reevaluation is perhaps somewhat important, since some usage
+  // patterns may involve the creation of large numbers of
+  // MediaQueryList objects which almost immediately become garbage
+  // (after a single call to the .matches getter).
+  //
+  // This pointer does make us a little more dependent on cycle
+  // collection.
+  //
+  // We have a non-null mPresContext for our entire lifetime except
+  // after cycle collection unlinking.  Having a non-null mPresContext
+  // is equivalent to being in that pres context's mDOMMediaQueryLists
+  // linked list.
+  nsRefPtr<nsPresContext> mPresContext;
+
+  nsRefPtr<nsMediaList> mMediaList;
+  PRPackedBool mMatches;
+  PRPackedBool mMatchesValid;
+  ListenerList mListeners;
+};
+
+#endif /* !defined(nsDOMMediaQueryList_h_) */
--- a/layout/style/nsIMediaList.h
+++ b/layout/style/nsIMediaList.h
@@ -157,18 +157,19 @@ public:
   // Returns null on out-of-memory.
   nsMediaExpression* NewExpression()    { return mExpressions.AppendElement(); }
 
   void AppendToString(nsAString& aString) const;
 
   nsMediaQuery* Clone() const;
 
   // Does this query apply to the presentation?
+  // If |aKey| is non-null, add cache information to it.
   PRBool Matches(nsPresContext* aPresContext,
-                 nsMediaQueryResultCacheKey& aKey) const;
+                 nsMediaQueryResultCacheKey* aKey) const;
 
 private:
   PRPackedBool mNegated;
   PRPackedBool mHasOnly; // only needed for serialization
   PRPackedBool mTypeOmitted; // only needed for serialization
   PRPackedBool mHadUnknownExpression;
   nsCOMPtr<nsIAtom> mMediaType;
   nsTArray<nsMediaExpression> mExpressions;
@@ -179,18 +180,22 @@ public:
   nsMediaList();
 
   NS_DECL_ISUPPORTS
 
   NS_DECL_NSIDOMMEDIALIST
 
   nsresult GetText(nsAString& aMediaText);
   nsresult SetText(const nsAString& aMediaText);
+
+  // Does this query apply to the presentation?
+  // If |aKey| is non-null, add cache information to it.
   PRBool Matches(nsPresContext* aPresContext,
-                 nsMediaQueryResultCacheKey& aKey);
+                 nsMediaQueryResultCacheKey* aKey);
+
   nsresult SetStyleSheet(nsCSSStyleSheet* aSheet);
   nsresult AppendQuery(nsAutoPtr<nsMediaQuery>& aQuery) {
     // Takes ownership of aQuery (if it succeeds)
     if (!mArray.AppendElement(aQuery.get())) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     aQuery.forget();
     return NS_OK;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -3625,16 +3625,138 @@ static const TransitionPropInfo animatio
 // Information about each transition or animation property that changes
 // during ComputeDisplayData.
 struct TransitionPropData {
   const nsCSSValueList *list;
   nsCSSUnit unit;
   PRUint32 num;
 };
 
+static PRUint32
+CountTransitionProps(const TransitionPropInfo* aInfo,
+                     TransitionPropData* aData,
+                     size_t aLength,
+                     nsStyleDisplay* aDisplay,
+                     const nsStyleDisplay* aParentDisplay,
+                     const nsRuleData* aRuleData,
+                     PRBool& aCanStoreInRuleTree)
+{
+  // The four transition properties or eight animation properties are
+  // stored in nsCSSDisplay in a single array for all properties.  The
+  // number of transitions is equal to the number of items in the
+  // longest property's value.  Properties that have fewer values than
+  // the longest are filled in by repeating the list.  However, this
+  // repetition does not extend the computed value of that particular
+  // property (for purposes of inheritance, or, in our code, for when
+  // other properties are overridden by a more specific rule).
+
+  // But actually, since the spec isn't clear yet, we'll fully compute
+  // all of them (so we can switch easily later), but only care about
+  // the ones up to the number of items for 'transition-property', per
+  // http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html .
+
+  // Transitions are difficult to handle correctly because of this.  For
+  // example, we need to handle scenarios such as:
+  //  * a more general rule specifies transition-property: a, b, c;
+  //  * a more specific rule overrides as transition-property: d;
+  //
+  // If only the general rule applied, we would fill in the extra
+  // properties (duration, delay, etc) with initial values to create 3
+  // fully-specified transitions.  But when the more specific rule
+  // applies, we should only create a single transition.  In order to do
+  // this we need to remember which properties were explicitly specified
+  // and which ones were just filled in with initial values to get a
+  // fully-specified transition, which we do by remembering the number
+  // of values for each property.
+
+  PRUint32 numTransitions = 0;
+  for (size_t i = 0; i < aLength; ++i) {
+    const TransitionPropInfo& info = aInfo[i];
+    TransitionPropData& data = aData[i];
+
+    // cache whether any of the properties are specified as 'inherit' so
+    // we can use it below
+
+    const nsCSSValue& value = *aRuleData->ValueFor(info.property);
+    data.unit = value.GetUnit();
+    data.list = (value.GetUnit() == eCSSUnit_List ||
+                 value.GetUnit() == eCSSUnit_ListDep)
+                  ? value.GetListValue() : nsnull;
+
+    // General algorithm to determine how many total transitions we need
+    // to build.  For each property:
+    //  - if there is no value specified in for the property in
+    //    displayData, use the values from the start struct, but only if
+    //    they were explicitly specified
+    //  - if there is a value specified for the property in displayData:
+    //    - if the value is 'inherit', count the number of values for
+    //      that property are specified by the parent, but only those
+    //      that were explicitly specified
+    //    - otherwise, count the number of values specified in displayData
+
+
+    // calculate number of elements
+    if (data.unit == eCSSUnit_Inherit) {
+      data.num = aParentDisplay->*(info.sdCount);
+      aCanStoreInRuleTree = PR_FALSE;
+    } else if (data.list) {
+      data.num = ListLength(data.list);
+    } else {
+      data.num = aDisplay->*(info.sdCount);
+    }
+    if (data.num > numTransitions)
+      numTransitions = data.num;
+  }
+
+  return numTransitions;
+}
+
+static void
+ComputeTimingFunction(const nsCSSValue& aValue, nsTimingFunction& aResult)
+{
+  switch (aValue.GetUnit()) {
+    case eCSSUnit_Enumerated:
+      aResult = nsTimingFunction(aValue.GetIntValue());
+      break;
+    case eCSSUnit_Cubic_Bezier:
+      {
+        nsCSSValue::Array* array = aValue.GetArrayValue();
+        NS_ASSERTION(array && array->Count() == 4,
+                     "Need 4 control points");
+        aResult = nsTimingFunction(array->Item(0).GetFloatValue(),
+                                   array->Item(1).GetFloatValue(),
+                                   array->Item(2).GetFloatValue(),
+                                   array->Item(3).GetFloatValue());
+      }
+      break;
+    case eCSSUnit_Steps:
+      {
+        nsCSSValue::Array* array = aValue.GetArrayValue();
+        NS_ASSERTION(array && array->Count() == 2,
+                     "Need 2 items");
+        NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer,
+                     "unexpected first value");
+        NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
+                     (array->Item(1).GetIntValue() ==
+                       NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
+                      array->Item(1).GetIntValue() ==
+                       NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END),
+                     "unexpected second value");
+        nsTimingFunction::Type type =
+          (array->Item(1).GetIntValue() ==
+            NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END)
+            ? nsTimingFunction::StepEnd : nsTimingFunction::StepStart;
+        aResult = nsTimingFunction(type, array->Item(0).GetIntValue());
+      }
+      break;
+    default:
+      NS_NOTREACHED("Invalid transition property unit");
+  }
+}
+
 const void*
 nsRuleNode::ComputeDisplayData(void* aStartStruct,
                                const nsRuleData* aRuleData,
                                nsStyleContext* aContext,
                                nsRuleNode* aHighestNode,
                                const RuleDetail aRuleDetail,
                                const PRBool aCanStoreInRuleTree)
 {
@@ -3647,83 +3769,21 @@ nsRuleNode::ComputeDisplayData(void* aSt
   TransitionPropData& duration = transitionPropData[1];
   TransitionPropData& property = transitionPropData[2];
   TransitionPropData& timingFunction = transitionPropData[3];
 
 #define FOR_ALL_TRANSITION_PROPS(var_) \
                                       for (PRUint32 var_ = 0; var_ < 4; ++var_)
 
   // CSS Transitions
-
-  // The four transition properties are stored in nsCSSDisplay in a
-  // single array for all properties.  The number of transitions is
-  // equal to the number of items in the longest property's value.
-  // Properties that have fewer values than the longest are filled in by
-  // repeating the list.  However, this repetition does not extend the
-  // computed value of that particular property (for purposes of
-  // inheritance, or, in our code, for when other properties are
-  // overridden by a more specific rule).
-
-  // But actually, since the spec isn't clear yet, we'll fully compute
-  // all of them (so we can switch easily later), but only care about
-  // the ones up to the number of items for 'transition-property', per
-  // http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html .
-
-  // Transitions are difficult to handle correctly because of this.  For
-  // example, we need to handle scenarios such as:
-  //  * a more general rule specifies transition-property: a, b, c;
-  //  * a more specific rule overrides as transition-property: d;
-  //
-  // If only the general rule applied, we would fill in the extra
-  // properties (duration, delay, etc) with initial values to create 3
-  // fully-specified transitions.  But when the more specific rule
-  // applies, we should only create a single transition.  In order to do
-  // this we need to remember which properties were explicitly specified
-  // and which ones were just filled in with initial values to get a
-  // fully-specified transition, which we do by remembering the number
-  // of values for each property.
-
-  PRUint32 numTransitions = 0;
-  FOR_ALL_TRANSITION_PROPS(p) {
-    const TransitionPropInfo& i = transitionPropInfo[p];
-    TransitionPropData& d = transitionPropData[p];
-
-    // cache whether any of the properties are specified as 'inherit' so
-    // we can use it below
-
-    const nsCSSValue& value = *aRuleData->ValueFor(i.property);
-    d.unit = value.GetUnit();
-    d.list = (value.GetUnit() == eCSSUnit_List ||
-              value.GetUnit() == eCSSUnit_ListDep)
-      ? value.GetListValue() : nsnull;
-
-    // General algorithm to determine how many total transitions we need
-    // to build.  For each property:
-    //  - if there is no value specified in for the property in
-    //    displayData, use the values from the start struct, but only if
-    //    they were explicitly specified
-    //  - if there is a value specified for the property in displayData:
-    //    - if the value is 'inherit', count the number of values for
-    //      that property are specified by the parent, but only those
-    //      that were explicitly specified
-    //    - otherwise, count the number of values specified in displayData
-
-
-    // calculate number of elements
-    if (d.unit == eCSSUnit_Inherit) {
-      d.num = parentDisplay->*(i.sdCount);
-      canStoreInRuleTree = PR_FALSE;
-    } else if (d.list) {
-      d.num = ListLength(d.list);
-    } else {
-      d.num = display->*(i.sdCount);
-    }
-    if (d.num > numTransitions)
-      numTransitions = d.num;
-  }
+  PRUint32 numTransitions =
+    CountTransitionProps(transitionPropInfo, transitionPropData,
+                         NS_ARRAY_LENGTH(transitionPropData),
+                         display, parentDisplay, aRuleData,
+                         canStoreInRuleTree);
 
   if (!display->mTransitions.SetLength(numTransitions)) {
     NS_WARNING("failed to allocate transitions array");
     display->mTransitions.SetLength(1);
     NS_ABORT_IF_FALSE(display->mTransitions.Length() == 1,
                       "could not allocate using auto array buffer");
     numTransitions = 1;
     FOR_ALL_TRANSITION_PROPS(p) {
@@ -3834,59 +3894,18 @@ nsRuleNode::ComputeDisplayData(void* aSt
       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
                         "should have made canStoreInRuleTree false above");
       transition->SetTimingFunction(
         parentDisplay->mTransitions[i].GetTimingFunction());
     } else if (timingFunction.unit == eCSSUnit_Initial) {
       transition->SetTimingFunction(
         nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
     } else if (timingFunction.list) {
-      switch (timingFunction.list->mValue.GetUnit()) {
-        case eCSSUnit_Enumerated:
-          transition->SetTimingFunction(
-            nsTimingFunction(timingFunction.list->mValue.GetIntValue()));
-          break;
-        case eCSSUnit_Cubic_Bezier:
-          {
-            nsCSSValue::Array* array =
-              timingFunction.list->mValue.GetArrayValue();
-            NS_ASSERTION(array && array->Count() == 4,
-                         "Need 4 control points");
-            transition->SetTimingFunction(
-              nsTimingFunction(array->Item(0).GetFloatValue(),
-                               array->Item(1).GetFloatValue(),
-                               array->Item(2).GetFloatValue(),
-                               array->Item(3).GetFloatValue()));
-          }
-          break;
-        case eCSSUnit_Steps:
-          {
-            nsCSSValue::Array* array =
-              timingFunction.list->mValue.GetArrayValue();
-            NS_ASSERTION(array && array->Count() == 2,
-                         "Need 2 items");
-            NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer,
-                         "unexpected first value");
-            NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
-                         (array->Item(1).GetIntValue() ==
-                           NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
-                          array->Item(1).GetIntValue() ==
-                           NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END),
-                         "unexpected second value");
-            transition->SetTimingFunction(
-              nsTimingFunction((
-                array->Item(1).GetIntValue() ==
-                  NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END)
-                  ? nsTimingFunction::StepEnd : nsTimingFunction::StepStart,
-                array->Item(0).GetIntValue()));
-          }
-          break;
-        default:
-          NS_NOTREACHED("Invalid transition property unit");
-      }
+      ComputeTimingFunction(timingFunction.list->mValue,
+                            transition->TimingFunctionSlot());
     }
 
     FOR_ALL_TRANSITION_PROPS(p) {
       const TransitionPropInfo& info = transitionPropInfo[p];
       TransitionPropData& d = transitionPropData[p];
 
       // if we're at the end of the list, start at the beginning and repeat
       // until we're out of transitions to populate
@@ -3908,56 +3927,23 @@ nsRuleNode::ComputeDisplayData(void* aSt
   TransitionPropData& animDirection = animationPropData[4];
   TransitionPropData& animFillMode = animationPropData[5];
   TransitionPropData& animPlayState = animationPropData[6];
   TransitionPropData& animIterationCount = animationPropData[7];
 
 #define FOR_ALL_ANIMATION_PROPS(var_) \
     for (PRUint32 var_ = 0; var_ < 8; ++var_)
 
-  // CSS Animations.  See transitions, above.
-
-  PRUint32 numAnimations = 0;
-  FOR_ALL_ANIMATION_PROPS(p) {
-    const TransitionPropInfo& i = animationPropInfo[p];
-    TransitionPropData& d = animationPropData[p];
-
-    // cache whether any of the properties are specified as 'inherit' so
-    // we can use it below
-
-    const nsCSSValue& value = *aRuleData->ValueFor(i.property);
-    d.unit = value.GetUnit();
-    d.list = (value.GetUnit() == eCSSUnit_List ||
-              value.GetUnit() == eCSSUnit_ListDep)
-      ? value.GetListValue() : nsnull;
-
-    // General algorithm to determine how many total animations we need
-    // to build.  For each property:
-    //  - if there is no value specified in for the property in
-    //    displayData, use the values from the start struct, but only if
-    //    they were explicitly specified
-    //  - if there is a value specified for the property in displayData:
-    //    - if the value is 'inherit', count the number of values for
-    //      that property are specified by the parent, but only those
-    //      that were explicitly specified
-    //    - otherwise, count the number of values specified in displayData
-
-
-    // calculate number of elements
-    if (d.unit == eCSSUnit_Inherit) {
-      d.num = parentDisplay->*(i.sdCount);
-      canStoreInRuleTree = PR_FALSE;
-    } else if (d.list) {
-      d.num = ListLength(d.list);
-    } else {
-      d.num = display->*(i.sdCount);
-    }
-    if (d.num > numAnimations)
-      numAnimations = d.num;
-  }
+  // CSS Animations.
+
+  PRUint32 numAnimations =
+    CountTransitionProps(animationPropInfo, animationPropData,
+                         NS_ARRAY_LENGTH(animationPropData),
+                         display, parentDisplay, aRuleData,
+                         canStoreInRuleTree);
 
   if (!display->mAnimations.SetLength(numAnimations)) {
     NS_WARNING("failed to allocate animations array");
     display->mAnimations.SetLength(1);
     NS_ABORT_IF_FALSE(display->mAnimations.Length() == 1,
                       "could not allocate using auto array buffer");
     numAnimations = 1;
     FOR_ALL_ANIMATION_PROPS(p) {
@@ -4068,59 +4054,18 @@ nsRuleNode::ComputeDisplayData(void* aSt
       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
                         "should have made canStoreInRuleTree false above");
       animation->SetTimingFunction(
         parentDisplay->mAnimations[i].GetTimingFunction());
     } else if (animTimingFunction.unit == eCSSUnit_Initial) {
       animation->SetTimingFunction(
         nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
     } else if (animTimingFunction.list) {
-      switch (animTimingFunction.list->mValue.GetUnit()) {
-        case eCSSUnit_Enumerated:
-          animation->SetTimingFunction(
-            nsTimingFunction(animTimingFunction.list->mValue.GetIntValue()));
-          break;
-        case eCSSUnit_Cubic_Bezier:
-          {
-            nsCSSValue::Array* array =
-              animTimingFunction.list->mValue.GetArrayValue();
-            NS_ASSERTION(array && array->Count() == 4,
-                         "Need 4 control points");
-            animation->SetTimingFunction(
-              nsTimingFunction(array->Item(0).GetFloatValue(),
-                               array->Item(1).GetFloatValue(),
-                               array->Item(2).GetFloatValue(),
-                               array->Item(3).GetFloatValue()));
-          }
-          break;
-        case eCSSUnit_Steps:
-          {
-            nsCSSValue::Array* array =
-              animTimingFunction.list->mValue.GetArrayValue();
-            NS_ASSERTION(array && array->Count() == 2,
-                         "Need 2 items");
-            NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer,
-                         "unexpected first value");
-            NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
-                         (array->Item(1).GetIntValue() ==
-                           NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
-                          array->Item(1).GetIntValue() ==
-                           NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END),
-                         "unexpected second value");
-            animation->SetTimingFunction(
-              nsTimingFunction((
-                array->Item(1).GetIntValue() ==
-                  NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END)
-                  ? nsTimingFunction::StepEnd : nsTimingFunction::StepStart,
-                array->Item(0).GetIntValue()));
-          }
-          break;
-        default:
-          NS_NOTREACHED("Invalid animation property unit");
-      }
+      ComputeTimingFunction(animTimingFunction.list->mValue,
+                            animation->TimingFunctionSlot());
     }
 
     if (i >= animDirection.num) {
       animation->SetDirection(display->mAnimations[i % animDirection.num].GetDirection());
     } else if (animDirection.unit == eCSSUnit_Inherit) {
       NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationDirectionCount,
                         "animDirection.num computed incorrectly");
       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
--- a/layout/style/nsStyleAnimation.cpp
+++ b/layout/style/nsStyleAnimation.cpp
@@ -1802,18 +1802,17 @@ BuildStyleRule(nsCSSProperty aProperty,
 #endif
   }
 
   nsCSSProperty propertyToCheck = nsCSSProps::IsShorthand(aProperty) ?
     nsCSSProps::SubpropertyEntryFor(aProperty)[0] : aProperty;
 
   // Get a parser, parse the property, and check for CSS parsing errors.
   // If any of these steps fails, we bail out and delete the declaration.
-  if (!parser ||
-      NS_FAILED(parser.ParseProperty(aProperty, aSpecifiedValue,
+  if (NS_FAILED(parser.ParseProperty(aProperty, aSpecifiedValue,
                                      doc->GetDocumentURI(), baseURI,
                                      aTargetElement->NodePrincipal(),
                                      declaration, &changed, PR_FALSE)) ||
       // check whether property parsed without CSS parsing errors
       !declaration->HasNonImportantValueFor(propertyToCheck)) {
     NS_WARNING("failure in BuildStyleRule");
     return nsnull;
   }
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1329,39 +1329,51 @@ struct nsTimingFunction {
   nsTimingFunction(Type aType, PRUint32 aSteps)
     : mType(aType)
   {
     NS_ABORT_IF_FALSE(mType == StepStart || mType == StepEnd, "wrong type");
     mSteps = aSteps;
   }
 
   nsTimingFunction(const nsTimingFunction& aOther)
-    : mType(aOther.mType)
   {
-    if (mType == Function) {
-      mFunc.mX1 = aOther.mFunc.mX1;
-      mFunc.mY1 = aOther.mFunc.mY1;
-      mFunc.mX2 = aOther.mFunc.mX2;
-      mFunc.mY2 = aOther.mFunc.mY2;
-    } else {
-      mSteps = aOther.mSteps;
-    }
+    *this = aOther;
   }
 
   Type mType;
   union {
     struct {
       float mX1;
       float mY1;
       float mX2;
       float mY2;
     } mFunc;
     PRUint32 mSteps;
   };
 
+  nsTimingFunction&
+  operator=(const nsTimingFunction& aOther)
+  {
+    if (&aOther == this)
+      return *this;
+
+    mType = aOther.mType;
+
+    if (mType == Function) {
+      mFunc.mX1 = aOther.mFunc.mX1;
+      mFunc.mY1 = aOther.mFunc.mY1;
+      mFunc.mX2 = aOther.mFunc.mX2;
+      mFunc.mY2 = aOther.mFunc.mY2;
+    } else {
+      mSteps = aOther.mSteps;
+    }
+
+    return *this;
+  }
+
   bool operator==(const nsTimingFunction& aOther) const
   {
     if (mType != aOther.mType) {
       return false;
     }
     if (mType == Function) {
       return mFunc.mX1 == aOther.mFunc.mX1 && mFunc.mY1 == aOther.mFunc.mY1 &&
              mFunc.mX2 == aOther.mFunc.mX2 && mFunc.mY2 == aOther.mFunc.mY2;
@@ -1403,16 +1415,18 @@ struct nsTransition {
     }
   void SetUnknownProperty(const nsAString& aUnknownProperty);
   void CopyPropertyFrom(const nsTransition& aOther)
     {
       mProperty = aOther.mProperty;
       mUnknownProperty = aOther.mUnknownProperty;
     }
 
+  nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
+
 private:
   nsTimingFunction mTimingFunction;
   float mDuration;
   float mDelay;
   nsCSSProperty mProperty;
   nsCOMPtr<nsIAtom> mUnknownProperty; // used when mProperty is
                                       // eCSSProperty_UNKNOWN
 };
@@ -1441,16 +1455,18 @@ struct nsAnimation {
   void SetDuration(float aDuration) { mDuration = aDuration; }
   void SetName(const nsSubstring& aName) { mName = aName; }
   void SetDirection(PRUint8 aDirection) { mDirection = aDirection; }
   void SetFillMode(PRUint8 aFillMode) { mFillMode = aFillMode; }
   void SetPlayState(PRUint8 aPlayState) { mPlayState = aPlayState; }
   void SetIterationCount(float aIterationCount)
     { mIterationCount = aIterationCount; }
 
+  nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
+
 private:
   nsTimingFunction mTimingFunction;
   float mDuration;
   float mDelay;
   nsString mName; // empty string for 'none'
   PRUint8 mDirection;
   PRUint8 mFillMode;
   PRUint8 mPlayState;
--- a/layout/style/test/Makefile.in
+++ b/layout/style/test/Makefile.in
@@ -150,16 +150,17 @@ GARBAGE += css_properties.js
 		test_ident_escaping.html \
 		test_inherit_computation.html \
 		test_inherit_storage.html \
 		test_initial_computation.html \
 		test_initial_storage.html \
 		test_media_queries.html \
 		test_media_queries_dynamic.html \
 		test_media_queries_dynamic_xbl.html \
+		test_media_query_list.html \
 		test_moz_device_pixel_ratio.html \
 		test_namespace_rule.html \
 		test_of_type_selectors.xhtml \
 		test_parse_ident.html \
 		test_parse_rule.html \
 		test_parse_url.html \
 		test_pixel_lengths.html \
 		test_pointer-events.html \
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -1001,25 +1001,16 @@ var gCSSProperties = {
 	"-moz-window-shadow": {
 		domProp: "MozWindowShadow",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "default" ],
 		other_values: [ "none", "menu", "tooltip", "sheet" ],
 		invalid_values: []
 	},
-	"azimuth": {
-		domProp: "azimuth",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "center", "0deg" ],
-		other_values: [ "center behind", "behind far-right", "left-side", "73deg", "90.1deg", "0.1deg" ],
-		invalid_values: [ "0deg behind", "behind 0deg", "90deg behind", "behind 90deg" ]
-	},
 	"background": {
 		domProp: "background",
 		inherited: false,
 		type: CSS_TYPE_TRUE_SHORTHAND,
 		subproperties: [ "background-attachment", "background-color", "background-image", "background-position", "background-repeat", "background-clip", "background-origin", "background-size" ],
 		initial_values: [ "transparent", "none", "repeat", "scroll", "0% 0%", "top left", "left top", "transparent none", "top left none", "left top none", "none left top", "none top left", "none 0% 0%", "transparent none repeat scroll top left", "left top repeat none scroll transparent" ],
 		other_values: [
 				/* without multiple backgrounds */
@@ -1740,44 +1731,16 @@ var gCSSProperties = {
 	"counter-reset": {
 		domProp: "counterReset",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "none" ],
 		other_values: [ "foo 1", "bar", "foo 3 bar baz 2", "\\32  1", "-\\32  1", "-c 1", "\\32 1", "-\\32 1", "\\2  1", "-\\2  1", "-c 1", "\\2 1", "-\\2 1" ],
 		invalid_values: []
 	},
-	"cue": {
-		domProp: "cue",
-		inherited: false,
-		backend_only: true,
-		type: CSS_TYPE_TRUE_SHORTHAND,
-		subproperties: [ "cue-before", "cue-after" ],
-		initial_values: [ "none", "none none" ],
-		other_values: [ "url(404.wav)", "url(404.wav) none", "none url(404.wav)" ],
-		invalid_values: []
-	},
-	"cue-after": {
-		domProp: "cueAfter",
-		inherited: false,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "none" ],
-		other_values: [ "url(404.wav)" ],
-		invalid_values: []
-	},
-	"cue-before": {
-		domProp: "cueBefore",
-		inherited: false,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "none" ],
-		other_values: [ "url(404.wav)" ],
-		invalid_values: []
-	},
 	"cursor": {
 		domProp: "cursor",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "auto" ],
 		other_values: [ "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress", "copy", "alias", "context-menu", "cell", "not-allowed", "col-resize", "row-resize", "no-drop", "vertical-text", "all-scroll", "nesw-resize", "nwse-resize", "ns-resize", "ew-resize", "none", "-moz-grab", "-moz-grabbing", "-moz-zoom-in", "-moz-zoom-out" ],
 		invalid_values: []
 	},
@@ -1794,25 +1757,16 @@ var gCSSProperties = {
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "inline" ],
 		/* XXX none will really mess with other properties */
 		prerequisites: { "float": "none", "position": "static" },
 		other_values: [ "block", "list-item", "inline-block", "table", "inline-table", "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", "table-column", "table-cell", "table-caption", "none" ],
 		invalid_values: []
 	},
-	"elevation": {
-		domProp: "elevation",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "level", "0deg" ],
-		other_values: [ "below", "above", "60deg", "higher", "lower", "-79deg", "0.33deg" ],
-		invalid_values: []
-	},
 	"empty-cells": {
 		domProp: "emptyCells",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "show" ],
 		other_values: [ "hide" ],
 		invalid_values: []
 	},
@@ -2399,62 +2353,16 @@ var gCSSProperties = {
 		domProp: "pageBreakInside",
 		inherited: true,
 		backend_only: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "auto" ],
 		other_values: [ "avoid" ],
 		invalid_values: []
 	},
-	"pause": {
-		domProp: "pause",
-		inherited: false,
-		backend_only: true,
-		type: CSS_TYPE_TRUE_SHORTHAND,
-		subproperties: [ "pause-before", "pause-after" ],
-		initial_values: [ "0s", "0ms", "0s 0ms" ],
-		other_values: [ "1s", "200ms", "-2s", "50%", "-10%", "10% 200ms", "-3s -5%" ],
-		invalid_values: [ "0", "0px", "0 0", "0ms 0" ]
-	},
-	"pause-after": {
-		domProp: "pauseAfter",
-		inherited: false,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "0s", "0ms" ],
-		other_values: [ "1s", "200ms", "-2s", "50%", "-10%" ],
-		invalid_values: [ "0", "0px" ]
-	},
-	"pause-before": {
-		domProp: "pauseBefore",
-		inherited: false,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "0s", "0ms" ],
-		other_values: [ "1s", "200ms", "-2s", "50%", "-10%" ],
-		invalid_values: [ "0", "0px" ]
-	},
-	"pitch": {
-		domProp: "pitch",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "medium" ],
-		other_values: [ "x-low", "low", "high", "x-high" ],
-		invalid_values: []
-	},
-	"pitch-range": {
-		domProp: "pitchRange",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "50", "50.0" ],
-		other_values: [ "0", "100.0", "99.7", "47", "3.2" ],
-		invalid_values: [" -0.01", "100.2", "108", "-3" ]
-	},
 	"pointer-events": {
 		domProp: "pointerEvents",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "auto" ],
 		other_values: [ "visiblePainted", "visibleFill", "visibleStroke", "visible",
 						"painted", "fill", "stroke", "all", "none" ],
 		invalid_values: []
@@ -2471,25 +2379,16 @@ var gCSSProperties = {
 		domProp: "quotes",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ '"\u201C" "\u201D" "\u2018" "\u2019"',
 						  '"\\201C" "\\201D" "\\2018" "\\2019"' ],
 		other_values: [ "none", "'\"' '\"'" ],
 		invalid_values: []
 	},
-	"richness": {
-		domProp: "richness",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "50", "50.0" ],
-		other_values: [ "0", "100.0", "99.7", "47", "3.2" ],
-		invalid_values: [" -0.01", "100.2", "108", "-3" ]
-	},
 	"right": {
 		domProp: "right",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		/* FIXME: run tests with multiple prerequisites */
 		prerequisites: { "position": "relative" },
 		/* XXX 0 may or may not be equal to auto */
 		initial_values: [ "auto" ],
@@ -2511,72 +2410,16 @@ var gCSSProperties = {
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "auto" ],
 		other_values: [ "landscape", "portrait", "8.5in 11in", "14in 11in", "297mm 210mm", "21cm 29.7cm", "100mm" ],
 		invalid_values: [
 			// XXX spec unclear on 0s and negatives
 			"100mm 100mm 100mm"
 		]
 	},
-	"speak": {
-		domProp: "speak",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "normal" ],
-		other_values: [ "none", "spell-out" ],
-		invalid_values: []
-	},
-	"speak-header": {
-		domProp: "speakHeader",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "once" ],
-		other_values: [ "always" ],
-		invalid_values: []
-	},
-	"speak-numeral": {
-		domProp: "speakNumeral",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "continuous" ],
-		other_values: [ "digits" ],
-		invalid_values: []
-	},
-	"speak-punctuation": {
-		domProp: "speakPunctuation",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "none" ],
-		other_values: [ "code" ],
-		invalid_values: []
-	},
-	"speech-rate": {
-		domProp: "speechRate",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "medium" ],
-		other_values: [ "x-slow", "slow", "fast", "x-fast", "faster", "slower", "80", "500", "73.2" ],
-		invalid_values: [
-			// "0", "-80" // unclear
-		]
-	},
-	"stress": {
-		domProp: "stress",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "50", "50.0" ],
-		other_values: [ "0", "100.0", "99.7", "47", "3.2" ],
-		invalid_values: [" -0.01", "100.2", "108", "-3" ]
-	},
 	"table-layout": {
 		domProp: "tableLayout",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "auto" ],
 		other_values: [ "fixed" ],
 		invalid_values: []
 	},
@@ -2745,34 +2588,16 @@ var gCSSProperties = {
 	"visibility": {
 		domProp: "visibility",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "visible" ],
 		other_values: [ "hidden", "collapse" ],
 		invalid_values: []
 	},
-	"voice-family": {
-		domProp: "voiceFamily",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "male" ], /* arbitrary guess */
-		other_values: [ "female", "child", "Bob, male", "Jane, Juliet, female" ],
-		invalid_values: []
-	},
-	"volume": {
-		domProp: "volume",
-		inherited: true,
-		backend_only: true,
-		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "50", "50.0", "medium" ],
-		other_values: [ "0", "100.0", "99.7", "47", "3.2", "silent", "x-soft", "soft", "loud", "x-loud" ],
-		invalid_values: [" -0.01", "100.2", "108", "-3" ]
-	},
 	"white-space": {
 		domProp: "whiteSpace",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "normal" ],
 		other_values: [ "pre", "nowrap", "pre-wrap", "pre-line" ],
 		invalid_values: []
 	},
--- a/layout/style/test/test_media_queries_dynamic.html
+++ b/layout/style/test/test_media_queries_dynamic.html
@@ -52,21 +52,16 @@ function run() {
   function should_apply(cs) {
     ok(query_applies(cs), cs._originalQueryText + " should apply");
   }
 
   function should_not_apply(cs) {
     ok(!query_applies(cs), cs._originalQueryText + " should not apply");
   }
 
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-  const CI = Components.interfaces;
-  var iframe_docshell = subwin.QueryInterface(CI.nsIInterfaceRequestor).getInterface(CI.nsIWebNavigation).QueryInterface(CI.nsIDocShell);
-  var iframe_mudv = iframe_docshell.contentViewer.QueryInterface(CI.nsIMarkupDocumentViewer);
-
   var content_div = document.getElementById("content");
   content_div.style.font = "-moz-initial";
   var em_size =
     getComputedStyle(content_div, "").fontSize.match(/^(\d+)px$/)[1];
 
   let width_val = 317; // pick two not-too-round numbers
   let height_val = 228;
   iframe_style.width = width_val + "px";
@@ -90,36 +85,36 @@ function run() {
                      (Math.floor(width_val/(em_size*2)) - 1) + "em)")
   ];
 
   is(wh_queries[0].fontSize, em_size + "px", "text zoom is 1.0");
   should_not_apply(wh_queries[0]);
   should_apply(wh_queries[1]);
   should_apply(wh_queries[2]);
   should_not_apply(wh_queries[3]);
-  iframe_mudv.textZoom = 2.0;
+  SpecialPowers.setTextZoom(subwin, 2.0);
   isnot(wh_queries[0].fontSize, em_size + "px", "text zoom is not 1.0");
   should_not_apply(wh_queries[4]);
   should_apply(wh_queries[5]);
   should_apply(wh_queries[6]);
   should_not_apply(wh_queries[7]);
-  iframe_mudv.textZoom = 1.0;
+  SpecialPowers.setTextZoom(subwin, 1.0);
   is(wh_queries[0].fontSize, em_size + "px", "text zoom is 1.0");
   is(subwin.innerHeight, 228, "full zoom is 1.0");
   should_not_apply(wh_queries[0]);
   should_apply(wh_queries[1]);
   should_apply(wh_queries[2]);
   should_not_apply(wh_queries[3]);
-  iframe_mudv.fullZoom = 2.0;
+  SpecialPowers.setFullZoom(subwin, 2.0);
   isnot(subwin.innerHeight, 228, "full zoom is not 1.0");
   should_not_apply(wh_queries[4]);
   should_apply(wh_queries[5]);
   should_apply(wh_queries[6]);
   should_not_apply(wh_queries[7]);
-  iframe_mudv.fullZoom = 1.0;
+  SpecialPowers.setFullZoom(subwin, 1.0);
   is(subwin.innerHeight, 228, "full zoom is 1.0");
 
   SimpleTest.finish();
 }
 
 </script>
 </pre>
 </body>
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_media_query_list.html
@@ -0,0 +1,259 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=542058
+-->
+<head>
+  <title>Test for MediaQueryList (Bug 542058)</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="run()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=542058">Mozilla Bug 542058</a>
+<iframe id="subdoc" src="about:blank"></iframe>
+<div id="content" style="display:none"></div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for MediaQueryList (Bug 542058) **/
+
+SimpleTest.waitForExplicitFinish();
+
+function run() {
+  var iframe = document.getElementById("subdoc");
+  var subdoc = iframe.contentDocument;
+  var subwin = iframe.contentWindow;
+  var subroot = subdoc.documentElement;
+
+  var content_div = document.getElementById("content");
+  content_div.style.font = "-moz-initial";
+  var em_size =
+    getComputedStyle(content_div, "").fontSize.match(/^(\d+)px$/)[1];
+
+  var w = Math.floor(em_size * 9.3);
+  var h = Math.floor(em_size * 4.2);
+  iframe.style.width = w + "px";
+  iframe.style.height = h + "px";
+  subroot.offsetWidth; // flush layout
+
+  function setup_mql(str) {
+    var obj = { str: str, mql: subwin.matchMedia(str), notifyCount: 0 }
+    obj.mql.addListener(function(mql) {
+                          is(mql, obj.mql,
+                             "correct argument to listener: " + obj.str);
+                          ++obj.notifyCount;
+                          // Test the last match result only on odd
+                          // notifications.
+                          if (obj.notifyCount & 1) {
+                            obj.lastOddMatchResult = mql.matches;
+                          }
+                        });
+    return obj;
+  }
+
+  var w_exact_w = setup_mql("(width: " + w + "px)");
+  var w_min_9em = setup_mql("(min-width : 9em)");
+  var w_min_10em = setup_mql("(  min-width: 10em ) ");
+  var w_max_9em = setup_mql("(max-width: 9em)");
+  var w_max_10em = setup_mql("(max-width: 10em)");
+
+  is(w_exact_w.mql.media, "(width: " + w + "px)", "serialization");
+  is(w_min_9em.mql.media, "(min-width: 9em)", "serialization");
+  is(w_min_10em.mql.media, "(min-width: 10em)", "serialization");
+  is(w_max_9em.mql.media, "(max-width: 9em)", "serialization");
+  is(w_max_10em.mql.media, "(max-width: 10em)", "serialization");
+
+  function check_match(obj, expected, desc) {
+    is(obj.mql.matches, expected,
+       obj.str + " media query list .matches " + desc);
+    if (obj.notifyCount & 1) { // odd notifications only
+      is(obj.lastOddMatchResult, expected,
+       obj.str + " media query list last notify result " + desc);
+    }
+  }
+  function check_notify(obj, expected, desc) {
+    is(obj.notifyCount, expected,
+       obj.str + " media query list .notify count " + desc);
+  }
+  check_match(w_exact_w, true, "initially");
+  check_notify(w_exact_w, 0, "initially");
+  check_match(w_min_9em, true, "initially");
+  check_notify(w_min_9em, 0, "initially");
+  check_match(w_min_10em, false, "initially");
+  check_notify(w_min_10em, 0, "initially");
+  check_match(w_max_9em, false, "initially");
+  check_notify(w_max_9em, 0, "initially");
+  check_match(w_max_10em, true, "initially");
+  check_notify(w_max_10em, 0, "initially");
+
+  var w2 = Math.floor(em_size * 10.3);
+  iframe.style.width = w2 + "px";
+  subroot.offsetWidth; // flush layout
+
+  check_match(w_exact_w, false, "after width increase to around 10.3em");
+  check_notify(w_exact_w, 1, "after width increase to around 10.3em");
+  check_match(w_min_9em, true, "after width increase to around 10.3em");
+  check_notify(w_min_9em, 0, "after width increase to around 10.3em");
+  check_match(w_min_10em, true, "after width increase to around 10.3em");
+  check_notify(w_min_10em, 1, "after width increase to around 10.3em");
+  check_match(w_max_9em, false, "after width increase to around 10.3em");
+  check_notify(w_max_9em, 0, "after width increase to around 10.3em");
+  check_match(w_max_10em, false, "after width increase to around 10.3em");
+  check_notify(w_max_10em, 1, "after width increase to around 10.3em");
+
+  var w3 = w * 2;
+  iframe.style.width = w3 + "px";
+  subroot.offsetWidth; // flush layout
+
+  check_match(w_exact_w, false, "after width double from original");
+  check_notify(w_exact_w, 1, "after width double from original");
+  check_match(w_min_9em, true, "after width double from original");
+  check_notify(w_min_9em, 0, "after width double from original");
+  check_match(w_min_10em, true, "after width double from original");
+  check_notify(w_min_10em, 1, "after width double from original");
+  check_match(w_max_9em, false, "after width double from original");
+  check_notify(w_max_9em, 0, "after width double from original");
+  check_match(w_max_10em, false, "after width double from original");
+  check_notify(w_max_10em, 1, "after width double from original");
+
+  SpecialPowers.setFullZoom(subwin, 2.0);
+  subroot.offsetWidth; // flush layout
+
+  check_match(w_exact_w, true, "after zoom");
+  check_notify(w_exact_w, 2, "after zoom");
+  check_match(w_min_9em, true, "after zoom");
+  check_notify(w_min_9em, 0, "after zoom");
+  check_match(w_min_10em, false, "after zoom");
+  check_notify(w_min_10em, 2, "after zoom");
+  check_match(w_max_9em, false, "after zoom");
+  check_notify(w_max_9em, 0, "after zoom");
+  check_match(w_max_10em, true, "after zoom");
+  check_notify(w_max_10em, 2, "after zoom");
+
+  SpecialPowers.setFullZoom(subwin, 1.0);
+
+  // Additional tests of listener mutation.
+  (function() {
+    var received = [];
+    var received_mql = [];
+    function listener1(mql) {
+      received.push(1);
+      received_mql.push(mql);
+    }
+    function listener2(mql) {
+      received.push(2);
+      received_mql.push(mql);
+    }
+
+    iframe.style.width = "200px";
+    subroot.offsetWidth; // flush layout
+
+    var mql = subwin.matchMedia("(min-width: 150px)");
+    mql.addListener(listener1);
+    mql.addListener(listener1);
+    mql.addListener(listener2);
+    is(JSON.stringify(received), "[]", "listeners before notification");
+
+    iframe.style.width = "100px";
+    subroot.offsetWidth; // flush layout
+
+    is(JSON.stringify(received), "[1,2]", "duplicate listeners removed");
+    received = [];
+    mql.removeListener(listener1);
+
+    iframe.style.width = "200px";
+    subroot.offsetWidth; // flush layout
+
+    is(JSON.stringify(received), "[2]", "listener removal");
+    received = [];
+    mql.addListener(listener1);
+
+    iframe.style.width = "100px";
+    subroot.offsetWidth; // flush layout
+
+    is(JSON.stringify(received), "[2,1]", "listeners notified in order");
+    received = [];
+    mql.addListener(listener2);
+
+    iframe.style.width = "200px";
+    subroot.offsetWidth; // flush layout
+
+    is(JSON.stringify(received), "[2,1]", "add of existing listener is no-op");
+    received = [];
+    mql.addListener(listener1);
+
+    iframe.style.width = "100px";
+    subroot.offsetWidth; // flush layout
+
+    is(JSON.stringify(received), "[2,1]", "add of existing listener is no-op");
+    mql.removeListener(listener2);
+    received = [];
+    received_mql = [];
+
+    var mql2 = subwin.matchMedia("(min-width: 160px)");
+    mql2.addListener(listener1);
+    mql.addListener(listener2);
+
+    iframe.style.width = "200px";
+    subroot.offsetWidth; // flush layout
+
+    // mql (1, 2), mql2 (1)
+    is(JSON.stringify(received), "[1,2,1]",
+       "notification of lists in order created");
+    is(received_mql[0], mql,
+       "notification of lists in order created");
+    is(received_mql[1], mql,
+       "notification of lists in order created");
+    is(received_mql[2], mql2,
+       "notification of lists in order created");
+    received = [];
+    received_mql = [];
+
+    function removing_listener(mql) {
+      received.push(3);
+      received_mql.push(mql);
+      mql.removeListener(listener2);
+      mql2.removeListener(listener1);
+    }
+
+    mql.addListener(removing_listener);
+    mql.removeListener(listener2);
+    mql.addListener(listener2); // after removing_listener (3)
+
+    iframe.style.width = "100px";
+    subroot.offsetWidth; // flush layout
+
+    // mql(1, 3, 2) mql2(1)
+    is(JSON.stringify(received), "[1,3,2,1]",
+       "listeners still notified after removed if change was before");
+    is(received_mql[0], mql,
+       "notification order (removal tests)");
+    is(received_mql[1], mql,
+       "notification order (removal tests)");
+    is(received_mql[2], mql,
+       "notification order (removal tests)");
+    is(received_mql[3], mql2,
+       "notification order (removal tests)");
+    received = [];
+    received_mql = [];
+
+    iframe.style.width = "200px";
+    subroot.offsetWidth; // flush layout
+
+    // mql(1, 3)
+    is(JSON.stringify(received), "[1,3]",
+       "listeners not notified for changes after their removal");
+    is(received_mql[0], mql,
+       "notification order (removal tests)");
+    is(received_mql[1], mql,
+       "notification order (removal tests)");
+  })();
+
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/style/test/test_units_angle.html
+++ b/layout/style/test/test_units_angle.html
@@ -26,18 +26,18 @@ var tests = {
   "45deg": "50grad",
   "150grad": "135deg",
   "1rad": null
 };
 
 var p = document.getElementById("display");
 
 for (var test in tests) {
-  p.setAttribute("style", "elevation: " + test);
-  is(p.style.getPropertyValue("elevation"), test,
+  p.setAttribute("style", "-moz-transform: rotate(" + test + ")");
+  is(p.style.getPropertyValue("-moz-transform"), "rotate(" + test + ")",
      test + " serializes to exactly itself");
   // We can't test any equivalence since we don't have any properties
   // with angle values that we compute.  (-moz-transform doesn't help.)
 /*
   var equiv = tests[test];
   if (equiv) {
     var cm1 = getComputedStyle(p, "").elevation;
     p.style.elevation = equiv;
--- a/layout/style/test/test_units_frequency.html
+++ b/layout/style/test/test_units_frequency.html
@@ -25,21 +25,26 @@
 var tests = {
   "7kHz": "7000Hz",
   "300Hz": "0.3khz"
 };
 
 var p = document.getElementById("display");
 
 for (var test in tests) {
+  // We can't test this because we no longer support any properties
+  // with frequency values.
+  todo(false, "no tests to run, for now");
+  /*
   p.setAttribute("style", "pitch: " + test);
   is(p.style.getPropertyValue("pitch"), test,
      test + " serializes to exactly itself");
+  */
   // We can't test any equivalence since we don't have any properties
-  // with angle values that we compute.
+  // with frequency values that we compute.
 /*
   var equiv = tests[test];
   if (equiv) {
     var cm1 = getComputedStyle(p, "").pitch;
     p.style.pitch = equiv;
     var cm2 = getComputedStyle(p, "").pitch;
     is(cm1, cm2, test + " should compute to the same as " + equiv);
   }
--- a/layout/style/test/test_units_time.html
+++ b/layout/style/test/test_units_time.html
@@ -25,28 +25,24 @@
 var tests = {
   "3s": "3000ms",
   "500ms": "0.5s"
 };
 
 var p = document.getElementById("display");
 
 for (var test in tests) {
-  p.setAttribute("style", "pause-before: " + test);
-  is(p.style.getPropertyValue("pause-before"), test,
+  p.setAttribute("style", "-moz-transition-duration: " + test);
+  is(p.style.getPropertyValue("-moz-transition-duration"), test,
      test + " serializes to exactly itself");
-  // We can't test any equivalence since we don't have any properties
-  // with angle values that we compute.
-/*
   var equiv = tests[test];
   if (equiv) {
-    var cm1 = getComputedStyle(p, "").pauseBefore;
-    p.style.pauseBefore = equiv;
-    var cm2 = getComputedStyle(p, "").pauseBefore;
+    var cm1 = getComputedStyle(p, "").MozTransitionDuration;
+    p.style.MozTransitionDuration = equiv;
+    var cm2 = getComputedStyle(p, "").MozTransitionDuration;
     is(cm1, cm2, test + " should compute to the same as " + equiv);
   }
-*/
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/mobile/chrome/tests/browser_tapping.js
+++ b/mobile/chrome/tests/browser_tapping.js
@@ -218,17 +218,19 @@ gTests.push({
     clearEvents();
     EventUtils.synthesizeMouse(inputHandler, width / 2, height / 3, { type: "mousedown" });
     EventUtils.synthesizeMouse(inputHandler, width / 2, height * 2 / 3, { type: "mousemove" });
     setTimeout(function() {
       EventUtils.synthesizeMouse(inputHandler, width / 2, height * 2 / 3, { type: "mouseup" });
       ok(checkEvents([]), "Fired a pan + delay which should be seen as a non-event");
       clearEvents();
 
-      gCurrentTest.longTapPassTest();
+      window.addEventListener("PanFinished", function() {
+        setTimeout(gCurrentTest.longTapPassTest, 0);
+      }, true);
     }, 500);
   },
 
   longTapPassTest: function() {
     let browser = gCurrentTab.browser;
     let inputHandler = browser.parentNode;
     let width = inputHandler.getBoundingClientRect().width;
     let height = inputHandler.getBoundingClientRect().height;
--- a/modules/plugin/Makefile.in
+++ b/modules/plugin/Makefile.in
@@ -48,17 +48,17 @@ DIRS = \
   base/public \
   base/src \
   $(NULL)
 
 # These subdirs rely on GTK libraries and header files, it is not
 #  buildable on other non-GTK unix builds
 
 ifdef ENABLE_TESTS
-ifneq (,$(filter WINNT Darwin Linux OS2 SunOS,$(OS_ARCH)))
+ifneq (,$(filter gtk2 cocoa windows android qt os2,$(MOZ_WIDGET_TOOLKIT)))
 DIRS += test
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 $(DIST)/bin/plugins:
 	$(NSINSTALL) -D $@
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -5120,16 +5120,17 @@ AddonInstall.prototype = {
   wrapper: null,
   stream: null,
   crypto: null,
   originalHash: null,
   hash: null,
   loadGroup: null,
   badCertHandler: null,
   listeners: null,
+  restartDownload: false,
 
   name: null,
   type: null,
   version: null,
   iconURL: null,
   releaseNotesURI: null,
   sourceURI: null,
   file: null,
@@ -5500,16 +5501,30 @@ AddonInstall.prototype = {
                                                this.listeners, this.wrapper)
       return;
     }
 
     // If a listener changed our state then do not proceed with the download
     if (this.state != AddonManager.STATE_DOWNLOADING)
       return;
 
+    if (this.channel) {
+      // A previous download attempt hasn't finished cleaning up yet, signal
+      // that it should restart when complete
+      LOG("Waiting for previous download to complete");
+      this.restartDownload = true;
+      return;
+    }
+
+    this.openChannel();
+  },
+
+  openChannel: function AI_openChannel() {
+    this.restartDownload = false;
+
     try {
       this.file = getTemporaryFile();
       this.ownsTempFile = true;
       this.stream = Cc["@mozilla.org/network/file-output-stream;1"].
                     createInstance(Ci.nsIFileOutputStream);
       this.stream.init(this.file, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE |
                        FileUtils.MODE_TRUNCATE, FileUtils.PERMS_FILE, 0);
     }
@@ -5645,16 +5660,18 @@ AddonInstall.prototype = {
     this.stream.close();
     this.channel = null;
     this.badCerthandler = null;
     Services.obs.removeObserver(this, "network:offline-about-to-go-offline");
 
     // If the download was cancelled then all events will have already been sent
     if (aStatus == Cr.NS_BINDING_ABORTED) {
       this.removeTemporaryFile();
+      if (this.restartDownload)
+        this.openChannel();
       return;
     }
 
     LOG("Download of " + this.sourceURI.spec + " completed.");
 
     if (Components.isSuccessCode(aStatus)) {
       if (!(aRequest instanceof Ci.nsIHttpChannel) || aRequest.requestSucceeded) {
         if (!this.hash && (aRequest instanceof Ci.nsIChannel)) {
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -50,16 +50,17 @@ Cu.import("resource://gre/modules/AddonR
 
 const PREF_DISCOVERURL = "extensions.webservice.discoverURL";
 const PREF_MAXRESULTS = "extensions.getAddons.maxResults";
 const PREF_CHECK_COMPATIBILITY = "extensions.checkCompatibility";
 const PREF_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
 const PREF_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault";
 const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
 const PREF_GETADDONS_CACHE_ID_ENABLED = "extensions.%ID%.getAddons.cache.enabled";
+const PREF_UI_LASTCATEGORY = "extensions.ui.lastCategory";
 
 const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi;
 
 const LOADING_MSG_DELAY = 100;
 
 const SEARCH_SCORE_MULTIPLIER_NAME = 2;
 const SEARCH_SCORE_MULTIPLIER_DESCRIPTION = 2;
 
@@ -106,19 +107,38 @@ var gPendingInitializations = 1;
 function initialize() {
   document.removeEventListener("load", initialize, true);
   gCategories.initialize();
   gHeader.initialize();
   gViewController.initialize();
   gEventManager.initialize();
   Services.obs.addObserver(sendEMPong, "EM-ping", false);
   Services.obs.notifyObservers(window, "EM-loaded", "");
-  // Send this after the above notifications to give observers of them a chance
-  // to initialize us to a different view.
-  gViewController.updateState(window.history.state);
+
+  // If the initial view has already been selected (by a call to loadView from
+  // the above notifications) then bail out now
+  if (gViewController.initialViewSelected)
+    return;
+
+  // If there is a history state to restore then use that
+  if (window.history.state) {
+    gViewController.updateState(window.history.state);
+    return;
+  }
+
+  // Default to the last selected category
+  var view = gCategories.node.value;
+
+  // Allow passing in a view through the window arguments
+  if ("arguments" in window && window.arguments.length > 0 &&
+      "view" in window.arguments[0]) {
+    view = window.arguments[0].view;
+  }
+
+  gViewController.loadInitialView(view);
 }
 
 function notifyInitialized() {
   if (!gIsInitializing)
     return;
 
   gPendingInitializations--;
   if (!gIsInitializing) {
@@ -510,60 +530,47 @@ var gViewController = {
         }
       }
     }
 
     window.controllers.removeController(this);
   },
 
   updateState: function(state) {
-    // If this is a navigation to a previous state then load that state
-    if (state) {
-      this.loadViewInternal(state.view, state.previousView, state);
-      return;
-    }
-
-    // If the initial view has already been selected (by a call to loadView) then
-    // bail out now
-    if (this.initialViewSelected)
-      return;
-
-    // Otherwise load the default view
-    var view = VIEW_DEFAULT;
-    if (gCategories.node.selectedItem &&
-        gCategories.node.selectedItem.id != "category-search")
-      view = gCategories.node.selectedItem.value;
-
-    if ("arguments" in window && window.arguments.length > 0) {
-      if ("view" in window.arguments[0])
-        view = window.arguments[0].view;
-    }
-
-    this.loadInitialView(view);
+    this.loadViewInternal(state.view, state.previousView, state);
   },
 
   parseViewId: function(aViewId) {
     var matchRegex = /^addons:\/\/([^\/]+)\/(.*)$/;
     var [,viewType, viewParam] = aViewId.match(matchRegex) || [];
     return {type: viewType, param: decodeURIComponent(viewParam)};
   },
 
   get isLoading() {
     return !this.currentViewObj || this.currentViewObj.node.hasAttribute("loading");
   },
 
   loadView: function(aViewId) {
-    if (aViewId == this.currentViewId)
-      return;
+    var isRefresh = false;
+    if (aViewId == this.currentViewId) {
+      if (this.isLoading)
+        return;
+      if (!("refresh" in this.currentViewObj))
+        return;
+      if (!this.currentViewObj.canRefresh())
+        return;
+      isRefresh = true;
+    }
 
     var state = {
       view: aViewId,
       previousView: this.currentViewId
     };
-    gHistory.pushState(state);
+    if (!isRefresh)
+      gHistory.pushState(state);
     this.loadViewInternal(aViewId, this.currentViewId, state);
   },
 
   // Replaces the existing view with a new one, rewriting the current history
   // entry to match.
   replaceView: function(aViewId) {
     if (aViewId == this.currentViewId)
       return;
@@ -593,17 +600,17 @@ var gViewController = {
 
     if (!view.type || !(view.type in this.viewObjects))
       throw new Error("Invalid view: " + view.type);
 
     var viewObj = this.viewObjects[view.type];
     if (!viewObj.node)
       throw new Error("Root node doesn't exist for '" + view.type + "' view");
 
-    if (this.currentViewObj) {
+    if (this.currentViewObj && aViewId != aPreviousView) {
       try {
         let canHide = this.currentViewObj.hide();
         if (canHide === false)
           return;
         this.viewPort.selectedPanel.removeAttribute("loading");
       } catch (e) {
         // this shouldn't be fatal
         Cu.reportError(e);
@@ -612,17 +619,21 @@ var gViewController = {
 
     gCategories.select(aViewId, aPreviousView);
 
     this.currentViewId = aViewId;
     this.currentViewObj = viewObj;
 
     this.viewPort.selectedPanel = this.currentViewObj.node;
     this.viewPort.selectedPanel.setAttribute("loading", "true");
-    this.currentViewObj.show(view.param, ++this.currentViewRequest, aState);
+
+    if (aViewId == aPreviousView)
+      this.currentViewObj.refresh(view.param, ++this.currentViewRequest, aState);
+    else
+      this.currentViewObj.show(view.param, ++this.currentViewRequest, aState);
   },
 
   // Moves back in the document history and removes the current history entry
   popState: function(aCallback) {
     this.viewChangeCallback = aCallback;
     gHistory.popState();
   },
 
@@ -1399,17 +1410,25 @@ var gCategories = {
   node: null,
   _search: null,
   _maybeHidden: null,
 
   initialize: function() {
     this.node = document.getElementById("categories");
     this._search = this.get("addons://search/");
 
-    this.maybeHideSearch();
+    try {
+      this.node.value = Services.prefs.getCharPref(PREF_UI_LASTCATEGORY);
+    } catch (e) { }
+
+    // If there was no last view or no existing category matched the last view
+    // then the list will default to selecting the search category and we never
+    // want to show that as the first view so switch to the default category
+    if (this.node.selectedItem == this._search)
+      this.node.value = VIEW_DEFAULT;
 
     var self = this;
     this.node.addEventListener("select", function() {
       self.maybeHideSearch();
       gViewController.loadView(self.node.selectedItem.value);
     }, false);
 
     this.node.addEventListener("click", function(aEvent) {
@@ -1490,16 +1509,18 @@ var gCategories = {
 
   select: function(aId, aPreviousView) {
     var view = gViewController.parseViewId(aId);
     if (view.type == "detail" && aPreviousView) {
       aId = aPreviousView;
       view = gViewController.parseViewId(aPreviousView);
     }
 
+    Services.prefs.setCharPref(PREF_UI_LASTCATEGORY, aId);
+
     if (this.node.selectedItem &&
         this.node.selectedItem.value == aId) {
       this.node.selectedItem.hidden = false;
       this.node.selectedItem.disabled = false;
       return;
     }
 
     if (view.type == "search")
@@ -1509,18 +1530,16 @@ var gCategories = {
 
     if (item) {
       item.hidden = false;
       item.disabled = false;
       this.node.suppressOnSelect = true;
       this.node.selectedItem = item;
       this.node.suppressOnSelect = false;
       this.node.ensureElementIsVisible(item);
-      // When supressing onselect last-selected doesn't get updated
-      this.node.setAttribute("last-selected", item.id);
 
       this.maybeHideSearch();
     }
   },
 
   get: function(aId) {
     var items = document.getElementsByAttribute("value", aId);
     if (items.length)
@@ -1650,17 +1669,17 @@ var gDiscoverView = {
         return;
       }
 
       self._browser.homePage = self.homepageURL.spec;
       self._browser.addProgressListener(self, Ci.nsIWebProgress.NOTIFY_ALL |
                                               Ci.nsIWebProgress.NOTIFY_STATE_ALL);
 
       if (self.loaded)
-        self._loadURL(self.homepageURL.spec, notifyInitialized);
+        self._loadURL(self.homepageURL.spec, false, notifyInitialized);
       else
         notifyInitialized();
     }
 
     if (Services.prefs.getBoolPref(PREF_GETADDONS_CACHE_ENABLED) == false) {
       setURL(url);
       return;
     }
@@ -1684,63 +1703,79 @@ var gDiscoverView = {
           isBlocklisted: aAddon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED
         }
       });
 
       setURL(url + "#" + JSON.stringify(list));
     });
   },
 
-  show: function(aParam, aRequest, aState) {
+  show: function(aParam, aRequest, aState, aIsRefresh) {
     gViewController.updateCommands();
 
     // If we're being told to load a specific URL then just do that
     if (aState && "url" in aState) {
       this.loaded = true;
       this._loadURL(aState.url);
     }
 
-    // If the view has loaded before and the error page is not visible then
-    // there is nothing else to do
-    if (this.loaded && this.node.selectedPanel != this._error) {
+    // If the view has loaded before and still at the homepage (if refreshing),
+    // and the error page is not visible then there is nothing else to do
+    if (this.loaded && this.node.selectedPanel != this._error &&
+        (!aIsRefresh || (this._browser.currentURI &&
+         this._browser.currentURI.spec == this._browser.homePage))) {
       gViewController.notifyViewChanged();
       return;
     }
 
     this.loaded = true;
 
     // No homepage means initialization isn't complete, the browser will get
     // loaded once initialization is complete
     if (!this.homepageURL) {
       this._loadListeners.push(gViewController.notifyViewChanged.bind(gViewController));
       return;
     }
 
-    this._loadURL(this.homepageURL.spec,
+    this._loadURL(this.homepageURL.spec, aIsRefresh,
                   gViewController.notifyViewChanged.bind(gViewController));
   },
+  
+  canRefresh: function() {
+    if (this._browser.currentURI &&
+        this._browser.currentURI.spec == this._browser.homePage)
+      return false;
+    return true;
+  },
+
+  refresh: function(aParam, aRequest, aState) {
+    this.show(aParam, aRequest, aState, true);
+  },
 
   hide: function() { },
 
   showError: function() {
     this.node.selectedPanel = this._error;
   },
 
-  _loadURL: function(aURL, aCallback) {
+  _loadURL: function(aURL, aKeepHistory, aCallback) {
     if (this._browser.currentURI.spec == aURL) {
       if (aCallback)
         aCallback();
       return;
     }
 
     if (aCallback)
       this._loadListeners.push(aCallback);
 
-    this._browser.loadURIWithFlags(aURL,
-                                   Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY);
+    var flags = 0;
+    if (!aKeepHistory)
+      flags |= Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
+
+    this._browser.loadURIWithFlags(aURL, flags);
   },
 
   onLocationChange: function(aWebProgress, aRequest, aLocation) {
     // Ignore the about:blank load
     if (aLocation.spec == "about:blank")
       return;
 
     // When using the real session history the inner-frame will update the
--- a/toolkit/mozapps/extensions/content/extensions.xul
+++ b/toolkit/mozapps/extensions/content/extensions.xul
@@ -202,17 +202,17 @@
     </toolbarbutton>
     <textbox id="header-search" type="search" searchbutton="true"
              placeholder="&search.placeholder;"/>
   </hbox>
 
   <hbox flex="1">
 
     <!-- category list -->
-    <richlistbox id="categories" persist="last-selected">
+    <richlistbox id="categories">
       <richlistitem id="category-search" value="addons://search/"
                     class="category"
                     name="&view.search.label;"
                     tooltiptext="&view.search.label;" disabled="true"/>
       <richlistitem id="category-discover" value="addons://discover/"
                     class="category"
                     name="&view.discover.label;"
                     tooltiptext="&view.discover.label;"/>
--- a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js
@@ -839,8 +839,68 @@ add_test(function() {
           is_element_hidden(doc.getElementById("forward-btn"), "Forward button should be hidden");
         }
 
         close_manager(aManager, run_next_test);
       });
     });
   }, true);
 });
+
+// Tests that refreshing the disicovery pane integrates properly with history
+add_test(function() {
+  open_manager("addons://list/plugin", function(aManager) {
+    is_in_list(aManager, "addons://list/plugin", false, false);
+
+    EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-discover"), { }, aManager);
+
+    wait_for_view_load(aManager, function(aManager) {
+      is_in_discovery(aManager, MAIN_URL, true, false);
+
+      clickLink(aManager, "link-good", function() {
+        is_in_discovery(aManager, SECOND_URL, true, false);
+
+        EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-discover"), { }, aManager);
+        
+        waitForLoad(aManager, function() {
+          is_in_discovery(aManager, MAIN_URL, true, false);
+
+          go_back(aManager);
+
+          waitForLoad(aManager, function() {
+            is_in_discovery(aManager, SECOND_URL, true, true);
+
+            go_back(aManager);
+
+            waitForLoad(aManager, function() {
+              is_in_discovery(aManager, MAIN_URL, true, true);
+
+              go_back(aManager);
+
+              wait_for_view_load(aManager, function(aManager) {
+                is_in_list(aManager, "addons://list/plugin", false, true);
+
+                go_forward(aManager);
+
+                wait_for_view_load(aManager, function(aManager) {
+                  is_in_discovery(aManager, MAIN_URL, true, true);
+
+                  waitForLoad(aManager, function() {
+                    is_in_discovery(aManager, SECOND_URL, true, true);
+
+                    waitForLoad(aManager, function() {
+                      is_in_discovery(aManager, MAIN_URL, true, false);
+
+                      close_manager(aManager, run_next_test);
+                    });
+                    go_forward(aManager);
+                  });
+
+                  go_forward(aManager);
+                });
+              });
+            });
+          });
+        });
+      });
+    });
+  });
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_discovery.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_discovery.js
@@ -405,17 +405,17 @@ add_test(function() {
     var browser = gManagerWindow.document.getElementById("discover-browser");
     is(getURL(browser), MAIN_URL, "Should have loaded the right url");
 
     clickLink("link-good", function() {
       is(getURL(browser), "https://example.com/" + RELATIVE_DIR + "releaseNotes.xhtml", "Should have loaded the right url");
 
       gCategoryUtilities.openType("extension", function() {
         gCategoryUtilities.openType("discover", function() {
-          is(getURL(browser), "https://example.com/" + RELATIVE_DIR + "releaseNotes.xhtml", "Should have loaded the right url");
+          is(getURL(browser), MAIN_URL, "Should have loaded the right url");
 
           close_manager(gManagerWindow, run_next_test);
         });
       });
     });
   });
 });
 
--- a/toolkit/mozapps/extensions/test/browser/browser_searching.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_searching.js
@@ -590,16 +590,19 @@ add_test(function() {
 });
 
 // Tests that restarting the manager doesn't change search results
 add_test(function() {
   restart_manager(gManagerWindow, null, function(aWindow) {
     gManagerWindow = aWindow;
     gCategoryUtilities = new CategoryUtilities(gManagerWindow);
 
+    // We never restore to the search pane
+    is(gCategoryUtilities.selectedCategory, "discover", "View should have changed to discover");
+
     // Installed add-on is considered local on new search
     gAddonInstalled = true;
 
     search(QUERY, false, function() {
       check_filtered_results(QUERY, "relevancescore", false);
 
       var installBtn = get_install_button(get_addon_item(REMOTE_TO_INSTALL));
       is(installBtn.hidden, true, "Install button should be hidden for installed item");
--- a/toolkit/mozapps/extensions/test/xpcshell/test_install.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js
@@ -1538,23 +1538,84 @@ function run_test_26() {
           aSubtype != AM_Ci.nsIHttpActivityObserver.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE)
         return;
 
       // Request should have been cancelled
       do_check_eq(aChannel.status, Components.results.NS_BINDING_ABORTED);
 
       observerService.removeObserver(this);
 
-      do_test_finished();
+      run_test_27();
     }
   });
 
   let url = "http://localhost:4444/redirect?/addons/test_install1.xpi";
   AddonManager.getInstallForURL(url, function(aInstall) {
     aInstall.addListener({
       onDownloadProgress: function(aInstall) {
         aInstall.cancel();
       }
     });
 
     aInstall.install();
   }, "application/x-xpinstall");
 }
+
+
+// Tests that an install can be restarted during onDownloadCancelled after being
+// cancelled in mid-download
+function run_test_27() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install3.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    ensure_test_completed();
+
+    do_check_neq(aInstall, null);
+    do_check_eq(aInstall.state, AddonManager.STATE_AVAILABLE);
+
+    aInstall.addListener({
+      onDownloadProgress: function() {
+        aInstall.removeListener(this);
+        aInstall.cancel();
+      }
+    });
+
+    prepare_test({}, [
+      "onDownloadStarted",
+      "onDownloadCancelled",
+    ], check_test_27);
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+function check_test_27(aInstall) {
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onInstalling"
+    ]
+  }, [
+    "onDownloadStarted",
+    "onDownloadEnded",
+    "onInstallStarted",
+    "onInstallEnded"
+  ], finish_test_27);
+
+  aInstall.install();
+}
+
+function finish_test_27(aInstall) {
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onOperationCancelled"
+    ]
+  }, [
+    "onInstallCancelled"
+  ]);
+
+  aInstall.cancel();
+
+  ensure_test_completed();
+
+  do_test_finished();
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/xre/EventTracer.cpp
@@ -0,0 +1,189 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ted Mielczarek <ted.mielczarek@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 ***** */
+
+/*
+ * Event loop instrumentation. This code attempts to measure the
+ * latency of the UI-thread event loop by firing native events at it from
+ * a background thread, and measuring how long it takes for them
+ * to be serviced. The measurement interval (kMeasureInterval, below)
+ * is also used as the upper bound of acceptable response time.
+ * When an event takes longer than that interval to be serviced,
+ * a sample will be written to the log.
+ *
+ * Usage:
+ *
+ * Set MOZ_INSTRUMENT_EVENT_LOOP=1 in the environment to enable
+ * this instrumentation. Currently only the UI process is instrumented.
+ *
+ * Set MOZ_INSTRUMENT_EVENT_LOOP_OUTPUT in the environment to a
+ * file path to contain the log output, the default is to log to stdout.
+ *
+ * All logged output lines start with MOZ_EVENT_TRACE. All timestamps
+ * output are milliseconds since the epoch (PRTime / 1000).
+ *
+ * On startup, a line of the form:
+ *   MOZ_EVENT_TRACE start <timestamp>
+ * will be output.
+ *
+ * On shutdown, a line of the form:
+ *   MOZ_EVENT_TRACE stop <timestamp>
+ * will be output.
+ *
+ * When an event servicing time exceeds the threshold, a line of the form:
+ *   MOZ_EVENT_TRACE sample <timestamp> <duration>
+ * will be output, where <duration> is the number of milliseconds that
+ * it took for the event to be serviced.
+ */
+
+#include "EventTracer.h"
+
+#include <stdio.h>
+
+#include "mozilla/TimeStamp.h"
+#include "mozilla/WidgetTraceEvent.h"
+#include <prenv.h>
+#include <prinrval.h>
+#include <prthread.h>
+#include <prtime.h>
+
+using mozilla::TimeDuration;
+using mozilla::TimeStamp;
+using mozilla::FireAndWaitForTracerEvent;
+
+namespace {
+
+PRThread* sTracerThread = NULL;
+bool sExit = false;
+
+/*
+ * The tracer thread fires events at the native event loop roughly
+ * every kMeasureInterval. It will sleep to attempt not to send them
+ * more quickly, but if the response time is longer than kMeasureInterval
+ * it will not send another event until the previous response is received.
+ *
+ * The output defaults to stdout, but can be redirected to a file by
+ * settting the environment variable MOZ_INSTRUMENT_EVENT_LOOP_OUTPUT
+ * to the name of a file to use.
+ */
+void TracerThread(void *arg)
+{
+  // This should be set to the maximum latency we'd like to allow
+  // for responsiveness.
+  const PRIntervalTime kMeasureInterval = PR_MillisecondsToInterval(50);
+
+  FILE* log = NULL;
+  char* envfile = PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP_OUTPUT");
+  if (envfile) {
+    log = fopen(envfile, "w");
+  }
+  if (log == NULL)
+    log = stdout;
+
+  fprintf(log, "MOZ_EVENT_TRACE start %llu\n", PR_Now() / PR_USEC_PER_MSEC);
+
+  while (!sExit) {
+    TimeStamp start(TimeStamp::Now());
+    PRIntervalTime next_sleep = kMeasureInterval;
+
+    //TODO: only wait up to a maximum of kMeasureInterval, return
+    // early if that threshold is exceeded and dump a stack trace
+    // or do something else useful.
+    if (FireAndWaitForTracerEvent()) {
+      TimeDuration duration = TimeStamp::Now() - start;
+      // Only report samples that exceed our measurement interval.
+      if (duration.ToMilliseconds() > kMeasureInterval) {
+        fprintf(log, "MOZ_EVENT_TRACE sample %llu %d\n",
+                PR_Now() / PR_USEC_PER_MSEC,
+                int(duration.ToSecondsSigDigits() * 1000));
+      }
+
+      if (next_sleep > duration.ToMilliseconds()) {
+        next_sleep -= int(duration.ToMilliseconds());
+      }
+      else {
+        // Don't sleep at all if this event took longer than the measure
+        // interval to deliver.
+        next_sleep = 0;
+      }
+    }
+
+    if (next_sleep != 0 && !sExit) {
+      PR_Sleep(next_sleep);
+    }
+  }
+
+  fprintf(log, "MOZ_EVENT_TRACE stop %llu\n", PR_Now() / PR_USEC_PER_MSEC);
+
+  if (log != stdout)
+    fclose(log);
+}
+
+} // namespace
+
+namespace mozilla {
+
+bool InitEventTracing()
+{
+  // Initialize the widget backend.
+  if (!InitWidgetTracing())
+    return false;
+
+  // Create a thread that will fire events back at the
+  // main thread to measure responsiveness.
+  NS_ABORT_IF_FALSE(!sTracerThread, "Event tracing already initialized!");
+  sTracerThread = PR_CreateThread(PR_USER_THREAD,
+                                  TracerThread,
+                                  NULL,
+                                  PR_PRIORITY_NORMAL,
+                                  PR_GLOBAL_THREAD,
+                                  PR_JOINABLE_THREAD,
+                                  0);
+  return sTracerThread != NULL;
+}
+
+void ShutdownEventTracing()
+{
+  sExit = true;
+  if (sTracerThread)
+    PR_JoinThread(sTracerThread);
+  sTracerThread = NULL;
+
+  // Allow the widget backend to clean up.
+  CleanUpWidgetTracing();
+}
+
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/toolkit/xre/EventTracer.h
@@ -0,0 +1,54 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ted Mielczarek <ted.mielczarek@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 XRE_EVENTTRACER_H_
+#define XRE_EVENTTRACER_H_
+
+namespace mozilla {
+
+// Create a thread that will fire events back at the
+// main thread to measure responsiveness. Return true
+// if the thread was created successfully.
+bool InitEventTracing();
+
+// Signal the background thread to stop, and join it.
+// Must be called from the same thread that called InitEventTracing.
+void ShutdownEventTracing();
+
+}  // namespace mozilla
+
+#endif /* XRE_EVENTTRACER_H_ */
--- a/toolkit/xre/MacApplicationDelegate.mm
+++ b/toolkit/xre/MacApplicationDelegate.mm
@@ -83,41 +83,43 @@ private:
 @interface MacApplicationDelegate : NSObject
 {
 }
 
 @end
 
 static PRBool sProcessedGetURLEvent = PR_FALSE;
 
+@class GeckoNSApplication;
+
 // Methods that can be called from non-Objective-C code.
 
 // This is needed, on relaunch, to force the OS to use the "Cocoa Dock API"
 // instead of the "Carbon Dock API".  For more info see bmo bug 377166.
 void
 EnsureUseCocoaDockAPI()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
-  [NSApplication sharedApplication];
+  [GeckoNSApplication sharedApplication];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 void
 SetupMacApplicationDelegate()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   // this is called during startup, outside an event loop, and therefore
   // needs an autorelease pool to avoid cocoa object leakage (bug 559075)
   AutoAutoreleasePool pool;
 
   // Ensure that ProcessPendingGetURLAppleEvents() doesn't regress bug 377166.
-  [NSApplication sharedApplication];
+  [GeckoNSApplication sharedApplication];
 
   // This call makes it so that application:openFile: doesn't get bogus calls
   // from Cocoa doing its own parsing of the argument string. And yes, we need
   // to use a string with a boolean value in it. That's just how it works.
   [[NSUserDefaults standardUserDefaults] setObject:@"NO"
                                             forKey:@"NSTreatUnknownArgumentsAsOpen"];
 
   // Create the delegate. This should be around for the lifetime of the app.
--- a/toolkit/xre/Makefile.in
+++ b/toolkit/xre/Makefile.in
@@ -61,16 +61,20 @@ CPPSRCS = \
   nsAppRunner.cpp \
   nsConsoleWriter.cpp \
   nsXREDirProvider.cpp \
   nsNativeAppSupportBase.cpp \
   nsAppData.cpp \
   nsSigHandlers.cpp \
   $(NULL)
 
+ifdef MOZ_INSTRUMENT_EVENT_LOOP
+CPPSRCS += EventTracer.cpp
+endif
+
 ifdef MOZ_SPLASHSCREEN
 ifeq ($(OS_ARCH),WINCE)
 CPPSRCS += nsSplashScreenWin.cpp
 else
 CPPSRCS += nsSplashScreenDummy.cpp
 endif
 endif
 
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -57,16 +57,20 @@
 #endif // MOZ_WIDGET_QT
 
 #include "mozilla/dom/ContentParent.h"
 using mozilla::dom::ContentParent;
 
 #include "nsAppRunner.h"
 #include "nsUpdateDriver.h"
 
+#ifdef MOZ_INSTRUMENT_EVENT_LOOP
+#include "EventTracer.h"
+#endif
+
 #ifdef XP_MACOSX
 #include "MacLaunchHelper.h"
 #include "MacApplicationDelegate.h"
 #include "MacAutoreleasePool.h"
 #endif
 
 #ifdef XP_OS2
 #include "private/pprthred.h"
@@ -3739,16 +3743,23 @@ XRE_main(int argc, char* argv[], const n
           if (remoteService)
             remoteService->Startup(gAppData->name,
                                    PromiseFlatCString(profileName).get());
 #endif /* MOZ_ENABLE_XREMOTE */
 
           nativeApp->Enable();
         }
 
+#ifdef MOZ_INSTRUMENT_EVENT_LOOP
+        bool event_tracing_running = false;
+        if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP")) {
+          event_tracing_running = mozilla::InitEventTracing();
+        }
+#endif /* MOZ_INSTRUMENT_EVENT_LOOP */
+
         NS_TIME_FUNCTION_MARK("Next: Run");
 
         NS_TIME_FUNCTION_MARK("appStartup->Run");
 
         MOZ_SPLASHSCREEN_UPDATE(90);
         {
           NS_TIMELINE_ENTER("appStartup->Run");
           rv = appStartup->Run();
@@ -3758,16 +3769,21 @@ XRE_main(int argc, char* argv[], const n
             gLogConsoleErrors = PR_TRUE;
           }
         }
 
         NS_TIME_FUNCTION_MARK("Next: Finish");
 
         NS_TIME_FUNCTION_MARK("appStartup->Run done");
 
+#ifdef MOZ_INSTRUMENT_EVENT_LOOP
+        if (event_tracing_running)
+          mozilla::ShutdownEventTracing();
+#endif
+
         // Check for an application initiated restart.  This is one that
         // corresponds to nsIAppStartup.quit(eRestart)
         if (rv == NS_SUCCESS_RESTART_APP)
           appInitiatedRestart = PR_TRUE;
 
         if (!shuttingDown) {
 #ifdef MOZ_ENABLE_XREMOTE
           // shut down the x remote proxy window
--- a/widget/public/Makefile.in
+++ b/widget/public/Makefile.in
@@ -47,16 +47,22 @@ XPIDL_MODULE	= widget
 GRE_MODULE	= 1
 
 EXPORTS_NAMESPACES = IPC
 
 EXPORTS_IPC = \
 		nsGUIEventIPC.h \
 		$(NULL)
 
+ifdef MOZ_INSTRUMENT_EVENT_LOOP
+EXPORTS_NAMESPACES += mozilla
+EXPORTS_mozilla = \
+  WidgetTraceEvent.h
+endif
+
 EXPORTS		= \
 		nsIWidget.h \
 		nsGUIEvent.h \
 		nsEvent.h \
 		nsNativeWidget.h \
 		nsWidgetInitData.h \
 		nsWidgetsCID.h \
 		nsILookAndFeel.h \
new file mode 100644
--- /dev/null
+++ b/widget/public/WidgetTraceEvent.h
@@ -0,0 +1,60 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ted Mielczarek <ted.mielczarek@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 WIDGET_PUBLIC_WIDGETTRACEEVENT_H_
+#define WIDGET_PUBLIC_WIDGETTRACEEVENT_H_
+
+namespace mozilla {
+
+// Perform any required initialization in the widget backend for
+// event tracing. Return true if initialization was successful.
+bool InitWidgetTracing();
+
+// Perform any required cleanup in the widget backend for event tracing.
+void CleanUpWidgetTracing();
+
+// Fire a tracer event at the UI-thread event loop, and block until
+// the event is processed. This should only be called by
+// a thread that's not the UI thread.
+bool FireAndWaitForTracerEvent();
+
+// Signal that the event has been received by the event loop.
+void SignalTracerThread();
+
+}
+
+#endif  // WIDGET_PUBLIC_WIDGETTRACEEVENT_H_
new file mode 100644
--- /dev/null
+++ b/widget/src/cocoa/CustomCocoaEvents.h
@@ -0,0 +1,51 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ted Mielczarek <ted.mielczarek@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 ***** */
+
+/*
+ * This file defines constants to be used in the "subtype" field of
+ * NSApplicationDefined type NSEvents.
+ */
+
+#ifndef WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_
+#define WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_
+
+// Empty event, just used for prodding the event loop into responding.
+const short kEventSubtypeNone = 0;
+// Tracer event, used for timing the event loop responsiveness.
+const short kEventSubtypeTrace = 1;
+
+#endif /* WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_ */
--- a/widget/src/cocoa/Makefile.in
+++ b/widget/src/cocoa/Makefile.in
@@ -55,50 +55,51 @@ LIBXUL_LIBRARY = 1
 
 EXPORTS = \
 		mozView.h \
 		nsChangeObserver.h \
 		nsCocoaUtils.h \
 		$(NULL)
 
 CMMSRCS = \
-		nsBidiKeyboard.mm \
-		nsClipboard.mm \
-		nsMenuX.mm \
-		nsMenuBarX.mm \
-		nsMenuItemX.mm \
-		nsMenuItemIconX.mm \
-		nsMenuUtilsX.mm \
-		nsMenuGroupOwnerX.mm \
-		nsFilePicker.mm \
-		nsDragService.mm \
-		nsToolkit.mm \
-		nsAppShell.mm \
-		nsCocoaUtils.mm \
-		nsCocoaWindow.mm \
-		nsChildView.mm \
-		nsWindowMap.mm \
-		nsWidgetFactory.mm \
-		nsCursorManager.mm \
-		nsMacCursor.mm \
-		nsScreenCocoa.mm \
-		nsScreenManagerCocoa.mm \
-		nsSound.mm \
-		nsLookAndFeel.mm \
-		nsNativeThemeCocoa.mm \
-		nsDeviceContextSpecX.mm \
-		nsPrintDialogX.mm \
-		nsPrintOptionsX.mm \
-		nsPrintSettingsX.mm \
-		nsIdleServiceX.mm \
-		nsCocoaTextInputHandler.mm \
-		nsMacDockSupport.mm \
-		nsStandaloneNativeMenu.mm \
-		GfxInfo.mm \
-		$(NULL)
+  nsBidiKeyboard.mm \
+  nsClipboard.mm \
+  nsMenuX.mm \
+  nsMenuBarX.mm \
+  nsMenuItemX.mm \
+  nsMenuItemIconX.mm \
+  nsMenuUtilsX.mm \
+  nsMenuGroupOwnerX.mm \
+  nsFilePicker.mm \
+  nsDragService.mm \
+  nsToolkit.mm \
+  nsAppShell.mm \
+  nsCocoaUtils.mm \
+  nsCocoaWindow.mm \
+  nsChildView.mm \
+  nsWindowMap.mm \
+  nsWidgetFactory.mm \
+  nsCursorManager.mm \
+  nsMacCursor.mm \
+  nsScreenCocoa.mm \
+  nsScreenManagerCocoa.mm \
+  nsSound.mm \
+  nsLookAndFeel.mm \
+  nsNativeThemeCocoa.mm \
+  nsDeviceContextSpecX.mm \
+  nsPrintDialogX.mm \
+  nsPrintOptionsX.mm \
+  nsPrintSettingsX.mm \
+  nsIdleServiceX.mm \
+  nsCocoaTextInputHandler.mm \
+  nsMacDockSupport.mm \
+  nsStandaloneNativeMenu.mm \
+  GfxInfo.mm \
+  WidgetTraceEvent.mm \
+  $(NULL)
 
 ifeq (x86_64,$(TARGET_CPU))
 CMMSRCS += ComplexTextInputPanel.mm
 endif
 
 XPIDLSRCS	+= \
 		nsPIWidgetCocoa.idl \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/widget/src/cocoa/WidgetTraceEvent.mm
@@ -0,0 +1,110 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ted Mielczarek <ted.mielczarek@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 <Cocoa/Cocoa.h>
+#include "CustomCocoaEvents.h"
+#include <Foundation/NSAutoreleasePool.h>
+#include <mozilla/CondVar.h>
+#include <mozilla/Mutex.h>
+#include "mozilla/WidgetTraceEvent.h"
+
+using mozilla::CondVar;
+using mozilla::Mutex;
+using mozilla::MutexAutoLock;
+
+namespace {
+
+Mutex* sMutex = NULL;
+CondVar* sCondVar = NULL;
+bool sTracerProcessed = false;
+
+}
+
+namespace mozilla {
+
+bool InitWidgetTracing()
+{
+  sMutex = new Mutex("Event tracer thread mutex");
+  sCondVar = new CondVar(*sMutex, "Event tracer thread condvar");
+  return sMutex && sCondVar;
+}
+
+void CleanUpWidgetTracing()
+{
+  delete sMutex;
+  delete sCondVar;
+  sMutex = NULL;
+  sCondVar = NULL;
+}
+
+// This function is called from the main (UI) thread.
+void SignalTracerThread()
+{
+  MutexAutoLock lock(*sMutex);
+  NS_ABORT_IF_FALSE(!sTracerProcessed, "Tracer synchronization state is wrong");
+  sTracerProcessed = true;
+  sCondVar->Notify();
+}
+
+// This function is called from the background tracer thread.
+bool FireAndWaitForTracerEvent()
+{
+  NS_ABORT_IF_FALSE(sMutex && sCondVar, "Tracing not initialized!");
+  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+  MutexAutoLock lock(*sMutex);
+  NS_ABORT_IF_FALSE(!sTracerProcessed, "Tracer synchronization state is wrong");
+
+  // Post an application-defined event to the main thread's event queue
+  // and wait for it to get processed.
+  [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
+                                      location:NSMakePoint(0,0)
+                                 modifierFlags:0
+                                     timestamp:0
+                                  windowNumber:0
+                                       context:NULL
+                                       subtype:kEventSubtypeTrace
+                                         data1:0
+                                         data2:0]
+             atStart:NO];
+  while (!sTracerProcessed)
+    sCondVar->Wait();
+  sTracerProcessed = false;
+  [pool release];
+  return true;
+}
+
+}  // namespace mozilla
--- a/widget/src/cocoa/nsAppShell.mm
+++ b/widget/src/cocoa/nsAppShell.mm
@@ -38,16 +38,18 @@
 /*
  * Runs the main native Cocoa run loop, interrupting it as needed to process
  * Gecko events.
  */
 
 #import <Cocoa/Cocoa.h>
 #include <dlfcn.h>
 
+#include "CustomCocoaEvents.h"
+#include "mozilla/WidgetTraceEvent.h"
 #include "nsAppShell.h"
 #include "nsCOMPtr.h"
 #include "nsIFile.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsString.h"
 #include "nsIRollupListener.h"
 #include "nsIWidget.h"
 #include "nsThreadUtils.h"
@@ -164,16 +166,37 @@ PRBool nsCocoaAppModalWindowList::GeckoM
   if (mList.IsEmpty())
     return PR_FALSE;
 
   nsCocoaAppModalWindowListItem &topItem = mList.ElementAt(mList.Length() - 1);
 
   return (topItem.mWidget != nsnull);
 }
 
+// GeckoNSApplication
+//
+// Subclass of NSApplication for filtering out certain events.
+@interface GeckoNSApplication : NSApplication
+{
+}
+@end
+
+@implementation GeckoNSApplication
+- (void)sendEvent:(NSEvent *)anEvent
+{
+  if ([anEvent type] == NSApplicationDefined &&
+      [anEvent subtype] == kEventSubtypeTrace) {
+    mozilla::SignalTracerThread();
+    return;
+  }
+  [super sendEvent:anEvent];
+}
+@end
+
+
 // AppShellDelegate
 //
 // Cocoa bridge class.  An object of this class is registered to receive
 // notifications.
 //
 @interface AppShellDelegate : NSObject
 {
   @private
@@ -281,17 +304,17 @@ nsAppShell::Init()
   // 1) we're using xre -- NSApp's already been initialized by
   //    MacApplicationDelegate.mm's EnsureUseCocoaDockAPI().
   // 2) Camino is running (or another embedding app that uses
   //    NSApplicationMain()) -- NSApp's already been initialized and
   //    its main run loop is already running.
   [NSBundle loadNibFile:
                      [NSString stringWithUTF8String:(const char*)nibPath.get()]
       externalNameTable:
-           [NSDictionary dictionaryWithObject:[NSApplication sharedApplication]
+           [NSDictionary dictionaryWithObject:[GeckoNSApplication sharedApplication]
                                        forKey:@"NSOwner"]
                withZone:NSDefaultMallocZone()];
 
   mDelegate = [[AppShellDelegate alloc] initWithAppShell:this];
   NS_ENSURE_STATE(mDelegate);
 
   // Add a CFRunLoopSource to the main native run loop.  The source is
   // responsible for interrupting the run loop when Gecko events are ready.
@@ -383,17 +406,17 @@ nsAppShell::ProcessGeckoEvents(void* aIn
     // seems to prevent the OS from ever trying to associate our bogus event
     // with a particular NSWindow object.
     [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
                                         location:NSMakePoint(0,0)
                                    modifierFlags:0
                                        timestamp:0
                                     windowNumber:0
                                          context:NULL
-                                         subtype:0
+                                         subtype:kEventSubtypeNone
                                            data1:0
                                            data2:0]
              atStart:NO];
   }
 
   if (self->mSuspendNativeCount <= 0) {
     ++self->mNativeEventCallbackDepth;
     self->NativeEventCallback();
@@ -405,17 +428,17 @@ nsAppShell::ProcessGeckoEvents(void* aIn
   // Still needed to fix bug 343033 ("5-10 second delay or hang or crash
   // when quitting Cocoa Firefox").
   [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
                                       location:NSMakePoint(0,0)
                                  modifierFlags:0
                                      timestamp:0
                                   windowNumber:0
                                        context:NULL
-                                       subtype:0
+                                       subtype:kEventSubtypeNone
                                          data1:0
                                          data2:0]
            atStart:NO];
 
   // Normally every call to ScheduleNativeEventCallback() results in
   // exactly one call to ProcessGeckoEvents().  So each Release() here
   // normally balances exactly one AddRef() in ScheduleNativeEventCallback().
   // But if Exit() is called just after ScheduleNativeEventCallback(), the
--- a/widget/src/gtk2/Makefile.in
+++ b/widget/src/gtk2/Makefile.in
@@ -57,33 +57,34 @@ NATIVE_THEME_SUPPORT = 1
 CSRCS		= \
 		mozcontainer.c \
 		$(NULL)
 
 ifdef ACCESSIBILITY
 CSRCS += maiRedundantObjectFactory.c
 endif
 
-CPPSRCS		= \
-		nsWindow.cpp \
-		nsAppShell.cpp \
-		nsWidgetFactory.cpp \
-		nsToolkit.cpp \
-		nsBidiKeyboard.cpp \
-		nsLookAndFeel.cpp \
-		nsGtkKeyUtils.cpp \
-		nsFilePicker.cpp \
-		nsSound.cpp \
-		nsNativeKeyBindings.cpp \
-		nsScreenGtk.cpp \
-		nsScreenManagerGtk.cpp \
-		nsImageToPixbuf.cpp \
-		nsAccessibilityHelper.cpp \
-		nsGtkIMModule.cpp \
-		$(NULL)
+CPPSRCS = \
+  nsWindow.cpp \
+  nsAppShell.cpp \
+  nsWidgetFactory.cpp \
+  nsToolkit.cpp \
+  nsBidiKeyboard.cpp \
+  nsLookAndFeel.cpp \
+  nsGtkKeyUtils.cpp \
+  nsFilePicker.cpp \
+  nsSound.cpp \
+  nsNativeKeyBindings.cpp \
+  nsScreenGtk.cpp \
+  nsScreenManagerGtk.cpp \
+  nsImageToPixbuf.cpp \
+  nsAccessibilityHelper.cpp \
+  nsGtkIMModule.cpp \
+  WidgetTraceEvent.cpp \
+  $(NULL)
 
 ifdef MOZ_X11
 CPPSRCS         += nsIdleServiceGTK.cpp
 endif
 
 ifdef NS_PRINTING
 CPPSRCS		+= \
 		nsDeviceContextSpecG.cpp \
new file mode 100644
--- /dev/null
+++ b/widget/src/gtk2/WidgetTraceEvent.cpp
@@ -0,0 +1,103 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ted Mielczarek <ted.mielczarek@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 "mozilla/WidgetTraceEvent.h"
+
+#include <glib.h>
+#include <mozilla/CondVar.h>
+#include <mozilla/Mutex.h>
+#include <stdio.h>
+
+using mozilla::CondVar;
+using mozilla::Mutex;
+using mozilla::MutexAutoLock;
+
+namespace {
+
+Mutex* sMutex = NULL;
+CondVar* sCondVar = NULL;
+bool sTracerProcessed = false;
+
+// This function is called from the main (UI) thread.
+gboolean TracerCallback(gpointer data)
+{
+  MutexAutoLock lock(*sMutex);
+  NS_ABORT_IF_FALSE(!sTracerProcessed, "Tracer synchronization state is wrong");
+  sTracerProcessed = true;
+  sCondVar->Notify();
+  return FALSE;
+}
+
+} // namespace
+
+namespace mozilla {
+
+bool InitWidgetTracing()
+{
+  sMutex = new Mutex("Event tracer thread mutex");
+  sCondVar = new CondVar(*sMutex, "Event tracer thread condvar");
+  return sMutex && sCondVar;
+}
+
+void CleanUpWidgetTracing()
+{
+  delete sMutex;
+  delete sCondVar;
+  sMutex = NULL;
+  sCondVar = NULL;
+}
+
+// This function is called from the background tracer thread.
+bool FireAndWaitForTracerEvent()
+{
+  NS_ABORT_IF_FALSE(sMutex && sCondVar, "Tracing not initialized!");
+
+  // Send a default-priority idle event through the
+  // event loop, and wait for it to finish.
+  MutexAutoLock lock(*sMutex);
+  NS_ABORT_IF_FALSE(!sTracerProcessed, "Tracer synchronization state is wrong");
+  g_idle_add_full(G_PRIORITY_DEFAULT,
+                  TracerCallback,
+                  NULL,
+                  NULL);
+  while (!sTracerProcessed)
+    sCondVar->Wait();
+  sTracerProcessed = false;
+  return true;
+}
+
+}  // namespace mozilla
--- a/widget/src/windows/Makefile.in
+++ b/widget/src/windows/Makefile.in
@@ -42,42 +42,43 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= widget
 LIBRARY_NAME	= widget_windows
 LIBXUL_LIBRARY = 1
 
 
-CPPSRCS		= \
-	nsWindow.cpp \
-	nsWindowGfx.cpp \
-	nsWindowDbg.cpp \
-	nsAppShell.cpp \
-	nsToolkit.cpp \
-	nsFilePicker.cpp \
-	nsScreenWin.cpp	\
-	nsScreenManagerWin.cpp \
-	nsLookAndFeel.cpp \
-	nsUXThemeData.cpp \
-	nsNativeThemeWin.cpp \
-	nsWinGesture.cpp \
-	nsIdleServiceWin.cpp \
-	nsSound.cpp \
-	nsIMM32Handler.cpp \
-	WindowHook.cpp \
-	WinTaskbar.cpp \
-	TaskbarPreview.cpp \
-	TaskbarTabPreview.cpp \
-	TaskbarWindowPreview.cpp \
-	TaskbarPreviewButton.cpp \
- 	JumpListBuilder.cpp \
- 	JumpListItem.cpp \
-	GfxInfo.cpp \
-	$(NULL)
+CPPSRCS = \
+  nsWindow.cpp \
+  nsWindowGfx.cpp \
+  nsWindowDbg.cpp \
+  nsAppShell.cpp \
+  nsToolkit.cpp \
+  nsFilePicker.cpp \
+  nsScreenWin.cpp  \
+  nsScreenManagerWin.cpp \
+  nsLookAndFeel.cpp \
+  nsUXThemeData.cpp \
+  nsNativeThemeWin.cpp \
+  nsWinGesture.cpp \
+  nsIdleServiceWin.cpp \
+  nsSound.cpp \
+  nsIMM32Handler.cpp \
+  WindowHook.cpp \
+  WinTaskbar.cpp \
+  TaskbarPreview.cpp \
+  TaskbarTabPreview.cpp \
+  TaskbarWindowPreview.cpp \
+  TaskbarPreviewButton.cpp \
+  JumpListBuilder.cpp \
+  JumpListItem.cpp \
+  GfxInfo.cpp \
+  WidgetTraceEvent.cpp \
+  $(NULL)
 
 ifdef MOZ_CRASHREPORTER
 CPPSRCS += LSPAnnotator.cpp
 endif
 
 ifdef NS_PRINTING
 CPPSRCS		+= \
 	nsPrintOptionsWin.cpp \
new file mode 100644
--- /dev/null
+++ b/widget/src/windows/WidgetTraceEvent.cpp
@@ -0,0 +1,158 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ted Mielczarek <ted.mielczarek@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 ***** */
+
+/*
+ * Windows widget support for event loop instrumentation.
+ * See toolkit/xre/EventTracer.cpp for more details.
+ */
+
+#include <stdio.h>
+#include <windows.h>
+
+#include "mozilla/WidgetTraceEvent.h"
+#include "nsAppShellCID.h"
+#include "nsComponentManagerUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIAppShellService.h"
+#include "nsIBaseWindow.h"
+#include "nsIDocShell.h"
+#include "nsIWidget.h"
+#include "nsIXULWindow.h"
+#include "nsAutoPtr.h"
+#include "nsServiceManagerUtils.h"
+#include "nsThreadUtils.h"
+#include "nsWindowDefs.h"
+
+namespace {
+
+// Used for signaling the background thread from the main thread.
+HANDLE sEventHandle = NULL;
+
+// We need a runnable in order to find the hidden window on the main
+// thread.
+class HWNDGetter : public nsRunnable {
+public:
+  HWNDGetter() : hidden_window_hwnd(NULL) {}
+
+  HWND hidden_window_hwnd;
+
+  NS_IMETHOD Run() {
+    // Jump through some hoops to locate the hidden window.
+    nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
+    nsCOMPtr<nsIXULWindow> hiddenWindow;
+
+    nsresult rv = appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    nsCOMPtr<nsIDocShell> docShell;
+    rv = hiddenWindow->GetDocShell(getter_AddRefs(docShell));
+    if (NS_FAILED(rv) || !docShell) {
+      return rv;
+    }
+
+    nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell));
+    
+    if (!baseWindow)
+      return NS_ERROR_FAILURE;
+
+    nsCOMPtr<nsIWidget> widget;
+    baseWindow->GetMainWidget(getter_AddRefs(widget));
+
+    if (!widget)
+      return NS_ERROR_FAILURE;
+
+    hidden_window_hwnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
+
+    return NS_OK;
+  }
+};
+
+HWND GetHiddenWindowHWND()
+{
+  // Need to dispatch this to the main thread because plenty of
+  // the things it wants to access are main-thread-only.
+  nsRefPtr<HWNDGetter> getter = new HWNDGetter();
+  NS_DispatchToMainThread(getter, NS_DISPATCH_SYNC);
+  return getter->hidden_window_hwnd;
+}
+
+} // namespace
+
+namespace mozilla {
+
+bool InitWidgetTracing()
+{
+  sEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
+  return sEventHandle != NULL;
+}
+
+void CleanUpWidgetTracing()
+{
+  CloseHandle(sEventHandle);
+}
+
+// This function is called from the main (UI) thread.
+void SignalTracerThread()
+{
+  if (sEventHandle != NULL)
+    SetEvent(sEventHandle);
+}
+
+// This function is called from the background tracer thread.
+bool FireAndWaitForTracerEvent()
+{
+  NS_ABORT_IF_FALSE(sEventHandle, "Tracing not initialized!");
+
+  // First, try to find the hidden window.
+  static HWND hidden_window = NULL;
+  if (hidden_window == NULL) {
+    hidden_window = GetHiddenWindowHWND();
+  }
+
+  if (hidden_window == NULL)
+    return false;
+
+  // Post the tracer message into the hidden window's message queue,
+  // and then block until it's processed.
+  PostMessage(hidden_window, MOZ_WM_TRACE, 0, 0);
+  WaitForSingleObject(sEventHandle, INFINITE);
+  return true;
+}
+
+}  // namespace mozilla
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -113,16 +113,17 @@
 #include <commctrl.h>
 #include <unknwn.h>
 
 #include "prlog.h"
 #include "prtime.h"
 #include "prprf.h"
 #include "prmem.h"
 
+#include "mozilla/WidgetTraceEvent.h"
 #include "nsIAppShell.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIDOMNSUIEvent.h"
 #include "nsITheme.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefBranch2.h"
 #include "nsIPrefService.h"
 #include "nsIObserverService.h"
@@ -4594,16 +4595,23 @@ LRESULT CALLBACK nsWindow::WindowProcInt
       hWnd = ::GetParent(::GetParent(hWnd));
     } else {
       // Handle all other messages with its original window procedure.
       WNDPROC prevWindowProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
       return ::CallWindowProcW(prevWindowProc, hWnd, msg, wParam, lParam);
     }
   }
 
+  if (msg == MOZ_WM_TRACE) {
+    // This is a tracer event for measuring event loop latency.
+    // See WidgetTraceEvent.cpp for more details.
+    mozilla::SignalTracerThread();
+    return 0;
+  }
+
   // Get the window which caused the event and ask it to process the message
   nsWindow *someWindow = GetNSWindowPtr(hWnd);
 
   if (someWindow)
     someWindow->IPCWindowProcHandler(msg, wParam, lParam);
 
   // create this here so that we store the last rolled up popup until after
   // the event has been processed.
--- a/widget/src/windows/nsWindowDefs.h
+++ b/widget/src/windows/nsWindowDefs.h
@@ -51,16 +51,18 @@
  *
  * SECTION: defines
  * 
  **************************************************************/
 
 // A magic APP message that can be sent to quit, sort of like a QUERYENDSESSION/ENDSESSION,
 // but without the query.
 #define MOZ_WM_APP_QUIT                   (WM_APP+0x0300)
+// Used as a "tracer" event to probe event loop latency.
+#define MOZ_WM_TRACE                      (WM_APP+0x0301)
 
 // GetWindowsVersion constants
 #define WIN2K_VERSION                     0x500
 #define WINXP_VERSION                     0x501
 #define WIN2K3_VERSION                    0x502
 #define VISTA_VERSION                     0x600
 #define WIN7_VERSION                      0x601
 
--- a/xpcom/glue/nsCycleCollectionParticipant.h
+++ b/xpcom/glue/nsCycleCollectionParticipant.h
@@ -395,16 +395,25 @@ public:
     {                                                                          \
       PRUint32 i, length = (_array).Length();                                  \
       for (i = 0; i < length; ++i)                                             \
         NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR((_array)[i],              \
                                                      _element_class,           \
                                                      _name "[i]");             \
     }
 
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(_field)         \
+    {                                                                          \
+      PRUint32 i, length = tmp->_field.Length();                               \
+      for (i = 0; i < length; ++i) {                                           \
+        NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, #_field "[i]");                 \
+        cb.NoteXPCOMChild(tmp->_field[i].get());                               \
+      }                                                                        \
+    }
+
 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_MEMBER(_field,              \
                                                           _element_class)      \
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(tmp->_field, _element_class,    \
                                                #_field)
 
 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS                       \
     TraverseScriptObjects(tmp, cb);
 
--- a/xpcom/io/SpecialSystemDirectory.cpp
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -676,29 +676,35 @@ GetSpecialSystemDirectory(SystemDirector
 
         case Win_ProgramFiles:
         {
             return GetWindowsFolder(CSIDL_PROGRAM_FILES, aFile);
         }
 
         case Win_HomeDirectory:
         {
+            nsresult rv = GetWindowsFolder(CSIDL_PROFILE, aFile);
+            if (NS_SUCCEEDED(rv))
+                return rv;
+
             PRInt32 len;
             if ((len = ::GetEnvironmentVariableW(L"HOME", path, MAX_PATH)) > 0)
             {
                 // Need enough space to add the trailing backslash
                 if (len > MAX_PATH - 2)
                     break;
 
                 path[len]   = L'\\';
                 path[++len] = L'\0';
 
-                return NS_NewLocalFile(nsDependentString(path, len),
-                                       PR_TRUE,
-                                       aFile);
+                rv = NS_NewLocalFile(nsDependentString(path, len),
+                                     PR_TRUE,
+                                     aFile);
+                if (NS_SUCCEEDED(rv))
+                    return rv;
             }
 
             len = ::GetEnvironmentVariableW(L"HOMEDRIVE", path, MAX_PATH);
             if (0 < len && len < MAX_PATH)
             {
                 WCHAR temp[MAX_PATH];
                 DWORD len2 = ::GetEnvironmentVariableW(L"HOMEPATH", temp, MAX_PATH);
                 if (0 < len2 && len + len2 < MAX_PATH)
new file mode 100644
--- /dev/null
+++ b/xpcom/tests/unit/test_home.js
@@ -0,0 +1,24 @@
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+
+const CWD = do_get_cwd();
+function checkOS(os) {
+  const nsILocalFile_ = "nsILocalFile" + os;
+  return nsILocalFile_ in Components.interfaces &&
+         CWD instanceof Components.interfaces[nsILocalFile_];
+}
+
+const isWin = checkOS("Win");
+
+function run_test() {
+  var envVar = isWin ? "USERPROFILE" : "HOME";
+
+  var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
+  var homeDir = dirSvc.get("Home", Ci.nsIFile);
+
+  var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
+  var expected = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+  expected.initWithPath(env.get(envVar));
+
+  do_check_eq(homeDir.path, expected.path);
+}