Merge with mozilla-central 6f998cc964be
authorDoug Turner <dougt@dougt.org>
Tue, 22 Nov 2011 12:48:22 -0800
changeset 83576 9543a1bb4ca6d4088872366f65d67497bf821fa1
parent 83575 c26b7a14e5bd15ed873e270a456b7f1226fdd036 (current diff)
parent 82276 6f998cc964be237a2fc77b19006a01227837b9c3 (diff)
child 83577 68ad2016a7d0a9b2e9e91bc0715a6e8c43997ef6
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone11.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 with mozilla-central 6f998cc964be
browser/app/application.ini
config/autoconf.mk.in
configure.in
dom/base/nsGlobalWindow.cpp
layout/base/nsPresShell.cpp
layout/generic/nsFrame.cpp
layout/generic/nsSubDocumentFrame.cpp
mobile/android/app/Makefile.in
mobile/android/app/application.ini
mobile/android/app/nsBrowserApp.cpp
mobile/android/base/GeckoApp.java
mobile/android/confvars.sh
mobile/android/installer/removed-files.in
mobile/xul/app/application.ini
toolkit/library/Makefile.in
toolkit/mozapps/installer/packager.mk
toolkit/mozapps/update/nsUpdateService.js
toolkit/xre/Makefile.in
toolkit/xre/nsAndroidStartup.cpp
view/public/nsIViewObserver.h
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -1582,16 +1582,24 @@ nsAccessibleWrap::FirePlatformEvent(AccE
 #ifdef DEBUG_A11Y
   printf("\n\nMSAA event: event: %d, target: %s@id='%s', childid: %d, hwnd: %d\n\n",
          eventType, NS_ConvertUTF16toUTF8(tag).get(), id.get(),
          childID, hWnd);
 #endif
 
   // Fire MSAA event for client area window.
   NotifyWinEvent(winEvent, hWnd, OBJID_CLIENT, childID);
+
+  // JAWS announces collapsed combobox navigation based on focus events.
+  if (nsWinUtils::IsWindowEmulationFor(kJAWSModuleHandle)) {
+    if (eventType == nsIAccessibleEvent::EVENT_SELECTION &&
+      accessible->Role() == nsIAccessibleRole::ROLE_COMBOBOX_OPTION) {
+      NotifyWinEvent(EVENT_OBJECT_FOCUS, hWnd, OBJID_CLIENT, childID);
+    }
+  }
   return NS_OK;
 }
 
 //------- Helper methods ---------
 
 PRInt32 nsAccessibleWrap::GetChildIDFor(nsAccessible* aAccessible)
 {
   // A child ID of the window is required, when we use NotifyWinEvent,
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -56,52 +56,29 @@ PREF_JS_EXPORTS = $(srcdir)/profile/fire
 # hardcode en-US for the moment
 AB_CD = en-US
 
 DEFINES += -DAB_CD=$(AB_CD)
 
 APP_VERSION = $(shell cat $(srcdir)/../config/version.txt)
 DEFINES += -DAPP_VERSION="$(APP_VERSION)"
 
-DIST_FILES = application.ini
-
-GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
-GRE_BUILDID = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build BuildID)
-
-DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DGRE_BUILDID=$(GRE_BUILDID)
-
-MOZ_SOURCE_STAMP ?= $(shell hg -R $(topsrcdir) parent --template="{node|short}\n" 2>/dev/null)
-ifdef MOZ_SOURCE_STAMP
-DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
-endif
-
-SOURCE_REPO := $(shell hg -R $(topsrcdir) showconfig paths.default 2>/dev/null | sed -e "s/^ssh:/http:/")
-ifdef SOURCE_REPO
-DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
-endif
-
-DEFINES += -DMOZ_APP_BASENAME="$(MOZ_APP_BASENAME)" \
-           -DMOZ_APP_VENDOR="$(MOZ_APP_VENDOR)"
-
-ifdef MOZ_APP_PROFILE
-DEFINES += -DMOZ_APP_PROFILE="$(MOZ_APP_PROFILE)"
-endif
-
 ifdef LIBXUL_SDK
 include $(topsrcdir)/config/rules.mk
 else
 # Build a binary bootstrapping with XRE_main
 
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 
 CPPSRCS = nsBrowserApp.cpp
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
+LOCAL_INCLUDES += -I$(DEPTH)/build
 
 DEFINES += -DXPCOM_GLUE
 STL_FLAGS=
 
 LIBS += \
 	$(EXTRA_DSO_LIBS) \
 	$(XPCOM_STANDALONE_GLUE_LDOPTS) \
 	$(NULL)
@@ -182,20 +159,16 @@ libs::
 GARBAGE += $(addprefix $(DIST)/bin/defaults/pref/, firefox.js)
 
 endif
 
 endif # LIBXUL_SDK
 
 DEFINES += -DFIREFOX_ICO=\"$(DIST)/branding/firefox.ico\" -DDOCUMENT_ICO=\"$(DIST)/branding/document.ico\"
 
-ifdef MOZILLA_OFFICIAL
-DEFINES += -DMOZILLA_OFFICIAL
-endif
-
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 libs::
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(DIST)/bin/icons
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default16.png  $(DIST)/bin/chrome/icons/default
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default32.png  $(DIST)/bin/chrome/icons/default
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png  $(DIST)/bin/chrome/icons/default
 endif
 
@@ -223,17 +196,17 @@ clean clobber repackage::
 	$(RM) -r $(DIST)/$(APP_NAME).app
 
 ifdef LIBXUL_SDK
 APPFILES = Resources
 else
 APPFILES = MacOS
 endif
 
-libs repackage:: $(PROGRAM) application.ini
+libs repackage:: $(PROGRAM)
 	$(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/MacOS
 	rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
 	$(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" -e "s/%LOWER_APP_NAME%/$(LOWER_APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
 	sed -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
 	$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -31,18 +31,18 @@
  * 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 "application.ini.h"
 #include "nsXPCOMGlue.h"
-#include "nsXULAppAPI.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
 #elif defined(XP_UNIX)
 #include <sys/time.h>
 #include <sys/resource.h>
 #endif
 
@@ -135,30 +135,17 @@ static const nsDynamicFunctionLoad kXULF
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { nsnull, nsnull }
 };
 
 static int do_main(const char *exePath, int argc, char* argv[])
 {
   nsCOMPtr<nsILocalFile> appini;
-#ifdef XP_WIN
-  // exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
-  // encoded path, so it is safe to convert it
-  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
-                                getter_AddRefs(appini));
-#else
-  nsresult rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
-                                      getter_AddRefs(appini));
-#endif
-  if (NS_FAILED(rv)) {
-    return 255;
-  }
-
-  appini->SetNativeLeafName(NS_LITERAL_CSTRING("application.ini"));
+  nsresult rv;
 
   // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
   // Note that -app must be the *first* argument.
   const char *appDataFile = getenv("XUL_APP_FILE");
   if (appDataFile && *appDataFile) {
     rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
     if (NS_FAILED(rv)) {
       Output("Invalid path found: '%s'", appDataFile);
@@ -183,25 +170,42 @@ static int do_main(const char *exePath, 
       Output("Couldn't set %s.\n", appEnv);
       return 255;
     }
     argv[2] = argv[0];
     argv += 2;
     argc -= 2;
   }
 
-  nsXREAppData *appData;
-  rv = XRE_CreateAppData(appini, &appData);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't read application.ini");
-    return 255;
+  int result;
+  if (appini) {
+    nsXREAppData *appData;
+    rv = XRE_CreateAppData(appini, &appData);
+    if (NS_FAILED(rv)) {
+      Output("Couldn't read application.ini");
+      return 255;
+    }
+    result = XRE_main(argc, argv, appData);
+    XRE_FreeAppData(appData);
+  } else {
+#ifdef XP_WIN
+    // exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
+    // encoded path, so it is safe to convert it
+    rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), PR_FALSE,
+                         getter_AddRefs(appini));
+#else
+    rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_FALSE,
+                               getter_AddRefs(appini));
+#endif
+    if (NS_FAILED(rv)) {
+      return 255;
+    }
+    result = XRE_main(argc, argv, &sAppData);
   }
 
-  int result = XRE_main(argc, argv, appData);
-  XRE_FreeAppData(appData);
   return result;
 }
 
 int main(int argc, char* argv[])
 {
   char exePath[MAXPATHLEN];
 
   nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
@@ -235,16 +239,18 @@ int main(int argc, char* argv[])
   }
 
 
   rv = XPCOMGlueStartup(exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XPCOM.\n");
     return 255;
   }
+  // Reset exePath so that it is the directory name and not the xpcom dll name
+  *lastSlash = 0;
 
   rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XRE functions.\n");
     return 255;
   }
 
 #ifdef XRE_HAS_DLL_BLOCKLIST
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3926,24 +3926,23 @@ var FullScreen = {
       return;
     }
 
     // We receive "mozfullscreenchange" events for each subdocument which
     // is an ancestor of the document containing the element which requested
     // full-screen. Only add listeners and show warning etc when the event we
     // receive is targeted at the chrome document, i.e. only once every time
     // we enter DOM full-screen mode.
-    let targetDoc = event.target.ownerDocument ? event.target.ownerDocument : event.target;
-    if (targetDoc != document) {
+    if (event.target != document) {
       // However, if we receive a "mozfullscreenchange" event for a document
       // which is not a subdocument of the currently selected tab, we know that
       // we've switched tabs since the request to enter full-screen was made,
       // so we should exit full-screen since the "full-screen document" isn't
       // acutally visible.
-      if (targetDoc.defaultView.top != gBrowser.contentWindow) {
+      if (event.target.defaultView.top != gBrowser.contentWindow) {
         document.mozCancelFullScreen();
       }
       return;
     }
 
     let focusManger = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
     if (focusManger.activeWindow != window) {
       // The top-level window has lost focus since the request to enter
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -46,8 +46,12 @@ MOZ_SAFE_BROWSING=1
 MOZ_SERVICES_SYNC=1
 MOZ_APP_VERSION=$FIREFOX_VERSION
 MOZ_EXTENSIONS_DEFAULT=" gnomevfs"
 # MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
 # Changing either of these values requires a clobber to ensure correct results,
 # because branding dependencies are broken.
 MOZ_BRANDING_DIRECTORY=browser/branding/nightly
 MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official
+MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
+MOZ_PROFILE_MIGRATOR=1
+MOZ_EXTENSION_MANAGER=1
+MOZ_APP_STATIC_INI=1
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -21,16 +21,17 @@
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Rob Campbell <rcampbell@mozilla.com> (original author)
  *   Mihai Șucan <mihai.sucan@gmail.com>
  *   Julian Viereck <jviereck@mozilla.com>
  *   Paul Rouget <paul@mozilla.com>
  *   Kyle Simpson <ksimpson@mozilla.com>
+ *   Johan Charlez <johan.charlez@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
@@ -1107,18 +1108,18 @@ InspectorUI.prototype = {
   {
     if (!this.inspecting) {
       return;
     }
 
     this.inspectToolbutton.checked = false;
     // Detach event listeners from content window and child windows to disable
     // highlighting. We still want to be notified if the user presses "ESCAPE"
-    // to unlock the node, so we don't remove the "keypress" event until
-    // the highlighter is removed.
+    // to close the inspector, or "RETURN" to unlock the node, so we don't 
+    // remove the "keypress" event until the highlighter is removed.
     this.highlighter.detachInspectListeners();
 
     this.inspecting = false;
     this.toolsDim(false);
     if (this.highlighter.node) {
       this.select(this.highlighter.node, true, true, !aPreventScroll);
     } else {
       this.select(null, true, true);
@@ -1181,17 +1182,18 @@ InspectorUI.prototype = {
 
     if (this.store.getValue(this.winID, "inspecting")) {
       this.startInspecting();
     }
 
     this.restoreToolState(this.winID);
 
     this.win.focus();
-    Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.OPENED, null);
+    Services.obs.notifyObservers({wrappedJSObject: this},
+                                 INSPECTOR_NOTIFICATIONS.OPENED, null);
   },
 
   /**
    * Main callback handler for events.
    *
    * @param event
    *        The event to be handled.
    */
@@ -1243,18 +1245,22 @@ InspectorUI.prototype = {
 
         if (this.store.isEmpty()) {
           this.tabbrowser.tabContainer.removeEventListener("TabSelect", this,
                                                          false);
         }
         break;
       case "keypress":
         switch (event.keyCode) {
+          case this.chromeWin.KeyEvent.DOM_VK_ESCAPE:
+            this.closeInspectorUI(false);
+            event.preventDefault();
+            event.stopPropagation();
+            break;
           case this.chromeWin.KeyEvent.DOM_VK_RETURN:
-          case this.chromeWin.KeyEvent.DOM_VK_ESCAPE:
             this.toggleInspection();
             event.preventDefault();
             event.stopPropagation();
             break;
           case this.chromeWin.KeyEvent.DOM_VK_LEFT:
             let node;
             if (this.selection) {
               node = this.selection.parentNode;
--- a/browser/devtools/highlighter/test/browser_inspector_highlighter.js
+++ b/browser/devtools/highlighter/test/browser_inspector_highlighter.js
@@ -89,21 +89,24 @@ function setupHighlighterTests()
 {
   h1 = doc.querySelector("h1");
   ok(h1, "we have the header");
   Services.obs.addObserver(runSelectionTests,
     InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
   InspectorUI.toggleInspectorUI();
 }
 
-function runSelectionTests()
+function runSelectionTests(subject)
 {
   Services.obs.removeObserver(runSelectionTests,
     InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
 
+  is(subject.wrappedJSObject, InspectorUI,
+     "InspectorUI accessible in the observer");
+
   executeSoon(function() {
     Services.obs.addObserver(performTestComparisons,
       InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
     EventUtils.synthesizeMouse(h1, 2, 2, {type: "mousemove"}, content);
   });
 }
 
 function performTestComparisons(evt)
--- a/browser/devtools/highlighter/test/browser_inspector_keybindings.js
+++ b/browser/devtools/highlighter/test/browser_inspector_keybindings.js
@@ -39,41 +39,44 @@ function test()
     });
   }
 
   function lockNode()
   {
     Services.obs.removeObserver(lockNode,
       InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
 
-    EventUtils.synthesizeKey("VK_ESCAPE", { });
+    EventUtils.synthesizeKey("VK_RETURN", { });
 
     executeSoon(isTheNodeLocked);
   }
 
   function isTheNodeLocked()
   {
     is(InspectorUI.selection, node, "selection matches node");
     ok(!InspectorUI.inspecting, "the node is locked");
     unlockNode();
   }
 
   function unlockNode() {
-    EventUtils.synthesizeKey("VK_ESCAPE", { });
+    EventUtils.synthesizeKey("VK_RETURN", { });
 
     executeSoon(isTheNodeUnlocked);
   }
 
   function isTheNodeUnlocked()
   {
     ok(InspectorUI.inspecting, "the node is unlocked");
 
+    // Let's close the inspector
     Services.obs.addObserver(finishUp,
       InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
-    InspectorUI.closeInspectorUI();
+
+    EventUtils.synthesizeKey("VK_ESCAPE", {});
+    ok(true, "Inspector is closing successfuly");
   }
 
   function finishUp() {
     Services.obs.removeObserver(finishUp,
                                 InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED);
     doc = node = null;
     gBrowser.removeCurrentTab();
     finish();
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -3757,18 +3757,18 @@ HeadsUpDisplay.prototype = {
         name: "PageJS",
         category: "js",
         severities: [
           { name: "ConsoleErrors", prefKey: "exception" },
           { name: "ConsoleWarnings", prefKey: "jswarn" }
         ]
       },
       {
-        name: "PageWebDeveloper",
-        category: "webdev",
+        name: "PageLogging",
+        category: "logging",
         severities: [
           { name: "ConsoleErrors", prefKey: "error" },
           { name: "ConsoleWarnings", prefKey: "warn" },
           { name: "ConsoleInfo", prefKey: "info" },
           { name: "ConsoleLog", prefKey: "log" }
         ]
       }
     ];
--- a/browser/devtools/webconsole/test/browser/browser_webconsole_bug_601667_filter_buttons.js
+++ b/browser/devtools/webconsole/test/browser/browser_webconsole_bug_601667_filter_buttons.js
@@ -16,17 +16,17 @@ function testFilterButtons() {
 
   let hud = HUDService.getHudByWindow(content);
   hudId = hud.hudId;
   hudBox = hud.HUDBox;
 
   testMenuFilterButton("net");
   testMenuFilterButton("css");
   testMenuFilterButton("js");
-  testMenuFilterButton("webdev");
+  testMenuFilterButton("logging");
 
   finishTest();
 }
 
 function testMenuFilterButton(aCategory) {
   let selector = ".webconsole-filter-button[category=\"" + aCategory + "\"]";
   let button = hudBox.querySelector(selector);
   ok(button, "we have the \"" + aCategory + "\" button");
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -9,16 +9,17 @@
 @DLL_PREFIX@xpcom_compat@DLL_SUFFIX@
 @DLL_PREFIX@xpistub@DLL_SUFFIX@
 @DLL_PREFIX@zlib@DLL_SUFFIX@
 @DLL_PREFIX@jemalloc@DLL_SUFFIX@
 #ifdef MOZ_STATIC_JS
 @DLL_PREFIX@mozjs@DLL_SUFFIX@
 #endif
 LICENSE
+update.locale
 browserconfig.properties
 chrome/US.jar
 chrome/app-chrome.manifest
 chrome/browser.manifest
 chrome/chrome.rdf
 chrome/chromelist.txt
 chrome/classic.jar
 chrome/classic.manifest
--- a/browser/locales/en-US/chrome/browser/devtools/gcli.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/gcli.properties
@@ -15,17 +15,17 @@ canonDescNone=(No description)
 # of JavaScript like traditional developer tool command lines. This describes
 # the '{' command.
 cliEvalJavascript=Enter JavaScript directly
 
 # LOCALIZATION NOTE (fieldSelectionSelect): When a command has a parameter
 # that has a number of pre-defined options the user interface presents these
 # in a drop-down menu, where the first 'option' is an indicator that a
 # selection should be made. This string describes that first option.
-fieldSelectionSelect=Select a %S ...
+fieldSelectionSelect=Select a %S …
 
 # LOCALIZATION NOTE (fieldArrayAdd): When a command has a parameter that can
 # be repeated a number of times (e.g. like the 'cat a.txt b.txt' command) the
 # user interface presents buttons to add and remove arguments. This string is
 # used to add arguments.
 fieldArrayAdd=Add
 
 # LOCALIZATION NOTE (fieldArrayDel): When a command has a parameter that can
--- a/browser/locales/en-US/chrome/browser/devtools/inspector.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/inspector.properties
@@ -1,8 +1,17 @@
+# LOCALIZATION NOTE These strings are used inside the Inspector
+# which is available from the Web Developer sub-menu -> 'Inspect'.
+#
+# The correct localization of this file might be to keep it in
+# English, or another language commonly spoken among web developers.
+# You want to make that choice consistent across the developer tools.
+# A good criteria is the language in which you'd find the best
+# documentation on web development on the web.
+
 # LOCALIZATION NOTE (confirmNavigationAway): Used in the Inspector tool, when
 # the user tries to navigate away from a web page, to confirm the change of
 # page.
 confirmNavigationAway.message=Leaving this page will close the Inspector and the changes you have made will be lost.
 confirmNavigationAway.buttonLeave=Leave Page
 confirmNavigationAway.buttonLeaveAccesskey=L
 confirmNavigationAway.buttonStay=Stay on Page
 confirmNavigationAway.buttonStayAccesskey=S
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd
@@ -1,11 +1,17 @@
 <!-- LOCALIZATION NOTE : FILE This file contains the Scratchpad window strings -->
 <!-- LOCALIZATION NOTE : FILE Do not translate commandkeys -->
 
+<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
+  - keep it in English, or another language commonly spoken among web developers.
+  - You want to make that choice consistent across the developer tools.
+  - A good criteria is the language in which you'd find the best
+  - documentation on web development on the web. -->
+
 <!-- LOCALIZATION NOTE (scratchpad.title):
   -  The Scratchpad is intended to provide a simple text editor for creating
   -  and evaluating bits of JavaScript code for the purposes of function
   -  prototyping, experimentation and convenient scripting.
   -
   -  It's quite possible that you won't have a good analogue for the word
   -  "Scratchpad" in your locale. You should feel free to find a close
   -  approximation to it or choose a word (or words) that means
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
@@ -1,8 +1,17 @@
+# LOCALIZATION NOTE These strings are used inside the JavaScript scratchpad
+# which is available from the Web Developer sub-menu -> 'Scratchpad'.
+#
+# The correct localization of this file might be to keep it in
+# English, or another language commonly spoken among web developers.
+# You want to make that choice consistent across the developer tools.
+# A good criteria is the language in which you'd find the best
+# documentation on web development on the web.
+
 # LOCALIZATION NOTE  (propertyPanel.updateButton.label): Used in the Property
 # Panel that is opened by the Scratchpad window when inspecting an object. This
 # is the Update button label.
 propertyPanel.updateButton.label=Update
 propertyPanel.updateButton.accesskey=U
 
 # LOCALIZATION NOTE  (export.fileOverwriteConfirmation): This is displayed when
 # the user attempts to save to an already existing file.
--- a/browser/locales/en-US/chrome/browser/devtools/styleinspector.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/styleinspector.dtd
@@ -1,8 +1,14 @@
+<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
+  - keep it in English, or another language commonly spoken among web developers.
+  - You want to make that choice consistent across the developer tools.
+  - A good criteria is the language in which you'd find the best
+  - documentation on web development on the web. -->
+
 <!-- LOCALIZATION NOTE (userStylesLabel): This is the label for the checkbox
   -  that specifies whether the styles that are not from the user's stylesheet
   -  should be displayed or not. -->
 <!ENTITY userStylesLabel    "Only user styles">
 
 <!-- LOCALIZATION NOTE (userStylesSearch): This is the placeholder that goes in
   -  the search box when no search term has been entered. -->
 <!ENTITY userStylesSearch      "Search">
--- a/browser/locales/en-US/chrome/browser/devtools/styleinspector.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/styleinspector.properties
@@ -1,9 +1,16 @@
 # LOCALIZATION NOTE These strings are used inside the Style Inspector.
+#
+# The correct localization of this file might be to keep it in
+# English, or another language commonly spoken among web developers.
+# You want to make that choice consistent across the developer tools.
+# A good criteria is the language in which you'd find the best
+# documentation on web development on the web.
+
 
 # LOCALIZATION NOTE (panelTitle): This is the panel title
 panelTitle=Style Inspector
 
 # LOCALIZATION NOTE (rule.status): For each style property the panel shows
 # the rules which hold that specific property. For every rule, the rule status
 # is also displayed: a rule can be the best match, a match, a parent match, or a
 # rule did not match the element the user has highlighted.
--- a/browser/locales/en-US/chrome/browser/devtools/webConsole.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/webConsole.dtd
@@ -1,8 +1,14 @@
+<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
+  - keep it in English, or another language commonly spoken among web developers.
+  - You want to make that choice consistent across the developer tools.
+  - A good criteria is the language in which you'd find the best
+  - documentation on web development on the web. -->
+
 <!ENTITY networkPanel.requestURL                  "Request URL">
 <!ENTITY networkPanel.requestMethod               "Request Method">
 <!ENTITY networkPanel.statusCode                  "Status Code">
 
 <!ENTITY networkPanel.requestHeaders              "Request Headers">
 <!ENTITY networkPanel.requestCookie               "Sent Cookie">
 <!ENTITY networkPanel.requestBody                 "Request Body">
 <!ENTITY networkPanel.requestFormData             "Sent Form Data">
--- a/browser/locales/en-US/chrome/browser/devtools/webconsole.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/webconsole.properties
@@ -1,8 +1,15 @@
+# LOCALIZATION NOTE
+# The correct localization of this file might be to keep it in
+# English, or another language commonly spoken among web developers.
+# You want to make that choice consistent across the developer tools.
+# A good criteria is the language in which you'd find the best
+# documentation on web development on the web.
+
 typeError=Error: 
 typeWarning=Warning: 
 typeNetwork=Network: 
 typeException=Exception:  
 typeCssParser=CSS Parser: 
 typeStrict=Strict Warning: 
 msgCategory=Category: 
 errLine=Line: %S
@@ -13,29 +20,27 @@ categoryConsole=Console:
 btnMutation=DOM Mutation
 tipMutation=Toggle DOM Mutation event logging
 btnPageNet=Net
 tipPageNet=Log network access
 btnPageCSS=CSS
 tipPageCSS=Log CSS parsing errors
 btnPageJS=JS
 tipPageJS=Log JavaScript exceptions
-# LOCALIZATION NOTE (btnPageWebDeveloper):
+# LOCALIZATION NOTE (btnPageLogging):
 #
-# This is used as the text of the "Web Developer" button on the toolbar. It
+# This is used as the text of the "Logging" button on the toolbar. It
 # shows or hides messages that the web developer inserted on the page for
-# debugging purposes, using calls such console.log() and console.error(). You
-# may wish to localize this as "Page" if that is clearer in your locale. See
-# bug 601667 for more information.
-btnPageWebDeveloper=Web Developer
-# LOCALIZATION NOTE (tipPageWebDeveloper):
+# debugging purposes, using calls such console.log() and console.error().
+btnPageLogging=Logging
+# LOCALIZATION NOTE (tipPageLogging):
 #
-# This is used as the text of the tool tip for the "Web Developer" button on
+# This is used as the text of the tool tip for the "Logging" button on
 # the toolbar.
-tipPageWebDeveloper=Log messages sent to the "console" object
+tipPageLogging=Log messages sent to the "console" object
 btnConsoleErrors=Errors
 tipConsoleErrors=Log calls to console.error()
 btnConsoleInfo=Info
 tipConsoleInfo=Log calls to console.info()
 btnConsoleWarnings=Warnings
 tipConsoleWarnings=Log calls to console.warn()
 btnConsoleLog=Log
 tipConsoleLog=Log calls to console.log()
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -61,16 +61,70 @@ ifeq (android,$(MOZ_WIDGET_TOOLKIT))
   DIRS += mobile/sutagent/android \
           mobile/sutagent/android/watcher \
           mobile/sutagent/android/ffxcp \
           mobile/sutagent/android/fencp \
           $(NULL)
 endif
 endif
 
+ifdef MOZ_APP_BASENAME
+DIST_FILES = application.ini
+
+ifdef LIBXUL_SDK
+GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
+APP_INI_DEPS = $(LIBXUL_DIST)/bin/platform.ini
+else
+GRE_MILESTONE = $(shell tail -n 1 $(topsrcdir)/config/milestone.txt 2>/dev/null || tail -1 $(topsrcdir)/config/milestone.txt)
+APP_INI_DEPS = $(topsrcdir)/config/milestone.txt
+endif
+
+APP_BUILDID := $(shell cat $(DEPTH)/config/buildid)
+APP_INI_DEPS += $(DEPTH)/config/buildid
+
+DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DAPP_BUILDID=$(APP_BUILDID)
+
+DEFINES += -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)"
+APP_INI_DEPS += $(DEPTH)/config/autoconf.mk
+
+MOZ_SOURCE_STAMP ?= $(firstword $(shell hg -R $(topsrcdir) parent --template="{node|short}\n" 2>/dev/null))
+ifdef MOZ_SOURCE_STAMP
+DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
+endif
+
+_dollar=$$
+SOURCE_REPO := $(shell cd $(topsrcdir) && hg showconfig paths.default 2>/dev/null | head -n1 | sed -e "s/^ssh:/http:/" -e "s/\/$(_dollar)//" )
+ifdef SOURCE_REPO
+DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
+endif
+
+DEFINES += \
+  -DMOZ_APP_BASENAME="$(MOZ_APP_BASENAME)" \
+  -DMOZ_APP_VENDOR="$(MOZ_APP_VENDOR)" \
+  -DMOZ_APP_ID="$(MOZ_APP_ID)" \
+  $(NULL)
+
+ifdef MOZ_APP_PROFILE
+DEFINES += -DMOZ_APP_PROFILE="$(MOZ_APP_PROFILE)"
+endif
+
+ifdef MOZILLA_OFFICIAL
+DEFINES += -DMOZILLA_OFFICIAL
+endif
+
+ifdef MOZ_PROFILE_MIGRATOR
+DEFINES += -DMOZ_PROFILE_MIGRATOR
+endif
+
+ifdef MOZ_EXTENSION_MANAGER
+DEFINES += -DMOZ_EXTENSION_MANAGER
+endif
+
+endif
+
 include $(topsrcdir)/config/rules.mk
 
 # we install to _leaktest/
 TARGET_DEPTH = ..
 include $(srcdir)/automation-build.mk
 
 _LEAKTEST_DIR = $(DEPTH)/_leaktest
 GARBAGE_DIRS += $(_LEAKTEST_DIR)
@@ -95,16 +149,29 @@ GARBAGE_DIRS += $(_LEAKTEST_DIR)
 		$(topsrcdir)/build/pgo/blueprint/fancytype-screen.css \
 		$(NULL)
 
 leaktest.py: leaktest.py.in
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $^ > $@
 	chmod +x $@
 GARBAGE += leaktest.py
 
+ifdef MOZ_APP_BASENAME
+application.ini: application.ini.in $(APP_INI_DEPS)
+	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $< > $@
+GARBAGE += application.ini
+
+ifdef MOZ_APP_STATIC_INI
+application.ini.h: appini_header.py application.ini 
+	$(PYTHON) $^ > $@
+export:: application.ini.h
+GARBAGE += application.ini.h
+endif
+endif
+
 libs:: $(_LEAKTEST_FILES)
 	$(INSTALL) $^ $(_LEAKTEST_DIR)
 
 ifdef MOZ_VALGRIND
 _VALGRIND_DIR = $(DEPTH)/_valgrind
 GARBAGE_DIRS += $(_VALGRIND_DIR)
 
 _VALGRIND_FILES = \
new file mode 100644
--- /dev/null
+++ b/build/appini_header.py
@@ -0,0 +1,86 @@
+# ***** 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 a build helper for libraries
+#
+# 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):
+# Mike Hommey <mh@glandium.org>
+#
+# 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 *****
+
+'''Parses a given application.ini file and outputs the corresponding
+   XULAppData structure as a C++ header file'''
+
+import ConfigParser
+import sys
+
+def main(file):
+    config = ConfigParser.RawConfigParser()
+    config.read(file)
+    flags = set()
+    try:
+        if config.getint('XRE', 'EnableExtensionManager') == 1:
+            flags.add('NS_XRE_ENABLE_EXTENSION_MANAGER')
+    except: pass
+    try:
+        if config.getint('XRE', 'EnableProfileMigrator') == 1:
+            flags.add('NS_XRE_ENABLE_PROFILE_MIGRATOR')
+    except: pass
+    try:
+        if config.getint('Crash Reporter', 'Enabled') == 1:
+            flags.add('NS_XRE_ENABLE_CRASH_REPORTER')
+    except: pass
+    appdata = dict(("%s:%s" % (s, o), config.get(s, o)) for s in config.sections() for o in config.options(s))
+    appdata['flags'] = ' | '.join(flags) if flags else '0'
+    appdata['App:profile'] = '"%s"' % appdata['App:profile'] if 'App:profile' in appdata else 'NULL'
+
+    print '''#include "nsXULAppAPI.h"
+             static const nsXREAppData sAppData = {
+                 sizeof(nsXREAppData),
+                 NULL, // directory
+                 "%(App:vendor)s",
+                 "%(App:name)s",
+                 "%(App:version)s",
+                 "%(App:buildid)s",
+                 "%(App:id)s",
+                 NULL, // copyright
+                 %(flags)s,
+                 NULL, // xreDirectory
+                 "%(Gecko:minversion)s",
+                 "%(Gecko:maxversion)s",
+                 "%(Crash Reporter:serverurl)s",
+                 %(App:profile)s
+             };''' % appdata
+
+if __name__ == '__main__':
+    if len(sys.argv) != 1:
+        main(sys.argv[1])
+    else:
+        print >>sys.stderr, "Usage: %s /path/to/application.ini" % sys.argv[0]
rename from browser/app/application.ini
rename to build/application.ini.in
--- a/browser/app/application.ini
+++ b/build/application.ini.in
@@ -1,8 +1,14 @@
+#if MOZ_APP_STATIC_INI
+; This file is not used. If you modify it and want the application to use
+; your modifications, start with the "-app /path/to/application.ini"
+; argument.
+#endif
+#if 0
 ; ***** 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/
 ;
@@ -29,39 +35,43 @@
 ; 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 *****
-
+#endif
 #filter substitution
 [App]
 Vendor=@MOZ_APP_VENDOR@
 Name=@MOZ_APP_BASENAME@
-Version=@APP_VERSION@
+Version=@MOZ_APP_VERSION@
 #ifdef MOZ_APP_PROFILE
 Profile=@MOZ_APP_PROFILE@
 #endif
-BuildID=@GRE_BUILDID@
+BuildID=@APP_BUILDID@
 #ifdef MOZ_SOURCE_REPO
 SourceRepository=@MOZ_SOURCE_REPO@
 #endif
 #ifdef MOZ_SOURCE_STAMP
 SourceStamp=@MOZ_SOURCE_STAMP@
 #endif
-ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
+ID=@MOZ_APP_ID@
 
 [Gecko]
 MinVersion=@GRE_MILESTONE@
 MaxVersion=@GRE_MILESTONE@
 
 [XRE]
+#ifdef MOZ_PROFILE_MIGRATOR
 EnableProfileMigrator=1
+#endif
+#ifdef MOZ_EXTENSION_MANAGER
 EnableExtensionManager=1
+#endif
 
 [Crash Reporter]
 #if MOZILLA_OFFICIAL
 Enabled=1
 #endif
-ServerURL=https://crash-reports.mozilla.com/submit?id=ec8030f7-c20a-464f-9b0e-13a3a9e97384&version=@APP_VERSION@&buildid=@GRE_BUILDID@
+ServerURL=https://crash-reports.mozilla.com/submit?id=@MOZ_APP_ID@&version=@MOZ_APP_VERSION@&buildid=@APP_BUILDID@
--- a/build/win32/Makefile.in
+++ b/build/win32/Makefile.in
@@ -108,11 +108,11 @@ libs::
 endif
 
 endif # ! MOZ_DEBUG
 endif # WIN32_REDIST_DIR
 
 # run the binscope tool to make sure the binary and all libraries
 # are using all available Windows OS-level security mechanisms
 check::
-	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/firefox.exe $(DIST)/crashreporter-symbols/
+	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/$(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/crashreporter-symbols/
 	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/plugin-container.exe $(DIST)/crashreporter-symbols/
 
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -47,19 +47,23 @@ MOZILLA_VERSION = @MOZILLA_VERSION@
 FIREFOX_VERSION	= @FIREFOX_VERSION@
 
 MOZ_BUILD_APP = @MOZ_BUILD_APP@
 MOZ_APP_NAME	= @MOZ_APP_NAME@
 MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@
 MOZ_APP_BASENAME = @MOZ_APP_BASENAME@
 MOZ_APP_VENDOR = @MOZ_APP_VENDOR@
 MOZ_APP_PROFILE = @MOZ_APP_PROFILE@
+MOZ_APP_ID = @MOZ_APP_ID@
+MOZ_PROFILE_MIGRATOR = @MOZ_PROFILE_MIGRATOR@
+MOZ_EXTENSION_MANAGER = @MOZ_EXTENSION_MANAGER@
 MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
 MOZ_APP_VERSION = @MOZ_APP_VERSION@
 MOZ_UA_BUILDID = @MOZ_UA_BUILDID@
+MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@
 
 MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@
 
 prefix		= @prefix@
 exec_prefix	= @exec_prefix@
 bindir		= @bindir@
 includedir	= @includedir@/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
 libdir		= @libdir@
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -59,18 +59,16 @@ endif
 
 ifdef SDK_XPIDLSRCS
 XPIDLSRCS += $(SDK_XPIDLSRCS)
 endif
 ifdef SDK_HEADERS
 EXPORTS += $(SDK_HEADERS)
 endif
 
-REPORT_BUILD = @echo $(notdir $<)
-
 ifeq ($(OS_ARCH),OS2)
 EXEC			=
 else
 EXEC			= exec
 endif
 
 # Don't copy xulrunner files at install time, when using system xulrunner
 ifdef SYSTEM_LIBXUL
@@ -1145,53 +1143,45 @@ MAKE_DEPS_AUTO_CC = $(MAKE_DEPS_AUTO)
 MAKE_DEPS_AUTO_CXX = $(MAKE_DEPS_AUTO)
 
 endif # COMPILER_DEPEND
 
 endif # MOZ_AUTO_DEPS
 
 # Rules for building native targets must come first because of the host_ prefix
 host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 %:: %.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
 
 # DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
 # 'moc' only knows about #defines it gets on the command line (-D...), not in
 # included headers like mozilla-config.h
 moc_%.cpp: %.h $(GLOBAL_DEPS)
 	$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
 
 moc_%.cc: %.cc $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
 
 ifdef ASFILES
 # The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
 # a '-c' flag.
 %.$(OBJ_SUFFIX): %.$(ASM_SUFFIX) $(GLOBAL_DEPS)
 	$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
 endif
@@ -1202,38 +1192,34 @@ endif
 %:: %.cpp $(GLOBAL_DEPS)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CCC) $(OUTOPTION)$@ $(CXXFLAGS) $(_VPATH_SRCS) $(LDFLAGS)
 
 #
 # Please keep the next two rules in sync.
 #
 %.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 ifdef STRICT_CPLUSPLUS_SUFFIX
 	echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc
 	$(RM) t_$*.cc
 else
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 endif #STRICT_CPLUSPLUS_SUFFIX
 
 $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
 
 $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
 
 %.s: %.cpp
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
 %.s: %.cc
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
@@ -1473,29 +1459,27 @@ endif
 
 XPIDL_DEPS = \
   $(topsrcdir)/xpcom/idl-parser/header.py \
   $(topsrcdir)/xpcom/idl-parser/typelib.py \
   $(topsrcdir)/xpcom/idl-parser/xpidl.py \
   $(NULL)
 
 $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
-	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
 ifndef NO_GEN_XPT
 # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
 # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
 $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
-	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  -I$(topsrcdir)/xpcom/typelib/xpt/tools \
 	  $(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 
 # no need to link together if XPIDLSRCS contains only XPIDL_MODULE
 ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
@@ -1774,25 +1758,22 @@ else # ! COMPILER_DEPEND
 
 ifndef MOZ_AUTO_DEPS
 
 define MAKE_DEPS_NOAUTO
 	$(MKDEPEND) -w1024 -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $@
 endef
 
 $(MDDEPDIR)/%.pp: %.c
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 $(MDDEPDIR)/%.pp: %.cpp
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 $(MDDEPDIR)/%.pp: %.s
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
 depend:: $(SUBMAKEFILES) $(MAKE_DIRS) $(MDDEPFILES)
 else
 depend:: $(SUBMAKEFILES)
 endif
 	$(LOOP_OVER_PARALLEL_DIRS)
--- a/configure.in
+++ b/configure.in
@@ -2345,17 +2345,20 @@ case "$target" in
     esac
     ;;
 
 *-darwin*)
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
     MOZ_OPTIMIZE_FLAGS="-O3"
     _PEDANTIC=
-    MOZ_MEMORY=1
+    # Statically disable jemalloc on 10.5 and 32-bit 10.6.  See bug 702250.
+    if test "$HAVE_64BIT_OS"; then
+        MOZ_MEMORY=1
+    fi
     CFLAGS="$CFLAGS -fno-common"
     CXXFLAGS="$CXXFLAGS -fno-common"
     DLL_SUFFIX=".dylib"
     DSO_LDOPTS=''
     STRIP="$STRIP -x -S"
     # Check whether we're targeting OS X or iOS
     AC_CACHE_CHECK(for iOS target,
                    ac_cv_ios_target,
@@ -7277,17 +7280,17 @@ AC_SUBST(WIN32_CRT_LIBS)
 dnl Need to set this for make because NSS doesn't have configure
 AC_SUBST(DLLFLAGS)
 
 dnl We need to wrap dlopen and related functions on Android because we use
 dnl our own linker.
 if test "$OS_TARGET" = Android; then
     WRAP_LDFLAGS="${WRAP_LDFLAGS} -L$_objdir/dist/lib -lmozutils"
     if test "$MOZ_WIDGET_TOOLKIT" = android; then
-        WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=dlopen,--wrap=dlclose,--wrap=dlerror,--wrap=dlsym,--wrap=dladdr"
+        WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=dlopen,--wrap=dlclose,--wrap=dlerror,--wrap=dlsym,--wrap=dladdr,--wrap=getaddrinfo,--wrap=freeaddrinfo,--wrap=gai_strerror"
     fi
 fi
 
 dnl ========================================================
 dnl = Use malloc wrapper lib
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(wrap-malloc,
 [  --enable-wrap-malloc    Wrap malloc calls (gnu linker only)],
@@ -8496,40 +8499,55 @@ AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
 # versions of a given application (e.g. Aurora and Firefox both use
 # "Firefox"), but may vary for full rebrandings (e.g. Iceweasel). Used
 # for application.ini's "Name" field, which controls profile location in
 # the absence of a "Profile" field (see below), and various system
 # integration hooks (Unix remoting, Windows MessageWindow name, etc.)
 # - MOZ_APP_DISPLAYNAME: Used in user-visible fields (DLL properties,
 # Mac Bundle name, Updater, Installer), it is typically used for nightly
 # builds (e.g. Aurora for Firefox).
+# - MOZ_APP_VERSION: Defines the application version number.
 # - MOZ_APP_NAME: Used for e.g. the binary program file name. If not set,
 # defaults to a lowercase form of MOZ_APP_BASENAME.
 # - MOZ_APP_PROFILE: When set, used for application.ini's
 # "Profile" field, which controls profile location.
+# - MOZ_APP_ID: When set, used for application.ini's "ID" field, and
+# crash reporter server url.
+# - MOZ_PROFILE_MIGRATOR: When set, enables profile migrator.
+# - MOZ_EXTENSION_MANAGER: When set, enabled extension manager.
 
 if test -z "$MOZ_APP_NAME"; then
    MOZ_APP_NAME=`echo $MOZ_APP_BASENAME | tr A-Z a-z`
 fi
 
 AC_SUBST(MOZ_APP_NAME)
 AC_SUBST(MOZ_APP_DISPLAYNAME)
 AC_SUBST(MOZ_APP_BASENAME)
 AC_SUBST(MOZ_APP_VENDOR)
 AC_SUBST(MOZ_APP_PROFILE)
+AC_SUBST(MOZ_APP_ID)
+AC_SUBST(MOZ_PROFILE_MIGRATOR)
+AC_SUBST(MOZ_EXTENSION_MANAGER)
 AC_DEFINE_UNQUOTED(MOZ_APP_UA_NAME, "$MOZ_APP_UA_NAME")
 AC_SUBST(MOZ_APP_UA_NAME)
 AC_DEFINE_UNQUOTED(MOZ_APP_UA_VERSION, "$MOZ_APP_VERSION")
 AC_SUBST(MOZ_APP_VERSION)
 AC_DEFINE_UNQUOTED(MOZ_UA_FIREFOX_VERSION, "$FIREFOX_VERSION")
 AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIREFOX_VERSION)
 AC_SUBST(FIREFOX_VERSION)
 AC_DEFINE_UNQUOTED(MOZ_UA_BUILDID, "$MOZ_UA_BUILDID")
 AC_SUBST(MOZ_UA_BUILDID)
 
+# We can't use the static application.ini data when building against
+# a libxul SDK.
+if test -n "$LIBXUL_SDK"; then
+    MOZ_APP_STATIC_INI=
+fi
+AC_SUBST(MOZ_APP_STATIC_INI)
+
 AC_SUBST(MOZ_PKG_SPECIAL)
 
 AC_SUBST(MOZILLA_OFFICIAL)
 
 if test "$MOZ_TELEMETRY_REPORTING"; then
     AC_DEFINE(MOZ_TELEMETRY_REPORTING)
 fi
 
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -83,26 +83,33 @@ enum {
   ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 4
 };
 
 namespace mozilla {
 namespace dom {
 
 class Link;
 
+// IID for the dom::Element interface
+#define NS_ELEMENT_IID      \
+{ 0xa1588efb, 0x5a84, 0x49cd, \
+  { 0x99, 0x1a, 0xac, 0x84, 0x9d, 0x92, 0x05, 0x0f } }
+
 class Element : public nsIContent
 {
 public:
 #ifdef MOZILLA_INTERNAL_API
   Element(already_AddRefed<nsINodeInfo> aNodeInfo) :
     nsIContent(aNodeInfo),
     mState(NS_EVENT_STATE_MOZ_READONLY)
   {}
 #endif // MOZILLA_INTERNAL_API
 
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
+
   NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(Element, nsIContent)
 
   /**
    * Method to get the full state of this element.  See nsEventStates.h for
    * the possible bits that could be set here.
    */
   nsEventStates State() const {
     // mState is maintained by having whoever might have changed it
@@ -182,16 +189,18 @@ private:
                     "Should only be removing ESM-managed states here");
     RemoveStatesSilently(aStates);
     NotifyStateChange(aStates);
   }
 
   nsEventStates mState;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(Element, NS_ELEMENT_IID)
+
 } // namespace dom
 } // namespace mozilla
 
 inline mozilla::dom::Element* nsINode::AsElement() {
   NS_ASSERTION(IsElement(), "Not an element?");
   return static_cast<mozilla::dom::Element*>(this);
 }
 
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -119,18 +119,18 @@ class Loader;
 
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID \
-{ 0xc3e40e8e, 0x8b91, 0x424c, \
-  { 0xbe, 0x9c, 0x9c, 0xc1, 0x76, 0xa7, 0xf7, 0x24 } }
+{ 0x184e0a3c, 0x1899, 0x417d, \
+  { 0xbf, 0xf4, 0x5a, 0x15, 0xe6, 0xe8, 0xaa, 0x94 } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
@@ -1557,17 +1557,25 @@ public:
 
   virtual nsresult GetStateObject(nsIVariant** aResult) = 0;
 
   virtual nsDOMNavigationTiming* GetNavigationTiming() const = 0;
 
   virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) = 0;
 
   virtual Element* FindImageMap(const nsAString& aNormalizedMapName) = 0;
-  
+
+  // Called to notify the document that a listener on the "mozaudioavailable"
+  // event has been added. Media elements in the document need to ensure they
+  // fire the event.
+  virtual void NotifyAudioAvailableListener() = 0;
+
+  // Returns true if the document has "mozaudioavailable" event listeners.
+  virtual bool HasAudioAvailableListeners() = 0;
+
   // Add aLink to the set of links that need their status resolved. 
   void RegisterPendingLinkUpdate(mozilla::dom::Link* aLink);
   
   // Remove aLink from the set of links that need their status resolved.
   // This function must be called when links are removed from the document.
   void UnregisterPendingLinkUpdate(mozilla::dom::Link* aElement);
 
   // Update state on links in mLinksToUpdate.  This function must
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8232,16 +8232,35 @@ nsDocument::AddImage(imgIRequest* aImage
   if (oldCount == 0 && mAnimatingImages) {
     nsresult rv2 = aImage->IncrementAnimationConsumers();
     rv = NS_SUCCEEDED(rv) ? rv2 : rv;
   }
 
   return rv;
 }
 
+static void
+NotifyAudioAvailableListener(nsIContent *aContent, void *aUnused)
+{
+#ifdef MOZ_MEDIA
+  nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aContent));
+  if (domMediaElem) {
+    nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aContent);
+    mediaElem->NotifyAudioAvailableListener();
+  }
+#endif
+}
+
+void
+nsDocument::NotifyAudioAvailableListener()
+{
+  mHasAudioAvailableListener = true;
+  EnumerateFreezableElements(::NotifyAudioAvailableListener, nsnull);
+}
+
 nsresult
 nsDocument::RemoveImage(imgIRequest* aImage)
 {
   NS_ENSURE_ARG_POINTER(aImage);
 
   // Get the old count. It should exist and be > 0.
   PRUint32 count;
 #ifdef DEBUG
@@ -8601,38 +8620,68 @@ public:
   nsRefPtr<Element> mElement;
   nsCOMPtr<nsIDocument> mDoc;
   bool mWasCallerChrome;
 };
 
 void
 nsDocument::AsyncRequestFullScreen(Element* aElement)
 {
+  NS_ASSERTION(aElement,
+    "Must pass non-null element to nsDocument::AsyncRequestFullScreen");
   if (!aElement) {
     return;
   }
   // Request full-screen asynchronously.
   nsCOMPtr<nsIRunnable> event(new nsCallRequestFullScreen(aElement));
   NS_DispatchToCurrentThread(event);
 }
 
+static void
+LogFullScreenDenied(bool aLogFailure, const char* aMessage, nsIDocument* aDoc)
+{
+  if (!aLogFailure) {
+    return;
+  }
+  nsRefPtr<nsPLDOMEvent> e =
+    new nsPLDOMEvent(aDoc,
+                     NS_LITERAL_STRING("mozfullscreenerror"),
+                     true,
+                     false);
+  e->PostDOMEvent();
+  nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
+                                  aMessage,
+                                  nsnull, 0, nsnull,
+                                  EmptyString(), 0, 0,
+                                  nsIScriptError::warningFlag,
+                                  "DOM", aDoc);
+}
+
 void
 nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
 {
-  if (!aElement ||
-      !aElement->IsInDoc() ||
-      aElement->OwnerDoc() != this ||
-      !IsFullScreenEnabled(aWasCallerChrome) ||
-      !GetWindow()) {
-    nsRefPtr<nsPLDOMEvent> e =
-      new nsPLDOMEvent(this,
-                       NS_LITERAL_STRING("mozfullscreenerror"),
-                       true,
-                       false);
-    e->PostDOMEvent();
+  NS_ASSERTION(aElement,
+    "Must pass non-null element to nsDocument::RequestFullScreen");
+  if (!aElement) {
+    return;
+  }
+  if (!aElement->IsInDoc()) {
+    LogFullScreenDenied(true, "FullScreenDeniedNotInDocument", this);
+    return;
+  }
+  if (aElement->OwnerDoc() != this) {
+    LogFullScreenDenied(true, "FullScreenDeniedMovedDocument", this);
+    return;
+  }
+  if (!GetWindow()) {
+    LogFullScreenDenied(true, "FullScreenDeniedLostWindow", this);
+    return;
+  }
+  if (!IsFullScreenEnabled(aWasCallerChrome, true)) {
+    // IsFullScreenEnabled calls LogFullScreenDenied, no need to log.
     return;
   }
 
   // Turn off full-screen state in all documents which were previously
   // full-screen but which shouldn't be after this request is granted.
   // Note commonAncestor will be null when in a separate browser window
   // to the requesting document.
   nsIDocument* commonAncestor = nsnull;
@@ -8717,47 +8766,55 @@ nsDocument::GetMozFullScreen(bool *aFull
   *aFullScreen = IsFullScreenDoc();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::GetMozFullScreenEnabled(bool *aFullScreen)
 {
   NS_ENSURE_ARG_POINTER(aFullScreen);
-  *aFullScreen = IsFullScreenEnabled(nsContentUtils::IsCallerChrome());
+  *aFullScreen = IsFullScreenEnabled(nsContentUtils::IsCallerChrome(), false);
   return NS_OK;
 }
 
 bool
-nsDocument::IsFullScreenEnabled(bool aCallerIsChrome)
+nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
 {
   if (nsContentUtils::IsFullScreenApiEnabled() && aCallerIsChrome) {
     // Chrome code can always use the full-screen API, provided it's not
     // explicitly disabled. Note IsCallerChrome() returns true when running
     // in an nsRunnable, so don't use GetMozFullScreenEnabled() from an
     // nsRunnable!
     return true;
   }
 
-  if (!nsContentUtils::IsFullScreenApiEnabled() ||
-      nsContentUtils::HasPluginWithUncontrolledEventDispatch(this) ||
-      !IsVisible()) {
+  if (!nsContentUtils::IsFullScreenApiEnabled()) {
+    LogFullScreenDenied(aLogFailure, "FullScreenDeniedDisabled", this);
+    return false;
+  }
+  if (nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
+    LogFullScreenDenied(aLogFailure, "FullScreenDeniedPlugins", this);
+    return false;
+  }
+  if (!IsVisible()) {
+    LogFullScreenDenied(aLogFailure, "FullScreenDeniedHidden", this);
     return false;
   }
 
   // Ensure that all ancestor <iframe> elements have the mozallowfullscreen
   // boolean attribute set.
   nsINode* node = static_cast<nsINode*>(this);
   do {
     nsIContent* content = static_cast<nsIContent*>(node);
     if (content->IsHTML(nsGkAtoms::iframe) &&
         !content->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)) {
       // The node requesting fullscreen, or one of its crossdoc ancestors,
       // is an iframe which doesn't have the "mozalllowfullscreen" attribute.
       // This request is not authorized by the parent document.
+      LogFullScreenDenied(aLogFailure, "FullScreenDeniedIframeDisallowed", this);
       return false;
     }
     node = nsContentUtils::GetCrossDocParentNode(node);
   } while (node);
 
   return true;
 }
 
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -944,16 +944,23 @@ public:
 
   virtual nsresult GetStateObject(nsIVariant** aResult);
 
   virtual nsDOMNavigationTiming* GetNavigationTiming() const;
   virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming);
 
   virtual Element* FindImageMap(const nsAString& aNormalizedMapName);
 
+  virtual void NotifyAudioAvailableListener();
+
+  bool HasAudioAvailableListeners()
+  {
+    return mHasAudioAvailableListener;
+  }
+
   virtual Element* GetFullScreenElement();
   virtual void AsyncRequestFullScreen(Element* aElement);
   virtual void CancelFullScreen();
   virtual bool IsFullScreenDoc();
 
   // This is called asynchronously by nsIDocument::AsyncRequestFullScreen()
   // to move document into full-screen mode if allowed. aWasCallerChrome
   // should be true when nsIDocument::AsyncRequestFullScreen() was called
@@ -973,17 +980,19 @@ public:
 protected:
   friend class nsNodeUtils;
 
   // Returns true if a request for DOM full-screen is currently enabled in
   // this document. This returns true if there are no windowed plugins in this
   // doc tree, and if the document is visible, and if the api is not
   // disabled by pref. aIsCallerChrome must contain the return value of
   // nsContentUtils::IsCallerChrome() from the context we're checking.
-  bool IsFullScreenEnabled(bool aIsCallerChrome);
+  // If aLogFailure is true, an appropriate warning message is logged to the
+  // console, and a "mozfullscreenerror" event is dispatched to this document.
+  bool IsFullScreenEnabled(bool aIsCallerChrome, bool aLogFailure);
 
   /**
    * Check that aId is not empty and log a message to the console
    * service if it is.
    * @returns true if aId looks correct, false otherwise.
    */
   inline bool CheckGetElementByIdArg(const nsAString& aId)
   {
@@ -1150,16 +1159,20 @@ protected:
   bool mLoadedAsInteractiveData:1;
 
   // Whether we're currently holding a lock on all of our images.
   bool mLockingImages:1;
 
   // Whether we currently require our images to animate
   bool mAnimatingImages:1;
 
+  // Whether some node in this document has a listener for the
+  // "mozaudioavailable" event.
+  bool mHasAudioAvailableListener:1;
+
   // Whether we are currently in full-screen mode, as per the DOM API.
   bool mIsFullScreen:1;
 
   PRUint8 mXMLDeclarationBits;
 
   nsInterfaceHashtable<nsVoidPtrHashKey, nsPIBoxObject> *mBoxObjectTable;
 
   // The channel that got passed to StartDocumentLoad(), if any
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -3062,16 +3062,22 @@ nsGenericElement::UnbindFromTree(bool aD
   // Make sure to unbind this node before doing the kids
   nsIDocument *document =
     HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetCurrentDoc();
 
   if (aNullParent) {
     if (IsFullScreenAncestor(this)) {
       // The element being removed is an ancestor of the full-screen element,
       // exit full-screen state.
+      nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
+                                      "RemovedFullScreenElement",
+                                      nsnull, 0, nsnull,
+                                      EmptyString(), 0, 0,
+                                      nsIScriptError::warningFlag,
+                                      "DOM", OwnerDoc());      
       OwnerDoc()->CancelFullScreen();
     }
     if (GetParent()) {
       NS_RELEASE(mParent);
     } else {
       mParent = nsnull;
     }
     SetParentIsContent(false);
@@ -4338,16 +4344,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     }
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 
 NS_INTERFACE_MAP_BEGIN(nsGenericElement)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericElement)
+  NS_INTERFACE_MAP_ENTRY(Element)
   NS_INTERFACE_MAP_ENTRY(nsIContent)
   NS_INTERFACE_MAP_ENTRY(nsINode)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSElement, new nsNSElementTearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
                                  new nsNodeSupportsWeakRefTearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNodeSelector,
                                  new nsNodeSelectorTearoff(this))
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1771,16 +1771,20 @@ GK_ATOM(textInputFrame,"TextInputFrame")
 GK_ATOM(textFrame, "TextFrame")
 GK_ATOM(viewportFrame, "ViewportFrame")
 #ifdef MOZ_XUL
 GK_ATOM(XULLabelFrame, "XULLabelFrame")
 #endif
 GK_ATOM(svgAFrame, "SVGAFrame")
 GK_ATOM(svgClipPathFrame, "SVGClipPathFrame")
 GK_ATOM(svgDefsFrame, "SVGDefsFrame")
+GK_ATOM(svgFEContainerFrame, "SVGFEContainerFrame")
+GK_ATOM(svgFEImageFrame, "SVGFEImageFrame")
+GK_ATOM(svgFELeafFrame, "SVGFELeafFrame")
+GK_ATOM(svgFEUnstyledLeafFrame, "SVGFEUnstyledLeafFrame")
 GK_ATOM(svgFilterFrame, "SVGFilterFrame")
 GK_ATOM(svgForeignObjectFrame, "SVGForeignObjectFrame")
 GK_ATOM(svgGenericContainerFrame, "SVGGenericContainerFrame")
 GK_ATOM(svgGFrame, "SVGGFrame")
 GK_ATOM(svgGlyphFrame, "SVGGlyphFrame")
 GK_ATOM(svgGradientFrame, "SVGGradientFrame")
 GK_ATOM(svgImageFrame, "SVGImageFrame")
 GK_ATOM(svgInnerSVGFrame, "SVGInnerSVGFrame")
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1209,26 +1209,26 @@ nsXMLHttpRequest::Abort()
   PRUint32 responseLength = mResponseBody.Length();
   ResetResponse();
   mState |= XML_HTTP_REQUEST_ABORTED;
   
   if (!(mState & (XML_HTTP_REQUEST_UNSENT |
                   XML_HTTP_REQUEST_OPENED |
                   XML_HTTP_REQUEST_DONE))) {
     ChangeState(XML_HTTP_REQUEST_DONE, true);
-  }
-
-  if (!(mState & XML_HTTP_REQUEST_SYNCLOOPING)) {
-    NS_NAMED_LITERAL_STRING(abortStr, ABORT_STR);
-    DispatchProgressEvent(this, abortStr, mLoadLengthComputable, responseLength,
-                          mLoadTotal);
-    if (mUpload && !mUploadComplete) {
-      mUploadComplete = true;
-      DispatchProgressEvent(mUpload, abortStr, true, mUploadTransferred,
-                            mUploadTotal);
+
+    if (!(mState & XML_HTTP_REQUEST_SYNCLOOPING)) {
+      NS_NAMED_LITERAL_STRING(abortStr, ABORT_STR);
+      DispatchProgressEvent(this, abortStr, mLoadLengthComputable, responseLength,
+                            mLoadTotal);
+      if (mUpload && !mUploadComplete) {
+        mUploadComplete = true;
+        DispatchProgressEvent(mUpload, abortStr, true, mUploadTransferred,
+                              mUploadTotal);
+      }
     }
   }
 
   // The ChangeState call above calls onreadystatechange handlers which
   // if they load a new url will cause nsXMLHttpRequest::Open to clear
   // the abort state bit. If this occurs we're not uninitialized (bug 361773).
   if (mState & XML_HTTP_REQUEST_ABORTED) {
     ChangeState(XML_HTTP_REQUEST_UNSENT, false);  // IE seems to do it
@@ -1471,17 +1471,17 @@ bool
 nsXMLHttpRequest::IsSystemXHR()
 {
   return !!nsContentUtils::IsSystemPrincipal(mPrincipal);
 }
 
 bool
 nsXMLHttpRequest::IsWaitingForHTMLCharset()
 {
-  if (!mIsHtml) {
+  if (!mIsHtml || !mResponseXML) {
     return false;
   }
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(mResponseXML);
   return doc->GetDocumentCharacterSetSource() < kCharsetFromDocTypeDefault;
 }
 
 nsresult
 nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -523,16 +523,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug684671.html \
 		test_bug685798.html \
 		test_bug686449.xhtml \
 		test_bug690056.html \
 		test_bug692434.html \
 		file_bug692434.xml \
 		test_bug693875.html \
 		test_nodelist_holes.html \
+		test_xhr_abort_after_load.html \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
--- a/content/base/test/test_bug482935.html
+++ b/content/base/test/test_bug482935.html
@@ -22,42 +22,39 @@ function clearCache() {
 // after it has reached state 4
 function testCancelInPhase4() {
 
   clearCache();
 
   // First request - should be loaded from server
   var xhr = new XMLHttpRequest();
   xhr.addEventListener("readystatechange", function(e) {
-    if (xhr.readyState >= 4) {
-      xhr.addEventListener("abort", function() {
-        setTimeout(function() {
-          // This request was cancelled, so the responseText should be empty string
-          is(xhr.responseText, "", "Expected empty response to cancelled request");
-
-          // Second request - should be found in cache
-          var xhr2 = new XMLHttpRequest();
+    if (xhr.readyState < xhr.DONE) return;
+    is(xhr.readyState, xhr.DONE, "wrong readyState");
+    xhr.abort();
+    SimpleTest.executeSoon(function() {
+      // This request was cancelled, so the responseText should be empty string
+      is(xhr.responseText, "", "Expected empty response to cancelled request");
 
-          xhr2.addEventListener("load", function() {
-            is(xhr2.responseText, "0", "Received fresh value for second request");
-            SimpleTest.finish();
-          }, false);
+      // Second request - should be found in cache
+      var xhr2 = new XMLHttpRequest();
 
-          xhr2.open("GET", url);
-          xhr2.setRequestHeader("X-Request", "1", false);
-
-          try { xhr2.send(); }
-          catch(e) {
-            is(xhr2.status, "200", "Exception!");
-          }
-        }, 0);
+      xhr2.addEventListener("load", function() {
+        is(xhr2.responseText, "0", "Received fresh value for second request");
+        SimpleTest.finish();
       }, false);
 
-      xhr.abort();
-    }
+      xhr2.open("GET", url);
+      xhr2.setRequestHeader("X-Request", "1", false);
+
+      try { xhr2.send(); }
+      catch(e) {
+        is(xhr2.status, "200", "Exception!");
+      }
+    });
   }, false);
 
   xhr.open("GET", url, true);
   xhr.setRequestHeader("X-Request", "0", false);
   try { xhr.send(); }
   catch(e) {
     is("Nothing", "Exception", "Boom: " + e);
   }
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_xhr_abort_after_load.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test bug 482935</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="	/tests/SimpleTest/test.css" />
+</head>
+<body onload="onWindowLoad()">
+<script class="testbody" type="text/javascript">"use strict";
+SimpleTest.waitForExplicitFinish();
+
+var url = "file_XHR_pass1.xml";
+
+function onWindowLoad() {
+  runTest();
+}
+
+function runTest() {
+  var testFunctions = [
+    startTest1,
+    startTest2,
+    startTest3,
+  ];
+
+  function nextTest() {
+    if (testFunctions.length == 0) {
+      SimpleTest.finish();
+    }
+    (testFunctions.shift())();
+  }
+
+  nextTest();
+
+  var xhr;
+  function startTest1() {
+    xhr = new XMLHttpRequest();
+    xhr.onload = onLoad1;
+    xhr.open("GET", url);
+    xhr.send();
+  }
+
+  function onLoad1() {
+    is(xhr.readyState, xhr.DONE, "readyState should be DONE");
+    xhr.onabort = onAbort1;
+    xhr.abort();
+
+    function onAbort1(e) {
+      ok(false, e.type + " event should not be fired!");
+    }
+
+    is(xhr.readyState, xhr.UNSENT, "readyState should be UNSENT");
+    nextTest();
+  }
+
+  function startTest2() {
+    xhr = new XMLHttpRequest();
+    xhr.onloadstart = onAfterSend;
+    xhr.open("GET", url);
+    xhr.send();
+  }
+
+  function startTest3() {
+    xhr = new XMLHttpRequest();
+    xhr.open("GET", url);
+    xhr.send();
+    onAfterSend();
+  }
+
+  function onAfterSend() {
+    is(xhr.readyState, xhr.OPENED, "readyState should be OPENED");
+    var sent = false;
+    try {
+      xhr.send();
+    } catch (e) {
+      sent = true;
+    }
+    ok(sent, "send() flag should be set");
+    var aborted = false;
+    xhr.onabort = onAbort2;
+    xhr.abort();
+
+    function onAbort2() {
+      is(xhr.readyState, xhr.DONE, "readyState should be DONE");
+      aborted = true;
+    }
+
+    ok(aborted, "abort event should be fired");
+    is(xhr.readyState, xhr.UNSENT, "readyState should be UNSENT");
+    nextTest();
+  }
+}
+
+</script>
+</body>
+</html>
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -63,18 +63,16 @@
 #include "nsIEditorDocShell.h"
 #include "nsIFormControl.h"
 #include "nsIComboboxControlFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMXULControlElement.h"
 #include "nsINameSpaceManager.h"
 #include "nsIBaseWindow.h"
-#include "nsIView.h"
-#include "nsIViewManager.h"
 #include "nsISelection.h"
 #include "nsFrameSelection.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsIEnumerator.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
@@ -1025,18 +1023,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mAccessKeys);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 nsresult
 nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
                                     nsEvent *aEvent,
                                     nsIFrame* aTargetFrame,
-                                    nsEventStatus* aStatus,
-                                    nsIView* aView)
+                                    nsEventStatus* aStatus)
 {
   NS_ENSURE_ARG_POINTER(aStatus);
   NS_ENSURE_ARG(aPresContext);
   if (!aEvent) {
     NS_ERROR("aEvent is null.  This should never happen.");
     return NS_ERROR_NULL_POINTER;
   }
 
@@ -3024,18 +3021,17 @@ NodeAllowsClickThrough(nsINode* aNode)
   return true;
 }
 #endif
 
 nsresult
 nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
                                      nsEvent *aEvent,
                                      nsIFrame* aTargetFrame,
-                                     nsEventStatus* aStatus,
-                                     nsIView* aView)
+                                     nsEventStatus* aStatus)
 {
   NS_ENSURE_ARG(aPresContext);
   NS_ENSURE_ARG_POINTER(aStatus);
 
   HandleCrossProcessEvent(aEvent, aTargetFrame, aStatus);
 
   mCurrentTarget = aTargetFrame;
   mCurrentTargetContent = nsnull;
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -101,29 +101,27 @@ public:
    * cancelled should occur here.  Any processing which is intended to
    * be conditional based on either DOM or frame processing should occur in
    * PostHandleEvent.  Any centralized event processing which must occur before
    * DOM or frame event handling should occur here as well.
    */
   nsresult PreHandleEvent(nsPresContext* aPresContext,
                           nsEvent *aEvent,
                           nsIFrame* aTargetFrame,
-                          nsEventStatus* aStatus,
-                          nsIView* aView);
+                          nsEventStatus* aStatus);
 
   /* The PostHandleEvent method should contain all system processing which
    * should occur conditionally based on DOM or frame processing.  It should
    * also contain any centralized event processing which must occur after
    * DOM and frame processing.
    */
   nsresult PostHandleEvent(nsPresContext* aPresContext,
                            nsEvent *aEvent,
                            nsIFrame* aTargetFrame,
-                           nsEventStatus* aStatus,
-                           nsIView* aView);
+                           nsEventStatus* aStatus);
 
   void NotifyDestroyPresContext(nsPresContext* aPresContext);
   void SetPresContext(nsPresContext* aPresContext);
   void ClearFrameRefs(nsIFrame* aFrame);
 
   nsIFrame* GetEventTarget();
   already_AddRefed<nsIContent> GetEventTargetContent(nsEvent* aEvent);
 
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -37,17 +37,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIMEStateManager.h"
 #include "nsCOMPtr.h"
 #include "nsIWidget.h"
 #include "nsIViewManager.h"
-#include "nsIViewObserver.h"
 #include "nsIPresShell.h"
 #include "nsISupports.h"
 #include "nsPIDOMWindow.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIEditorDocShell.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -173,16 +173,23 @@ public:
   // has been resumed by the cache or because the element itself
   // asked the decoder to resumed the download.
   void DownloadResumed();
 
   // Called by the media decoder to indicate that the download has stalled
   // (no data has arrived for a while).
   void DownloadStalled();
 
+  // Called when a "MozAudioAvailable" event listener is added. The media
+  // element will then notify its decoder that it needs to make a copy of
+  // the audio data sent to hardware and dispatch it in "mozaudioavailable"
+  // events. This allows us to not perform the copy and thus reduce overhead
+  // in the common case where we don't have a "MozAudioAvailable" listener.
+  void NotifyAudioAvailableListener();
+
   // Called by the media decoder and the video frame to get the
   // ImageContainer containing the video data.
   ImageContainer* GetImageContainer();
 
   // Called by the video frame to get the print surface, if this is
   // a static document and we're not actually playing video
   gfxASurface* GetPrintSurface() { return mPrintSurface; }
 
@@ -296,22 +303,16 @@ public:
   void NotifyLoadError();
 
   /**
    * Called when data has been written to the underlying audio stream.
    */
   void NotifyAudioAvailable(float* aFrameBuffer, PRUint32 aFrameBufferLength,
                             float aTime);
 
-  /**
-   * Called in order to check whether some node (this window, its document,
-   * or content in that document) has a MozAudioAvailable event listener.
-   */
-  bool MayHaveAudioAvailableEventListener();
-
   virtual bool IsNodeOfType(PRUint32 aFlags) const;
 
   /**
    * Returns the current load ID. Asynchronous events store the ID that was
    * current when they were enqueued, and if it has changed when they come to
    * fire, they consider themselves cancelled, and don't fire.
    */
   PRUint32 GetCurrentLoadID() { return mCurrentLoadID; }
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -113,16 +113,17 @@
 #include "nsContentCreatorFunctions.h"
 #include "mozAutoDocUpdate.h"
 #include "nsHtml5Module.h"
 #include "nsITextControlElement.h"
 #include "mozilla/dom/Element.h"
 #include "nsHTMLFieldSetElement.h"
 #include "nsHTMLMenuElement.h"
 #include "nsPLDOMEvent.h"
+#include "nsIScriptError.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/FromParser.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #include "nsThreadUtils.h"
@@ -3463,16 +3464,22 @@ nsGenericHTMLElement::Focus()
 nsresult nsGenericHTMLElement::MozRequestFullScreen()
 {
   // Only grant full-screen requests if this is called from inside a trusted
   // event handler (i.e. inside an event handler for a user initiated event).
   // This stops the full-screen from being abused similar to the popups of old,
   // and it also makes it harder for bad guys' script to go full-screen and
   // spoof the browser chrome/window and phish logins etc.
   if (!nsContentUtils::IsRequestFullScreenAllowed()) {
+    nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
+                                    "FullScreenDeniedNotInputDriven",
+                                    nsnull, 0, nsnull,
+                                    EmptyString(), 0, 0,
+                                    nsIScriptError::warningFlag,
+                                    "DOM", OwnerDoc());
     nsRefPtr<nsPLDOMEvent> e =
       new nsPLDOMEvent(OwnerDoc(),
                        NS_LITERAL_STRING("mozfullscreenerror"),
                        true,
                        false);
     e->PostDOMEvent();
     return NS_OK;
   }
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -2003,23 +2003,26 @@ nsHTMLInputElement::PostHandleEvent(nsEv
     noContentDispatch ? NS_EVENT_FLAG_NO_CONTENT_DISPATCH : NS_EVENT_FLAG_NONE;
 
   // now check to see if the event was "cancelled"
   if (mCheckedIsToggled && outerActivateEvent) {
     if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault) {
       // if it was cancelled and a radio button, then set the old
       // selected btn to TRUE. if it is a checkbox then set it to its
       // original value
-      nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton =
-        do_QueryInterface(aVisitor.mItemData);
-      if (selectedRadioButton) {
-        selectedRadioButton->SetChecked(true);
-        // If this one is no longer a radio button we must reset it back to
-        // false to cancel the action.  See how the web of hack grows?
-        if (mType != NS_FORM_INPUT_RADIO) {
+      if (oldType == NS_FORM_INPUT_RADIO) {
+        nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton =
+          do_QueryInterface(aVisitor.mItemData);
+        if (selectedRadioButton) {
+          selectedRadioButton->SetChecked(true);
+        }
+        // If there was no checked radio button or this one is no longer a
+        // radio button we must reset it back to false to cancel the action.
+        // See how the web of hack grows?
+        if (!selectedRadioButton || mType != NS_FORM_INPUT_RADIO) {
           DoSetChecked(false, true, true);
         }
       } else if (oldType == NS_FORM_INPUT_CHECKBOX) {
         bool originalIndeterminateValue =
           !!(aVisitor.mItemFlags & NS_ORIGINAL_INDETERMINATE_VALUE);
         SetIndeterminateInternal(originalIndeterminateValue, false);
         DoSetChecked(originalCheckedValue, true, true);
       }
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -697,34 +697,16 @@ void nsHTMLMediaElement::NotifyAudioAvai
     if (NS_FAILED(rv)) {
       mAllowAudioData = false;
     }
   }
 
   DispatchAudioAvailableEvent(frameBuffer.forget(), aFrameBufferLength, aTime);
 }
 
-bool nsHTMLMediaElement::MayHaveAudioAvailableEventListener()
-{
-  // Determine if the current element is focused, if it is not focused
-  // then we should not try to blur.  Note: we allow for the case of
-  // |var a = new Audio()| with no parent document.
-  nsIDocument *document = GetDocument();
-  if (!document) {
-    return true;
-  }
-
-  nsPIDOMWindow *window = document->GetInnerWindow();
-  if (!window) {
-    return true;
-  }
-
-  return window->HasAudioAvailableEventListeners();
-}
-
 void nsHTMLMediaElement::LoadFromSourceChildren()
 {
   NS_ASSERTION(mDelayingLoadEvent,
                "Should delay load event (if in document) during load");
   NS_ASSERTION(mIsLoadingFromSourceChildren,
                "Must remember we're loading from source children");
   while (true) {
     nsIContent* child = GetNextSource();
@@ -1493,16 +1475,23 @@ nsresult nsHTMLMediaElement::BindToTree(
                                                  aCompileEventHandlers);
   if (aDocument) {
     mAutoplayEnabled =
       IsAutoplayEnabled() && (!aDocument || !aDocument->IsStaticDocument()) &&
       !IsEditable();
     // The preload action depends on the value of the autoplay attribute.
     // It's value may have changed, so update it.
     UpdatePreloadAction();
+
+    if (aDocument->HasAudioAvailableListeners()) {
+      // The document already has listeners for the "MozAudioAvailable"
+      // event, so the decoder must be notified so it initiates
+      // "MozAudioAvailable" event dispatch.
+      NotifyAudioAvailableListener();
+    }
   }
 
   return rv;
 }
 
 void nsHTMLMediaElement::UnbindFromTree(bool aDeep,
                                         bool aNullParent)
 {
@@ -1909,16 +1898,20 @@ nsresult nsHTMLMediaElement::FinishDecod
 
   if (!mPaused) {
     SetPlayedOrSeeked(true);
     if (!mPausedForInactiveDocument) {
       rv = mDecoder->Play();
     }
   }
 
+  if (OwnerDoc()->HasAudioAvailableListeners()) {
+    NotifyAudioAvailableListener();
+  }
+
   mBegun = true;
   return rv;
 }
 
 nsresult nsHTMLMediaElement::NewURIFromString(const nsAutoString& aURISpec, nsIURI** aURI)
 {
   NS_ENSURE_ARG_POINTER(aURI);
 
@@ -2709,8 +2702,15 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMoz
   nsresult rv = GetDuration(&duration);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If there is no end fragment, or the fragment end is greater than the
   // duration, return the duration.
   *aTime = (mFragmentEnd < 0.0 || mFragmentEnd > duration) ? duration : mFragmentEnd;
   return NS_OK;
 }
+
+void nsHTMLMediaElement::NotifyAudioAvailableListener()
+{
+  if (mDecoder) {
+    mDecoder->NotifyAudioAvailableListener();
+  }
+}
--- a/content/html/content/src/nsHTMLSharedObjectElement.cpp
+++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp
@@ -44,16 +44,17 @@
 #include "nsDOMError.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLAppletElement.h"
 #include "nsIDOMHTMLEmbedElement.h"
 #include "nsThreadUtils.h"
 #include "nsIDOMGetSVGDocument.h"
 #include "nsIDOMSVGDocument.h"
+#include "nsIScriptError.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 class nsHTMLSharedObjectElement : public nsGenericHTMLElement
                                 , public nsObjectLoadingContent
                                 , public nsIDOMHTMLAppletElement
                                 , public nsIDOMHTMLEmbedElement
@@ -292,16 +293,22 @@ nsHTMLSharedObjectElement::BindToTree(ns
   if (aDocument &&
       aDocument->IsFullScreenDoc() &&
       nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
     // This content contains a windowed plugin for which we don't control
     // event dispatch, and we're in full-screen mode. Exit full-screen mode
     // to prevent phishing attacks.
     NS_DispatchToCurrentThread(
       NS_NewRunnableMethod(aDocument, &nsIDocument::CancelFullScreen));
+    nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
+                                    "AddedWindowedPluginWhileFullScreen",
+                                    nsnull, 0, nsnull,
+                                    EmptyString(), 0, 0,
+                                    nsIScriptError::warningFlag,
+                                    "DOM", aDocument);           
   }
 #endif
   return NS_OK;
 }
 
 void
 nsHTMLSharedObjectElement::UnbindFromTree(bool aDeep,
                                           bool aNullParent)
--- a/content/media/nsAudioAvailableEventManager.cpp
+++ b/content/media/nsAudioAvailableEventManager.cpp
@@ -79,17 +79,18 @@ public:
 
 
 nsAudioAvailableEventManager::nsAudioAvailableEventManager(nsBuiltinDecoder* aDecoder) :
   mDecoder(aDecoder),
   mSignalBuffer(new float[mDecoder->GetFrameBufferLength()]),
   mSignalBufferLength(mDecoder->GetFrameBufferLength()),
   mNewSignalBufferLength(mSignalBufferLength),
   mSignalBufferPosition(0),
-  mReentrantMonitor("media.audioavailableeventmanager")
+  mReentrantMonitor("media.audioavailableeventmanager"),
+  mHasListener(false)
 {
   MOZ_COUNT_CTOR(nsAudioAvailableEventManager);
 }
 
 nsAudioAvailableEventManager::~nsAudioAvailableEventManager()
 {
   MOZ_COUNT_DTOR(nsAudioAvailableEventManager);
 }
@@ -99,16 +100,20 @@ void nsAudioAvailableEventManager::Init(
   NS_ASSERTION(aChannels != 0 && aRate != 0, "Audio metadata not known.");
   mSamplesPerSecond = static_cast<float>(aChannels * aRate);
 }
 
 void nsAudioAvailableEventManager::DispatchPendingEvents(PRUint64 aCurrentTime)
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
+  if (!mHasListener) {
+    return;
+  }
+
   while (mPendingEvents.Length() > 0) {
     nsAudioAvailableEventRunner* e =
       (nsAudioAvailableEventRunner*)mPendingEvents[0].get();
     if (e->mTime * USECS_PER_S > aCurrentTime) {
       break;
     }
     nsCOMPtr<nsIRunnable> event = mPendingEvents[0];
     mPendingEvents.RemoveElementAt(0);
@@ -117,16 +122,20 @@ void nsAudioAvailableEventManager::Dispa
 }
 
 void nsAudioAvailableEventManager::QueueWrittenAudioData(AudioDataValue* aAudioData,
                                                          PRUint32 aAudioDataLength,
                                                          PRUint64 aEndTimeSampleOffset)
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
+  if (!mHasListener) {
+    return;
+  }
+
   PRUint32 currentBufferSize = mNewSignalBufferLength;
   if (currentBufferSize == 0) {
     NS_WARNING("Decoder framebuffer length not set.");
     return;
   }
 
   if (!mSignalBuffer ||
       (mSignalBufferPosition == 0 && mSignalBufferLength != currentBufferSize)) {
@@ -207,16 +216,20 @@ void nsAudioAvailableEventManager::Clear
   mPendingEvents.Clear();
   mSignalBufferPosition = 0;
 }
 
 void nsAudioAvailableEventManager::Drain(PRUint64 aEndTime)
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
+  if (!mHasListener) {
+    return;
+  }
+
   // Force all pending events to go now.
   for (PRUint32 i = 0; i < mPendingEvents.Length(); ++i) {
     nsCOMPtr<nsIRunnable> event = mPendingEvents[i];
     NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
   }
   mPendingEvents.Clear();
 
   // If there is anything left in the signal buffer, put it in an event and fire.
@@ -240,8 +253,14 @@ void nsAudioAvailableEventManager::Drain
 
 void nsAudioAvailableEventManager::SetSignalBufferLength(PRUint32 aLength)
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
   mNewSignalBufferLength = aLength;
 }
 
+void nsAudioAvailableEventManager::NotifyAudioAvailableListener()
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+  mHasListener = true;
+}
--- a/content/media/nsAudioAvailableEventManager.h
+++ b/content/media/nsAudioAvailableEventManager.h
@@ -75,16 +75,21 @@ public:
   // framebuffer. This is meant to be called only once when the audio finishes.
   // Called from the state machine thread.
   void Drain(PRUint64 aTime);
 
   // Sets the size of the signal buffer.
   // Called from the main and the state machine thread.
   void SetSignalBufferLength(PRUint32 aLength);
 
+  // Called by the media element to notify the manager that there is a
+  // listener on the "MozAudioAvailable" event, and that we need to dispatch
+  // such events. Called from the main thread.
+  void NotifyAudioAvailableListener();
+
 private:
   // The decoder associated with the event manager.  The event manager shares
   // the same lifetime as the decoder (the decoder holds a reference to the
   // manager).
   nsBuiltinDecoder* mDecoder;
 
   // The number of samples per second.
   float mSamplesPerSecond;
@@ -103,11 +108,16 @@ private:
 
   // The MozAudioAvailable events to be dispatched.  This queue is shared
   // between the state machine and audio threads.
   nsTArray< nsCOMPtr<nsIRunnable> > mPendingEvents;
 
   // ReentrantMonitor for shared access to mPendingEvents queue or
   // buffer length.
   ReentrantMonitor mReentrantMonitor;
+
+  // True if something in the owning document has a listener on the
+  // "MozAudioAvailable" event. If not, we don't need to bother copying played
+  // audio data and dispatching the event. Synchronized by mReentrantMonitor.
+  bool mHasListener;
 };
 
 #endif
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -392,24 +392,19 @@ void nsBuiltinDecoder::AudioAvailable(fl
                                       PRUint32 aFrameBufferLength,
                                       float aTime)
 {
   // Auto manage the frame buffer's memory. If we return due to an error
   // here, this ensures we free the memory. Otherwise, we pass off ownership
   // to HTMLMediaElement::NotifyAudioAvailable().
   nsAutoArrayPtr<float> frameBuffer(aFrameBuffer);
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
-  if (mShuttingDown) {
+  if (mShuttingDown || !mElement) {
     return;
   }
-
-  if (!mElement || !mElement->MayHaveAudioAvailableEventListener()) {
-    return;
-  }
-
   mElement->NotifyAudioAvailable(frameBuffer.forget(), aFrameBufferLength, aTime);
 }
 
 void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
                                       PRUint32 aRate)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (mShuttingDown) {
@@ -1000,11 +995,21 @@ void nsBuiltinDecoder::MoveLoadsToBackgr
 }
 
 void nsBuiltinDecoder::UpdatePlaybackOffset(PRInt64 aOffset)
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   mPlaybackPosition = NS_MAX(aOffset, mPlaybackPosition);
 }
 
-bool nsBuiltinDecoder::OnStateMachineThread() const {
+bool nsBuiltinDecoder::OnStateMachineThread() const
+{
   return IsCurrentThread(nsBuiltinDecoderStateMachine::GetStateMachineThread());
 }
+
+void nsBuiltinDecoder::NotifyAudioAvailableListener()
+{
+  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
+  if (mDecoderStateMachine) {
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+    mDecoderStateMachine->NotifyAudioAvailableListener();
+  }
+}
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -339,16 +339,20 @@ public:
   // immediately stop playback and buffer downloaded data. Must be called
   // with the decode monitor held. Called on the state machine thread and
   // the main thread.
   virtual void StartBuffering() = 0;
 
   // Sets the current size of the framebuffer used in MozAudioAvailable events.
   // Called on the state machine thread and the main thread.
   virtual void SetFrameBufferLength(PRUint32 aLength) = 0;
+
+  // Called when a "MozAudioAvailable" event listener is added to the media
+  // element. Called on the main thread.
+  virtual void NotifyAudioAvailableListener() = 0;
 };
 
 class nsBuiltinDecoder : public nsMediaDecoder
 {
   // ISupports
   NS_DECL_ISUPPORTS
 
   // nsIObserver
@@ -605,16 +609,20 @@ class nsBuiltinDecoder : public nsMediaD
 
   // Return the current decode state. The decoder monitor must be
   // obtained before calling this.
   nsDecoderStateMachine::State GetDecodeState() { return mDecoderStateMachine->GetState(); }
 
   // Drop reference to state machine.  Only called during shutdown dance.
   void ReleaseStateMachine() { mDecoderStateMachine = nsnull; }
 
+   // Called when a "MozAudioAvailable" event listener is added to the media
+   // element. Called on the main thread.
+   virtual void NotifyAudioAvailableListener();
+
 public:
   // Notifies the element that decoding has failed.
   void DecodeError();
 
   // Schedules the state machine to run one cycle on the shared state
   // machine thread. Main thread only.
   nsresult ScheduleStateMachineThread();
 
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -2196,9 +2196,13 @@ bool nsBuiltinDecoderStateMachine::OnSta
     return IsCurrentThread(GetStateMachineThread());
 }
  
 nsIThread* nsBuiltinDecoderStateMachine::GetStateMachineThread()
 {
   return StateMachineTracker::Instance().GetGlobalStateMachineThread();
 }
 
-
+void nsBuiltinDecoderStateMachine::NotifyAudioAvailableListener()
+{
+  mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
+  mEventManager.NotifyAudioAvailableListener();
+}
--- a/content/media/nsBuiltinDecoderStateMachine.h
+++ b/content/media/nsBuiltinDecoderStateMachine.h
@@ -260,16 +260,20 @@ public:
   void TimeoutExpired();
 
   // Set the media fragment end time. aEndTime is in microseconds.
   void SetFragmentEndTime(PRInt64 aEndTime);
 
   // Drop reference to decoder.  Only called during shutdown dance.
   void ReleaseDecoder() { mDecoder = nsnull; }
 
+   // Called when a "MozAudioAvailable" event listener is added to the media
+   // element. Called on the main thread.
+   void NotifyAudioAvailableListener();
+
 protected:
 
   // Returns true if we've got less than aAudioUsecs microseconds of decoded
   // and playable data. The decoder monitor must be held.
   bool HasLowDecodedData(PRInt64 aAudioUsecs) const;
 
   // Returns true if we're running low on data which is not yet decoded.
   // The decoder monitor must be held.
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -153,16 +153,21 @@ public:
   // Call from any thread safely. Return true if we are currently
   // seeking in the media resource.
   virtual bool IsSeeking() const = 0;
 
   // Return true if the decoder has reached the end of playback.
   // Call in the main thread only.
   virtual bool IsEnded() const = 0;
 
+  // Called when a "MozAudioAvailable" event listener is added. This enables
+  // the decoder to only dispatch "MozAudioAvailable" events when a
+  // handler exists, reducing overhead. Called on the main thread.
+  virtual void NotifyAudioAvailableListener() = 0;
+
   struct Statistics {
     // Estimate of the current playback rate (bytes/second).
     double mPlaybackRate;
     // Estimate of the current download rate (bytes/second). This
     // ignores time that the channel was paused by Gecko.
     double mDownloadRate;
     // Total length of media stream in bytes; -1 if not known
     PRInt64 mTotalBytes;
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -54,21 +54,18 @@
 #include "nsSVGFilters.h"
 #include "nsLayoutUtils.h"
 #include "nsSVGUtils.h"
 #include "nsStyleContext.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "gfxContext.h"
 #include "gfxMatrix.h"
-#include "nsIDOMSVGURIReference.h"
-#include "nsImageLoadingContent.h"
 #include "imgIContainer.h"
 #include "nsNetUtil.h"
-#include "SVGAnimatedPreserveAspectRatio.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsSVGFilterElement.h"
 #include "nsSVGString.h"
 #include "nsSVGEffects.h"
 #include "gfxUtils.h"
 
 #if defined(XP_WIN) 
 // Prevent Windows redefining LoadImage
@@ -246,16 +243,28 @@ nsSVGFE::ComputeChangeBBox(const nsTArra
   return r;
 }
 
 void
 nsSVGFE::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
 }
 
+bool
+nsSVGFE::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                   nsIAtom* aAttribute) const
+{
+  return aNameSpaceID == kNameSpaceID_None &&
+         (aAttribute == nsGkAtoms::x ||
+          aAttribute == nsGkAtoms::y ||
+          aAttribute == nsGkAtoms::width ||
+          aAttribute == nsGkAtoms::height ||
+          aAttribute == nsGkAtoms::result);
+}
+
 //----------------------------------------------------------------------
 // nsIDOMSVGFilterPrimitiveStandardAttributes methods
 
 /* readonly attribute nsIDOMSVGAnimatedLength x; */
 NS_IMETHODIMP nsSVGFE::GetX(nsIDOMSVGAnimatedLength * *aX)
 {
   return mLengthAttributes[X].ToDOMAnimatedLength(aX, this);
 }
@@ -303,95 +312,16 @@ nsSVGFE::IsAttributeMapped(const nsIAtom
 
 nsSVGElement::LengthAttributesInfo
 nsSVGFE::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
-inline static void DidAnimateAttr(Element *aFilterPrimitive)
-{
-  // nsSVGLeafFrame doesn't implement AttributeChanged.
-  nsIFrame* frame = aFilterPrimitive->GetPrimaryFrame();
-  if (frame) {
-    nsSVGEffects::InvalidateRenderingObservers(frame);
-  }
-}
-
-inline static void DidAnimateAttrViaParent(Element *aFilterPrimitive)
-{
-  // No frame, use parent's
-  NS_ASSERTION(!aFilterPrimitive->GetPrimaryFrame(), "Not expecting a frame");
-  nsIContent *parent = aFilterPrimitive->GetFlattenedTreeParent();
-  if (parent && parent->IsElement()) {
-    DidAnimateAttr(parent->AsElement());
-  }
-}
-
-void
-nsSVGFE::DidAnimateLength(PRUint8 aAttrEnum)
-{
-  DidAnimateAttr(this);
-}
-
-void
-nsSVGFE::DidAnimateNumber(PRUint8 aAttrEnum)
-{
-  DidAnimateAttr(this);
-}
-
-void
-nsSVGFE::DidAnimateNumberPair(PRUint8 aAttrEnum)
-{
-  DidAnimateAttr(this);
-}
-
-void
-nsSVGFE::DidAnimateNumberList(PRUint8 aAttrEnum)
-{
-  DidAnimateAttr(this);
-}
-
-void
-nsSVGFE::DidAnimateInteger(PRUint8 aAttrEnum)
-{
-  DidAnimateAttr(this);
-}
-
-void
-nsSVGFE::DidAnimateIntegerPair(PRUint8 aAttrEnum)
-{
-  DidAnimateAttr(this);
-}
-
-void
-nsSVGFE::DidAnimateEnum(PRUint8 aAttrEnum)
-{
-  DidAnimateAttr(this);
-}
-
-void
-nsSVGFE::DidAnimatePreserveAspectRatio()
-{
-  DidAnimateAttr(this);
-}
-
-void
-nsSVGFE::DidAnimateBoolean(PRUint8 aAttrEnum)
-{
-  DidAnimateAttr(this);
-}
-
-void
-nsSVGFE::DidAnimateString(PRUint8 aAttrEnum)
-{
-  DidAnimateAttr(this);
-}
-
 //---------------------Gaussian Blur------------------------
 
 typedef nsSVGFE nsSVGFEGaussianBlurElementBase;
 
 class nsSVGFEGaussianBlurElement : public nsSVGFEGaussianBlurElementBase,
                                    public nsIDOMSVGFEGaussianBlurElement
 {
   friend nsresult NS_NewSVGFEGaussianBlurElement(nsIContent **aResult,
@@ -406,16 +336,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEGaussianBlurElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo >& aSources);
   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
           const nsSVGFilterInstance& aInstance);
   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
           const nsSVGFilterInstance& aInstance);
@@ -795,16 +727,26 @@ nsSVGFEGaussianBlurElement::Filter(nsSVG
   nsIntRect computationRect = rect;
   InflateRectForBlurDXY(&computationRect, dx, dy);
   ClipComputationRectToSurface(aInstance, &computationRect);
   GaussianBlur(aSources[0], aTarget, computationRect, dx, dy);
   ClipTarget(aInstance, aTarget, computationRect);
   return NS_OK;
 }
 
+bool
+nsSVGFEGaussianBlurElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                      nsIAtom* aAttribute) const
+{
+  return nsSVGFEGaussianBlurElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::stdDeviation));
+}
+
 void
 nsSVGFEGaussianBlurElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
 }
 
 nsIntRect
 nsSVGFEGaussianBlurElement::InflateRectForBlur(const nsIntRect& aRect,
@@ -876,16 +818,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEBlendElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
 
   // Blend
   NS_DECL_NSIDOMSVGFEBLENDELEMENT
 
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEBlendElementBase::)
 
@@ -1030,16 +974,27 @@ nsSVGFEBlendElement::Filter(nsSVGFilterI
       }
       PRUint32 alpha = 255 * 255 - (255 - qa) * (255 - qb);
       FAST_DIVIDE_BY_255(targetData[targIndex + GFX_ARGB32_OFFSET_A], alpha);
     }
   }
   return NS_OK;
 }
 
+bool
+nsSVGFEBlendElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                               nsIAtom* aAttribute) const
+{
+  return nsSVGFEBlendElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::in2 ||
+           aAttribute == nsGkAtoms::mode));
+}
+
 void
 nsSVGFEBlendElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN2], this));
 }
 
 //----------------------------------------------------------------------
@@ -1078,16 +1033,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEColorMatrixElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
 
   // Color Matrix
   NS_DECL_NSIDOMSVGFECOLORMATRIXELEMENT
 
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEColorMatrixElementBase::)
 
@@ -1333,16 +1290,27 @@ nsSVGFEColorMatrixElement::Filter(nsSVGF
         static_cast<PRUint8>(col[2]);
       targetData[targIndex + GFX_ARGB32_OFFSET_A] =
         static_cast<PRUint8>(col[3]);
     }
   }
   return NS_OK;
 }
 
+bool
+nsSVGFEColorMatrixElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                     nsIAtom* aAttribute) const
+{
+  return nsSVGFEColorMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::type ||
+           aAttribute == nsGkAtoms::values));
+}
+
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 nsSVGElement::EnumAttributesInfo
 nsSVGFEColorMatrixElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             ArrayLength(sEnumInfo));
@@ -1381,16 +1349,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFECompositeElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
           const nsSVGFilterInstance& aInstance);
 
   // Composite
   NS_DECL_NSIDOMSVGFECOMPOSITEELEMENT
 
@@ -1592,16 +1562,31 @@ nsSVGFECompositeElement::Filter(nsSVGFil
                                            gfxContext::OPERATOR_ATOP,
                                            gfxContext::OPERATOR_XOR };
   ctx.SetOperator(opMap[op]);
   ctx.SetSource(aSources[0]->mImage);
   ctx.Paint();
   return NS_OK;
 }
 
+bool
+nsSVGFECompositeElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                   nsIAtom* aAttribute) const
+{
+  return nsSVGFECompositeElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::in2 ||
+           aAttribute == nsGkAtoms::k1 ||
+           aAttribute == nsGkAtoms::k2 ||
+           aAttribute == nsGkAtoms::k3 ||
+           aAttribute == nsGkAtoms::k4 ||
+           aAttribute == nsGkAtoms::_operator));
+}
+
 void
 nsSVGFECompositeElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN2], this));
 }
 
 nsIntRect
@@ -1675,16 +1660,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEComponentTransferElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
 
   // Component Transfer
   NS_DECL_NSIDOMSVGFECOMPONENTTRANSFERELEMENT
 
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEComponentTransferElementBase::)
 
@@ -1755,49 +1742,43 @@ nsSVGFEComponentTransferElement::GetStri
 }
 
 //--------------------------------------------
 
 #define NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID \
     { 0xafab106d, 0xbc18, 0x4f7f, \
   { 0x9e, 0x29, 0xfe, 0xb4, 0xb0, 0x16, 0x5f, 0xf4 } }
 
-typedef nsSVGElement nsSVGComponentTransferFunctionElementBase;
+typedef SVGFEUnstyledElement nsSVGComponentTransferFunctionElementBase;
 
 class nsSVGComponentTransferFunctionElement : public nsSVGComponentTransferFunctionElementBase
 {
   friend nsresult NS_NewSVGComponentTransferFunctionElement(nsIContent **aResult,
                                                             already_AddRefed<nsINodeInfo> aNodeInfo);
 protected:
   nsSVGComponentTransferFunctionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsSVGComponentTransferFunctionElementBase(aNodeInfo) {}
 
 public:
   // interfaces:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID)
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT
 
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
+
   virtual PRInt32 GetChannel() = 0;
   void GenerateLookupTable(PRUint8* aTable);
 
 protected:
   virtual NumberAttributesInfo GetNumberInfo();
-  virtual void DidAnimateNumber(PRUint8 aAttrEnum) {
-    DidAnimateAttrViaParent(this);
-  }
   virtual EnumAttributesInfo GetEnumInfo();
-  virtual void DidAnimateEnum(PRUint8 aAttrEnum) {
-    DidAnimateAttrViaParent(this);
-  }
   virtual NumberListAttributesInfo GetNumberListInfo();
-  virtual void DidAnimateNumberList(PRUint8 aAttrEnum) {
-    DidAnimateAttrViaParent(this);
-  }
 
   // nsIDOMSVGComponentTransferFunctionElement properties:
   enum { TABLEVALUES };
   SVGAnimatedNumberList mNumberListAttributes[1];
   static NumberListInfo sNumberListInfo[1];
 
   enum { SLOPE, INTERCEPT, AMPLITUDE, EXPONENT, OFFSET };
   nsSVGNumber2 mNumberAttributes[5];
@@ -1846,16 +1827,25 @@ nsSVGFEComponentTransferElement::Filter(
         tableR[sourceData[targIndex + GFX_ARGB32_OFFSET_R]];
       targetData[targIndex + GFX_ARGB32_OFFSET_A] =
         tableA[sourceData[targIndex + GFX_ARGB32_OFFSET_A]];
     }
   }
   return NS_OK;
 }
 
+bool
+nsSVGFEComponentTransferElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                           nsIAtom* aAttribute) const
+{
+  return nsSVGFEComponentTransferElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          aAttribute == nsGkAtoms::in);
+}
+
 void
 nsSVGFEComponentTransferElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
 }
 
 nsSVGElement::NumberListInfo nsSVGComponentTransferFunctionElement::sNumberListInfo[1] =
 {
@@ -1906,16 +1896,33 @@ NS_INTERFACE_MAP_BEGIN(nsSVGComponentTra
    // around that
    if ( aIID.Equals(NS_GET_IID(nsSVGComponentTransferFunctionElement)) )
      foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
    else
 NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElementBase)
 
 
 //----------------------------------------------------------------------
+// nsFEUnstyledElement methods
+
+bool
+nsSVGComponentTransferFunctionElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                                 nsIAtom* aAttribute) const
+{
+  return aNameSpaceID == kNameSpaceID_None &&
+         (aAttribute == nsGkAtoms::tableValues ||
+          aAttribute == nsGkAtoms::slope ||
+          aAttribute == nsGkAtoms::intercept ||
+          aAttribute == nsGkAtoms::amplitude ||
+          aAttribute == nsGkAtoms::exponent ||
+          aAttribute == nsGkAtoms::offset ||
+          aAttribute == nsGkAtoms::type);
+}
+
+//----------------------------------------------------------------------
 // nsIDOMSVGComponentTransferFunctionElement methods
 
 /* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
 NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
 {
   return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this);
 }
 
@@ -2281,17 +2288,17 @@ public:
 protected:
   virtual StringAttributesInfo GetStringInfo();
 
   enum { RESULT };
   nsSVGString mStringAttributes[1];
   static StringInfo sStringInfo[1];
 };
 
-typedef nsSVGStylableElement nsSVGFEMergeNodeElementBase;
+typedef SVGFEUnstyledElement nsSVGFEMergeNodeElementBase;
 
 #define NS_SVG_FE_MERGE_NODE_CID \
     { 0x413687ec, 0x77fd, 0x4077, \
   { 0x9d, 0x7a, 0x97, 0x51, 0xa8, 0x4b, 0x7b, 0x40 } }
 
 class nsSVGFEMergeNodeElement : public nsSVGFEMergeNodeElementBase,
                                 public nsIDOMSVGFEMergeNodeElement
 {
@@ -2311,16 +2318,19 @@ public:
 
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMergeNodeElementBase::)
 
   NS_FORWARD_NSIDOMNODE(nsSVGFEMergeNodeElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGFEMergeNodeElementBase::)
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
+
   const nsSVGString* In1() { return &mStringAttributes[IN1]; }
   
   operator nsISupports*() { return static_cast<nsIContent*>(this); }
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   virtual StringAttributesInfo GetStringInfo();
 
@@ -2428,16 +2438,26 @@ NS_INTERFACE_TABLE_HEAD(nsSVGFEMergeNode
 NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMergeNodeElementBase)
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMergeNodeElement)
 
 //----------------------------------------------------------------------
+// nsFEUnstyledElement methods
+
+bool
+nsSVGFEMergeNodeElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                   nsIAtom* aAttribute) const
+{
+  return aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::in;
+}
+
+//----------------------------------------------------------------------
 // nsIDOMSVGFEMergeNodeElement methods
 
 /* readonly attribute nsIDOMSVGAnimatedString in1; */
 NS_IMETHODIMP nsSVGFEMergeNodeElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
 {
   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
 }
 
@@ -2470,16 +2490,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEOffsetElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
           const nsSVGFilterInstance& aInstance);
   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
           const nsSVGFilterInstance& aInstance);
@@ -2591,16 +2613,27 @@ nsSVGFEOffsetElement::Filter(nsSVGFilter
   ctx.Clip(aTarget->mFilterPrimitiveSubregion);
   ctx.Translate(gfxPoint(offset.x, offset.y));
   ctx.SetSource(aSources[0]->mImage);
   ctx.Paint();
 
   return NS_OK;
 }
 
+bool
+nsSVGFEOffsetElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                nsIAtom* aAttribute) const
+{
+  return nsSVGFEOffsetElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::dx ||
+           aAttribute == nsGkAtoms::dy));
+}
+
 void
 nsSVGFEOffsetElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
 }
 
 nsIntRect
 nsSVGFEOffsetElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
@@ -2802,16 +2835,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETileElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
           const nsSVGFilterInstance& aInstance);
   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
           const nsSVGFilterInstance& aInstance);
@@ -2957,16 +2992,25 @@ nsSVGFETileElement::Filter(nsSVGFilterIn
         }
       }
     }
   }
 
   return NS_OK;
 }
 
+bool
+nsSVGFETileElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                              nsIAtom* aAttribute) const
+{
+  return nsSVGFETileElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          aAttribute == nsGkAtoms::in);
+}
+
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 nsSVGElement::StringAttributesInfo
 nsSVGFETileElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               ArrayLength(sStringInfo));
@@ -2993,16 +3037,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
           const nsSVGFilterInstance& aInstance);
 
   // Turbulence
   NS_DECL_NSIDOMSVGFETURBULENCEELEMENT
 
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::)
@@ -3296,16 +3342,29 @@ nsSVGFETurbulenceElement::Filter(nsSVGFi
       targetData[targIndex + GFX_ARGB32_OFFSET_R] = r;
       targetData[targIndex + GFX_ARGB32_OFFSET_A] = a;
     }
   }
 
   return NS_OK;
 }
 
+bool
+nsSVGFETurbulenceElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                    nsIAtom* aAttribute) const
+{
+  return nsSVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::seed ||
+           aAttribute == nsGkAtoms::baseFrequency ||
+           aAttribute == nsGkAtoms::numOctaves ||
+           aAttribute == nsGkAtoms::type ||
+           aAttribute == nsGkAtoms::stitchTiles));
+}
+
 void
 nsSVGFETurbulenceElement::InitSeed(PRInt32 aSeed)
 {
   double s;
   int i, j, k;
   aSeed = SetupSeed(aSeed);
   for (k = 0; k < 4; k++) {
     for (i = 0; i < sBSize; i++) {
@@ -3520,16 +3579,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMorphologyElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
           const nsSVGFilterInstance& aInstance);
   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
           const nsSVGFilterInstance& aInstance);
@@ -3793,16 +3854,27 @@ nsSVGFEMorphologyElement::Filter(nsSVGFi
       targetData[targIndex+1] = extrema[1];
       targetData[targIndex+2] = extrema[2];
       targetData[targIndex+3] = extrema[3];
     }
   }
   return NS_OK;
 }
 
+bool
+nsSVGFEMorphologyElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                    nsIAtom* aAttribute) const
+{
+  return nsSVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::radius ||
+           aAttribute == nsGkAtoms::_operator));
+}
+
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 nsSVGElement::NumberPairAttributesInfo
 nsSVGFEMorphologyElement::GetNumberPairInfo()
 {
   return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
                                   ArrayLength(sNumberPairInfo));
@@ -3841,16 +3913,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEConvolveMatrixElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
           const nsSVGFilterInstance& aInstance);
   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
           const nsSVGFilterInstance& aInstance);
@@ -4251,16 +4325,34 @@ nsSVGFEConvolveMatrixElement::Filter(nsS
     }
   }
 
   FinishScalingFilter(&info);
 
   return NS_OK;
 }
 
+bool
+nsSVGFEConvolveMatrixElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                        nsIAtom* aAttribute) const
+{
+  return nsSVGFEConvolveMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::divisor ||
+           aAttribute == nsGkAtoms::bias ||
+           aAttribute == nsGkAtoms::kernelUnitLength ||
+           aAttribute == nsGkAtoms::targetX ||
+           aAttribute == nsGkAtoms::targetY ||
+           aAttribute == nsGkAtoms::order ||
+           aAttribute == nsGkAtoms::preserveAlpha||
+           aAttribute == nsGkAtoms::edgeMode ||
+           aAttribute == nsGkAtoms::kernelMatrix));
+}
+
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 nsSVGElement::NumberAttributesInfo
 nsSVGFEConvolveMatrixElement::GetNumberInfo()
 {
   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
                               ArrayLength(sNumberInfo));
@@ -4312,17 +4404,17 @@ nsSVGElement::NumberListAttributesInfo
 nsSVGFEConvolveMatrixElement::GetNumberListInfo()
 {
   return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
                                   ArrayLength(sNumberListInfo));
 }
 
 //---------------------DistantLight------------------------
 
-typedef nsSVGElement nsSVGFEDistantLightElementBase;
+typedef SVGFEUnstyledElement nsSVGFEDistantLightElementBase;
 
 class nsSVGFEDistantLightElement : public nsSVGFEDistantLightElementBase,
                                    public nsIDOMSVGFEDistantLightElement
 {
   friend nsresult NS_NewSVGFEDistantLightElement(nsIContent **aResult,
                                                  already_AddRefed<nsINodeInfo> aNodeInfo);
 protected:
   nsSVGFEDistantLightElement(already_AddRefed<nsINodeInfo> aNodeInfo)
@@ -4332,24 +4424,24 @@ public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGFEDISTANTLIGHTELEMENT
 
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEDistantLightElementBase::)
   NS_FORWARD_NSIDOMNODE(nsSVGFEDistantLightElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGFEDistantLightElementBase::)
 
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
+
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   virtual NumberAttributesInfo GetNumberInfo();
-  virtual void DidAnimateNumber(PRUint8 aAttrEnum) {
-    DidAnimateAttrViaParent(this);
-  }
 
   enum { AZIMUTH, ELEVATION };
   nsSVGNumber2 mNumberAttributes[2];
   static NumberInfo sNumberInfo[2];
 };
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(FEDistantLight)
 
@@ -4375,16 +4467,28 @@ NS_INTERFACE_TABLE_HEAD(nsSVGFEDistantLi
 NS_INTERFACE_MAP_END_INHERITING(nsSVGFEDistantLightElementBase)
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEDistantLightElement)
 
 //----------------------------------------------------------------------
+// nsFEUnstyledElement methods
+
+bool
+nsSVGFEDistantLightElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                      nsIAtom* aAttribute) const
+{
+  return aNameSpaceID == kNameSpaceID_None &&
+         (aAttribute == nsGkAtoms::azimuth ||
+          aAttribute == nsGkAtoms::elevation);
+}
+
+//----------------------------------------------------------------------
 // nsIDOMSVGFEDistantLightElement methods
 
 NS_IMETHODIMP
 nsSVGFEDistantLightElement::GetAzimuth(nsIDOMSVGAnimatedNumber **aAzimuth)
 {
   return mNumberAttributes[AZIMUTH].ToDOMAnimatedNumber(aAzimuth,
                                                         this);
 }
@@ -4403,17 +4507,17 @@ nsSVGElement::NumberAttributesInfo
 nsSVGFEDistantLightElement::GetNumberInfo()
 {
   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
                               ArrayLength(sNumberInfo));
 }
 
 //---------------------PointLight------------------------
 
-typedef nsSVGElement nsSVGFEPointLightElementBase;
+typedef SVGFEUnstyledElement nsSVGFEPointLightElementBase;
 
 class nsSVGFEPointLightElement : public nsSVGFEPointLightElementBase,
                                  public nsIDOMSVGFEPointLightElement
 {
   friend nsresult NS_NewSVGFEPointLightElement(nsIContent **aResult,
                                                  already_AddRefed<nsINodeInfo> aNodeInfo);
 protected:
   nsSVGFEPointLightElement(already_AddRefed<nsINodeInfo> aNodeInfo)
@@ -4423,24 +4527,24 @@ public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGFEPOINTLIGHTELEMENT
 
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEPointLightElementBase::)
   NS_FORWARD_NSIDOMNODE(nsSVGFEPointLightElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGFEPointLightElementBase::)
 
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
+
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   virtual NumberAttributesInfo GetNumberInfo();
-  virtual void DidAnimateNumber(PRUint8 aAttrEnum) {
-    DidAnimateAttrViaParent(this);
-  }
 
   enum { X, Y, Z };
   nsSVGNumber2 mNumberAttributes[3];
   static NumberInfo sNumberInfo[3];
 };
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(FEPointLight)
 
@@ -4467,16 +4571,29 @@ NS_INTERFACE_TABLE_HEAD(nsSVGFEPointLigh
 NS_INTERFACE_MAP_END_INHERITING(nsSVGFEPointLightElementBase)
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEPointLightElement)
 
 //----------------------------------------------------------------------
+// nsFEUnstyledElement methods
+
+bool
+nsSVGFEPointLightElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                    nsIAtom* aAttribute) const
+{
+  return aNameSpaceID == kNameSpaceID_None &&
+         (aAttribute == nsGkAtoms::x ||
+          aAttribute == nsGkAtoms::y ||
+          aAttribute == nsGkAtoms::z);
+}
+
+//----------------------------------------------------------------------
 // nsIDOMSVGFEPointLightElement methods
 
 NS_IMETHODIMP
 nsSVGFEPointLightElement::GetX(nsIDOMSVGAnimatedNumber **aX)
 {
   return mNumberAttributes[X].ToDOMAnimatedNumber(aX, this);
 }
 
@@ -4499,17 +4616,17 @@ nsSVGElement::NumberAttributesInfo
 nsSVGFEPointLightElement::GetNumberInfo()
 {
   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
                               ArrayLength(sNumberInfo));
 }
 
 //---------------------SpotLight------------------------
 
-typedef nsSVGElement nsSVGFESpotLightElementBase;
+typedef SVGFEUnstyledElement nsSVGFESpotLightElementBase;
 
 class nsSVGFESpotLightElement : public nsSVGFESpotLightElementBase,
                                 public nsIDOMSVGFESpotLightElement
 {
   friend nsresult NS_NewSVGFESpotLightElement(nsIContent **aResult,
                                               already_AddRefed<nsINodeInfo> aNodeInfo);
   friend class nsSVGFELightingElement;
 protected:
@@ -4520,24 +4637,24 @@ public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGFESPOTLIGHTELEMENT
 
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFESpotLightElementBase::)
   NS_FORWARD_NSIDOMNODE(nsSVGFESpotLightElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGFESpotLightElementBase::)
 
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
+
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   virtual NumberAttributesInfo GetNumberInfo();
-  virtual void DidAnimateNumber(PRUint8 aAttrEnum) {
-    DidAnimateAttrViaParent(this);
-  }
 
   enum { X, Y, Z, POINTS_AT_X, POINTS_AT_Y, POINTS_AT_Z,
          SPECULAR_EXPONENT, LIMITING_CONE_ANGLE };
   nsSVGNumber2 mNumberAttributes[8];
   static NumberInfo sNumberInfo[8];
 };
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(FESpotLight)
@@ -4570,16 +4687,34 @@ NS_INTERFACE_TABLE_HEAD(nsSVGFESpotLight
 NS_INTERFACE_MAP_END_INHERITING(nsSVGFESpotLightElementBase)
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFESpotLightElement)
 
 //----------------------------------------------------------------------
+// nsFEUnstyledElement methods
+
+bool
+nsSVGFESpotLightElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                   nsIAtom* aAttribute) const
+{
+  return aNameSpaceID == kNameSpaceID_None &&
+         (aAttribute == nsGkAtoms::x ||
+          aAttribute == nsGkAtoms::y ||
+          aAttribute == nsGkAtoms::z ||
+          aAttribute == nsGkAtoms::pointsAtX ||
+          aAttribute == nsGkAtoms::pointsAtY ||
+          aAttribute == nsGkAtoms::pointsAtZ ||
+          aAttribute == nsGkAtoms::specularExponent ||
+          aAttribute == nsGkAtoms::limitingConeAngle);
+}
+
+//----------------------------------------------------------------------
 // nsIDOMSVGFESpotLightElement methods
 
 NS_IMETHODIMP
 nsSVGFESpotLightElement::GetX(nsIDOMSVGAnimatedNumber **aX)
 {
   return mNumberAttributes[X].ToDOMAnimatedNumber(aX, this);
 }
 
@@ -4653,16 +4788,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFELightingElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
   // XXX shouldn't we have ComputeTargetBBox here, since the output can
   // extend beyond the bounds of the inputs thanks to the convolution kernel?
   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
           const nsSVGFilterInstance& aInstance);
@@ -4980,16 +5117,27 @@ nsSVGFELightingElement::Filter(nsSVGFilt
     }
   }
 
   FinishScalingFilter(&info);
 
   return NS_OK;
 }
 
+bool
+nsSVGFELightingElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                  nsIAtom* aAttribute) const
+{
+  return nsSVGFELightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::surfaceScale ||
+           aAttribute == nsGkAtoms::kernelUnitLength));
+}
+
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 nsSVGElement::NumberAttributesInfo
 nsSVGFELightingElement::GetNumberInfo()
 {
   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
                               ArrayLength(sNumberInfo));
@@ -5029,16 +5177,19 @@ public:
   // DiffuseLighting
   NS_DECL_NSIDOMSVGFEDIFFUSELIGHTINGELEMENT
 
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEDiffuseLightingElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEDiffuseLightingElementBase::)
   NS_FORWARD_NSIDOMNODE(nsSVGFEDiffuseLightingElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGFEDiffuseLightingElementBase::)
 
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
+
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   virtual void LightPixel(const float *N, const float *L,
                           nscolor color, PRUint8 *targetData);
 
 };
@@ -5100,16 +5251,25 @@ nsSVGFEDiffuseLightingElement::GetKernel
 NS_IMETHODIMP
 nsSVGFEDiffuseLightingElement::GetKernelUnitLengthY(nsIDOMSVGAnimatedNumber **aKernelY)
 {
   return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(aKernelY,
                                                                        nsSVGNumberPair::eSecond,
                                                                        this);
 }
 
+bool
+nsSVGFEDiffuseLightingElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                         nsIAtom* aAttribute) const
+{
+  return nsSVGFEDiffuseLightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          aAttribute == nsGkAtoms::diffuseConstant);
+}
+
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 void
 nsSVGFEDiffuseLightingElement::LightPixel(const float *N, const float *L,
                                           nscolor color, PRUint8 *targetData)
 {
   float diffuseNL =
@@ -5157,16 +5317,18 @@ public:
   NS_FORWARD_NSIDOMELEMENT(nsSVGFESpecularLightingElementBase::)
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   virtual void LightPixel(const float *N, const float *L,
                           nscolor color, PRUint8 *targetData);
 
 };
 
@@ -5252,16 +5414,25 @@ nsSVGFESpecularLightingElement::Filter(n
 
   // specification defined range (15.22)
   if (specularExponent < 1 || specularExponent > 128)
     return NS_ERROR_FAILURE;
 
   return nsSVGFESpecularLightingElementBase::Filter(instance, aSources, aTarget, rect);
 }
 
+bool
+nsSVGFESpecularLightingElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                          nsIAtom* aAttribute) const
+{
+  return nsSVGFESpecularLightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::specularConstant ||
+           aAttribute == nsGkAtoms::specularExponent));
+}
 
 void
 nsSVGFESpecularLightingElement::LightPixel(const float *N, const float *L,
                                            nscolor color, PRUint8 *targetData)
 {
   float H[3];
   H[0] = L[0];
   H[1] = L[1];
@@ -5291,100 +5462,16 @@ nsSVGFESpecularLightingElement::LightPix
     targetData[GFX_ARGB32_OFFSET_G] = 0;
     targetData[GFX_ARGB32_OFFSET_R] = 0;
     targetData[GFX_ARGB32_OFFSET_A] = 255;
   }
 }
 
 //---------------------Image------------------------
 
-typedef nsSVGFE nsSVGFEImageElementBase;
-
-class nsSVGFEImageElement : public nsSVGFEImageElementBase,
-                            public nsIDOMSVGFEImageElement,
-                            public nsIDOMSVGURIReference,
-                            public nsImageLoadingContent
-{
-protected:
-  friend nsresult NS_NewSVGFEImageElement(nsIContent **aResult,
-                                          already_AddRefed<nsINodeInfo> aNodeInfo);
-  nsSVGFEImageElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  virtual ~nsSVGFEImageElement();
-
-public:
-  virtual bool SubregionIsUnionOfRegions() { return false; }
-
-  // interfaces:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // FE Base
-  NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEImageElementBase::)
-
-  virtual nsresult Filter(nsSVGFilterInstance* aInstance,
-                          const nsTArray<const Image*>& aSources,
-                          const Image* aTarget,
-                          const nsIntRect& aDataRect);
-  virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
-  virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
-          const nsSVGFilterInstance& aInstance);
-
-  NS_DECL_NSIDOMSVGFEIMAGEELEMENT
-  NS_DECL_NSIDOMSVGURIREFERENCE
-
-  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEImageElementBase::)
-
-  NS_FORWARD_NSIDOMNODE(nsSVGFEImageElementBase::)
-  NS_FORWARD_NSIDOMELEMENT(nsSVGFEImageElementBase::)
-
-  // nsIContent
-  NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
-
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-  virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
-                                const nsAString* aValue, bool aNotify);
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers);
-  virtual nsEventStates IntrinsicState() const;
-
-  // imgIDecoderObserver
-  NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
-                          const PRUnichar *statusArg);
-  // imgIContainerObserver
-  NS_IMETHOD FrameChanged(imgIContainer *aContainer,
-                          const nsIntRect *aDirtyRect);
-  // imgIContainerObserver
-  NS_IMETHOD OnStartContainer(imgIRequest *aRequest,
-                              imgIContainer *aContainer);
-
-  void MaybeLoadSVGImage();
-
-  virtual nsXPCClassInfo* GetClassInfo();
-private:
-  // Invalidate users of the filter containing this element.
-  void Invalidate();
-
-  nsresult LoadSVGImage(bool aForce, bool aNotify);
-
-protected:
-  virtual bool OperatesOnSRGB(nsSVGFilterInstance*,
-                                PRInt32, Image*) { return true; }
-
-  virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio();
-  virtual StringAttributesInfo GetStringInfo();
-  virtual void DidAnimateString(PRUint8 aAttrEnum);
-
-  enum { RESULT, HREF };
-  nsSVGString mStringAttributes[2];
-  static StringInfo sStringInfo[2];
-
-  SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
-};
-
 nsSVGElement::StringInfo nsSVGFEImageElement::sStringInfo[2] =
 {
   { &nsGkAtoms::result, kNameSpaceID_None, true },
   { &nsGkAtoms::href, kNameSpaceID_XLink, true }
 };
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(FEImage)
 
@@ -5463,20 +5550,32 @@ nsSVGFEImageElement::IsAttributeMapped(c
     nsSVGFEImageElementBase::IsAttributeMapped(name);
 }
 
 nsresult
 nsSVGFEImageElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                   const nsAString* aValue, bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_XLink && aName == nsGkAtoms::href) {
-    if (aValue) {
-      LoadSVGImage(true, aNotify);
-    } else {
-      CancelImageRequests(aNotify);
+
+    // If there isn't a frame we still need to load the image in case
+    // the frame is created later e.g. by attaching to a document.
+    // If there is a frame then it should deal with loading as the image
+    // url may be animated.
+    if (!GetPrimaryFrame()) {
+
+      // Prevent setting image.src by exiting early
+      if (nsContentUtils::IsImageSrcSetDisabled()) {
+        return NS_OK;
+      }
+      if (aValue) {
+        LoadSVGImage(true, aNotify);
+      } else {
+        CancelImageRequests(aNotify);
+      }
     }
   }
 
   return nsSVGFEImageElementBase::AfterSetAttr(aNamespaceID, aName,
                                                aValue, aNotify);
 }
 
 void
@@ -5586,16 +5685,27 @@ nsSVGFEImageElement::Filter(nsSVGFilterI
     
     nsRefPtr<gfxContext> ctx = new gfxContext(aTarget->mImage);
     nsSVGUtils::CompositePatternMatrix(ctx, thebesPattern, TM, nativeWidth, nativeHeight, 1.0);
   }
 
   return NS_OK;
 }
 
+bool
+nsSVGFEImageElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                               nsIAtom* aAttribute) const
+{
+  // nsGkAtoms::href is deliberately omitted as the frame has special
+  // handling to load the image
+  return nsSVGFEImageElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          aAttribute == nsGkAtoms::preserveAspectRatio);
+}
+
 nsIntRect
 nsSVGFEImageElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
         const nsSVGFilterInstance& aInstance)
 {
   // XXX can do better here ... we could check what we know of the source
   // image bounds and compute an accurate bounding box for the filter
   // primitive result.
   return GetMaxRect();
@@ -5612,27 +5722,16 @@ nsSVGFEImageElement::GetPreserveAspectRa
 
 nsSVGElement::StringAttributesInfo
 nsSVGFEImageElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               ArrayLength(sStringInfo));
 }
 
-void
-nsSVGFEImageElement::DidAnimateString(PRUint8 aAttrEnum)
-{
-  if (aAttrEnum == HREF) {
-    LoadSVGImage(true, false);
-    return;
-  }
-
-  nsSVGFEImageElementBase::DidAnimateString(aAttrEnum);
-}
-
 //----------------------------------------------------------------------
 // imgIDecoderObserver methods
 
 NS_IMETHODIMP
 nsSVGFEImageElement::OnStopDecode(imgIRequest *aRequest,
                                   nsresult status,
                                   const PRUnichar *statusArg)
 {
@@ -5699,16 +5798,18 @@ public:
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEDisplacementMapElementBase::)
 
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
           const nsSVGFilterInstance& aInstance);
   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
           const nsSVGFilterInstance& aInstance);
@@ -5898,16 +5999,29 @@ nsSVGFEDisplacementMapElement::Filter(ns
         *(PRUint32*)(targetData + targIndex) =
           *(PRUint32*)(sourceData + sourceY * stride + 4 * sourceX);
       }
     }
   }
   return NS_OK;
 }
 
+bool
+nsSVGFEDisplacementMapElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
+                                                         nsIAtom* aAttribute) const
+{
+  return nsSVGFEDisplacementMapElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::in2 ||
+           aAttribute == nsGkAtoms::scale ||
+           aAttribute == nsGkAtoms::xChannelSelector ||
+           aAttribute == nsGkAtoms::yChannelSelector));
+}
+
 void
 nsSVGFEDisplacementMapElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN2], this));
 }
 
 nsIntRect
--- a/content/svg/content/src/nsSVGFilters.h
+++ b/content/svg/content/src/nsSVGFilters.h
@@ -34,23 +34,26 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGFILTERSELEMENT_H__
 #define __NS_SVGFILTERSELEMENT_H__
 
 #include "nsSVGStylableElement.h"
 #include "nsSVGLength2.h"
+#include "nsSVGString.h"
 #include "nsIFrame.h"
 #include "gfxRect.h"
 #include "gfxImageSurface.h"
 #include "nsIDOMSVGFilters.h"
+#include "nsImageLoadingContent.h"
+#include "nsIDOMSVGURIReference.h"
+#include "SVGAnimatedPreserveAspectRatio.h"
 
 class nsSVGFilterResource;
-class nsSVGString;
 class nsSVGNumberPair;
 class nsSVGFilterInstance;
 
 struct nsSVGStringInfo {
   nsSVGStringInfo(const nsSVGString* aString,
                   nsSVGElement *aElement) :
     mString(aString), mElement(aElement) {}
 
@@ -59,16 +62,21 @@ struct nsSVGStringInfo {
 };
 
 typedef nsSVGStylableElement nsSVGFEBase;
 
 #define NS_SVG_FE_CID \
 { 0x60483958, 0xd229, 0x4a77, \
   { 0x96, 0xb2, 0x62, 0x3e, 0x69, 0x95, 0x1e, 0x0e } }
 
+/**
+ * Base class for filter primitive elements
+ * Children of those elements e.g. feMergeNode
+ * derive from SVGFEUnstyledElement instead
+ */
 class nsSVGFE : public nsSVGFEBase
 //, public nsIDOMSVGFilterPrimitiveStandardAttributes
 {
   friend class nsSVGFilterInstance;
 
 public:
   class ColorModel {
   public:
@@ -189,16 +197,21 @@ public:
   // filter primitive subregion for this filter element and the
   // temporary surface area. Output need not be clipped to this rect but
   // it must be clipped to aTarget->mFilterPrimitiveSubregion.
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray<const Image*>& aSources,
                           const Image* aTarget,
                           const nsIntRect& aDataRect) = 0;
 
+  // returns true if changes to the attribute should cause us to
+  // repaint the filter
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
+
   static nsIntRect GetMaxRect() {
     // Try to avoid overflow errors dealing with this rect. It will
     // be intersected with some other reasonable-sized rect eventually.
     return nsIntRect(PR_INT32_MIN/2, PR_INT32_MIN/2, PR_INT32_MAX, PR_INT32_MAX);
   }
 
   operator nsISupports*() { return static_cast<nsIContent*>(this); }
   
@@ -215,26 +228,118 @@ protected:
 
     nsStyleContext* style = frame->GetStyleContext();
     return style->GetStyleSVG()->mColorInterpolationFilters ==
              NS_STYLE_COLOR_INTERPOLATION_SRGB;
   }
 
   // nsSVGElement specializations:
   virtual LengthAttributesInfo GetLengthInfo();
-  virtual void DidAnimateLength(PRUint8 aAttrEnum);
-  virtual void DidAnimateNumber(PRUint8 aAttrEnum);
-  virtual void DidAnimateNumberPair(PRUint8 aAttrEnum);
-  virtual void DidAnimateNumberList(PRUint8 aAttrEnum);
-  virtual void DidAnimateInteger(PRUint8 aAttrEnum);
-  virtual void DidAnimateIntegerPair(PRUint8 aAttrEnum);
-  virtual void DidAnimateEnum(PRUint8 aAttrEnum);
-  virtual void DidAnimateBoolean(PRUint8 aAttrEnum);
-  virtual void DidAnimatePreserveAspectRatio();
-  virtual void DidAnimateString(PRUint8 aAttrEnum);
 
   // nsIDOMSVGFitlerPrimitiveStandardAttributes values
   enum { X, Y, WIDTH, HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
 };
 
+typedef nsSVGFE nsSVGFEImageElementBase;
+
+class nsSVGFEImageElement : public nsSVGFEImageElementBase,
+                            public nsIDOMSVGFEImageElement,
+                            public nsIDOMSVGURIReference,
+                            public nsImageLoadingContent
+{
+  friend class SVGFEImageFrame;
+
+protected:
+  friend nsresult NS_NewSVGFEImageElement(nsIContent **aResult,
+                                          already_AddRefed<nsINodeInfo> aNodeInfo);
+  nsSVGFEImageElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~nsSVGFEImageElement();
+
+public:
+  virtual bool SubregionIsUnionOfRegions() { return false; }
+
+  // interfaces:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // FE Base
+  NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEImageElementBase::)
+
+  virtual nsresult Filter(nsSVGFilterInstance* aInstance,
+                          const nsTArray<const Image*>& aSources,
+                          const Image* aTarget,
+                          const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
+  virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
+  virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
+          const nsSVGFilterInstance& aInstance);
+
+  NS_DECL_NSIDOMSVGFEIMAGEELEMENT
+  NS_DECL_NSIDOMSVGURIREFERENCE
+
+  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEImageElementBase::)
+
+  NS_FORWARD_NSIDOMNODE(nsSVGFEImageElementBase::)
+  NS_FORWARD_NSIDOMELEMENT(nsSVGFEImageElementBase::)
+
+  // nsIContent
+  NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
+                                const nsAString* aValue, bool aNotify);
+  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              bool aCompileEventHandlers);
+  virtual nsEventStates IntrinsicState() const;
+
+  // imgIDecoderObserver
+  NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
+                          const PRUnichar *statusArg);
+  // imgIContainerObserver
+  NS_IMETHOD FrameChanged(imgIContainer *aContainer,
+                          const nsIntRect *aDirtyRect);
+  // imgIContainerObserver
+  NS_IMETHOD OnStartContainer(imgIRequest *aRequest,
+                              imgIContainer *aContainer);
+
+  void MaybeLoadSVGImage();
+
+  virtual nsXPCClassInfo* GetClassInfo();
+private:
+  // Invalidate users of the filter containing this element.
+  void Invalidate();
+
+  nsresult LoadSVGImage(bool aForce, bool aNotify);
+
+protected:
+  virtual bool OperatesOnSRGB(nsSVGFilterInstance*,
+                                PRInt32, Image*) { return true; }
+
+  virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio();
+  virtual StringAttributesInfo GetStringInfo();
+
+  enum { RESULT, HREF };
+  nsSVGString mStringAttributes[2];
+  static StringInfo sStringInfo[2];
+
+  SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
+};
+
+typedef nsSVGElement SVGFEUnstyledElementBase;
+
+class SVGFEUnstyledElement : public SVGFEUnstyledElementBase
+{
+protected:
+  SVGFEUnstyledElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+    : SVGFEUnstyledElementBase(aNodeInfo) {}
+
+public:
+  // returns true if changes to the attribute should cause us to
+  // repaint the filter
+  virtual bool AttributeAffectsRendering(
+          PRInt32 aNameSpaceID, nsIAtom* aAttribute) const = 0;
+};
+
 #endif
--- a/content/svg/content/src/nsSVGImageElement.cpp
+++ b/content/svg/content/src/nsSVGImageElement.cpp
@@ -168,17 +168,20 @@ nsSVGImageElement::LoadSVGImage(bool aFo
 // nsIContent methods:
 
 nsresult
 nsSVGImageElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                 const nsAString* aValue, bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_XLink && aName == nsGkAtoms::href) {
 
-    // If there's a frame it will deal
+    // If there isn't a frame we still need to load the image in case
+    // the frame is created later e.g. by attaching to a document.
+    // If there is a frame then it should deal with loading as the image
+    // url may be animated
     if (!GetPrimaryFrame()) {
 
       // Prevent setting image.src by exiting early
       if (nsContentUtils::IsImageSrcSetDisabled()) {
         return NS_OK;
       }
 
       if (aValue) {
--- a/content/svg/content/src/nsSVGPathElement.cpp
+++ b/content/svg/content/src/nsSVGPathElement.cpp
@@ -422,22 +422,30 @@ nsSVGPathElement::GetMarkPoints(nsTArray
 
 void
 nsSVGPathElement::ConstructPath(gfxContext *aCtx)
 {
   mD.GetAnimValue().ConstructPath(aCtx);
 }
 
 gfxFloat
-nsSVGPathElement::GetPathLengthScale()
+nsSVGPathElement::GetPathLengthScale(PathLengthScaleForType aFor)
 {
+  NS_ABORT_IF_FALSE(aFor == eForTextPath || aFor == eForStroking,
+                    "Unknown enum");
   if (mPathLength.IsExplicitlySet()) {
-
-    nsRefPtr<gfxFlattenedPath> flat =
-      GetFlattenedPath(PrependLocalTransformTo(gfxMatrix()));
-    float pathLength = mPathLength.GetAnimValue();
-
-    if (flat && pathLength != 0) {
-      return flat->GetLength() / pathLength;
+    float authorsPathLengthEstimate = mPathLength.GetAnimValue();
+    if (authorsPathLengthEstimate > 0) {
+      gfxMatrix matrix;
+      if (aFor == eForTextPath) {
+        // For textPath, a transform on the referenced path affects the
+        // textPath layout, so when calculating the actual path length
+        // we need to take that into account.
+        matrix = PrependLocalTransformTo(gfxMatrix());
+      }
+      nsRefPtr<gfxFlattenedPath> path = GetFlattenedPath(matrix);
+      if (path) {
+        return path->GetLength() / authorsPathLengthEstimate;
+      }
     }
   }
   return 1.0;
 }
--- a/content/svg/content/src/nsSVGPathElement.h
+++ b/content/svg/content/src/nsSVGPathElement.h
@@ -93,22 +93,27 @@ public:
   virtual SVGAnimatedPathSegList* GetAnimPathSegList() {
     return &mD;
   }
 
   virtual nsIAtom* GetPathDataAttrName() const {
     return nsGkAtoms::d;
   }
 
+  enum PathLengthScaleForType {
+    eForTextPath,
+    eForStroking
+  };
+
   /**
    * Gets the ratio of the actual path length to the content author's estimated
    * length (as provided by the <path> element's 'pathLength' attribute). This
    * is used to scale stroke dashing, and to scale offsets along a textPath.
    */
-  gfxFloat GetPathLengthScale();
+  gfxFloat GetPathLengthScale(PathLengthScaleForType aFor);
 
 protected:
 
   // nsSVGElement method
   virtual NumberAttributesInfo GetNumberInfo();
 
   SVGAnimatedPathSegList mD;
   nsSVGNumber2 mPathLength;
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -63,17 +63,16 @@
 
 #include "nsIViewManager.h"
 
 #include "nsIDOMHTMLCanvasElement.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "nsLayoutUtils.h"
 #include "nsComputedDOMStyle.h"
-#include "nsIViewObserver.h"
 #include "nsIPresShell.h"
 #include "nsStyleAnimation.h"
 #include "nsCSSProps.h"
 #include "nsDOMFile.h"
 #include "BasicLayers.h"
 
 #if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2)
 #include <gdk/gdk.h>
@@ -470,31 +469,28 @@ nsDOMWindowUtils::SendMouseEventCommon(c
                           appPerDev);
   event.refPoint.y =
     NSAppUnitsToIntPixels(nsPresContext::CSSPixelsToAppUnits(aY) + offset.y,
                           appPerDev);
   event.ignoreRootScrollFrame = aIgnoreRootScrollFrame;
 
   nsEventStatus status;
   if (aToWindow) {
-    nsIPresShell* presShell = presContext->PresShell();
+    nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
     if (!presShell)
       return NS_ERROR_FAILURE;
-    nsCOMPtr<nsIViewObserver> vo = do_QueryInterface(presShell);
-    if (!vo)
-      return NS_ERROR_FAILURE;
     nsIViewManager* viewManager = presShell->GetViewManager();
     if (!viewManager)
       return NS_ERROR_FAILURE;
     nsIView* view = viewManager->GetRootView();
     if (!view)
       return NS_ERROR_FAILURE;
 
     status = nsEventStatus_eIgnore;
-    return vo->HandleEvent(view, &event, false, &status);
+    return presShell->HandleEvent(view->GetFrame(), &event, false, &status);
   }
   return widget->DispatchEvent(&event, status);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendMouseScrollEvent(const nsAString& aType,
                                        float aX,
                                        float aY,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -761,17 +761,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTimeout, Release)
 
 nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
 : mFrameElement(nsnull), mDocShell(nsnull), mModalStateDepth(0),
   mRunningTimeout(nsnull), mMutationBits(0), mIsDocumentLoaded(false),
   mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nsnull),
   mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
-  mMayHaveAudioAvailableEventListener(false),
   mMayHaveMouseEnterLeaveEventListener(false),
   mIsModalContentWindow(false),
   mIsActive(false), mIsBackground(false),
   mInnerWindow(nsnull), mOuterWindow(aOuterWindow),
   // Make sure no actual window ends up with mWindowID == 0
   mWindowID(++gNextWindowID), mHasNotifiedGlobalCreated(false)
  {}
 
@@ -10674,16 +10673,24 @@ nsGlobalModalWindow::SetNewDocument(nsID
   if (aDocument) {
     mReturnValue = nsnull;
   }
 
   return nsGlobalWindow::SetNewDocument(aDocument, aState,
                                         aForceReuseInnerWindow);
 }
 
+void
+nsGlobalWindow::SetHasAudioAvailableEventListeners()
+{
+  if (mDoc) {
+    mDoc->NotifyAudioAvailableListener();
+  }
+}
+
 //*****************************************************************************
 // nsGlobalWindow: Creator Function (This should go away)
 //*****************************************************************************
 
 nsresult
 NS_NewScriptGlobalObject(bool aIsChrome, bool aIsModalContentWindow,
                          nsIScriptGlobalObject **aResult)
 {
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -442,16 +442,18 @@ public:
   // Ask the user if further dialogs should be blocked. This is used
   // in the cases where we have no modifiable UI to show, in that case
   // we show a separate dialog when asking this question.
   bool ConfirmDialogAllowed();
 
   // Prevent further dialogs in this (top level) window
   void PreventFurtherDialogs();
 
+  virtual void SetHasAudioAvailableEventListeners();
+
   nsIScriptContext *GetContextInternal()
   {
     if (mOuterWindow) {
       return GetOuterWindowInternal()->mContext;
     }
 
     return mContext;
   }
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -75,18 +75,18 @@ class nsIDocument;
 class nsIScriptTimeoutHandler;
 struct nsTimeout;
 class nsScriptObjectHolder;
 class nsXBLPrototypeHandler;
 class nsIArray;
 class nsPIWindowRoot;
 
 #define NS_PIDOMWINDOW_IID \
-{ 0x8ce567b5, 0xcc8d, 0x410b, \
-  { 0xa2, 0x7b, 0x07, 0xaf, 0x31, 0xc0, 0x33, 0xb8 } }
+{ 0x9db588f7, 0x3472, 0x45d0, \
+  { 0x9f, 0x9b, 0x95, 0xca, 0xf6, 0x4d, 0x1a, 0xb1 } }
 
 class nsPIDOMWindow : public nsIDOMWindowInternal
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_IID)
 
   virtual nsPIDOMWindow* GetPrivateRoot() = 0;
 
@@ -453,32 +453,20 @@ public:
   }
 
   bool HasTouchEventListeners()
   {
     return mMayHaveTouchEventListener;
   }
 
   /**
-   * Call this to check whether some node (this window, its document,
-   * or content in that document) has a MozAudioAvailable event listener.
+   * Call this to indicate that some node (this window, its document,
+   * or content in that document) has a "MozAudioAvailable" event listener.
    */
-  bool HasAudioAvailableEventListeners()
-  {
-    return mMayHaveAudioAvailableEventListener;
-  }
-
-  /**
-   * Call this to indicate that some node (this window, its document,
-   * or content in that document) has a MozAudioAvailable event listener.
-   */
-  void SetHasAudioAvailableEventListeners()
-  {
-    mMayHaveAudioAvailableEventListener = true;
-  }
+  virtual void SetHasAudioAvailableEventListeners() = 0;
 
   /**
    * Call this to check whether some node (this window, its document,
    * or content in that document) has a mouseenter/leave event listener.
    */
   bool HasMouseEnterLeaveEventListeners()
   {
     return mMayHaveMouseEnterLeaveEventListener;
@@ -652,17 +640,16 @@ protected:
 
   PRUint32               mMutationBits;
 
   bool                   mIsDocumentLoaded;
   bool                   mIsHandlingResizeEvent;
   bool                   mIsInnerWindow;
   bool                   mMayHavePaintEventListener;
   bool                   mMayHaveTouchEventListener;
-  bool                   mMayHaveAudioAvailableEventListener;
   bool                   mMayHaveMouseEnterLeaveEventListener;
 
   // This variable is used on both inner and outer windows (and they
   // should match).
   bool                   mIsModalContentWindow;
 
   // Tracks activation state that's used for :-moz-window-inactive.
   // Only used on outer windows.
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -1155,65 +1155,66 @@ OpenKeyCursorHelper::DoDatabaseWork(mozI
 
   switch (mDirection) {
     case nsIIDBCursor::NEXT:
       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Upper();
       }
-      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( value = :") +
-                       currentKey + NS_LITERAL_CSTRING(" AND ") + keyColumn +
+      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") +
+                       currentKey + NS_LITERAL_CSTRING(" AND ( value > :") +
+                       currentKey + NS_LITERAL_CSTRING(" OR ") + keyColumn +
                        NS_LITERAL_CSTRING(" > :") + objectKey +
-                       NS_LITERAL_CSTRING(" ) OR ( value > :") + currentKey +
-                       NS_LITERAL_CSTRING(" ) )") + directionClause +
-                       NS_LITERAL_CSTRING(" LIMIT 1");
+                       NS_LITERAL_CSTRING(" )") + directionClause +
+                       NS_LITERAL_CSTRING(" LIMIT ");
       mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") +
                          currentKey + NS_LITERAL_CSTRING(" LIMIT ");
       break;
 
     case nsIIDBCursor::NEXT_NO_DUPLICATE:
       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Upper();
       }
       mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value > :") +
                        currentKey + directionClause +
-                       NS_LITERAL_CSTRING(" LIMIT 1");
+                       NS_LITERAL_CSTRING(" LIMIT ");
       mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") +
                          currentKey + directionClause +
                          NS_LITERAL_CSTRING(" LIMIT ");
       break;
 
     case nsIIDBCursor::PREV:
       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Lower();
       }
-      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( value = :") +
-                       currentKey + NS_LITERAL_CSTRING(" AND ") + keyColumn +
+
+      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") +
+                       currentKey + NS_LITERAL_CSTRING(" AND ( value < :") +
+                       currentKey + NS_LITERAL_CSTRING(" OR ") + keyColumn +
                        NS_LITERAL_CSTRING(" < :") + objectKey +
-                       NS_LITERAL_CSTRING(" ) OR ( value < :") + currentKey +
-                       NS_LITERAL_CSTRING(" ) )") + directionClause +
-                       NS_LITERAL_CSTRING(" LIMIT 1");
+                       NS_LITERAL_CSTRING(" ) ") + directionClause +
+                       NS_LITERAL_CSTRING(" LIMIT ");
       mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") +
                          currentKey + NS_LITERAL_CSTRING(" LIMIT ");
       break;
 
     case nsIIDBCursor::PREV_NO_DUPLICATE:
       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Lower();
       }
       mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value < :") +
                        currentKey + directionClause +
-                       NS_LITERAL_CSTRING(" LIMIT 1");
+                       NS_LITERAL_CSTRING(" LIMIT ");
       mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") +
                          currentKey + directionClause +
                          NS_LITERAL_CSTRING(" LIMIT ");
       break;
 
     default:
       NS_NOTREACHED("Unknown direction type!");
   }
@@ -1246,41 +1247,38 @@ OpenCursorHelper::DoDatabaseWork(mozISto
   nsCString indexTable;
   nsCString objectTable;
   nsCString objectDataIdColumn;
   nsCString keyValueColumn;
 
   if (mIndex->IsAutoIncrement()) {
     objectTable.AssignLiteral("ai_object_data");
     objectDataIdColumn.AssignLiteral("ai_object_data_id");
-    keyValueColumn.AssignLiteral("id");
+    keyValueColumn.AssignLiteral("ai_object_data_id");
     if (mIndex->IsUnique()) {
       indexTable.AssignLiteral("ai_unique_index_data");
     }
     else {
       indexTable.AssignLiteral("ai_index_data");
     }
   }
   else {
     objectTable.AssignLiteral("object_data");
     objectDataIdColumn.AssignLiteral("object_data_id");
-    keyValueColumn.AssignLiteral("key_value");
+    keyValueColumn.AssignLiteral("object_data_key");
     if (mIndex->IsUnique()) {
       indexTable.AssignLiteral("unique_index_data");
     }
     else {
       indexTable.AssignLiteral("index_data");
     }
   }
 
-  NS_NAMED_LITERAL_CSTRING(id, "id");
-
   nsCString value = indexTable + NS_LITERAL_CSTRING(".value");
-  nsCString data = objectTable + NS_LITERAL_CSTRING(".data");
-  nsCString keyValue = objectTable + NS_LITERAL_CSTRING(".") + keyValueColumn;
+  nsCString keyValue = indexTable + NS_LITERAL_CSTRING(".") + keyValueColumn;
 
   nsCString keyRangeClause;
   if (mKeyRange) {
     mKeyRange->GetBindingClause(value, keyRangeClause);
   }
 
   nsCAutoString directionClause = NS_LITERAL_CSTRING(" ORDER BY ") + value;
   switch (mDirection) {
@@ -1299,26 +1297,31 @@ OpenCursorHelper::DoDatabaseWork(mozISto
       directionClause += NS_LITERAL_CSTRING(" DESC, ") + keyValue +
                          NS_LITERAL_CSTRING(" ASC");
       break;
 
     default:
       NS_NOTREACHED("Unknown direction!");
   }
 
-  nsCString firstQuery = NS_LITERAL_CSTRING("SELECT ") + value +
-                         NS_LITERAL_CSTRING(", ") + keyValue +
-                         NS_LITERAL_CSTRING(", ") + data +
-                         NS_LITERAL_CSTRING(" FROM ") + objectTable +
-                         NS_LITERAL_CSTRING(" INNER JOIN ") + indexTable +
-                         NS_LITERAL_CSTRING(" ON ") + indexTable +
-                         NS_LITERAL_CSTRING(".") + objectDataIdColumn +
-                         NS_LITERAL_CSTRING(" = ") + objectTable +
-                         NS_LITERAL_CSTRING(".id WHERE ") + indexTable +
-                         NS_LITERAL_CSTRING(".index_id = :id") +
+  NS_NAMED_LITERAL_CSTRING(id, "id");
+  NS_NAMED_LITERAL_CSTRING(dot, ".");
+  NS_NAMED_LITERAL_CSTRING(commaspace, ", ");
+
+  nsCString data = objectTable + NS_LITERAL_CSTRING(".data");
+
+  nsCString firstQuery = NS_LITERAL_CSTRING("SELECT ") + value + commaspace +
+                         keyValue + commaspace + data +
+                         NS_LITERAL_CSTRING(" FROM ") + indexTable +
+                         NS_LITERAL_CSTRING(" INNER JOIN ") + objectTable +
+                         NS_LITERAL_CSTRING(" ON ") + indexTable + dot +
+                         objectDataIdColumn + NS_LITERAL_CSTRING(" = ") +
+                         objectTable + dot + id +
+                         NS_LITERAL_CSTRING(" WHERE ") + indexTable +
+                         NS_LITERAL_CSTRING(".index_id = :") + id +
                          keyRangeClause + directionClause +
                          NS_LITERAL_CSTRING(" LIMIT 1");
 
   nsCOMPtr<mozIStorageStatement> stmt =
     mTransaction->GetCachedStatement(firstQuery);
   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   mozStorageStatementScoper scoper(stmt);
@@ -1347,97 +1350,88 @@ OpenCursorHelper::DoDatabaseWork(mozISto
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 2,
                                                            mCloneBuffer);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Now we need to make the query to get the next match.
   nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT ") + value +
-                             NS_LITERAL_CSTRING(", ") + keyValue +
-                             NS_LITERAL_CSTRING(", ") + data +
-                             NS_LITERAL_CSTRING(" FROM ") + objectTable +
-                             NS_LITERAL_CSTRING(" INNER JOIN ") + indexTable +
-                             NS_LITERAL_CSTRING(" ON ") + indexTable +
-                             NS_LITERAL_CSTRING(".") + objectDataIdColumn +
-                             NS_LITERAL_CSTRING(" = ") + objectTable +
-                             NS_LITERAL_CSTRING(".id WHERE ") + indexTable +
-                             NS_LITERAL_CSTRING(".index_id = :id");
+                             commaspace + keyValue + commaspace + data +
+                             NS_LITERAL_CSTRING(" FROM ") + indexTable +
+                             NS_LITERAL_CSTRING(" INNER JOIN ") + objectTable +
+                             NS_LITERAL_CSTRING(" ON ") + indexTable + dot +
+                             objectDataIdColumn + NS_LITERAL_CSTRING(" = ") +
+                             objectTable + dot + id +
+                             NS_LITERAL_CSTRING(" WHERE ") + indexTable +
+                             NS_LITERAL_CSTRING(".index_id = :") + id;
 
   NS_NAMED_LITERAL_CSTRING(currentKey, "current_key");
   NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
   NS_NAMED_LITERAL_CSTRING(objectKey, "object_key");
 
+  NS_NAMED_LITERAL_CSTRING(andStr, " AND ");
+  NS_NAMED_LITERAL_CSTRING(orStr, " OR ");
+  NS_NAMED_LITERAL_CSTRING(ge, " >= :");
+  NS_NAMED_LITERAL_CSTRING(gt, " > :");
+  NS_NAMED_LITERAL_CSTRING(le, " <= :");
+  NS_NAMED_LITERAL_CSTRING(lt, " < :");
+  NS_NAMED_LITERAL_CSTRING(openparen, " ( ");
+  NS_NAMED_LITERAL_CSTRING(closeparen, " ) ");
+  NS_NAMED_LITERAL_CSTRING(limit, " LIMIT ");
+
   switch (mDirection) {
     case nsIIDBCursor::NEXT:
       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Upper();
       }
-      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( ") +
-                       value + NS_LITERAL_CSTRING(" = :") + currentKey +
-                       NS_LITERAL_CSTRING(" AND ") + keyValue +
-                       NS_LITERAL_CSTRING(" > :") + objectKey +
-                       NS_LITERAL_CSTRING(" ) OR ( ") + value +
-                       NS_LITERAL_CSTRING(" > :") + currentKey +
-                       NS_LITERAL_CSTRING(" ) )") + directionClause +
-                       NS_LITERAL_CSTRING(" LIMIT 1");
-      mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
-                         NS_LITERAL_CSTRING(" >= :") +
-                         currentKey + directionClause +
-                         NS_LITERAL_CSTRING(" LIMIT 1");
+      mContinueQuery = queryStart + andStr + value + ge + currentKey + andStr +
+                       openparen + value + gt + currentKey + orStr + keyValue +
+                       gt + objectKey + closeparen + directionClause + limit;
+      mContinueToQuery = queryStart + andStr + value + ge + currentKey +
+                         directionClause + limit;
       break;
 
     case nsIIDBCursor::NEXT_NO_DUPLICATE:
       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Upper();
       }
-      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
-                       NS_LITERAL_CSTRING(" > :") + currentKey +
-                       directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
-      mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
-                         NS_LITERAL_CSTRING(" >= :") + currentKey +
-                         directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
+      mContinueQuery = queryStart + andStr + value + gt + currentKey +
+                       directionClause + limit;
+      mContinueToQuery = queryStart + andStr + value + ge + currentKey +
+                         directionClause + limit;
       break;
 
     case nsIIDBCursor::PREV:
       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Lower();
       }
-      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( ") +
-                       value + NS_LITERAL_CSTRING(" = :") + currentKey +
-                       NS_LITERAL_CSTRING(" AND ") + keyValue +
-                       NS_LITERAL_CSTRING(" < :") + objectKey +
-                       NS_LITERAL_CSTRING(" ) OR ( ") + value +
-                       NS_LITERAL_CSTRING(" < :") + currentKey +
-                       NS_LITERAL_CSTRING(" ) )") + directionClause +
-                       NS_LITERAL_CSTRING(" LIMIT 1");
-      mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
-                         NS_LITERAL_CSTRING(" <= :") +
-                         currentKey + directionClause +
-                         NS_LITERAL_CSTRING(" LIMIT 1");
+      mContinueQuery = queryStart + andStr + value + le + currentKey + andStr +
+                       openparen + value + lt + currentKey + orStr + keyValue +
+                       lt + objectKey + closeparen + directionClause + limit;
+      mContinueToQuery = queryStart + andStr + value + le + currentKey +
+                         directionClause + limit;
       break;
 
     case nsIIDBCursor::PREV_NO_DUPLICATE:
       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                               queryStart);
         mRangeKey = mKeyRange->Lower();
       }
-      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
-                       NS_LITERAL_CSTRING(" < :") + currentKey +
-                       directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
-      mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
-                         NS_LITERAL_CSTRING(" <= :") + currentKey +
-                         directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
+      mContinueQuery = queryStart + andStr + value + lt + currentKey +
+                       directionClause +limit;
+      mContinueToQuery = queryStart + andStr + value + le + currentKey +
+                         directionClause + limit;
       break;
 
     default:
       NS_NOTREACHED("Unknown direction type!");
   }
 
   return NS_OK;
 }
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -659,17 +659,16 @@ IDBObjectStore::UpdateIndexes(IDBTransac
     NS_ASSERTION(aObjectDataId != LL_MININT, "Bad objectData id!");
   }
   else {
     NS_ASSERTION(aObjectDataId == LL_MININT, "Bad objectData id!");
   }
 #endif
 
   PRUint32 indexCount = aUpdateInfoArray.Length();
-  NS_ASSERTION(indexCount, "Don't call me!");
 
   nsCOMPtr<mozIStorageStatement> stmt;
   nsresult rv;
 
   if (!aAutoIncrement) {
     stmt = aTransaction->GetCachedStatement(
       "SELECT id "
       "FROM object_data "
@@ -697,44 +696,69 @@ IDBObjectStore::UpdateIndexes(IDBTransac
       return NS_ERROR_FAILURE;
     }
 
     aObjectDataId = stmt->AsInt64(0);
   }
 
   NS_ASSERTION(aObjectDataId != LL_MININT, "Bad objectData id!");
 
-  for (PRUint32 indexIndex = 0; indexIndex < indexCount; indexIndex++) {
-    const IndexUpdateInfo& updateInfo = aUpdateInfoArray[indexIndex];
-
-    stmt = aTransaction->IndexUpdateStatement(updateInfo.info.autoIncrement,
-                                              updateInfo.info.unique,
-                                              aOverwrite);
+  NS_NAMED_LITERAL_CSTRING(indexId, "index_id");
+  NS_NAMED_LITERAL_CSTRING(objectDataId, "object_data_id");
+  NS_NAMED_LITERAL_CSTRING(objectDataKey, "object_data_key");
+  NS_NAMED_LITERAL_CSTRING(value, "value");
+
+  if (aOverwrite) {
+    stmt = aTransaction->IndexDataDeleteStatement(aAutoIncrement, false);
     NS_ENSURE_TRUE(stmt, NS_ERROR_FAILURE);
 
     mozStorageStatementScoper scoper2(stmt);
 
-    rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
-                               updateInfo.info.id);
+    rv = stmt->BindInt64ByName(objectDataId, aObjectDataId);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = stmt->Execute();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    stmt = aTransaction->IndexDataDeleteStatement(aAutoIncrement, true);
+    NS_ENSURE_TRUE(stmt, NS_ERROR_FAILURE);
+
+    mozStorageStatementScoper scoper3(stmt);
+
+    rv = stmt->BindInt64ByName(objectDataId, aObjectDataId);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = stmt->Execute();
     NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("object_data_id"),
-                               aObjectDataId);
+  }
+
+  for (PRUint32 indexIndex = 0; indexIndex < indexCount; indexIndex++) {
+    const IndexUpdateInfo& updateInfo = aUpdateInfoArray[indexIndex];
+
+    NS_ASSERTION(updateInfo.info.autoIncrement == aAutoIncrement, "Huh?!");
+
+    // Insert new values.
+    stmt = aTransaction->IndexDataInsertStatement(aAutoIncrement,
+                                                  updateInfo.info.unique);
+    NS_ENSURE_TRUE(stmt, NS_ERROR_FAILURE);
+
+    mozStorageStatementScoper scoper4(stmt);
+
+    rv = stmt->BindInt64ByName(indexId, updateInfo.info.id);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = stmt->BindInt64ByName(objectDataId, aObjectDataId);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!updateInfo.info.autoIncrement) {
-      rv =
-        aObjectStoreKey.BindToStatement(stmt,
-                                        NS_LITERAL_CSTRING("object_data_key"));
+      rv = aObjectStoreKey.BindToStatement(stmt, objectDataKey);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
-    rv =
-      updateInfo.value.BindToStatementAllowUnset(stmt,
-                                                 NS_LITERAL_CSTRING("value"));
+    rv = updateInfo.value.BindToStatement(stmt, value);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = stmt->Execute();
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
@@ -1713,17 +1737,17 @@ AddHelper::DoDatabaseWork(mozIStorageCon
       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
       rv = stmt->Execute();
       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     }
   }
 
   // Update our indexes if needed.
-  if (!mIndexUpdateInfo.IsEmpty()) {
+  if (mOverwrite || !mIndexUpdateInfo.IsEmpty()) {
     PRInt64 objectDataId = autoIncrement ? mKey.ToInteger() : LL_MININT;
     rv = IDBObjectStore::UpdateIndexes(mTransaction, osid, mKey,
                                        autoIncrement, mOverwrite,
                                        objectDataId, mIndexUpdateInfo);
     if (rv == NS_ERROR_STORAGE_CONSTRAINT) {
       return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
     }
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@@ -1925,17 +1949,18 @@ OpenCursorHelper::DoDatabaseWork(mozISto
 
     default:
       NS_NOTREACHED("Unknown direction type!");
   }
 
   nsCString firstQuery = NS_LITERAL_CSTRING("SELECT ") + keyColumn +
                          NS_LITERAL_CSTRING(", data FROM ") + table +
                          NS_LITERAL_CSTRING(" WHERE object_store_id = :") +
-                         id + keyRangeClause + directionClause;
+                         id + keyRangeClause + directionClause +
+                         NS_LITERAL_CSTRING(" LIMIT 1");
 
   nsCOMPtr<mozIStorageStatement> stmt =
     mTransaction->GetCachedStatement(firstQuery);
   NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   mozStorageStatementScoper scoper(stmt);
 
   nsresult rv = stmt->BindInt64ByName(id, mObjectStore->Id());
@@ -2004,17 +2029,17 @@ OpenCursorHelper::DoDatabaseWork(mozISto
     default:
       NS_NOTREACHED("Unknown direction type!");
   }
 
   mContinueQuery = NS_LITERAL_CSTRING("SELECT ") + keyColumn +
                    NS_LITERAL_CSTRING(", data FROM ") + table +
                    NS_LITERAL_CSTRING(" WHERE object_store_id = :") + id +
                    keyRangeClause + directionClause +
-                   NS_LITERAL_CSTRING(" LIMIT 1");
+                   NS_LITERAL_CSTRING(" LIMIT ");
 
   mContinueToQuery = NS_LITERAL_CSTRING("SELECT ") + keyColumn +
                      NS_LITERAL_CSTRING(", data FROM ") + table +
                      NS_LITERAL_CSTRING(" WHERE object_store_id = :") + id +
                      continueToKeyRangeClause + directionClause +
                      NS_LITERAL_CSTRING(" LIMIT ");
 
   return NS_OK;
@@ -2210,18 +2235,18 @@ CreateIndexHelper::InsertDataFromObjectS
 
   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"),
                                       mIndex->ObjectStore()->Id());
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   bool hasResult;
   while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
     nsCOMPtr<mozIStorageStatement> insertStmt =
-      mTransaction->IndexUpdateStatement(mIndex->IsAutoIncrement(),
-                                         mIndex->IsUnique(), false);
+      mTransaction->IndexDataInsertStatement(mIndex->IsAutoIncrement(),
+                                             mIndex->IsUnique());
     NS_ENSURE_TRUE(insertStmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     mozStorageStatementScoper scoper2(insertStmt);
 
     rv = insertStmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
                                      mIndex->Id());
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -389,77 +389,76 @@ IDBTransaction::AddStatement(bool aCreat
     "UPDATE object_data "
     "SET data = :data "
     "WHERE object_store_id = :osid "
     "AND key_value = :key_value"
   );
 }
 
 already_AddRefed<mozIStorageStatement>
-IDBTransaction::IndexUpdateStatement(bool aAutoIncrement,
-                                     bool aUnique,
-                                     bool aOverwrite)
+IDBTransaction::IndexDataInsertStatement(bool aAutoIncrement,
+                                         bool aUnique)
 {
   if (aAutoIncrement) {
     if (aUnique) {
-      if (aOverwrite) {
-        return GetCachedStatement(
-          "INSERT OR REPLACE INTO ai_unique_index_data "
-            "(index_id, ai_object_data_id, value) "
-          "VALUES (:index_id, :object_data_id, :value)"
-        );
-      }
       return GetCachedStatement(
         "INSERT INTO ai_unique_index_data "
-          "(index_id, aI_object_data_id, value) "
-        "VALUES (:index_id, :object_data_id, :value)"
-      );
-    }
-    if (aOverwrite) {
-      return GetCachedStatement(
-        "INSERT OR REPLACE INTO ai_index_data "
           "(index_id, ai_object_data_id, value) "
         "VALUES (:index_id, :object_data_id, :value)"
       );
     }
     return GetCachedStatement(
       "INSERT INTO ai_index_data "
         "(index_id, ai_object_data_id, value) "
       "VALUES (:index_id, :object_data_id, :value)"
     );
   }
   if (aUnique) {
-    if (aOverwrite) {
-      return GetCachedStatement(
-        "INSERT OR REPLACE INTO unique_index_data "
-          "(index_id, object_data_id, object_data_key, value) "
-        "VALUES (:index_id, :object_data_id, :object_data_key, :value)"
-      );
-    }
     return GetCachedStatement(
       "INSERT INTO unique_index_data "
         "(index_id, object_data_id, object_data_key, value) "
       "VALUES (:index_id, :object_data_id, :object_data_key, :value)"
     );
   }
-  if (aOverwrite) {
-    return GetCachedStatement(
-      "INSERT INTO index_data ("
-        "index_id, object_data_id, object_data_key, value) "
-      "VALUES (:index_id, :object_data_id, :object_data_key, :value)"
-    );
-  }
   return GetCachedStatement(
     "INSERT INTO index_data ("
       "index_id, object_data_id, object_data_key, value) "
     "VALUES (:index_id, :object_data_id, :object_data_key, :value)"
   );
 }
 
 already_AddRefed<mozIStorageStatement>
+IDBTransaction::IndexDataDeleteStatement(bool aAutoIncrement,
+                                         bool aUnique)
+{
+  if (aAutoIncrement) {
+    if (aUnique) {
+      return GetCachedStatement(
+        "DELETE FROM ai_unique_index_data "
+        "WHERE ai_object_data_id = :object_data_id"
+      );
+    }
+    return GetCachedStatement(
+      "DELETE FROM ai_index_data "
+      "WHERE ai_object_data_id = :object_data_id"
+    );
+  }
+  if (aUnique) {
+    return GetCachedStatement(
+      "DELETE FROM unique_index_data "
+      "WHERE object_data_id = :object_data_id"
+    );
+  }
+  return GetCachedStatement(
+    "DELETE FROM index_data "
+    "WHERE object_data_id = :object_data_id"
+  );
+}
+
+already_AddRefed<mozIStorageStatement>
 IDBTransaction::GetCachedStatement(const nsACString& aQuery)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!aQuery.IsEmpty(), "Empty sql statement!");
   NS_ASSERTION(mConnection, "No connection!");
 
   nsCOMPtr<mozIStorageStatement> stmt;
 
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -113,19 +113,22 @@ public:
   nsresult GetOrCreateConnection(mozIStorageConnection** aConnection);
 
   already_AddRefed<mozIStorageStatement>
   AddStatement(bool aCreate,
                bool aOverwrite,
                bool aAutoIncrement);
 
   already_AddRefed<mozIStorageStatement>
-  IndexUpdateStatement(bool aAutoIncrement,
-                       bool aUnique,
-                       bool aOverwrite);
+  IndexDataInsertStatement(bool aAutoIncrement,
+                           bool aUnique);
+
+  already_AddRefed<mozIStorageStatement>
+  IndexDataDeleteStatement(bool aAutoIncrement,
+                           bool aUnique);
 
   already_AddRefed<mozIStorageStatement>
   GetCachedStatement(const nsACString& aQuery);
 
   template<int N>
   already_AddRefed<mozIStorageStatement>
   GetCachedStatement(const char (&aQuery)[N])
   {
--- a/dom/indexedDB/IndexedDatabase.h
+++ b/dom/indexedDB/IndexedDatabase.h
@@ -46,17 +46,17 @@
 #include "jsapi.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsDOMError.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 
-#define DB_SCHEMA_VERSION 5
+#define DB_SCHEMA_VERSION 6
 
 #define BEGIN_INDEXEDDB_NAMESPACE \
   namespace mozilla { namespace dom { namespace indexedDB {
 
 #define END_INDEXEDDB_NAMESPACE \
   } /* namespace indexedDB */ } /* namepsace dom */ } /* namespace mozilla */
 
 #define USING_INDEXEDDB_NAMESPACE \
--- a/dom/indexedDB/Key.h
+++ b/dom/indexedDB/Key.h
@@ -243,29 +243,16 @@ public:
     }
     else {
       NS_NOTREACHED("Bad key!");
     }
 
     return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
-  nsresult BindToStatementAllowUnset(mozIStorageStatement* aStatement,
-                                     const nsACString& aParamName) const
-  {
-    nsresult rv;
-
-    if (IsUnset()) {
-      rv = aStatement->BindStringByName(aParamName, EmptyString());
-      return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
-    }
-
-    return BindToStatement(aStatement, aParamName);
-  }
-
   nsresult SetFromStatement(mozIStorageStatement* aStatement,
                             PRUint32 aIndex)
   {
     PRInt32 columnType;
     nsresult rv = aStatement->GetTypeOfIndex(aIndex, &columnType);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     NS_ASSERTION(columnType == mozIStorageStatement::VALUE_TYPE_INTEGER ||
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -116,64 +116,52 @@ CreateTables(mozIStorageConnection* aDBC
       "dataVersion INTEGER NOT NULL"
     ");"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Table `object_store`
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE object_store ("
-      "id INTEGER, "
+      "id INTEGER PRIMARY KEY, "
       "name TEXT NOT NULL, "
       "key_path TEXT NOT NULL, "
       "auto_increment INTEGER NOT NULL DEFAULT 0, "
-      "PRIMARY KEY (id), "
       "UNIQUE (name)"
     ");"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Table `object_data`
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE object_data ("
-      "id INTEGER, "
+      "id INTEGER PRIMARY KEY, "
       "object_store_id INTEGER NOT NULL, "
+      "key_value DEFAULT NULL, "
       "data BLOB NOT NULL, "
-      "key_value DEFAULT NULL, " // NONE affinity
-      "PRIMARY KEY (id), "
+      "UNIQUE (object_store_id, key_value), "
       "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
         "CASCADE"
     ");"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
-    "CREATE UNIQUE INDEX key_index "
-    "ON object_data (key_value, object_store_id);"
-  ));
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // Table `ai_object_data`
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE ai_object_data ("
       "id INTEGER PRIMARY KEY AUTOINCREMENT, "
       "object_store_id INTEGER NOT NULL, "
       "data BLOB NOT NULL, "
+      "UNIQUE (object_store_id, id), "
       "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
         "CASCADE"
     ");"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
-    "CREATE UNIQUE INDEX ai_key_index "
-    "ON ai_object_data (id, object_store_id);"
-  ));
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // Table `index`
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE object_store_index ("
       "id INTEGER, "
       "object_store_id INTEGER NOT NULL, "
       "name TEXT NOT NULL, "
       "key_path TEXT NOT NULL, "
       "unique_index INTEGER NOT NULL, "
@@ -184,93 +172,107 @@ CreateTables(mozIStorageConnection* aDBC
         "CASCADE"
     ");"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Table `index_data`
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE index_data ("
-      "id INTEGER, "
       "index_id INTEGER NOT NULL, "
+      "value NOT NULL, "
+      "object_data_key NOT NULL, "
       "object_data_id INTEGER NOT NULL, "
-      "object_data_key NOT NULL, " // NONE affinity
-      "value NOT NULL, "
-      "PRIMARY KEY (id), "
+      "PRIMARY KEY (index_id, value, object_data_key), "
       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         "CASCADE, "
       "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
         "CASCADE"
     ");"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Need this to make cascading deletes from object_data and object_store fast.
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
-    "CREATE INDEX value_index "
-    "ON index_data (index_id, value);"
+    "CREATE INDEX index_data_object_data_id_index "
+    "ON index_data (object_data_id);"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Table `unique_index_data`
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE unique_index_data ("
-      "id INTEGER, "
       "index_id INTEGER NOT NULL, "
+      "value NOT NULL, "
+      "object_data_key NOT NULL, " // NONE affinity
       "object_data_id INTEGER NOT NULL, "
-      "object_data_key NOT NULL, " // NONE affinity
-      "value NOT NULL, "
-      "PRIMARY KEY (id), "
+      "PRIMARY KEY (index_id, value, object_data_key), "
       "UNIQUE (index_id, value), "
       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         "CASCADE "
       "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
         "CASCADE"
     ");"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Need this to make cascading deletes from object_data and object_store fast.
+  rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE INDEX unique_index_data_object_data_id_index "
+    "ON unique_index_data (object_data_id);"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // Table `ai_index_data`
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE ai_index_data ("
-      "id INTEGER, "
       "index_id INTEGER NOT NULL, "
+      "value NOT NULL, "
       "ai_object_data_id INTEGER NOT NULL, "
-      "value NOT NULL, "
-      "PRIMARY KEY (id), "
+      "PRIMARY KEY (index_id, value, ai_object_data_id), "
       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         "CASCADE, "
       "FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
         "CASCADE"
     ");"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Need this to make cascading deletes from ai_object_data and object_store
+  // fast.
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
-    "CREATE INDEX ai_value_index "
-    "ON ai_index_data (index_id, value);"
+    "CREATE INDEX ai_index_data_ai_object_data_id_index "
+    "ON ai_index_data (ai_object_data_id);"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Table `ai_unique_index_data`
   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE ai_unique_index_data ("
-      "id INTEGER, "
       "index_id INTEGER NOT NULL, "
+      "value NOT NULL, "
       "ai_object_data_id INTEGER NOT NULL, "
-      "value NOT NULL, "
-      "PRIMARY KEY (id), "
       "UNIQUE (index_id, value), "
+      "PRIMARY KEY (index_id, value, ai_object_data_id), "
       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         "CASCADE, "
       "FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
         "CASCADE"
     ");"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Need this to make cascading deletes from ai_object_data and object_store
+  // fast.
+  rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE INDEX ai_unique_index_data_ai_object_data_id_index "
+    "ON ai_unique_index_data (ai_object_data_id);"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
   rv = aDBConn->SetSchemaVersion(DB_SCHEMA_VERSION);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 CreateMetaData(mozIStorageConnection* aConnection,
@@ -372,103 +374,465 @@ UpgradeSchemaFrom4To5(mozIStorageConnect
 
     rv = stmt->BindInt64Parameter(2, dataVersion);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = stmt->Execute();
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  rv = aConnection->SetSchemaVersion(DB_SCHEMA_VERSION);
+  rv = aConnection->SetSchemaVersion(5);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = transaction.Commit();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+nsresult
+UpgradeSchemaFrom5To6(mozIStorageConnection* aConnection)
+{
+  mozStorageTransaction transaction(aConnection, false,
+                                 mozIStorageConnection::TRANSACTION_IMMEDIATE);
+
+  // Turn off foreign key constraints before we do anything here.
+  nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "PRAGMA foreign_keys = OFF;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // First, drop all the indexes we're no longer going to use.
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP INDEX key_index;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP INDEX ai_key_index;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP INDEX value_index;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP INDEX ai_value_index;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Now, reorder the columns of object_data to put the blob data last. We do
+  // this by copying into a temporary table, dropping the original, then copying
+  // back into a newly created table.
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TEMPORARY TABLE temp_upgrade ("
+      "id INTEGER PRIMARY KEY, "
+      "object_store_id, "
+      "key_value, "
+      "data "
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO temp_upgrade "
+      "SELECT id, object_store_id, key_value, data "
+      "FROM object_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE object_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TABLE object_data ("
+      "id INTEGER PRIMARY KEY, "
+      "object_store_id INTEGER NOT NULL, "
+      "key_value DEFAULT NULL, "
+      "data BLOB NOT NULL, "
+      "UNIQUE (object_store_id, key_value), "
+      "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
+        "CASCADE"
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO object_data "
+      "SELECT id, object_store_id, key_value, data "
+      "FROM temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // We need to add a unique constraint to our ai_object_data table. Copy all
+  // the data out of it using a temporary table as before.
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TEMPORARY TABLE temp_upgrade ("
+      "id INTEGER PRIMARY KEY, "
+      "object_store_id, "
+      "data "
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO temp_upgrade "
+      "SELECT id, object_store_id, data "
+      "FROM ai_object_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE ai_object_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TABLE ai_object_data ("
+      "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+      "object_store_id INTEGER NOT NULL, "
+      "data BLOB NOT NULL, "
+      "UNIQUE (object_store_id, id), "
+      "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
+        "CASCADE"
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO ai_object_data "
+      "SELECT id, object_store_id, data "
+      "FROM temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Fix up the index_data table. We're reordering the columns as well as
+  // changing the primary key from being a simple id to being a composite.
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TEMPORARY TABLE temp_upgrade ("
+      "index_id, "
+      "value, "
+      "object_data_key, "
+      "object_data_id "
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO temp_upgrade "
+      "SELECT index_id, value, object_data_key, object_data_id "
+      "FROM index_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE index_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TABLE index_data ("
+      "index_id INTEGER NOT NULL, "
+      "value NOT NULL, "
+      "object_data_key NOT NULL, "
+      "object_data_id INTEGER NOT NULL, "
+      "PRIMARY KEY (index_id, value, object_data_key), "
+      "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
+        "CASCADE, "
+      "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
+        "CASCADE"
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT OR IGNORE INTO index_data "
+      "SELECT index_id, value, object_data_key, object_data_id "
+      "FROM temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE INDEX index_data_object_data_id_index "
+    "ON index_data (object_data_id);"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Fix up the unique_index_data table. We're reordering the columns as well as
+  // changing the primary key from being a simple id to being a composite.
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TEMPORARY TABLE temp_upgrade ("
+      "index_id, "
+      "value, "
+      "object_data_key, "
+      "object_data_id "
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO temp_upgrade "
+      "SELECT index_id, value, object_data_key, object_data_id "
+      "FROM unique_index_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE unique_index_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TABLE unique_index_data ("
+      "index_id INTEGER NOT NULL, "
+      "value NOT NULL, "
+      "object_data_key NOT NULL, "
+      "object_data_id INTEGER NOT NULL, "
+      "PRIMARY KEY (index_id, value, object_data_key), "
+      "UNIQUE (index_id, value), "
+      "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
+        "CASCADE "
+      "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
+        "CASCADE"
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO unique_index_data "
+      "SELECT index_id, value, object_data_key, object_data_id "
+      "FROM temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE INDEX unique_index_data_object_data_id_index "
+    "ON unique_index_data (object_data_id);"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Fix up the ai_index_data table. We're reordering the columns as well as
+  // changing the primary key from being a simple id to being a composite.
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TEMPORARY TABLE temp_upgrade ("
+      "index_id, "
+      "value, "
+      "ai_object_data_id "
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO temp_upgrade "
+      "SELECT index_id, value, ai_object_data_id "
+      "FROM ai_index_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE ai_index_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TABLE ai_index_data ("
+      "index_id INTEGER NOT NULL, "
+      "value NOT NULL, "
+      "ai_object_data_id INTEGER NOT NULL, "
+      "PRIMARY KEY (index_id, value, ai_object_data_id), "
+      "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
+        "CASCADE, "
+      "FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
+        "CASCADE"
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT OR IGNORE INTO ai_index_data "
+      "SELECT index_id, value, ai_object_data_id "
+      "FROM temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE INDEX ai_index_data_ai_object_data_id_index "
+    "ON ai_index_data (ai_object_data_id);"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Fix up the ai_unique_index_data table. We're reordering the columns as well
+  // as changing the primary key from being a simple id to being a composite.
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TEMPORARY TABLE temp_upgrade ("
+      "index_id, "
+      "value, "
+      "ai_object_data_id "
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO temp_upgrade "
+      "SELECT index_id, value, ai_object_data_id "
+      "FROM ai_unique_index_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE ai_unique_index_data;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE TABLE ai_unique_index_data ("
+      "index_id INTEGER NOT NULL, "
+      "value NOT NULL, "
+      "ai_object_data_id INTEGER NOT NULL, "
+      "UNIQUE (index_id, value), "
+      "PRIMARY KEY (index_id, value, ai_object_data_id), "
+      "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
+        "CASCADE, "
+      "FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
+        "CASCADE"
+    ");"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "INSERT INTO ai_unique_index_data "
+      "SELECT index_id, value, ai_object_data_id "
+      "FROM temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "DROP TABLE temp_upgrade;"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "CREATE INDEX ai_unique_index_data_ai_object_data_id_index "
+    "ON ai_unique_index_data (ai_object_data_id);"
+  ));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aConnection->SetSchemaVersion(6);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = transaction.Commit();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 CreateDatabaseConnection(const nsAString& aName,
                          nsIFile* aDBFile,
                          mozIStorageConnection** aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
-  nsCOMPtr<nsIFile> dbDirectory;
-  nsresult rv = aDBFile->GetParent(getter_AddRefs(dbDirectory));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  bool exists;
-  rv = aDBFile->Exists(&exists);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   NS_NAMED_LITERAL_CSTRING(quotaVFSName, "quota");
 
   nsCOMPtr<mozIStorageServiceQuotaManagement> ss =
     do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE);
 
   nsCOMPtr<mozIStorageConnection> connection;
-  rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
-                               getter_AddRefs(connection));
+  nsresult rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
+                                        getter_AddRefs(connection));
   if (rv == NS_ERROR_FILE_CORRUPTED) {
     // Nuke the database file.  The web services can recreate their data.
     rv = aDBFile->Remove(false);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    exists = false;
-
     rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
                                  getter_AddRefs(connection));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Check to make sure that the database schema is correct.
   PRInt32 schemaVersion;
   rv = connection->GetSchemaVersion(&schemaVersion);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (schemaVersion != DB_SCHEMA_VERSION) {
-    // This logic needs to change next time we change the schema!
-    PR_STATIC_ASSERT(DB_SCHEMA_VERSION == 5);
-    if (schemaVersion == 4) {
-      rv = UpgradeSchemaFrom4To5(connection);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-    else {
-      // Nuke it from orbit, it's the only way to be sure.
-      if (exists) {
-        // If the connection is not at the right schema version, nuke it.
-        rv = aDBFile->Remove(false);
-        NS_ENSURE_SUCCESS(rv, rv);
+  if (!schemaVersion) {
+    // Brand new file, initialize our tables.
+    mozStorageTransaction transaction(connection, false,
+                                  mozIStorageConnection::TRANSACTION_IMMEDIATE);
+
+    rv = CreateTables(connection);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = CreateMetaData(connection, aName);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = transaction.Commit();
+    NS_ENSURE_SUCCESS(rv, rv);
 
-        rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
-                                     getter_AddRefs(connection));
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
+    NS_ASSERTION(NS_SUCCEEDED(connection->GetSchemaVersion(&schemaVersion)) &&
+                 schemaVersion == DB_SCHEMA_VERSION,
+                 "CreateTables set a bad schema version!");
+  }
+  else if (schemaVersion != DB_SCHEMA_VERSION) {
+    // This logic needs to change next time we change the schema!
+    PR_STATIC_ASSERT(DB_SCHEMA_VERSION == 6);
 
-      mozStorageTransaction transaction(connection, false,
-                                        mozIStorageConnection::TRANSACTION_IMMEDIATE);
-      rv = CreateTables(connection);
-      NS_ENSURE_SUCCESS(rv, rv);
+#define UPGRADE_SCHEMA_CASE(_from, _to)                                        \
+  if (schemaVersion == _from) {                                                \
+    rv = UpgradeSchemaFrom##_from##To##_to (connection);                       \
+    NS_ENSURE_SUCCESS(rv, rv);                                                 \
+                                                                               \
+    rv = connection->GetSchemaVersion(&schemaVersion);                         \
+    NS_ENSURE_SUCCESS(rv, rv);                                                 \
+                                                                               \
+    NS_ASSERTION(schemaVersion == _to, "Bad upgrade function!");               \
+  }
 
-      rv = CreateMetaData(connection, aName);
-      NS_ENSURE_SUCCESS(rv, rv);
+    UPGRADE_SCHEMA_CASE(4, 5)
+    UPGRADE_SCHEMA_CASE(5, 6)
 
-      rv = transaction.Commit();
-      NS_ENSURE_SUCCESS(rv, rv);
+#undef UPGRADE_SCHEMA_CASE
+
+    if (schemaVersion != DB_SCHEMA_VERSION) {
+      NS_WARNING("Unable to open IndexedDB database, schema doesn't match");
+      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
   }
 
-  // Check to make sure that the database schema is correct again.
-  NS_ASSERTION(NS_SUCCEEDED(connection->GetSchemaVersion(&schemaVersion)) &&
-               schemaVersion == DB_SCHEMA_VERSION,
-               "CreateTables failed!");
-
   // Turn on foreign key constraints.
   rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "PRAGMA foreign_keys = ON;"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
   connection.forget(aConnection);
   return NS_OK;
--- a/dom/indexedDB/test/Makefile.in
+++ b/dom/indexedDB/test/Makefile.in
@@ -73,16 +73,17 @@ TEST_FILES = \
   test_event_propagation.html \
   test_event_source.html \
   test_exceptions_in_success_events.html \
   test_getAll.html \
   test_global_data.html \
   test_index_getAll.html \
   test_index_getAllObjects.html \
   test_index_object_cursors.html \
+  test_index_update_delete.html \
   test_indexes.html \
   test_indexes_bad_values.html \
   test_key_requirements.html \
   test_leaving_page.html \
   test_objectCursors.html \
   test_objectStore_inline_autoincrement_key_added_on_put.html \
   test_objectStore_remove_values.html \
   test_object_identity.html \
@@ -103,16 +104,17 @@ TEST_FILES = \
   test_transaction_abort.html \
   test_transaction_lifetimes.html \
   test_transaction_lifetimes_nested.html \
   test_transaction_ordering.html \
   test_setVersion.html \
   test_setVersion_abort.html \
   test_setVersion_events.html \
   test_setVersion_exclusion.html \
+  test_unique_index_update.html \
   test_writer_starvation.html \
   third_party_iframe1.html \
   third_party_iframe2.html \
   $(NULL)
 
 ifeq (browser,$(MOZ_BUILD_APP))
 BROWSER_TEST_FILES = \
   browser_forgetThisSite.js \
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_index_update_delete.html
@@ -0,0 +1,180 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Indexed Database Property Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7">
+    function testSteps()
+    {
+      let request = mozIndexedDB.open(window.location.pathname, 1);
+      request.onerror = errorHandler;
+      request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
+
+      let event = yield;
+
+      let db = event.target.result;
+      db.onerror = errorHandler;
+
+      for each (let autoIncrement in [false, true]) {
+        let objectStore =
+          db.createObjectStore(autoIncrement, { keyPath: "id",
+                                                autoIncrement: autoIncrement });
+
+        for (let i = 0; i < 10; i++) {
+          objectStore.add({ id: i, index: i });
+        }
+
+        for each (let unique in [false, true]) {
+          objectStore.createIndex(unique, "index", { unique: unique });
+        }
+
+        for (let i = 10; i < 20; i++) {
+          objectStore.add({ id: i, index: i });
+        }
+      }
+
+      event = yield;
+      is(event.type, "success", "expect a success event");
+
+      for each (let autoIncrement in [false, true]) {
+        let objectStore = db.transaction(autoIncrement)
+                            .objectStore(autoIncrement);
+
+        objectStore.count().onsuccess = grabEventAndContinueHandler;
+        let event = yield;
+
+        is(event.target.result, 20, "Correct number of entries in objectStore");
+
+        let objectStoreCount = event.target.result;
+        let indexCount = event.target.result;
+
+        for each (let unique in [false, true]) {
+          let index = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
+                        .objectStore(autoIncrement)
+                        .index(unique);
+
+          index.count().onsuccess = grabEventAndContinueHandler;
+          let event = yield;
+
+          is(event.target.result, indexCount,
+             "Correct number of entries in index");
+
+          let modifiedEntry = unique ? 5 : 10;
+          let keyRange = IDBKeyRange.only(modifiedEntry);
+
+          let sawEntry = false;
+          index.openCursor(keyRange).onsuccess = function(event) {
+            let cursor = event.target.result;
+            if (cursor) {
+              sawEntry = true;
+              is(cursor.key, modifiedEntry, "Correct key");
+
+              cursor.value.index = unique ? 30 : 35;
+              cursor.update(cursor.value).onsuccess = function(event) {
+                cursor.continue();
+              }
+            }
+            else {
+              continueToNextStep();
+            }
+          }
+          yield;
+
+          is(sawEntry, true, "Saw entry for key value " + modifiedEntry);
+
+          // Recount index. Shouldn't change.
+          index = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
+                    .objectStore(autoIncrement)
+                    .index(unique);
+
+          index.count().onsuccess = grabEventAndContinueHandler;
+          event = yield;
+
+          is(event.target.result, indexCount,
+             "Correct number of entries in index");
+
+          modifiedEntry = unique ? 30 : 35;
+          keyRange = IDBKeyRange.only(modifiedEntry);
+
+          sawEntry = false;
+          index.openCursor(keyRange).onsuccess = function(event) {
+            let cursor = event.target.result;
+            if (cursor) {
+              sawEntry = true;
+              is(cursor.key, modifiedEntry, "Correct key");
+
+              delete cursor.value.index;
+              cursor.update(cursor.value).onsuccess = function(event) {
+                indexCount--;
+                cursor.continue();
+              }
+            }
+            else {
+              continueToNextStep();
+            }
+          }
+          yield;
+
+          is(sawEntry, true, "Saw entry for key value " + modifiedEntry);
+
+          // Recount objectStore. Should be unchanged.
+          objectStore = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
+                          .objectStore(autoIncrement);
+
+          objectStore.count().onsuccess = grabEventAndContinueHandler;
+          event = yield;
+
+          is(event.target.result, objectStoreCount,
+             "Correct number of entries in objectStore");
+
+          // Recount index. Should be one item less.
+          index = objectStore.index(unique);
+
+          index.count().onsuccess = grabEventAndContinueHandler;
+          event = yield;
+
+          is(event.target.result, indexCount,
+             "Correct number of entries in index");
+
+          modifiedEntry = objectStoreCount - 1;
+
+          objectStore.delete(modifiedEntry).onsuccess =
+            grabEventAndContinueHandler;
+          event = yield;
+
+          objectStoreCount--;
+          indexCount--;
+
+          objectStore.count().onsuccess = grabEventAndContinueHandler;
+          event = yield;
+
+          is(event.target.result, objectStoreCount,
+             "Correct number of entries in objectStore");
+
+          index.count().onsuccess = grabEventAndContinueHandler;
+          event = yield;
+
+          is(event.target.result, indexCount,
+             "Correct number of entries in index");
+        }
+      }
+
+      finishTest();
+      yield;
+    }
+
+  </script>
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+
+</head>
+
+<body onload="runTest();"></body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_unique_index_update.html
@@ -0,0 +1,79 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Indexed Database Property Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7">
+    function testSteps()
+    {
+      let request = mozIndexedDB.open(window.location.pathname, 1);
+      request.onerror = errorHandler;
+      request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
+
+      let event = yield;
+
+      let db = event.target.result;
+
+      for each (let autoIncrement in [false, true]) {
+        let objectStore =
+          db.createObjectStore(autoIncrement, { keyPath: "id",
+                                                autoIncrement: autoIncrement });
+        objectStore.createIndex("", "index", { unique: true });
+
+        for (let i = 0; i < 10; i++) {
+          objectStore.add({ id: i, index: i });
+        }
+      }
+
+      event = yield;
+      is(event.type, "success", "expect a success event");
+
+      for each (let autoIncrement in [false, true]) {
+        objectStore = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
+                        .objectStore(autoIncrement);
+
+        request = objectStore.put({ id: 5, index: 6 });
+        request.onsuccess = unexpectedSuccessHandler;
+        request.onerror = new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
+        event = yield;
+
+        event.preventDefault();
+
+        let keyRange = IDBKeyRange.only(5);
+
+        objectStore.index("").openCursor(keyRange).onsuccess = function(event) {
+          let cursor = event.target.result;
+          ok(cursor, "Must have a cursor here");
+
+          is(cursor.value.index, 5, "Still have the right index value");
+
+          cursor.value.index = 6;
+
+          request = cursor.update(cursor.value);
+          request.onsuccess = unexpectedSuccessHandler;
+          request.onerror =
+            new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
+        };
+
+        yield;
+      }
+
+      finishTest();
+      yield;
+    }
+
+  </script>
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+
+</head>
+
+<body onload="runTest();"></body>
+
+</html>
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -110,10 +110,20 @@ TextContentWarning=Use of attributes' te
 EnablePrivilegeWarning=Use of enablePrivilege is deprecated.  Please use code that runs with the system principal (e.g. an extension) instead.
 PositionWarning=Use of XMLHttpRequest's progress events' position attribute is deprecated.
 TotalSizeWarning=Use of XMLHttpRequest's progress events' totalSize attribute is deprecated.
 nsIJSONDecodeDeprecatedWarning=nsIJSON.decode is deprecated.  Please use JSON.parse instead.
 nsIJSONEncodeDeprecatedWarning=nsIJSON.encode is deprecated.  Please use JSON.stringify instead.
 nsIDOMWindowInternalWarning=Use of nsIDOMWindowInternal is deprecated. Use nsIDOMWindow instead.
 InputEncodingWarning=Use of inputEncoding is deprecated.
 GlobalStorageWarning=Use of globalStorage is deprecated. Please use localStorage instead.
+FullScreenDeniedDisabled=Request for full-screen was denied because full-screen API is disabled by user preference.
+FullScreenDeniedPlugins=Request for full-screen was denied because a document on this page contains a windowed plugin.
+FullScreenDeniedHidden=Request for full-screen was denied because the document is no longer visible.
+FullScreenDeniedIframeDisallowed=Request for full-screen was denied because at least one of the document's containing iframes does not have a "mozallowfullscreen" attribute.
+FullScreenDeniedNotInputDriven=Request for full-screen was denied because Element.mozRequestFullScreen() was not called from inside a short running user-generated event handler.
+FullScreenDeniedNotInDocument=Request for full-screen was denied because requesting element is no longer in its document.
+FullScreenDeniedMovedDocument=Request for full-screen was denied because requesting element has moved document.
+FullScreenDeniedLostWindow=Request for full-screen was denied because we no longer have a window.
+RemovedFullScreenElement=Exited full-screen because full-screen element was removed from document.
+AddedWindowedPluginWhileFullScreen=Exited full-screen because windowed plugin was added to document.
 HTMLMultipartXHRWarning=HTML parsing in XMLHttpRequest is not supported for multipart responses.
 HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -649,19 +649,16 @@ nsresult nsPluginHost::GetURLWithHeaders
                                          const char* target,
                                          nsIPluginStreamListener* streamListener,
                                          const char* altHost,
                                          const char* referrer,
                                          bool forceJSEnabled,
                                          PRUint32 getHeadersLength,
                                          const char* getHeaders)
 {
-  nsAutoString string;
-  string.AssignWithConversion(url);
-
   // we can only send a stream back to the plugin (as specified by a
   // null target) if we also have a nsIPluginStreamListener to talk to
   if (!target && !streamListener)
     return NS_ERROR_ILLEGAL_VALUE;
 
   nsresult rv = DoURLLoadSecurityCheck(pluginInst, url);
   if (NS_FAILED(rv))
     return rv;
@@ -676,17 +673,18 @@ nsresult nsPluginHost::GetURLWithHeaders
       else if (0 == PL_strcmp(target, "_current"))
         target = "_self";
 
       rv = owner->GetURL(url, target, nsnull, nsnull, 0);
     }
   }
 
   if (streamListener)
-    rv = NewPluginURLStream(string, pluginInst, streamListener, nsnull,
+    rv = NewPluginURLStream(NS_ConvertUTF8toUTF16(url), pluginInst,
+                            streamListener, nsnull,
                             getHeaders, getHeadersLength);
 
   return rv;
 }
 
 nsresult nsPluginHost::PostURL(nsISupports* pluginInst,
                                     const char* url,
                                     PRUint32 postDataLen,
@@ -695,21 +693,18 @@ nsresult nsPluginHost::PostURL(nsISuppor
                                     const char* target,
                                     nsIPluginStreamListener* streamListener,
                                     const char* altHost,
                                     const char* referrer,
                                     bool forceJSEnabled,
                                     PRUint32 postHeadersLength,
                                     const char* postHeaders)
 {
-  nsAutoString string;
   nsresult rv;
 
-  string.AssignWithConversion(url);
-
   // we can only send a stream back to the plugin (as specified
   // by a null target) if we also have a nsIPluginStreamListener
   // to talk to also
   if (!target && !streamListener)
     return NS_ERROR_ILLEGAL_VALUE;
 
   nsNPAPIPluginInstance* instance = static_cast<nsNPAPIPluginInstance*>(pluginInst);
 
@@ -770,17 +765,18 @@ nsresult nsPluginHost::PostURL(nsISuppor
       rv = owner->GetURL(url, target, postStream,
                          (void*)postHeaders, postHeadersLength);
     }
   }
 
   // if we don't have a target, just create a stream.  This does
   // NS_OpenURI()!
   if (streamListener)
-    rv = NewPluginURLStream(string, instance, streamListener,
+    rv = NewPluginURLStream(NS_ConvertUTF8toUTF16(url), instance,
+                            streamListener,
                             postStream, postHeaders, postHeadersLength);
 
   return rv;
 }
 
 /* This method queries the prefs for proxy information.
  * It has been tested and is known to work in the following three cases
  * when no proxy host or port is specified
--- a/dom/plugins/ipc/BrowserStreamChild.cpp
+++ b/dom/plugins/ipc/BrowserStreamChild.cpp
@@ -244,18 +244,19 @@ BrowserStreamChild::Deliver()
   // NPP_StreamAsFile() is documented (at MDN) to be called "when the stream
   // is complete" -- i.e. after all calls to NPP_WriteReady() and NPP_Write()
   // have finished.  We make these calls asynchronously (from
   // DeliverPendingData()).  So we need to make sure all the "pending data"
   // has been "delivered" before calling NPP_StreamAsFile() (also
   // asynchronously).  Doing this resolves bug 687610, bug 670036 and possibly
   // also other bugs.
   if (mStreamAsFilePending) {
-    mInstance->mPluginIface->asfile(&mInstance->mData, &mStream,
-                                    mStreamAsFileName.get());
+    if (mStreamStatus == kStreamOpen)
+      mInstance->mPluginIface->asfile(&mInstance->mData, &mStream,
+                                      mStreamAsFileName.get());
     mStreamAsFilePending = false;
   }
 
   if (DESTROY_PENDING == mDestroyPending) {
     mDestroyPending = DESTROYED;
     if (mState != DYING)
       NS_RUNTIMEABORT("mDestroyPending but state not DYING");
 
--- a/dom/workers/XMLHttpRequestPrivate.cpp
+++ b/dom/workers/XMLHttpRequestPrivate.cpp
@@ -561,16 +561,29 @@ public:
     else if (mType.EqualsASCII(sEventStrings[STRING_loadend])) {
       if (mUploadEvent) {
         mProxy->mSeenUploadLoadStart = false;
       }
       else {
         mProxy->mSeenLoadStart = false;
       }
     }
+    else if (mType.EqualsASCII(sEventStrings[STRING_abort])) {
+      if ((mUploadEvent && !mProxy->mSeenUploadLoadStart) ||
+          (!mUploadEvent && !mProxy->mSeenLoadStart)) {
+        // We've already dispatched premature abort events.
+        return true;
+      }
+    }
+    else if (mType.EqualsASCII(sEventStrings[STRING_readystatechange])) {
+      if (mReadyState == 4 && !mUploadEvent && !mProxy->mSeenLoadStart) {
+        // We've already dispatched premature abort events.
+        return true;
+      }
+    }
 
     if (mProgressEvent) {
       // Cache these for premature abort events.
       if (mUploadEvent) {
         mProxy->mLastUploadLengthComputable = mLengthComputable;
         mProxy->mLastUploadLoaded = mLoaded;
         mProxy->mLastUploadTotal = mTotal;
       }
@@ -1528,17 +1541,17 @@ XMLHttpRequestPrivate::Abort(JSContext* 
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
     return false;
   }
 
   if (mProxy) {
-    if (!MaybeDispatchPrematureAbortEvents(aCx, false)) {
+    if (!MaybeDispatchPrematureAbortEvents(aCx)) {
       return false;
     }
   }
   else {
     return true;
   }
 
   mProxy->mOuterChannelId++;
@@ -1614,17 +1627,17 @@ XMLHttpRequestPrivate::Open(JSContext* a
 
   nsDependentJSString method, url, user, password;
   if (!method.init(aCx, aMethod) || !url.init(aCx, aURL) ||
       !user.init(aCx, aUser) || !password.init(aCx, aPassword)) {
     return false;
   }
 
   if (mProxy) {
-    if (!MaybeDispatchPrematureAbortEvents(aCx, true)) {
+    if (!MaybeDispatchPrematureAbortEvents(aCx)) {
       return false;
     }
   }
   else {
     mProxy = new Proxy(this);
   }
 
   mProxy->mOuterChannelId++;
@@ -1826,18 +1839,17 @@ XMLHttpRequestPrivate::OverrideMimeType(
 
   nsRefPtr<OverrideMimeTypeRunnable> runnable =
     new OverrideMimeTypeRunnable(mWorkerPrivate, mProxy, 
                                  NS_ConvertUTF16toUTF8(mimeType));
   return runnable->Dispatch(aCx);
 }
 
 bool
-XMLHttpRequestPrivate::MaybeDispatchPrematureAbortEvents(JSContext* aCx,
-                                                         bool aFromOpen)
+XMLHttpRequestPrivate::MaybeDispatchPrematureAbortEvents(JSContext* aCx)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
   NS_ASSERTION(mProxy, "Must have a proxy here!");
 
   xhr::StateData state = {
     JSVAL_VOID, JSVAL_VOID, JSVAL_VOID, INT_TO_JSVAL(4), JSVAL_VOID,
     false, false, false, false, false
   };
@@ -1860,21 +1872,19 @@ XMLHttpRequestPrivate::MaybeDispatchPrem
     NS_ASSERTION(target, "Must have a target!");
 
     if (!xhr::UpdateXHRState(aCx, target, false, state) ||
         !DispatchPrematureAbortEvent(aCx, target, STRING_readystatechange,
                                      false)) {
       return false;
     }
 
-    if (aFromOpen) {
-      if (!DispatchPrematureAbortEvent(aCx, target, STRING_abort, false) ||
-          !DispatchPrematureAbortEvent(aCx, target, STRING_loadend, false)) {
-        return false;
-      }
+    if (!DispatchPrematureAbortEvent(aCx, target, STRING_abort, false) ||
+        !DispatchPrematureAbortEvent(aCx, target, STRING_loadend, false)) {
+      return false;
     }
 
     mProxy->mSeenLoadStart = false;
   }
 
   return true;
 }
 
--- a/dom/workers/XMLHttpRequestPrivate.h
+++ b/dom/workers/XMLHttpRequestPrivate.h
@@ -150,17 +150,17 @@ public:
 private:
   void
   ReleaseProxy();
 
   bool
   RootJSObject(JSContext* aCx);
 
   bool
-  MaybeDispatchPrematureAbortEvents(JSContext* aCx, bool aFromOpen);
+  MaybeDispatchPrematureAbortEvents(JSContext* aCx);
 
   bool
   DispatchPrematureAbortEvent(JSContext* aCx, JSObject* aTarget,
                               PRUint64 aEventType, bool aUploadTarget);
 
   bool
   SendInProgress() const
   {
--- a/gfx/cairo/libpixman/src/Makefile.in
+++ b/gfx/cairo/libpixman/src/Makefile.in
@@ -180,21 +180,18 @@ CFLAGS += -DPACKAGE="mozpixman" -D_USE_M
 
 # Disable spammy "missing initializer" GCC warning
 ifdef GNU_CC
 CFLAGS += -Wno-missing-field-initializers
 endif # GNU_CC
 
 # special rule for pixman-mmx to get the right cflags
 pixman-mmx.$(OBJ_SUFFIX): pixman-mmx.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(MMX_CFLAGS) $(_VPATH_SRCS)
 
 pixman-sse2.$(OBJ_SUFFIX): pixman-sse2.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_CFLAGS) $(_VPATH_SRCS)
 
 pixman-arm-neon.$(OBJ_SUFFIX): pixman-arm-neon.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(ARM_NEON_CFLAGS) $(_VPATH_SRCS)
--- a/gfx/qcms/Makefile.in
+++ b/gfx/qcms/Makefile.in
@@ -63,16 +63,14 @@ CFLAGS          += -DMOZ_QCMS
 
 # Disable spammy "missing initializer" GCC warning
 ifdef GNU_CC
 CFLAGS += -Wno-missing-field-initializers
 endif # GNU_CC
 
 # special rules for transform-sse*.c to get the right cflags. (taken from pixman/src/Makefile.in)
 transform-sse1.$(OBJ_SUFFIX): transform-sse1.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE1_FLAGS) $(_VPATH_SRCS)
 
 transform-sse2.$(OBJ_SUFFIX): transform-sse2.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_FLAGS) $(_VPATH_SRCS)
--- a/hal/linux/UPowerClient.cpp
+++ b/hal/linux/UPowerClient.cpp
@@ -379,18 +379,16 @@ UPowerClient::GetDeviceProperties(const 
   return hashTable;
 }
 
 void
 UPowerClient::UpdateSavedInfo(GHashTable* aHashTable)
 {
   bool isFull = false;
 
-  mLevel = g_value_get_double(static_cast<const GValue*>(g_hash_table_lookup(aHashTable, "Percentage")))*0.01;
-
   /*
    * State values are confusing...
    * First of all, after looking at upower sources (0.9.13), it seems that
    * PendingDischarge and PendingCharge are not used.
    * In addition, FullyCharged and Empty states are not clear because we do not
    * know if the battery is actually charging or not. Those values come directly
    * from sysfs (in the Linux kernel) which have four states: "Empty", "Full",
    * "Charging" and "Discharging". In sysfs, "Empty" and "Full" are also only
@@ -415,16 +413,27 @@ UPowerClient::UpdateSavedInfo(GHashTable
       break;
     case eState_Discharging:
     case eState_Empty:
     case eState_PendingDischarge:
       mCharging = false;
       break;
   }
 
+  /*
+   * The battery level might be very close to 100% (like 99.xxxx%) without
+   * increasing. It seems that upower sets the battery state as 'full' in that
+   * case so we should trust it and not even try to get the value.
+   */
+  if (isFull) {
+    mLevel = 1.0;
+  } else {
+    mLevel = g_value_get_double(static_cast<const GValue*>(g_hash_table_lookup(aHashTable, "Percentage")))*0.01;
+  }
+
   if (isFull) {
     mRemainingTime = 0;
   } else {
     mRemainingTime = mCharging ? g_value_get_int64(static_cast<const GValue*>(g_hash_table_lookup(aHashTable, "TimeToFull")))
                                : g_value_get_int64(static_cast<const GValue*>(g_hash_table_lookup(aHashTable, "TimeToEmpty")));
 
     if (mRemainingTime == kUPowerUnknownRemainingTime) {
       mRemainingTime = kUnknownRemainingTime;
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -846,35 +846,32 @@ else
 EXTRA_LIBS	+= -lposix4 -ldl -lnsl -lsocket
 endif
 endif
 
 ifdef SOLARIS_SUNPRO_CXX
 ifeq ($(TARGET_CPU),sparc)
 # Sun Studio SPARC doesn't work well with gcc inline asm, use lock_SunOS_sparc*.il
 jslock.o: jslock.cpp Makefile.in lock_sparcv8plus.il lock_sparcv9.il
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 ifeq (sparcv9,$(findstring sparcv9,$(OS_TEST)))
 	$(CXX) -o $@ -c $(COMPILE_CFLAGS) $(srcdir)/lock_sparcv9.il $<
 else
 	$(CXX) -o $@ -c $(COMPILE_CFLAGS) $(srcdir)/lock_sparcv8plus.il $<
 endif # sparcv9
 endif # sparc
 endif # SOLARIS_SUNPRO_CXX
 
 # An AIX Optimization bug causes PR_dtoa() & JS_dtoa to produce wrong result.
 # This suppresses optimization for this single compilation unit.
 ifeq ($(OS_ARCH),AIX)
 jsatom.o: jsatom.cpp Makefile.in
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
 jsdtoa.o: jsdtoa.cpp Makefile.in
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
 endif
 
 # Compute the linker flags that programs linking against SpiderMonkey should
 # pass to get SpiderMonkey and its dependencies, beyond just the -L and -l
 # for the SpiderMonkey library itself.
 # - EXTRA_DSO_LDOPTS includes the NSPR -L and -l flags.
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -59,18 +59,16 @@ endif
 
 ifdef SDK_XPIDLSRCS
 XPIDLSRCS += $(SDK_XPIDLSRCS)
 endif
 ifdef SDK_HEADERS
 EXPORTS += $(SDK_HEADERS)
 endif
 
-REPORT_BUILD = @echo $(notdir $<)
-
 ifeq ($(OS_ARCH),OS2)
 EXEC			=
 else
 EXEC			= exec
 endif
 
 # Don't copy xulrunner files at install time, when using system xulrunner
 ifdef SYSTEM_LIBXUL
@@ -1145,53 +1143,45 @@ MAKE_DEPS_AUTO_CC = $(MAKE_DEPS_AUTO)
 MAKE_DEPS_AUTO_CXX = $(MAKE_DEPS_AUTO)
 
 endif # COMPILER_DEPEND
 
 endif # MOZ_AUTO_DEPS
 
 # Rules for building native targets must come first because of the host_ prefix
 host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 %:: %.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
 
 # DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
 # 'moc' only knows about #defines it gets on the command line (-D...), not in
 # included headers like mozilla-config.h
 moc_%.cpp: %.h $(GLOBAL_DEPS)
 	$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
 
 moc_%.cc: %.cc $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
 
 ifdef ASFILES
 # The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
 # a '-c' flag.
 %.$(OBJ_SUFFIX): %.$(ASM_SUFFIX) $(GLOBAL_DEPS)
 	$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
 endif
@@ -1202,38 +1192,34 @@ endif
 %:: %.cpp $(GLOBAL_DEPS)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CCC) $(OUTOPTION)$@ $(CXXFLAGS) $(_VPATH_SRCS) $(LDFLAGS)
 
 #
 # Please keep the next two rules in sync.
 #
 %.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 ifdef STRICT_CPLUSPLUS_SUFFIX
 	echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc
 	$(RM) t_$*.cc
 else
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 endif #STRICT_CPLUSPLUS_SUFFIX
 
 $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
 
 $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
 
 %.s: %.cpp
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
 %.s: %.cc
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
@@ -1473,29 +1459,27 @@ endif
 
 XPIDL_DEPS = \
   $(topsrcdir)/xpcom/idl-parser/header.py \
   $(topsrcdir)/xpcom/idl-parser/typelib.py \
   $(topsrcdir)/xpcom/idl-parser/xpidl.py \
   $(NULL)
 
 $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
-	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
 ifndef NO_GEN_XPT
 # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
 # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
 $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
-	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  -I$(topsrcdir)/xpcom/typelib/xpt/tools \
 	  $(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 
 # no need to link together if XPIDLSRCS contains only XPIDL_MODULE
 ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
@@ -1774,25 +1758,22 @@ else # ! COMPILER_DEPEND
 
 ifndef MOZ_AUTO_DEPS
 
 define MAKE_DEPS_NOAUTO
 	$(MKDEPEND) -w1024 -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $@
 endef
 
 $(MDDEPDIR)/%.pp: %.c
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 $(MDDEPDIR)/%.pp: %.cpp
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 $(MDDEPDIR)/%.pp: %.s
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_NOAUTO)
 
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
 depend:: $(SUBMAKEFILES) $(MAKE_DIRS) $(MDDEPFILES)
 else
 depend:: $(SUBMAKEFILES)
 endif
 	$(LOOP_OVER_PARALLEL_DIRS)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2431,17 +2431,16 @@ js::array_pop(JSContext *cx, uintN argc,
 }
 
 #ifdef JS_METHODJIT
 void JS_FASTCALL
 mjit::stubs::ArrayShift(VMFrame &f)
 {
     JSObject *obj = &f.regs.sp[-1].toObject();
     JS_ASSERT(obj->isDenseArray());
-    JS_ASSERT(!js_PrototypeHasIndexedProperties(f.cx, obj));
 
     /*
      * At this point the length and initialized length have already been
      * decremented and the result fetched, so just shift the array elements
      * themselves.
      */
     uint32 initlen = obj->getDenseArrayInitializedLength();
     obj->moveDenseArrayElements(0, 1, initlen);
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -121,19 +121,19 @@ CheckMarkedThing(JSTracer *trc, T *thing
 template<typename T>
 void
 Mark(JSTracer *trc, T *thing)
 {
     CheckMarkedThing(trc, thing);
 
     JSRuntime *rt = trc->runtime;
 
-    JS_OPT_ASSERT_IF(rt->gcCheckCompartment,
-                     thing->compartment() == rt->gcCheckCompartment ||
-                     thing->compartment() == rt->atomsCompartment);
+    JS_ASSERT_IF(rt->gcCheckCompartment,
+                 thing->compartment() == rt->gcCheckCompartment ||
+                 thing->compartment() == rt->atomsCompartment);
 
     /*
      * Don't mark things outside a compartment if we are in a per-compartment
      * GC.
      */
     if (!rt->gcCurrentCompartment || thing->compartment() == rt->gcCurrentCompartment) {
         if (IS_GC_MARKING_TRACER(trc))
             PushMarkStack(static_cast<GCMarker *>(trc), thing);
@@ -272,79 +272,82 @@ MarkXMLUnbarriered(JSTracer *trc, JSXML 
 
 void
 MarkXML(JSTracer *trc, const MarkablePtr<JSXML> &xml, const char *name)
 {
     MarkXMLUnbarriered(trc, xml.value, name);
 }
 #endif
 
+#define JS_COMPARTMENT_ASSERT(rt, thing)                                \
+    JS_ASSERT_IF((rt)->gcCurrentCompartment,                            \
+                 (thing)->compartment() == (rt)->gcCurrentCompartment);
+
+#define JS_COMPARTMENT_ASSERT_STR(rt, thing)                            \
+    JS_ASSERT_IF((rt)->gcCurrentCompartment,                            \
+                 (thing)->compartment() == (rt)->gcCurrentCompartment || \
+                 (thing)->compartment() == (rt)->atomsCompartment);
+
 void
 PushMarkStack(GCMarker *gcmarker, JSXML *thing)
 {
-    JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment,
-                     thing->compartment() == gcmarker->runtime->gcCurrentCompartment);
+    JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         gcmarker->pushXML(thing);
 }
 
 void
 PushMarkStack(GCMarker *gcmarker, JSObject *thing)
 {
-    JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment,
-                     thing->compartment() == gcmarker->runtime->gcCurrentCompartment);
+    JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         gcmarker->pushObject(thing);
 }
 
 void
 PushMarkStack(GCMarker *gcmarker, JSFunction *thing)
 {
-    JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment,
-                     thing->compartment() == gcmarker->runtime->gcCurrentCompartment);
+    JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         gcmarker->pushObject(thing);
 }
 
 void
 PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing)
 {
-    JS_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment,
-                 thing->compartment() == gcmarker->runtime->gcCurrentCompartment);
+    JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         gcmarker->pushType(thing);
 }
 
 void
 PushMarkStack(GCMarker *gcmarker, JSScript *thing)
 {
-    JS_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment,
-                 thing->compartment() == gcmarker->runtime->gcCurrentCompartment);
+    JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     /*
      * We mark scripts directly rather than pushing on the stack as they can
      * refer to other scripts only indirectly (like via nested functions) and
      * we cannot get to deep recursion.
      */
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         MarkChildren(gcmarker, thing);
 }
 
 static void
 ScanShape(GCMarker *gcmarker, const Shape *shape);
 
 void
 PushMarkStack(GCMarker *gcmarker, const Shape *thing)
 {
-    JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment,
-                     thing->compartment() == gcmarker->runtime->gcCurrentCompartment);
+    JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     /* We mark shapes directly rather than pushing on the stack. */
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         ScanShape(gcmarker, thing);
 }
 
 static void
 MarkAtomRange(JSTracer *trc, size_t len, JSAtom **vec, const char *name)
@@ -712,19 +715,17 @@ restart:
     shape = shape->previous();
     if (shape && shape->markIfUnmarked(gcmarker->getMarkColor()))
         goto restart;
 }
 
 static inline void
 ScanRope(GCMarker *gcmarker, JSRope *rope)
 {
-    JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment,
-                     rope->compartment() == gcmarker->runtime->gcCurrentCompartment
-                     || rope->compartment() == gcmarker->runtime->atomsCompartment);
+    JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, rope);
     JS_ASSERT(rope->isMarked());
 
     JSString *leftChild = NULL;
     do {
         JSString *rightChild = rope->rightChild();
 
         if (rightChild->isRope()) {
             if (rightChild->markIfUnmarked())
@@ -740,19 +741,17 @@ ScanRope(GCMarker *gcmarker, JSRope *rop
         }
         rope = &leftChild->asRope();
     } while (leftChild->markIfUnmarked());
 }
 
 static inline void
 PushMarkStack(GCMarker *gcmarker, JSString *str)
 {
-    JS_OPT_ASSERT_IF(gcmarker->runtime->gcCurrentCompartment,
-                     str->compartment() == gcmarker->runtime->gcCurrentCompartment
-                     || str->compartment() == gcmarker->runtime->atomsCompartment);
+    JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, str);
 
     if (str->isLinear()) {
         str->asLinear().mark(gcmarker);
     } else {
         JS_ASSERT(str->isRope());
         if (str->markIfUnmarked())
             ScanRope(gcmarker, &str->asRope());
     }
@@ -897,20 +896,18 @@ MarkChildren(JSTracer *trc, JSString *st
 }
 
 
 void
 MarkChildren(JSTracer *trc, JSScript *script)
 {
     CheckScript(script, NULL);
 
-#ifdef JS_CRASH_DIAGNOSTICS
-    JSRuntime *rt = trc->runtime;
-    JS_OPT_ASSERT_IF(rt->gcCheckCompartment, script->compartment() == rt->gcCheckCompartment);
-#endif
+    JS_ASSERT_IF(trc->runtime->gcCheckCompartment,
+                 script->compartment() == trc->runtime->gcCheckCompartment);
 
     MarkAtomRange(trc, script->natoms, script->atoms, "atoms");
 
     if (JSScript::isValidOffset(script->objectsOffset)) {
         JSObjectArray *objarray = script->objects();
         MarkObjectRange(trc, objarray->length, objarray->vector, "objects");
     }
 
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -137,16 +137,17 @@
 
 #include "nsIScrollableFrame.h"
 
 #include "nsIXBLService.h"
 
 #undef NOISY_FIRST_LETTER
 
 #include "nsMathMLParts.h"
+#include "nsIDOMSVGFilters.h"
 #include "nsSVGFeatures.h"
 #include "nsSVGEffects.h"
 #include "nsSVGUtils.h"
 #include "nsSVGOuterSVGFrame.h"
 
 #include "nsRefreshDriver.h"
 #include "nsRuleProcessorData.h"
 
@@ -208,17 +209,23 @@ nsIFrame*
 NS_NewSVGTextPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewSVGFilterFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewSVGPatternFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
-NS_NewSVGLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+NS_NewSVGFEContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+nsIFrame*
+NS_NewSVGFELeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+nsIFrame*
+NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+nsIFrame*
+NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 #include "nsIDocument.h"
 #include "nsIScrollable.h"
 #include "nsINodeInfo.h"
 #include "prenv.h"
 #include "nsWidgetsCID.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
@@ -4712,46 +4719,39 @@ nsCSSFrameConstructor::FindSVGData(Eleme
     aParentFrame ? aParentFrame->GetContent() : nsnull;
   // XXXbz should this really be based on the XBL-resolved tag of the parent
   // frame's content?  Should it not be based on the type of the parent frame
   // (e.g. whether it's an SVG frame)?
   if (parentContent) {
     PRInt32 parentNSID;
     nsIAtom* parentTag =
       parentContent->OwnerDoc()->BindingManager()->
-        ResolveTag(aParentFrame->GetContent(), &parentNSID);
+        ResolveTag(parentContent, &parentNSID);
 
     // It's not clear whether the SVG spec intends to allow any SVG
     // content within svg:foreignObject at all (SVG 1.1, section
     // 23.2), but if it does, it better be svg:svg.  So given that
     // we're allowing it, treat it as a non-SVG parent.
     parentIsSVG = parentNSID == kNameSpaceID_SVG &&
                   parentTag != nsGkAtoms::foreignObject;
   }
 
   if ((aTag != nsGkAtoms::svg && !parentIsSVG) ||
-      (aTag == nsGkAtoms::desc || aTag == nsGkAtoms::title ||
-       aTag == nsGkAtoms::feFuncR || aTag == nsGkAtoms::feFuncG ||
-       aTag == nsGkAtoms::feFuncB || aTag == nsGkAtoms::feFuncA ||
-       aTag == nsGkAtoms::feDistantLight || aTag == nsGkAtoms::fePointLight ||
-       aTag == nsGkAtoms::feSpotLight)) {
+      (aTag == nsGkAtoms::desc || aTag == nsGkAtoms::title)) {
     // Sections 5.1 and G.4 of SVG 1.1 say that SVG elements other than
     // svg:svg not contained within svg:svg are incorrect, although they
     // don't seem to specify error handling.  Ignore them, since many of
     // our frame classes can't deal.  It *may* be that the document
     // should at that point be considered in error according to F.2, but
     // it's hard to tell.
     //
     // Style mutation can't change this situation, so don't bother
     // adding to the undisplayed content map.
     //
     // We don't currently handle any UI for desc/title
-    //
-    // The filter types are children of filter elements that use their
-    // parent frames when necessary
     return &sSuppressData;
   }
 
   // We don't need frames for animation elements
   if (aElement->IsNodeOfType(nsINode::eANIMATION)) {
     return &sSuppressData;
   }
 
@@ -4770,16 +4770,34 @@ nsCSSFrameConstructor::FindSVGData(Eleme
   
   if (!nsSVGFeatures::PassesConditionalProcessingTests(aElement)) {
     // Elements with failing conditional processing attributes never get
     // rendered.  Note that this is not where we select which frame in a
     // <switch> to render!  That happens in nsSVGSwitchFrame::PaintSVG.
     return &sContainerData;
   }
 
+  // Special case for filter primitive elements.
+  // These elements must have a filter element as a parent
+  nsCOMPtr<nsIDOMSVGFilterPrimitiveStandardAttributes> filterPrimitive =
+    do_QueryInterface(aElement);
+  if (filterPrimitive && aParentFrame->GetType() != nsGkAtoms::svgFilterFrame) {
+    return &sSuppressData;
+  }
+
+  // Some elements must be children of filter primitive elements.
+  if ((aTag == nsGkAtoms::feDistantLight || aTag == nsGkAtoms::fePointLight ||
+       aTag == nsGkAtoms::feSpotLight ||
+       aTag == nsGkAtoms::feFuncR || aTag == nsGkAtoms::feFuncG ||
+       aTag == nsGkAtoms::feFuncB || aTag == nsGkAtoms::feFuncA ||
+       aTag == nsGkAtoms::feMergeNode) &&
+       aParentFrame->GetType() != nsGkAtoms::svgFEContainerFrame) {
+    return &sSuppressData;
+  }
+
   // Special cases for text/tspan/textPath, because the kind of frame
   // they get depends on the parent frame.  We ignore 'a' elements when
   // determining the parent, however.
   nsIFrame *ancestorFrame =
     nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
   if (ancestorFrame) {
     if (aTag == nsGkAtoms::tspan || aTag == nsGkAtoms::altGlyph) {
       // tspan and altGlyph must be children of another text content element.
@@ -4829,32 +4847,40 @@ nsCSSFrameConstructor::FindSVGData(Eleme
     SIMPLE_SVG_CREATE(use, NS_NewSVGUseFrame),
     SIMPLE_SVG_CREATE(marker, NS_NewSVGMarkerFrame),
     SIMPLE_SVG_CREATE(image, NS_NewSVGImageFrame),
     SIMPLE_SVG_CREATE(clipPath, NS_NewSVGClipPathFrame),
     SIMPLE_SVG_CREATE(textPath, NS_NewSVGTextPathFrame),
     SIMPLE_SVG_CREATE(filter, NS_NewSVGFilterFrame),
     SIMPLE_SVG_CREATE(pattern, NS_NewSVGPatternFrame),
     SIMPLE_SVG_CREATE(mask, NS_NewSVGMaskFrame),
-    SIMPLE_SVG_CREATE(feBlend, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feColorMatrix, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feComposite, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feComponentTransfer, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feConvolveMatrix, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feDiffuseLighting, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feDisplacementMap, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feFlood, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feGaussianBlur, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feImage, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feMergeNode, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feMorphology, NS_NewSVGLeafFrame), 
-    SIMPLE_SVG_CREATE(feOffset, NS_NewSVGLeafFrame), 
-    SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGLeafFrame),
-    SIMPLE_SVG_CREATE(feTile, NS_NewSVGLeafFrame), 
-    SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGLeafFrame) 
+    SIMPLE_SVG_CREATE(feDistantLight, NS_NewSVGFEUnstyledLeafFrame),
+    SIMPLE_SVG_CREATE(fePointLight, NS_NewSVGFEUnstyledLeafFrame),
+    SIMPLE_SVG_CREATE(feSpotLight, NS_NewSVGFEUnstyledLeafFrame),
+    SIMPLE_SVG_CREATE(feBlend, NS_NewSVGFELeafFrame),
+    SIMPLE_SVG_CREATE(feColorMatrix, NS_NewSVGFELeafFrame),
+    SIMPLE_SVG_CREATE(feFuncR, NS_NewSVGFEUnstyledLeafFrame),
+    SIMPLE_SVG_CREATE(feFuncG, NS_NewSVGFEUnstyledLeafFrame),
+    SIMPLE_SVG_CREATE(feFuncB, NS_NewSVGFEUnstyledLeafFrame),
+    SIMPLE_SVG_CREATE(feFuncA, NS_NewSVGFEUnstyledLeafFrame),
+    SIMPLE_SVG_CREATE(feComposite, NS_NewSVGFELeafFrame),
+    SIMPLE_SVG_CREATE(feComponentTransfer, NS_NewSVGFEContainerFrame),
+    SIMPLE_SVG_CREATE(feConvolveMatrix, NS_NewSVGFELeafFrame),
+    SIMPLE_SVG_CREATE(feDiffuseLighting, NS_NewSVGFEContainerFrame),
+    SIMPLE_SVG_CREATE(feDisplacementMap, NS_NewSVGFELeafFrame),
+    SIMPLE_SVG_CREATE(feFlood, NS_NewSVGFELeafFrame),
+    SIMPLE_SVG_CREATE(feGaussianBlur, NS_NewSVGFELeafFrame),
+    SIMPLE_SVG_CREATE(feImage, NS_NewSVGFEImageFrame),
+    SIMPLE_SVG_CREATE(feMerge, NS_NewSVGFEContainerFrame),
+    SIMPLE_SVG_CREATE(feMergeNode, NS_NewSVGFEUnstyledLeafFrame),
+    SIMPLE_SVG_CREATE(feMorphology, NS_NewSVGFELeafFrame), 
+    SIMPLE_SVG_CREATE(feOffset, NS_NewSVGFELeafFrame), 
+    SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGFEContainerFrame),
+    SIMPLE_SVG_CREATE(feTile, NS_NewSVGFELeafFrame), 
+    SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame) 
   };
 
   const FrameConstructionData* data =
     FindDataByTag(aTag, aElement, aStyleContext, sSVGData,
                   ArrayLength(sSVGData));
 
   if (!data) {
     data = &sContainerData;
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -97,21 +97,23 @@ class gfxASurface;
 class gfxContext;
 class nsIDOMEvent;
 class nsDisplayList;
 class nsDisplayListBuilder;
 class nsPIDOMWindow;
 struct nsPoint;
 struct nsIntPoint;
 struct nsIntRect;
+class nsRegion;
 class nsRefreshDriver;
 class nsARefreshObserver;
 #ifdef ACCESSIBILITY
 class nsAccessibilityService;
 #endif
+class nsIWidget;
 
 typedef short SelectionType;
 typedef PRUint64 nsFrameState;
 
 namespace mozilla {
 namespace dom {
 class Element;
 } // namespace dom
@@ -134,18 +136,18 @@ typedef struct CapturingContentInfo {
   // capture should only be allowed during a mousedown event
   bool mAllowed;
   bool mRetargetToElement;
   bool mPreventDrag;
   nsIContent* mContent;
 } CapturingContentInfo;
 
 #define NS_IPRESSHELL_IID    \
-{ 0x67eab923, 0x5c15, 0x4c13,\
-  { 0xb5, 0xcc, 0xb2, 0x75, 0xb3, 0x5a, 0xa5, 0x38 } }
+{ 0x4e23d557, 0x741a, 0x4fd0,\
+  { 0x91, 0x52, 0x34, 0xe2, 0xb4, 0xef, 0xe8, 0x2e } }
 
 // Constants for ScrollContentIntoView() function
 #define NS_PRESSHELL_SCROLL_TOP      0
 #define NS_PRESSHELL_SCROLL_BOTTOM   100
 #define NS_PRESSHELL_SCROLL_LEFT     0
 #define NS_PRESSHELL_SCROLL_RIGHT    100
 #define NS_PRESSHELL_SCROLL_CENTER   50
 #define NS_PRESSHELL_SCROLL_ANYWHERE -1
@@ -1131,16 +1133,30 @@ public:
 
   /**
    * Dispatch a mouse move event based on the most recent mouse position if
    * this PresShell is visible. This is used when the contents of the page
    * moved (aFromScroll is false) or scrolled (aFromScroll is true).
    */
   virtual void SynthesizeMouseMove(bool aFromScroll) = 0;
 
+  virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget,
+                     const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion,
+                     bool aPaintDefaultBackground, bool aWillSendDidPaint) = 0;
+  virtual nsresult HandleEvent(nsIFrame*       aFrame,
+                               nsGUIEvent*     aEvent,
+                               bool            aDontRetargetEvents,
+                               nsEventStatus*  aEventStatus) = 0;
+  virtual bool ShouldIgnoreInvalidation() = 0;
+  virtual void WillPaint(bool aWillSendDidPaint) = 0;
+  virtual void DidPaint() = 0;
+  virtual void ClearMouseCaptureOnView(nsIView* aView) = 0;
+  virtual bool IsVisible() = 0;
+  virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange) = 0;
+
   /**
    * Refresh observer management.
    */
 protected:
   virtual bool AddRefreshObserverExternal(nsARefreshObserver* aObserver,
                                             mozFlushType aFlushType);
   bool AddRefreshObserverInternal(nsARefreshObserver* aObserver,
                                     mozFlushType aFlushType);
--- a/layout/base/nsImageLoader.cpp
+++ b/layout/base/nsImageLoader.cpp
@@ -101,20 +101,24 @@ nsImageLoader::Destroy()
     list = todestroy->mNextLoader;
     todestroy->mNextLoader = nsnull;
     todestroy->Destroy();
   }
 
   if (mRequest && mFrame) {
     nsLayoutUtils::DeregisterImageRequest(mFrame->PresContext(), mRequest,
                                           &mRequestRegistered);
+  }
+
+  mFrame = nsnull;
+
+  if (mRequest) {
     mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
   }
 
-  mFrame = nsnull;
   mRequest = nsnull;
 }
 
 nsresult
 nsImageLoader::Load(imgIRequest *aImage)
 {
   NS_ASSERTION(!mRequest, "can't reuse image loaders");
   NS_ASSERTION(mFrame, "not initialized");
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -505,19 +505,17 @@ nsLayoutUtils::GetCrossDocParentFrame(co
     return nsnull;
   v = v->GetParent(); // anonymous inner view
   if (!v)
     return nsnull;
   if (aExtraOffset) {
     *aExtraOffset += v->GetPosition();
   }
   v = v->GetParent(); // subdocumentframe's view
-  if (!v)
-    return nsnull;
-  return static_cast<nsIFrame*>(v->GetClientData());
+  return v ? v->GetFrame() : nsnull;
 }
 
 // static
 bool
 nsLayoutUtils::IsProperAncestorFrameCrossDoc(nsIFrame* aAncestorFrame, nsIFrame* aFrame,
                                              nsIFrame* aCommonAncestor)
 {
   if (aFrame == aCommonAncestor)
@@ -748,26 +746,26 @@ nsIFrame* nsLayoutUtils::GetLastSibling(
     aFrame = next;
   }
   return aFrame;
 }
 
 // static
 nsIView*
 nsLayoutUtils::FindSiblingViewFor(nsIView* aParentView, nsIFrame* aFrame) {
-  nsIFrame* parentViewFrame = static_cast<nsIFrame*>(aParentView->GetClientData());
+  nsIFrame* parentViewFrame = aParentView->GetFrame();
   nsIContent* parentViewContent = parentViewFrame ? parentViewFrame->GetContent() : nsnull;
   for (nsIView* insertBefore = aParentView->GetFirstChild(); insertBefore;
        insertBefore = insertBefore->GetNextSibling()) {
-    nsIFrame* f = static_cast<nsIFrame*>(insertBefore->GetClientData());
+    nsIFrame* f = insertBefore->GetFrame();
     if (!f) {
       // this view could be some anonymous view attached to a meaningful parent
       for (nsIView* searchView = insertBefore->GetParent(); searchView;
            searchView = searchView->GetParent()) {
-        f = static_cast<nsIFrame*>(searchView->GetClientData());
+        f = searchView->GetFrame();
         if (f) {
           break;
         }
       }
       NS_ASSERTION(f, "Can't find a frame anywhere!");
     }
     if (!f || !aFrame->GetContent() || !f->GetContent() ||
         CompareTreePosition(aFrame->GetContent(), f->GetContent(), parentViewContent) > 0) {
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -337,18 +337,17 @@ public:
   static bool ScrolledByViewportScrolling(nsIFrame* aActiveScrolledRoot,
                                             nsDisplayListBuilder* aBuilder);
 
   /**
     * GetFrameFor returns the root frame for a view
     * @param aView is the view to return the root frame for
     * @return the root frame for the view
     */
-  static nsIFrame* GetFrameFor(nsIView *aView)
-  { return static_cast<nsIFrame*>(aView->GetClientData()); }
+  static nsIFrame* GetFrameFor(nsIView *aView) { return aView->GetFrame(); }
 
   /**
     * GetScrollableFrameFor returns the scrollable frame for a scrolled frame
     */
   static nsIScrollableFrame* GetScrollableFrameFor(nsIFrame *aScrolledFrame);
 
   /**
    * GetNearestScrollableFrameForDirection locates the first ancestor of
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2296,17 +2296,17 @@ nsPresContext::IsRootContentDocument()
   if (!view) {
     return true;
   }
   view = view->GetParent(); // subdocumentframe's view
   if (!view) {
     return true;
   }
 
-  nsIFrame* f = static_cast<nsIFrame*>(view->GetClientData());
+  nsIFrame* f = view->GetFrame();
   return (f && f->PresContext()->IsChrome());
 }
 
 nsRootPresContext::nsRootPresContext(nsIDocument* aDocument,
                                      nsPresContextType aType)
   : nsPresContext(aDocument, aType),
     mUpdatePluginGeometryForFrame(nsnull),
     mDOMGeneration(0),
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -67,17 +67,18 @@
 #include "nsIDocument.h"
 #include "nsIDOMXULDocument.h"
 #include "nsCSSStyleSheet.h" // XXX for UA sheet loading hack, can this go away please?
 #include "nsIDOMCSSStyleSheet.h"  // for Pref-related rule management (bugs 22963,20760,31816)
 #include "nsAnimationManager.h"
 #include "nsINameSpaceManager.h"  // for Pref-related rule management (bugs 22963,20760,31816)
 #include "nsIServiceManager.h"
 #include "nsFrame.h"
-#include "nsIViewManager.h"
+#include "nsViewManager.h"
+#include "nsView.h"
 #include "nsCRTGlue.h"
 #include "prlog.h"
 #include "prmem.h"
 #include "prprf.h"
 #include "prinrval.h"
 #include "nsTArray.h"
 #include "nsCOMArray.h"
 #include "nsHashtable.h"
@@ -949,18 +950,18 @@ PresShell::PresShell()
     registeredReporter = true;
   }
 
   new (this) nsFrameManager();
 
   sLiveShells->PutEntry(this);
 }
 
-NS_IMPL_ISUPPORTS8(PresShell, nsIPresShell, nsIDocumentObserver,
-                   nsIViewObserver, nsISelectionController,
+NS_IMPL_ISUPPORTS7(PresShell, nsIPresShell, nsIDocumentObserver,
+                   nsISelectionController,
                    nsISelectionDisplay, nsIObserver, nsISupportsWeakReference,
                    nsIMutationObserver)
 
 PresShell::~PresShell()
 {
   sLiveShells->RemoveEntry(this);
 
   if (!mHaveShutDown) {
@@ -1025,17 +1026,17 @@ PresShell::Init(nsIDocument* aDocument,
   mDocument = aDocument;
   NS_ADDREF(mDocument);
   mViewManager = aViewManager;
 
   // Create our frame constructor.
   mFrameConstructor = new nsCSSFrameConstructor(mDocument, this);
 
   // The document viewer owns both view manager and pres shell.
-  mViewManager->SetViewObserver(this);
+  mViewManager->SetPresShell(this);
 
   // Bind the context to the presentation shell.
   mPresContext = aPresContext;
   NS_ADDREF(mPresContext);
   aPresContext->SetShell(this);
 
   // Now we can initialize the style set.
   result = aStyleSet->Init(aPresContext);
@@ -1231,17 +1232,17 @@ PresShell::Destroy()
     mCurrentEventFrameStack[i] = nsnull;
   }
 
   mFramesToDirty.Clear();
 
   if (mViewManager) {
     // Clear the view manager's weak pointer back to |this| in case it
     // was leaked.
-    mViewManager->SetViewObserver(nsnull);
+    mViewManager->SetPresShell(nsnull);
     mViewManager = nsnull;
   }
 
   mStyleSet->BeginShutdown(mPresContext);
   nsRefreshDriver* rd = GetPresContext()->RefreshDriver();
 
   // This shell must be removed from the document before the frame
   // hierarchy is torn down to avoid finding deleted frames through
@@ -3626,34 +3627,34 @@ nsresult PresShell::GetLinkLocation(nsID
       return NS_OK;
     }
   }
 
   // if no link, fail.
   return NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP_(void)
+void
 PresShell::DispatchSynthMouseMove(nsGUIEvent *aEvent,
                                   bool aFlushOnHoverChange)
 {
   PRUint32 hoverGenerationBefore = mFrameConstructor->GetHoverGeneration();
   nsEventStatus status;
   nsIView* targetView = nsIView::GetViewFor(aEvent->widget);
   targetView->GetViewManager()->DispatchEvent(aEvent, targetView, &status);
   if (aFlushOnHoverChange &&
       hoverGenerationBefore != mFrameConstructor->GetHoverGeneration()) {
     // Flush so that the resulting reflow happens now so that our caller
     // can suppress any synthesized mouse moves caused by that reflow.
     FlushPendingNotifications(Flush_Layout);
   }
 }
 
-NS_IMETHODIMP_(void)
-PresShell::ClearMouseCapture(nsIView* aView)
+void
+PresShell::ClearMouseCaptureOnView(nsIView* aView)
 {
   if (gCaptureInfo.mContent) {
     if (aView) {
       // if a view was specified, ensure that the captured content is within
       // this view.
       nsIFrame* frame = gCaptureInfo.mContent->GetPrimaryFrame();
       if (frame) {
         nsIView* view = frame->GetClosestView();
@@ -5257,17 +5258,17 @@ void PresShell::SynthesizeMouseMove(bool
  * traverse the entire view hierarchy --- use carefully.
  */
 static nsIView* FindFloatingViewContaining(nsIView* aView, nsPoint aPt)
 {
   if (aView->GetVisibility() == nsViewVisibility_kHide)
     // No need to look into descendants.
     return nsnull;
 
-  nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
+  nsIFrame* frame = aView->GetFrame();
   if (frame) {
     if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) ||
         !frame->PresContext()->PresShell()->IsActive()) {
       return nsnull;
     }
   }
 
   for (nsIView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
@@ -5294,17 +5295,17 @@ static nsIView* FindFloatingViewContaini
  */
 static nsIView* FindViewContaining(nsIView* aView, nsPoint aPt)
 {
   if (!aView->GetDimensions().Contains(aPt) ||
       aView->GetVisibility() == nsViewVisibility_kHide) {
     return nsnull;
   }
 
-  nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
+  nsIFrame* frame = aView->GetFrame();
   if (frame) {
     if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) ||
         !frame->PresContext()->PresShell()->IsActive()) {
       return nsnull;
     }
   }
 
   for (nsIView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
@@ -5369,41 +5370,41 @@ PresShell::ProcessSynthMouseMoveEvent(bo
     view = rootView;
     nsIView *pointView = FindViewContaining(rootView, mMouseLocation);
     // pointView can be null in situations related to mouse capture
     pointVM = (pointView ? pointView : view)->GetViewManager();
     refpoint = mMouseLocation + rootView->ViewToWidgetOffset();
     viewAPD = APD;
   } else {
     pointVM = view->GetViewManager();
-    nsIFrame* frame = static_cast<nsIFrame*>(view->GetClientData());
+    nsIFrame* frame = view->GetFrame();
     NS_ASSERTION(frame, "floating views can't be anonymous");
     viewAPD = frame->PresContext()->AppUnitsPerDevPixel();
     refpoint = mMouseLocation.ConvertAppUnits(APD, viewAPD);
     refpoint -= view->GetOffsetTo(rootView);
     refpoint += view->ViewToWidgetOffset();
   }
   NS_ASSERTION(view->GetWidget(), "view should have a widget here");
   nsMouseEvent event(true, NS_MOUSE_MOVE, view->GetWidget(),
                      nsMouseEvent::eSynthesized);
   event.refPoint = refpoint.ToNearestPixels(viewAPD);
   event.time = PR_IntervalNow();
   // XXX set event.isShift, event.isControl, event.isAlt, event.isMeta ?
 
-  nsCOMPtr<nsIViewObserver> observer = pointVM->GetViewObserver();
-  if (observer) {
-    observer->DispatchSynthMouseMove(&event, !aFromScroll);
+  nsCOMPtr<nsIPresShell> shell = pointVM->GetPresShell();
+  if (shell) {
+    shell->DispatchSynthMouseMove(&event, !aFromScroll);
   }
 
   if (!aFromScroll) {
     mSynthMouseMoveEvent.Forget();
   }
 }
 
-NS_IMETHODIMP
+void
 PresShell::Paint(nsIView*           aViewToPaint,
                  nsIWidget*         aWidgetToPaint,
                  const nsRegion&    aDirtyRegion,
                  const nsIntRegion& aIntDirtyRegion,
                  bool               aPaintDefaultBackground,
                  bool               aWillSendDidPaint)
 {
 #ifdef NS_FUNCTION_TIMER
@@ -5419,18 +5420,17 @@ PresShell::Paint(nsIView*           aVie
 
   NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
   NS_ASSERTION(aViewToPaint, "null view");
   NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget");
 
   nsPresContext* presContext = GetPresContext();
   AUTO_LAYOUT_PHASE_ENTRY_POINT(presContext, Paint);
 
-  nsIFrame* frame = aPaintDefaultBackground
-      ? nsnull : static_cast<nsIFrame*>(aViewToPaint->GetClientData());
+  nsIFrame* frame = aPaintDefaultBackground ? nsnull : aViewToPaint->GetFrame();
 
   bool isRetainingManager;
   LayerManager* layerManager =
     aWidgetToPaint->GetLayerManager(&isRetainingManager);
   NS_ASSERTION(layerManager, "Must be in paint event");
   layerManager->BeginTransaction();
 
   if (frame && isRetainingManager) {
@@ -5439,17 +5439,17 @@ PresShell::Paint(nsIView*           aVie
     // a non-retained layer manager (like the BasicLayerManager that
     // draws the window title bar on Mac), because a) it won't work
     // and b) below we don't want to clear NS_FRAME_UPDATE_LAYER_TREE,
     // that will cause us to forget to update the real layer manager!
     if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) {
       if (layerManager->EndEmptyTransaction()) {
         frame->UpdatePaintCountForPaintedPresShells();
         presContext->NotifyDidPaintForSubtree();
-        return NS_OK;
+        return;
       }
     }
 
     frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE);
   }
   if (frame) {
     frame->ClearPresShellsFromLastPaint();
   }
@@ -5468,33 +5468,32 @@ PresShell::Paint(nsIView*           aVie
     // need. (aPaintDefaultBackground will never be needed since the
     // chrome can always paint a default background.)
     nsLayoutUtils::PaintFrame(nsnull, frame, aDirtyRegion, bgcolor,
                               nsLayoutUtils::PAINT_WIDGET_LAYERS |
                               nsLayoutUtils::PAINT_EXISTING_TRANSACTION);
 
     frame->EndDeferringInvalidatesForDisplayRoot();
     presContext->NotifyDidPaintForSubtree();
-    return NS_OK;
+    return;
   }
 
   nsRefPtr<ColorLayer> root = layerManager->CreateColorLayer();
   if (root) {
     nsPresContext* pc = GetPresContext();
     nsIntRect bounds =
       pc->GetVisibleArea().ToOutsidePixels(pc->AppUnitsPerDevPixel());
     bgcolor = NS_ComposeColors(bgcolor, mCanvasBackgroundColor);
     root->SetColor(bgcolor);
     root->SetVisibleRegion(bounds);
     layerManager->SetRoot(root);
   }
   layerManager->EndTransaction(NULL, NULL);
 
   presContext->NotifyDidPaintForSubtree();
-  return NS_OK;
 }
 
 // static
 void
 nsIPresShell::SetCapturingContent(nsIContent* aContent, PRUint8 aFlags)
 {
   NS_IF_RELEASE(gCaptureInfo.mContent);
 
@@ -5640,26 +5639,19 @@ PresShell::RetargetEventToParent(nsGUIEv
   // Send this events straight up to the parent pres shell.
   // We do this for keystroke events in zombie documents or if either a frame
   // or a root content is not present.
   // That way at least the UI key bindings can work.
 
   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
   nsCOMPtr<nsIPresShell> parentPresShell = GetParentPresShell();
   NS_ENSURE_TRUE(parentPresShell, NS_ERROR_FAILURE);
-  nsCOMPtr<nsIViewObserver> parentViewObserver = 
-    do_QueryInterface(parentPresShell);
-  if (!parentViewObserver) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Fake the event as though it'ss from the parent pres shell's root view.
-  nsIView *parentRootView = parentPresShell->GetViewManager()->GetRootView();
-  
-  return parentViewObserver->HandleEvent(parentRootView, aEvent, true, aEventStatus);
+
+  // Fake the event as though it's from the parent pres shell's root frame.
+  return parentPresShell->HandleEvent(parentPresShell->GetRootFrame(), aEvent, true, aEventStatus);
 }
 
 void
 PresShell::DisableNonTestMouseEvents(bool aDisable)
 {
   sDisableNonTestMouseEvents = aDisable;
 }
 
@@ -5721,39 +5713,39 @@ PresShell::RecordMouseLocation(nsGUIEven
     printf("[ps=%p]got mouse exit for %p\n",
            this, aEvent->widget);
     printf("[ps=%p]clearing mouse location\n",
            this);
 #endif
   }
 }
 
-NS_IMETHODIMP
-PresShell::HandleEvent(nsIView         *aView,
+nsresult
+PresShell::HandleEvent(nsIFrame        *aFrame,
                        nsGUIEvent*     aEvent,
                        bool            aDontRetargetEvents,
                        nsEventStatus*  aEventStatus)
 {
-  NS_ASSERTION(aView, "null view");
+  NS_ASSERTION(aFrame, "null frame");
 
   if (mIsDestroying ||
       (sDisableNonTestMouseEvents && NS_IS_MOUSE_EVENT(aEvent) &&
        !(aEvent->flags & NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT))) {
     return NS_OK;
   }
 
   RecordMouseLocation(aEvent);
 
 #ifdef ACCESSIBILITY
   if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT) {
     NS_TIME_FUNCTION_MIN(1.0);
 
     // Accessibility events come through OS requests and not from scripts,
     // so it is safe to handle here
-    return HandleEventInternal(aEvent, aView, aEventStatus);
+    return HandleEventInternal(aEvent, aEventStatus);
   }
 #endif
 
   if (!nsContentUtils::IsSafeToRunScript())
     return NS_OK;
 
   NS_TIME_FUNCTION_MIN(1.0);
 
@@ -5784,27 +5776,22 @@ PresShell::HandleEvent(nsIView         *
         return NS_OK;
     } else if (capturingContent) {
       // if the mouse is being captured then retarget the mouse event at the
       // document that is being captured.
       retargetEventDoc = capturingContent->GetCurrentDoc();
     }
 
     if (retargetEventDoc) {
-      nsIPresShell* presShell = retargetEventDoc->GetShell();
+      nsCOMPtr<nsIPresShell> presShell = retargetEventDoc->GetShell();
       if (!presShell)
         return NS_OK;
 
       if (presShell != this) {
-        nsCOMPtr<nsIViewObserver> viewObserver = do_QueryInterface(presShell);
-        if (!viewObserver)
-          return NS_ERROR_FAILURE;
-
-        nsIView* view = presShell->GetViewManager()->GetRootView();
-        return viewObserver->HandleEvent(view, aEvent, true, aEventStatus);
+        return presShell->HandleEvent(presShell->GetRootFrame(), aEvent, true, aEventStatus);
       }
     }
   }
 
   // Check for a theme change up front, since the frame type is irrelevant
   if (aEvent->message == NS_THEMECHANGED && mPresContext) {
     mPresContext->ThemeChanged();
     return NS_OK;
@@ -5816,30 +5803,20 @@ PresShell::HandleEvent(nsIView         *
       nsUIStateChangeEvent* event = (nsUIStateChangeEvent*)aEvent;
       win->SetKeyboardIndicators(event->showAccelerators, event->showFocusRings);
     }
     return NS_OK;
   }
 
   // Check for a system color change up front, since the frame type is
   // irrelevant
-  if ((aEvent->message == NS_SYSCOLORCHANGED) && mPresContext) {
-    nsIViewManager* vm = GetViewManager();
-    if (vm) {
-      // Only dispatch system color change when the message originates from
-      // from the root views widget. This is necessary to prevent us from 
-      // dispatching the SysColorChanged notification for each child window 
-      // which may be redundant.
-      nsIView* view = vm->GetRootView();
-      if (view == aView) {
-        *aEventStatus = nsEventStatus_eConsumeDoDefault;
-        mPresContext->SysColorChanged();
-        return NS_OK;
-      }
-    }
+  if ((aEvent->message == NS_SYSCOLORCHANGED) && mPresContext &&
+      aFrame == FrameManager()->GetRootFrame()) {
+    *aEventStatus = nsEventStatus_eConsumeDoDefault;
+    mPresContext->SysColorChanged();
     return NS_OK;
   }
 
   if (aEvent->eventStructType == NS_KEY_EVENT &&
       mDocument && mDocument->EventHandlingSuppressed()) {
     if (aEvent->message == NS_KEY_DOWN) {
       mNoDelayedKeyEvents = true;
     } else if (!mNoDelayedKeyEvents) {
@@ -5847,38 +5824,18 @@ PresShell::HandleEvent(nsIView         *
         new nsDelayedKeyEvent(static_cast<nsKeyEvent*>(aEvent));
       if (!mDelayedEvents.AppendElement(event)) {
         delete event;
       }
     }
     return NS_OK;
   }
 
-  nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
+  nsIFrame* frame = aFrame;
   bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
-
-  // if this event has no frame, we need to retarget it at a parent
-  // view that has a frame.
-  if (!frame &&
-      (dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) ||
-       NS_IS_IME_RELATED_EVENT(aEvent) ||
-       NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) ||
-       aEvent->message == NS_PLUGIN_ACTIVATE ||
-       aEvent->message == NS_PLUGIN_FOCUS)) {
-    nsIView* targetView = aView;
-    while (targetView && !targetView->GetClientData()) {
-      targetView = targetView->GetParent();
-    }
-    
-    if (targetView) {
-      aView = targetView;
-      frame = static_cast<nsIFrame*>(aView->GetClientData());
-    }
-  }
-
   if (dispatchUsingCoordinates) {
     NS_WARN_IF_FALSE(frame, "Nothing to handle this event!");
     if (!frame)
       return NS_OK;
 
     nsPresContext* framePresContext = frame->PresContext();
     nsPresContext* rootPresContext = framePresContext->GetRootPresContext();
     NS_ASSERTION(rootPresContext == mPresContext->GetRootPresContext(),
@@ -5977,17 +5934,16 @@ PresShell::HandleEvent(nsIView         *
                                                         capturingContent))) {
       // A check was already done above to ensure that capturingContent is
       // in this presshell.
       NS_ASSERTION(capturingContent->GetCurrentDoc() == GetDocument(),
                    "Unexpected document");
       nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
       if (capturingFrame) {
         frame = capturingFrame;
-        aView = frame->GetClosestView();
       }
     }
 
     // Suppress mouse event if it's being targeted at an element inside
     // a document which needs events suppressed
     if (aEvent->eventStructType == NS_MOUSE_EVENT &&
         frame->PresContext()->Document()->EventHandlingSuppressed()) {
       if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
@@ -6021,35 +5977,32 @@ PresShell::HandleEvent(nsIView         *
         activeESM != shell->GetPresContext()->EventStateManager() &&
         static_cast<nsEventStateManager*>(activeESM)->GetPresContext()) {
       nsIPresShell* activeShell =
         static_cast<nsEventStateManager*>(activeESM)->GetPresContext()->GetPresShell();
       if (activeShell &&
           nsContentUtils::ContentIsCrossDocDescendantOf(activeShell->GetDocument(),
                                                         shell->GetDocument())) {
         shell = static_cast<PresShell*>(activeShell);
-        nsIView* activeShellRootView = shell->GetViewManager()->GetRootView();
-        frame = static_cast<nsIFrame*>(activeShellRootView->GetClientData());
+        frame = shell->GetRootFrame();
       }
     }
 
     if (shell != this) {
       // Handle the event in the correct shell.
       // Prevent deletion until we're done with event handling (bug 336582).
       nsCOMPtr<nsIPresShell> kungFuDeathGrip(shell);
-      nsIView* subshellRootView = shell->GetViewManager()->GetRootView();
-      // We pass the subshell's root view as the view to start from. This is
+      // We pass the subshell's root frame as the frame to start from. This is
       // the only correct alternative; if the event was captured then it
       // must have been captured by us or some ancestor shell and we
       // now ask the subshell to dispatch it normally.
-      return shell->HandlePositionedEvent(subshellRootView, frame,
-                                          aEvent, aEventStatus);
-    }
-
-    return HandlePositionedEvent(aView, frame, aEvent, aEventStatus);
+      return shell->HandlePositionedEvent(frame, aEvent, aEventStatus);
+    }
+
+    return HandlePositionedEvent(frame, aEvent, aEventStatus);
   }
   
   nsresult rv = NS_OK;
   
   if (frame) {
     PushCurrentEventInfo(nsnull, nsnull);
 
     // key and IME related events go to the focused frame in this DOM window.
@@ -6103,54 +6056,50 @@ PresShell::HandleEvent(nsIView         *
           NS_RELEASE(gKeyDownTarget);
         }
       }
 
       mCurrentEventFrame = nsnull;
       nsIDocument* targetDoc = eventTarget ? eventTarget->OwnerDoc() : nsnull;
       if (targetDoc && targetDoc != mDocument) {
         PopCurrentEventInfo();
-        nsIPresShell* shell = targetDoc->GetShell();
-        nsCOMPtr<nsIViewObserver> vo = do_QueryInterface(shell);
-        if (vo) {
-          nsIView* root = shell->GetViewManager()->GetRootView();
-          rv = static_cast<PresShell*>(shell)->HandleRetargetedEvent(aEvent,
-                                                                     root,
-                                                                     aEventStatus,
-                                                                     eventTarget);
+        nsCOMPtr<nsIPresShell> shell = targetDoc->GetShell();
+        if (shell) {
+          rv = static_cast<PresShell*>(shell.get())->
+            HandleRetargetedEvent(aEvent, aEventStatus, eventTarget);
         }
         return rv;
       } else {
         mCurrentEventContent = eventTarget;
       }
         
       if (!mCurrentEventContent || !GetCurrentEventFrame() ||
           InZombieDocument(mCurrentEventContent)) {
         rv = RetargetEventToParent(aEvent, aEventStatus);
         PopCurrentEventInfo();
         return rv;
       }
     } else {
       mCurrentEventFrame = frame;
     }
     if (GetCurrentEventFrame()) {
-      rv = HandleEventInternal(aEvent, aView, aEventStatus);
+      rv = HandleEventInternal(aEvent, aEventStatus);
     }
   
 #ifdef NS_DEBUG
     ShowEventTargetDebug();
 #endif
     PopCurrentEventInfo();
   } else {
     // Activation events need to be dispatched even if no frame was found, since
     // we don't want the focus to be out of sync.
 
     if (!NS_EVENT_NEEDS_FRAME(aEvent)) {
       mCurrentEventFrame = nsnull;
-      return HandleEventInternal(aEvent, aView, aEventStatus);
+      return HandleEventInternal(aEvent, aEventStatus);
     }
     else if (NS_IS_KEY_EVENT(aEvent)) {
       // Keypress events in new blank tabs should not be completely thrown away.
       // Retarget them -- the parent chrome shell might make use of them.
       return RetargetEventToParent(aEvent, aEventStatus);
     }
   }
 
@@ -6171,18 +6120,17 @@ PresShell::ShowEventTargetDebug()
     mDrawEventTargetFrame = mCurrentEventFrame;
     mDrawEventTargetFrame->Invalidate(
         nsRect(nsPoint(0, 0), mDrawEventTargetFrame->GetSize()));
   }
 }
 #endif
 
 nsresult
-PresShell::HandlePositionedEvent(nsIView*       aView,
-                                 nsIFrame*      aTargetFrame,
+PresShell::HandlePositionedEvent(nsIFrame*      aTargetFrame,
                                  nsGUIEvent*    aEvent,
                                  nsEventStatus* aEventStatus)
 {
   nsresult rv = NS_OK;
   
   PushCurrentEventInfo(nsnull, nsnull);
   
   mCurrentEventFrame = aTargetFrame;
@@ -6214,32 +6162,32 @@ PresShell::HandlePositionedEvent(nsIView
         mCurrentEventFrame = nsnull;
       } else if (targetElement != mCurrentEventContent) {
         mCurrentEventContent = targetElement;
       }
     }
   }
 
   if (GetCurrentEventFrame()) {
-    rv = HandleEventInternal(aEvent, aView, aEventStatus);
+    rv = HandleEventInternal(aEvent, aEventStatus);
   }
 
 #ifdef NS_DEBUG
   ShowEventTargetDebug();
 #endif
   PopCurrentEventInfo();
   return rv;
 }
 
 nsresult
 PresShell::HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame,
                                  nsIContent* aContent, nsEventStatus* aStatus)
 {
   PushCurrentEventInfo(aFrame, aContent);
-  nsresult rv = HandleEventInternal(aEvent, nsnull, aStatus);
+  nsresult rv = HandleEventInternal(aEvent, aStatus);
   PopCurrentEventInfo();
   return rv;
 }
 
 static inline bool
 IsSynthesizedMouseEvent(nsEvent* aEvent)
 {
   return aEvent->eventStructType == NS_MOUSE_EVENT &&
@@ -6318,18 +6266,17 @@ IsFullScreenAndRestrictedKeyEvent(nsICon
     default:
       // Otherwise, fullscreen is enabled, key input is restricted, and the key
       // code is not an allowed key code.
       return true;
   }
 }
 
 nsresult
-PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
-                               nsEventStatus* aStatus)
+PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
 {
   NS_TIME_FUNCTION_MIN(1.0);
 
 #ifdef ACCESSIBILITY
   if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT)
   {
     nsAccessibleEvent *accEvent = static_cast<nsAccessibleEvent*>(aEvent);
     accEvent->mAccessible = nsnull;
@@ -6438,21 +6385,19 @@ PresShell::HandleEventInternal(nsEvent* 
     }
 
     nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
 
     // FIXME. If the event was reused, we need to clear the old target,
     // bug 329430
     aEvent->target = nsnull;
 
-    nsWeakView weakView(aView);
     // 1. Give event to event manager for pre event state changes and
     //    generation of synthetic events.
-    rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame,
-                                 aStatus, aView);
+    rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aStatus);
 
     // 2. Give event to the DOM for third party and JS use.
     if (GetCurrentEventFrame() && NS_SUCCEEDED(rv)) {
       bool wasHandlingKeyBoardEvent =
         nsContentUtils::IsHandlingKeyBoardEvent();
       if (aEvent->eventStructType == NS_KEY_EVENT) {
         nsContentUtils::SetIsHandlingKeyBoardEvent(true);
       }
@@ -6481,18 +6426,17 @@ PresShell::HandleEventInternal(nsEvent* 
       }
 
       nsContentUtils::SetIsHandlingKeyBoardEvent(wasHandlingKeyBoardEvent);
 
       // 3. Give event to event manager for post event state changes and
       //    generation of synthetic events.
       if (!mIsDestroying && NS_SUCCEEDED(rv)) {
         rv = manager->PostHandleEvent(mPresContext, aEvent,
-                                      GetCurrentEventFrame(), aStatus,
-                                      weakView.GetView());
+                                      GetCurrentEventFrame(), aStatus);
       }
     }
 
     if (aEvent->message == NS_MOUSE_BUTTON_UP) {
       // reset the capturing content now that the mouse button is up
       SetCapturingContent(nsnull, 0);
     } else if (aEvent->message == NS_MOUSE_MOVE) {
       nsIPresShell::AllowMouseCapture(false);
@@ -6891,29 +6835,23 @@ PresShell::GetCurrentItemAndPositionForE
     aTargetPt.x = presContext->AppUnitsToDevPixels(frameOrigin.x);
     aTargetPt.y = presContext->AppUnitsToDevPixels(
                     frameOrigin.y + extra + extraTreeY);
   }
 
   NS_IF_ADDREF(*aTargetToUse = focusedContent);
 }
 
-NS_IMETHODIMP
-PresShell::ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight)
-{
-  return ResizeReflow(aWidth, aHeight);
-}
-
-NS_IMETHODIMP_(bool)
+bool
 PresShell::ShouldIgnoreInvalidation()
 {
   return mPaintingSuppressed || !mIsActive;
 }
 
-NS_IMETHODIMP_(void)
+void
 PresShell::WillPaint(bool aWillSendDidPaint)
 {
   // Don't bother doing anything if some viewmanager in our tree is painting
   // while we still have painting suppressed or we are not active.
   if (mPaintingSuppressed || !mIsActive || !IsVisible()) {
     return;
   }
 
@@ -6931,33 +6869,33 @@ PresShell::WillPaint(bool aWillSendDidPa
 
   // Process reflows, if we have them, to reduce flicker due to invalidates and
   // reflow being interspersed.  Note that we _do_ allow this to be
   // interruptible; if we can't do all the reflows it's better to flicker a bit
   // than to freeze up.
   FlushPendingNotifications(Flush_InterruptibleLayout);
 }
 
-NS_IMETHODIMP_(void)
+void
 PresShell::DidPaint()
 {
   if (mPaintingSuppressed || !mIsActive || !IsVisible()) {
     return;
   }
 
   nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
   if (!rootPresContext) {
     return;
   }
   if (rootPresContext == mPresContext) {
     rootPresContext->UpdatePluginGeometry();
   }
 }
 
-NS_IMETHODIMP_(bool)
+bool
 PresShell::IsVisible()
 {
   if (!mViewManager)
     return false;
 
   nsIView* view = mViewManager->GetRootView();
   if (!view)
     return true;
@@ -6967,17 +6905,17 @@ PresShell::IsVisible()
   if (!view)
     return true;
   
   // subdoc view
   view = view->GetParent();
   if (!view)
     return true;
 
-  nsIFrame* frame = static_cast<nsIFrame*>(view->GetClientData());
+  nsIFrame* frame = view->GetFrame();
   if (!frame)
     return true;
 
   return frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY);
 }
 
 nsresult
 PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets)
@@ -8070,17 +8008,17 @@ PresShell::VerifyIncrementalReflow()
   // exact same style information that this document has.
   nsAutoPtr<nsStyleSet> newSet(CloneStyleSet(mStyleSet));
   nsCOMPtr<nsIPresShell> sh;
   rv = mDocument->CreateShell(cx, vm, newSet, getter_AddRefs(sh));
   NS_ENSURE_SUCCESS(rv, false);
   newSet.forget();
   // Note that after we create the shell, we must make sure to destroy it
   sh->SetVerifyReflowEnable(false); // turn off verify reflow while we're reflowing the test frame tree
-  vm->SetViewObserver((nsIViewObserver *)((PresShell*)sh.get()));
+  vm->SetPresShell(sh);
   {
     nsAutoCauseReflowNotifier crNotifier(this);
     sh->InitialReflow(r.width, r.height);
   }
   mDocument->BindingManager()->ProcessAttachedQueue();
   sh->FlushPendingNotifications(Flush_Layout);
   sh->SetVerifyReflowEnable(true);  // turn on verify reflow again now that we're done reflowing the test frame tree
   // Force the non-primary presshell to unsuppress; it doesn't want to normally
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -55,17 +55,16 @@
  */
 
 /* a presentation of a document, part 2 */
 
 #ifndef nsPresShell_h_
 #define nsPresShell_h_
 
 #include "nsIPresShell.h"
-#include "nsIViewObserver.h"
 #include "nsStubDocumentObserver.h"
 #include "nsISelectionController.h"
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 #include "nsCRT.h"
 #include "nsAutoPtr.h"
 #include "nsIWidget.h"
 #include "nsStyleSet.h"
@@ -164,17 +163,17 @@ private:
 
   // the size of the mark array
   PRUint32 mMarkLength;
 };
 
 class nsPresShellEventCB;
 class nsAutoCauseReflowNotifier;
 
-class PresShell : public nsIPresShell, public nsIViewObserver,
+class PresShell : public nsIPresShell,
                   public nsStubDocumentObserver,
                   public nsISelectionController, public nsIObserver,
                   public nsSupportsWeakReference
 {
 public:
   PresShell();
 
   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
@@ -309,40 +308,35 @@ public:
   virtual void SetIgnoreViewportScrolling(bool aIgnore);
 
   virtual void SetDisplayPort(const nsRect& aDisplayPort);
 
   virtual nsresult SetResolution(float aXResolution, float aYResolution);
 
   //nsIViewObserver interface
 
-  NS_IMETHOD Paint(nsIView* aViewToPaint,
-                   nsIWidget* aWidget,
-                   const nsRegion& aDirtyRegion,
-                   const nsIntRegion& aIntDirtyRegion,
-                   bool aPaintDefaultBackground,
-                   bool aWillSendDidPaint);
-  NS_IMETHOD HandleEvent(nsIView*        aView,
-                         nsGUIEvent*     aEvent,
-                         bool            aDontRetargetEvents,
-                         nsEventStatus*  aEventStatus);
+  virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget,
+                     const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion,
+                     bool aPaintDefaultBackground, bool aWillSendDidPaint);
+  virtual nsresult HandleEvent(nsIFrame*       aFrame,
+                               nsGUIEvent*     aEvent,
+                               bool            aDontRetargetEvents,
+                               nsEventStatus*  aEventStatus);
   virtual NS_HIDDEN_(nsresult) HandleDOMEventWithTarget(nsIContent* aTargetContent,
                                                         nsEvent* aEvent,
                                                         nsEventStatus* aStatus);
   virtual NS_HIDDEN_(nsresult) HandleDOMEventWithTarget(nsIContent* aTargetContent,
                                                         nsIDOMEvent* aEvent,
                                                         nsEventStatus* aStatus);
-  NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
-  NS_IMETHOD_(bool) ShouldIgnoreInvalidation();
-  NS_IMETHOD_(void) WillPaint(bool aWillSendDidPaint);
-  NS_IMETHOD_(void) DidPaint();
-  NS_IMETHOD_(void) DispatchSynthMouseMove(nsGUIEvent *aEvent,
-                                           bool aFlushOnHoverChange);
-  NS_IMETHOD_(void) ClearMouseCapture(nsIView* aView);
-  NS_IMETHOD_(bool) IsVisible();
+  virtual bool ShouldIgnoreInvalidation();
+  virtual void WillPaint(bool aWillSendDidPaint);
+  virtual void DidPaint();
+  virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange);
+  virtual void ClearMouseCaptureOnView(nsIView* aView);
+  virtual bool IsVisible();
 
   // caret handling
   virtual NS_HIDDEN_(already_AddRefed<nsCaret>) GetCaret() const;
   virtual NS_HIDDEN_(void) MaybeInvalidateCaretPosition();
   NS_IMETHOD SetCaretEnabled(bool aInEnable);
   NS_IMETHOD SetCaretReadOnly(bool aReadOnly);
   NS_IMETHOD GetCaretEnabled(bool *aOutEnabled);
   NS_IMETHOD SetCaretVisibilityDuringSelection(bool aVisibility);
@@ -600,24 +594,23 @@ protected:
       frameSelection->SetMouseDownState(false);
     }
     if (gCaptureInfo.mContent &&
         gCaptureInfo.mContent->OwnerDoc() == mDocument) {
       SetCapturingContent(nsnull, 0);
     }
   }
 
-  nsresult HandleRetargetedEvent(nsEvent* aEvent, nsIView* aView,
-                                 nsEventStatus* aStatus, nsIContent* aTarget)
+  nsresult HandleRetargetedEvent(nsEvent* aEvent, nsEventStatus* aStatus, nsIContent* aTarget)
   {
     PushCurrentEventInfo(nsnull, nsnull);
     mCurrentEventContent = aTarget;
     nsresult rv = NS_OK;
     if (GetCurrentEventFrame()) {
-      rv = HandleEventInternal(aEvent, aView, aStatus);
+      rv = HandleEventInternal(aEvent, aStatus);
     }
     PopCurrentEventInfo();
     return rv;
   }
 
   nsRefPtr<nsCSSStyleSheet> mPrefStyleSheet; // mStyleSet owns it but we
                                              // maintain a ref, may be null
 #ifdef DEBUG
@@ -796,20 +789,18 @@ private:
 
   //helper funcs for event handling
 protected:
   //protected because nsPresShellEventCB needs this.
   nsIFrame* GetCurrentEventFrame();
 private:
   void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
   void PopCurrentEventInfo();
-  nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView,
-                               nsEventStatus *aStatus);
-  nsresult HandlePositionedEvent(nsIView*       aView,
-                                 nsIFrame*      aTargetFrame,
+  nsresult HandleEventInternal(nsEvent* aEvent, nsEventStatus *aStatus);
+  nsresult HandlePositionedEvent(nsIFrame*      aTargetFrame,
                                  nsGUIEvent*    aEvent,
                                  nsEventStatus* aEventStatus);
   // This returns the focused DOM window under our top level window.
   //  I.e., when we are deactive, this returns the *last* focused DOM window.
   already_AddRefed<nsPIDOMWindow> GetFocusedDOMWindowInOurWindow();
 
   /*
    * This and the next two helper methods are used to target and position the
--- a/layout/forms/test/Makefile.in
+++ b/layout/forms/test/Makefile.in
@@ -72,16 +72,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug571352.html \
 		test_bug572406.html \
 		test_bug572649.html \
 		test_bug36619.html \
 		test_bug620936.html \
 		test_bug595310.html \
 		test_bug644542.html \
 		test_bug672810.html \
+		test_bug704049.html \
 		$(NULL)
 
 _CHROME_FILES = \
 		test_bug536567.html \
 		     bug536567_subframe.html \
 		test_bug665540.html \
 		     bug665540_window.xul \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/layout/forms/test/test_bug704049.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=704049
+-->
+<head>
+  <title>Test for Bug 704049</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.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=704049">Mozilla Bug 704049</a>
+<p id="display"></p>
+<input type="radio" id="radio11" name="group1">
+<input type="radio" id="radio12" name="group1">
+<input type="radio" id="radio21" name="group2" checked>
+<input type="radio" id="radio22" name="group2">
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 704049 **/
+
+window.addEventListener("click", function (e) { e.preventDefault(); }, false);
+
+function doTest()
+{
+  var target = document.getElementById("radio11");
+  synthesizeMouseAtCenter(target, {});
+  is(target.checked, false, "radio11 is checked");
+  target = document.getElementById("radio12");
+  synthesizeMouseAtCenter(target, {});
+  is(target.checked, false, "radio12 is checked");
+  target = document.getElementById("radio21");
+  synthesizeMouseAtCenter(target, {});
+  is(target.checked, true, "radio21 is not checked");
+  target = document.getElementById("radio22");
+  synthesizeMouseAtCenter(target, {});
+  is(target.checked, false, "radio22 is checked");
+
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(doTest);
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -240,17 +240,17 @@ nsContainerFrame::RemoveFrame(ChildListI
   return NS_OK;
 }
 
 void
 nsContainerFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Prevent event dispatch during destruction
   if (HasView()) {
-    GetView()->SetClientData(nsnull);
+    GetView()->SetFrame(nsnull);
   }
 
   // Delete the primary child list
   mFrames.DestroyFramesFrom(aDestructRoot);
 
   // Destroy auxiliary frame lists
   nsPresContext* prescontext = PresContext();
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -570,17 +570,17 @@ nsFrame::DestroyFrom(nsIFrame* aDestruct
 
   if ((mState & NS_FRAME_EXTERNAL_REFERENCE) ||
       (mState & NS_FRAME_SELECTED_CONTENT)) {
     shell->ClearFrameRefs(this);
   }
 
   if (view) {
     // Break association between view and frame
-    view->SetClientData(nsnull);
+    view->SetFrame(nsnull);
 
     // Destroy the view
     view->Destroy();
   }
 
   // Make sure that our deleted frame can't be returned from GetPrimaryFrame()
   if (mContent && mContent->GetPrimaryFrame() == this) {
     mContent->SetPrimaryFrame(nsnull);
@@ -4044,17 +4044,17 @@ nsIFrame::GetViewExternal() const
 {
   return GetView();
 }
 
 nsresult
 nsIFrame::SetView(nsIView* aView)
 {
   if (aView) {
-    aView->SetClientData(this);
+    aView->SetFrame(this);
 
     // Set a property on the frame
     Properties().Set(ViewProperty(), aView);
 
     // Set the frame state bit that says the frame has a view
     AddStateBits(NS_FRAME_HAS_VIEW);
 
     // Let all of the ancestors know they have a descendant with a view.
--- a/layout/generic/nsQueryFrame.h
+++ b/layout/generic/nsQueryFrame.h
@@ -194,26 +194,29 @@ public:
     nsSplittableFrame_id,
     nsSplitterFrame_id,
     nsStackFrame_id,
     nsSubDocumentFrame_id,
     nsSVGAFrame_id,
     nsSVGClipPathFrame_id,
     nsSVGContainerFrame_id,
     nsSVGDisplayContainerFrame_id,
+    SVGFEContainerFrame_id,
+    SVGFEImageFrame_id,
+    SVGFELeafFrame_id,
+    SVGFEUnstyledLeafFrame_id,
     nsSVGFilterFrame_id,
     nsSVGForeignObjectFrame_id,
     nsSVGGenericContainerFrame_id,
     nsSVGGeometryFrame_id,
     nsSVGGFrame_id,
     nsSVGGlyphFrame_id,
     nsSVGGradientFrame_id,
     nsSVGImageFrame_id,
     nsSVGInnerSVGFrame_id,
-    nsSVGLeafFrame_id,
     nsSVGLinearGradientFrame_id,
     nsSVGMarkerFrame_id,
     nsSVGMaskFrame_id,
     nsSVGOuterSVGFrame_id,
     nsSVGPaintServerFrame_id,
     nsSVGPathGeometryFrame_id,
     nsSVGPatternFrame_id,
     nsSVGRadialGradientFrame_id,
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -102,17 +102,17 @@
 using namespace mozilla;
 using mozilla::layout::RenderFrameParent;
 
 static nsIDocument*
 GetDocumentFromView(nsIView* aView)
 {
   NS_PRECONDITION(aView, "");
 
-  nsIFrame* f = static_cast<nsIFrame*>(aView->GetClientData());
+  nsIFrame* f = aView->GetFrame();
   nsIPresShell* ps =  f ? f->PresContext()->PresShell() : nsnull;
   return ps ? ps->GetDocument() : nsnull;
 }
 
 class AsyncFrameInit;
 
 nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
   : nsLeafFrame(aContext)
@@ -245,19 +245,17 @@ nsSubDocumentFrame::GetSkipSides() const
 }
 
 nsIFrame*
 nsSubDocumentFrame::GetSubdocumentRootFrame()
 {
   if (!mInnerView)
     return nsnull;
   nsIView* subdocView = mInnerView->GetFirstChild();
-  if (!subdocView)
-    return nsnull;
-  return static_cast<nsIFrame*>(subdocView->GetClientData());
+  return subdocView ? subdocView->GetFrame() : nsnull;
 }
 
 NS_IMETHODIMP
 nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                      const nsRect&           aDirtyRect,
                                      const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
@@ -282,33 +280,31 @@ nsSubDocumentFrame::BuildDisplayList(nsD
   }
 
   nsIView* subdocView = mInnerView->GetFirstChild();
   if (!subdocView)
     return NS_OK;
 
   nsCOMPtr<nsIPresShell> presShell = nsnull;
 
-  nsIFrame* subdocRootFrame =
-    static_cast<nsIFrame*>(subdocView->GetClientData());
-
+  nsIFrame* subdocRootFrame = subdocView->GetFrame();
   if (subdocRootFrame) {
     presShell = subdocRootFrame->PresContext()->PresShell();
   }
   // If painting is suppressed in the presshell, we try to look for a better
   // presshell to use.
   if (!presShell || (presShell->IsPaintingSuppressed() &&
                      !aBuilder->IsIgnoringPaintSuppression())) {
     // During page transition mInnerView will sometimes have two children, the
     // first being the new page that may not have any frame, and the second
     // being the old page that will probably have a frame.
     nsIView* nextView = subdocView->GetNextSibling();
     nsIFrame* frame = nsnull;
     if (nextView) {
-      frame = static_cast<nsIFrame*>(nextView->GetClientData());
+      frame = nextView->GetFrame();
     }
     if (frame) {
       nsIPresShell* ps = frame->PresContext()->PresShell();
       if (!presShell || (ps && !ps->IsPaintingSuppressed())) {
         subdocView = nextView;
         subdocRootFrame = frame;
         presShell = ps;
       }
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -221,19 +221,21 @@ fails-if(Android) != text-language-00.xh
 fails-if(Android) random-if(gtk2Widget) != text-language-01.xhtml text-language-01-ref.xhtml # Fails on Linux tryserver due to lack of CJK fonts.
 == text-layout-01.svg text-layout-01-ref.svg
 == text-layout-02.svg text-layout-02-ref.svg
 == text-layout-03.svg text-layout-03-ref.svg
 == text-layout-04.svg text-layout-04-ref.svg
 == text-layout-05.svg text-layout-05-ref.svg
 == text-scale-01.svg text-scale-01-ref.svg
 == text-stroke-scaling-01.svg text-stroke-scaling-01-ref.svg
+== stroke-dasharray-and-pathLength-01.svg pass.svg
 == stroke-linecap-square-w-zero-length-segs-01.svg pass.svg
 == stroke-linecap-square-w-zero-length-segs-02.svg pass.svg
 == textPath-01.svg textPath-01-ref.svg
+== textPath-02.svg pass.svg
 == text-style-01a.svg text-style-01-ref.svg
 == text-style-01b.svg text-style-01-ref.svg
 == text-style-01c.svg text-style-01-ref.svg
 == text-style-01d.svg text-style-01-ref.svg
 == text-style-01e.svg text-style-01-ref.svg
 == thin-stroke-01.svg pass.svg
 == tspan-dxdy-01.svg tspan-dxdy-ref.svg
 == tspan-dxdy-02.svg tspan-dxdy-ref.svg
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/stroke-dasharray-and-pathLength-01.svg
@@ -0,0 +1,20 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+  <title>Test stroke-dasharray with pathLength and scaling</title>
+  <rect width="100%" height="100%" fill="lime"/>
+  <!--
+    Here we set the 'pathLength' to twice the actual length of the path,
+    which should cause the stroke-dasharray values to be scaled down by one
+    half. Visually, this should effectively cancel out the 2x scaling along
+    the x-axis introduced by the 'transform' attribute.
+  -->
+  <path d="M0.5,10 L100.5,10" stroke="red" stroke-width="18" stroke-dasharray="18 22" pathLength="200" transform="scale(2,1)"/>
+  <rect x="1" y="1" width="18" height="18" fill="lime"/>
+  <rect x="41" y="1" width="18" height="18" fill="lime"/>
+  <rect x="81" y="1" width="18" height="18" fill="lime"/>
+  <rect x="121" y="1" width="18" height="18" fill="lime"/>
+  <rect x="161" y="1" width="18" height="18" fill="lime"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/textPath-02.svg
@@ -0,0 +1,15 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <title>Test effect on startOffset of a scale transform on a textPath's path</title>
+  <defs>
+    <path id="path" d="M20,20 C20,150 150,150 150,20" pathLength="100" transform="scale(2,1)" fill="none" stroke="black"/>
+  </defs>
+  <rect width="100%" height="100%" fill="lime"/>
+  <text y="50">
+    <textPath xlink:href="#path" font-size="20" fill="red" startOffset="50">FAIL</textPath>
+  </text>
+  <rect x="160" y="80" width="100" height="60" fill="lime"/>
+</svg>
--- a/layout/svg/base/src/Makefile.in
+++ b/layout/svg/base/src/Makefile.in
@@ -58,17 +58,20 @@ CPPSRCS		= \
 		nsSVGGFrame.cpp \
 		nsSVGGenericContainerFrame.cpp \
 		nsSVGGeometryFrame.cpp \
 		nsSVGGlyphFrame.cpp \
 		nsSVGGradientFrame.cpp \
 		nsSVGImageFrame.cpp \
 		nsSVGInnerSVGFrame.cpp \
 		nsSVGIntegrationUtils.cpp \
-		nsSVGLeafFrame.cpp \
+		SVGFEContainerFrame.cpp \
+		SVGFEImageFrame.cpp \
+		SVGFELeafFrame.cpp \
+		SVGFEUnstyledLeafFrame.cpp \
 		nsSVGMarkerFrame.cpp \
 		nsSVGMaskFrame.cpp \
 		nsSVGOuterSVGFrame.cpp \
 		nsSVGPaintServerFrame.cpp \
 		nsSVGPathGeometryFrame.cpp \
 		nsSVGPatternFrame.cpp \
 		nsSVGStopFrame.cpp \
 		nsSVGSwitchFrame.cpp \
new file mode 100644
--- /dev/null
+++ b/layout/svg/base/src/SVGFEContainerFrame.cpp
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is Robert Longson.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsContainerFrame.h"
+#include "nsSVGEffects.h"
+#include "nsSVGFilters.h"
+
+typedef nsContainerFrame SVGFEContainerFrameBase;
+
+/*
+ * This frame is used by filter primitive elements that
+ * have special child elements that provide parameters.
+ */
+class SVGFEContainerFrame : public SVGFEContainerFrameBase
+{
+  friend nsIFrame*
+  NS_NewSVGFEContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+protected:
+  SVGFEContainerFrame(nsStyleContext* aContext) : SVGFEContainerFrameBase(aContext) {}
+
+public:
+  NS_DECL_FRAMEARENA_HELPERS
+
+  virtual bool IsFrameOfType(PRUint32 aFlags) const
+  {
+    return SVGFEContainerFrameBase::IsFrameOfType(
+            aFlags & ~(nsIFrame::eSVG | nsIFrame::eSVGContainer));
+  }
+
+#ifdef DEBUG
+  NS_IMETHOD GetFrameName(nsAString& aResult) const
+  {
+    return MakeFrameName(NS_LITERAL_STRING("SVGFEContainer"), aResult);
+  }
+#endif
+
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
+
+#ifdef DEBUG
+  NS_IMETHOD Init(nsIContent* aContent,
+                  nsIFrame*   aParent,
+                  nsIFrame*   aPrevInFlow);
+#endif
+  /**
+   * Get the "type" of the frame
+   *
+   * @see nsGkAtoms::svgFEContainerFrame
+   */
+  virtual nsIAtom* GetType() const;
+
+  NS_IMETHOD AttributeChanged(PRInt32  aNameSpaceID,
+                              nsIAtom* aAttribute,
+                              PRInt32  aModType);
+};
+
+nsIFrame*
+NS_NewSVGFEContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
+{
+  return new (aPresShell) SVGFEContainerFrame(aContext);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(SVGFEContainerFrame)
+
+/* virtual */ void
+SVGFEContainerFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+  SVGFEContainerFrameBase::DidSetStyleContext(aOldStyleContext);
+  nsSVGEffects::InvalidateRenderingObservers(this);
+}
+
+#ifdef DEBUG
+NS_IMETHODIMP
+SVGFEContainerFrame::Init(nsIContent* aContent,
+                          nsIFrame* aParent,
+                          nsIFrame* aPrevInFlow)
+{
+  nsCOMPtr<nsIDOMSVGFilterPrimitiveStandardAttributes> elem = do_QueryInterface(aContent);
+  NS_ASSERTION(elem,
+               "Trying to construct an SVGFEContainerFrame for a "
+               "content element that doesn't support the right interfaces");
+
+  return SVGFEContainerFrameBase::Init(aContent, aParent, aPrevInFlow);
+}
+#endif /* DEBUG */
+
+nsIAtom *
+SVGFEContainerFrame::GetType() const
+{
+  return nsGkAtoms::svgFEContainerFrame;
+}
+
+NS_IMETHODIMP
+SVGFEContainerFrame::AttributeChanged(PRInt32  aNameSpaceID,
+                                      nsIAtom* aAttribute,
+                                      PRInt32  aModType)
+{
+  nsSVGFE *element = static_cast<nsSVGFE*>(mContent);
+  if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
+    nsSVGEffects::InvalidateRenderingObservers(this);
+  }
+
+  return SVGFEContainerFrameBase::AttributeChanged(aNameSpaceID,
+                                                     aAttribute, aModType);
+}
new file mode 100644
--- /dev/null
+++ b/layout/svg/base/src/SVGFEImageFrame.cpp
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is Robert Longson.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsFrame.h"
+#include "nsSVGEffects.h"
+#include "nsSVGFilters.h"
+#include "nsContentUtils.h"
+#include "nsImageLoadingContent.h"
+
+using namespace mozilla;
+
+typedef nsFrame SVGFEImageFrameBase;
+
+class SVGFEImageFrame : public SVGFEImageFrameBase
+{
+  friend nsIFrame*
+  NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+protected:
+  SVGFEImageFrame(nsStyleContext* aContext) : SVGFEImageFrameBase(aContext) {}
+
+public:
+  NS_DECL_FRAMEARENA_HELPERS
+
+  NS_IMETHOD Init(nsIContent* aContent,
+                  nsIFrame*   aParent,
+                  nsIFrame*   aPrevInFlow);
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
+
+  virtual bool IsFrameOfType(PRUint32 aFlags) const
+  {
+    return SVGFEImageFrameBase::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
+  }
+
+#ifdef DEBUG
+  NS_IMETHOD GetFrameName(nsAString& aResult) const
+  {
+    return MakeFrameName(NS_LITERAL_STRING("SVGFEImage"), aResult);
+  }
+#endif
+
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
+
+  /**
+   * Get the "type" of the frame
+   *
+   * @see nsGkAtoms::svgFEImageFrame
+   */
+  virtual nsIAtom* GetType() const;
+
+  NS_IMETHOD AttributeChanged(PRInt32  aNameSpaceID,
+                              nsIAtom* aAttribute,
+                              PRInt32  aModType);
+};
+
+nsIFrame*
+NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
+{
+  return new (aPresShell) SVGFEImageFrame(aContext);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(SVGFEImageFrame)
+
+/* virtual */ void
+SVGFEImageFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+  SVGFEImageFrameBase::DidSetStyleContext(aOldStyleContext);
+  nsSVGEffects::InvalidateRenderingObservers(this);
+}
+
+/* virtual */ void
+SVGFEImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
+{
+  nsCOMPtr<nsIImageLoadingContent> imageLoader =
+    do_QueryInterface(SVGFEImageFrameBase::mContent);
+
+  if (imageLoader) {
+    imageLoader->FrameDestroyed(this);
+  }
+
+  SVGFEImageFrameBase::DestroyFrom(aDestructRoot);
+}
+
+NS_IMETHODIMP
+SVGFEImageFrame::Init(nsIContent* aContent,
+                        nsIFrame* aParent,
+                        nsIFrame* aPrevInFlow)
+{
+#ifdef DEBUG
+  nsCOMPtr<nsIDOMSVGFEImageElement> elem = do_QueryInterface(aContent);
+  NS_ASSERTION(elem,
+               "Trying to construct an SVGFEImageFrame for a "
+               "content element that doesn't support the right interfaces");
+#endif /* DEBUG */
+
+  SVGFEImageFrameBase::Init(aContent, aParent, aPrevInFlow);
+  nsCOMPtr<nsIImageLoadingContent> imageLoader =
+    do_QueryInterface(SVGFEImageFrameBase::mContent);
+
+  if (imageLoader) {
+    imageLoader->FrameCreated(this);
+  }
+
+  return NS_OK;
+}
+
+nsIAtom *
+SVGFEImageFrame::GetType() const
+{
+  return nsGkAtoms::svgFEImageFrame;
+}
+
+NS_IMETHODIMP
+SVGFEImageFrame::AttributeChanged(PRInt32  aNameSpaceID,
+                                  nsIAtom* aAttribute,
+                                  PRInt32  aModType)
+{
+  nsSVGFEImageElement *element = static_cast<nsSVGFEImageElement*>(mContent);
+  if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
+    nsSVGEffects::InvalidateRenderingObservers(this);
+  }
+  if (aNameSpaceID == kNameSpaceID_XLink &&
+      aAttribute == nsGkAtoms::href) {
+
+    // Prevent setting image.src by exiting early
+    if (nsContentUtils::IsImageSrcSetDisabled()) {
+      return NS_OK;
+    }
+
+    if (element->mStringAttributes[nsSVGFEImageElement::HREF].IsExplicitlySet()) {
+      element->LoadSVGImage(true, true);
+    } else {
+      element->CancelImageRequests(true);
+    }
+  }
+
+  return SVGFEImageFrameBase::AttributeChanged(aNameSpaceID,
+                                                 aAttribute, aModType);
+}
copy from layout/svg/base/src/nsSVGLeafFrame.cpp
copy to layout/svg/base/src/SVGFELeafFrame.cpp
--- a/layout/svg/base/src/nsSVGLeafFrame.cpp
+++ b/layout/svg/base/src/SVGFELeafFrame.cpp
@@ -30,83 +30,108 @@
  * 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 "nsFrame.h"
+#include "nsSVGFilters.h"
 #include "nsSVGEffects.h"
-#include "nsImageLoadingContent.h"
+
+typedef nsFrame SVGFELeafFrameBase;
 
-class nsSVGLeafFrame : public nsFrame
+/*
+ * This frame is used by filter primitive elements that don't
+ * have special child elements that provide parameters.
+ */
+class SVGFELeafFrame : public SVGFELeafFrameBase
 {
   friend nsIFrame*
-  NS_NewSVGLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+  NS_NewSVGFELeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
-  nsSVGLeafFrame(nsStyleContext* aContext) : nsFrame(aContext) {}
+  SVGFELeafFrame(nsStyleContext* aContext) : SVGFELeafFrameBase(aContext) {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
-  NS_IMETHOD Init(nsIContent*      aContent,
-                  nsIFrame*        aParent,
-                  nsIFrame*        asPrevInFlow);
-
-  virtual void DestroyFrom(nsIFrame* aDestructRoot);
+#ifdef DEBUG
+  NS_IMETHOD Init(nsIContent* aContent,
+                  nsIFrame*   aParent,
+                  nsIFrame*   aPrevInFlow);
+#endif
 
   virtual bool IsFrameOfType(PRUint32 aFlags) const
   {
-    return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
+    return SVGFELeafFrameBase::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
   }
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const
   {
-    return MakeFrameName(NS_LITERAL_STRING("SVGLeaf"), aResult);
+    return MakeFrameName(NS_LITERAL_STRING("SVGFELeaf"), aResult);
   }
 #endif
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
+
+  /**
+   * Get the "type" of the frame
+   *
+   * @see nsGkAtoms::svgFELeafFrame
+   */
+  virtual nsIAtom* GetType() const;
+
+  NS_IMETHOD AttributeChanged(PRInt32  aNameSpaceID,
+                              nsIAtom* aAttribute,
+                              PRInt32  aModType);
 };
 
 nsIFrame*
-NS_NewSVGLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
+NS_NewSVGFELeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
-  return new (aPresShell) nsSVGLeafFrame(aContext);
+  return new (aPresShell) SVGFELeafFrame(aContext);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(SVGFELeafFrame)
+
+/* virtual */ void
+SVGFELeafFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+  SVGFELeafFrameBase::DidSetStyleContext(aOldStyleContext);
+  nsSVGEffects::InvalidateRenderingObservers(this);
 }
 
-NS_IMPL_FRAMEARENA_HELPERS(nsSVGLeafFrame)
+#ifdef DEBUG
+NS_IMETHODIMP
+SVGFELeafFrame::Init(nsIContent* aContent,
+                     nsIFrame* aParent,
+                     nsIFrame* aPrevInFlow)
+{
+  nsCOMPtr<nsIDOMSVGFilterPrimitiveStandardAttributes> elem = do_QueryInterface(aContent);
+  NS_ASSERTION(elem,
+               "Trying to construct an SVGFELeafFrame for a "
+               "content element that doesn't support the right interfaces");
+
+  return SVGFELeafFrameBase::Init(aContent, aParent, aPrevInFlow);
+}
+#endif /* DEBUG */
+
+nsIAtom *
+SVGFELeafFrame::GetType() const
+{
+  return nsGkAtoms::svgFELeafFrame;
+}
 
 NS_IMETHODIMP
-nsSVGLeafFrame::Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* asPrevInFlow)
+SVGFELeafFrame::AttributeChanged(PRInt32  aNameSpaceID,
+                                 nsIAtom* aAttribute,
+                                 PRInt32  aModType)
 {
-  nsFrame::Init(aContent, aParent, asPrevInFlow);
-  nsCOMPtr<nsIImageLoadingContent> imageLoader =
-    do_QueryInterface(nsFrame::mContent);
-
-  if (imageLoader) {
-    imageLoader->FrameCreated(this);
+  nsSVGFE *element = static_cast<nsSVGFE*>(mContent);
+  if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
+    nsSVGEffects::InvalidateRenderingObservers(this);
   }
 
-  return NS_OK;
+  return SVGFELeafFrameBase::AttributeChanged(aNameSpaceID,
+                                                aAttribute, aModType);
 }
-
-/* virtual */ void
-nsSVGLeafFrame::DestroyFrom(nsIFrame* aDestructRoot)
-{
-  nsCOMPtr<nsIImageLoadingContent> imageLoader =
-    do_QueryInterface(nsFrame::mContent);
-
-  if (imageLoader) {
-    imageLoader->FrameDestroyed(this);
-  }
-
-  nsFrame::DestroyFrom(aDestructRoot);
-}
-
-/* virtual */ void
-nsSVGLeafFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
-{
-  nsFrame::DidSetStyleContext(aOldStyleContext);
-  nsSVGEffects::InvalidateRenderingObservers(this);
-}
new file mode 100644
--- /dev/null
+++ b/layout/svg/base/src/SVGFEUnstyledLeafFrame.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is Robert Longson.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsFrame.h"
+#include "nsSVGFilters.h"
+#include "nsSVGEffects.h"
+
+typedef nsFrame SVGFEUnstyledLeafFrameBase;
+
+class SVGFEUnstyledLeafFrame : public SVGFEUnstyledLeafFrameBase
+{
+  friend nsIFrame*
+  NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+protected:
+  SVGFEUnstyledLeafFrame(nsStyleContext* aContext) : SVGFEUnstyledLeafFrameBase(aContext) {}
+
+public:
+  NS_DECL_FRAMEARENA_HELPERS
+
+  virtual bool IsFrameOfType(PRUint32 aFlags) const
+  {
+    return SVGFEUnstyledLeafFrameBase::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
+  }
+
+#ifdef DEBUG
+  NS_IMETHOD GetFrameName(nsAString& aResult) const
+  {
+    return MakeFrameName(NS_LITERAL_STRING("SVGFEUnstyledLeaf"), aResult);
+  }
+#endif
+
+  /**
+   * Get the "type" of the frame
+   *
+   * @see nsGkAtoms::svgFEUnstyledLeafFrame
+   */
+  virtual nsIAtom* GetType() const;
+
+  NS_IMETHOD AttributeChanged(PRInt32  aNameSpaceID,
+                              nsIAtom* aAttribute,
+                              PRInt32  aModType);
+};
+
+nsIFrame*
+NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
+{
+  return new (aPresShell) SVGFEUnstyledLeafFrame(aContext);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(SVGFEUnstyledLeafFrame)
+
+nsIAtom *
+SVGFEUnstyledLeafFrame::GetType() const
+{
+  return nsGkAtoms::svgFEUnstyledLeafFrame;
+}
+
+NS_IMETHODIMP
+SVGFEUnstyledLeafFrame::AttributeChanged(PRInt32  aNameSpaceID,
+                                         nsIAtom* aAttribute,
+                                         PRInt32  aModType)
+{
+  SVGFEUnstyledElement *element = static_cast<SVGFEUnstyledElement*>(mContent);
+  if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
+    nsSVGEffects::InvalidateRenderingObservers(this);
+  }
+
+  return SVGFEUnstyledLeafFrameBase::AttributeChanged(aNameSpaceID,
+                                                        aAttribute, aModType);
+}
--- a/layout/svg/base/src/nsSVGGeometryFrame.cpp
+++ b/layout/svg/base/src/nsSVGGeometryFrame.cpp
@@ -115,18 +115,18 @@ nsSVGGeometryFrame::GetStrokeDashArray(g
   if (count) {
     const nsStyleCoord *dasharray = GetStyleSVG()->mStrokeDasharray;
     nsPresContext *presContext = PresContext();
     gfxFloat totalLength = 0.0f;
 
     gfxFloat pathScale = 1.0;
 
     if (mContent->Tag() == nsGkAtoms::path) {
-      pathScale =
-        static_cast<nsSVGPathElement*>(mContent)->GetPathLengthScale();
+      pathScale = static_cast<nsSVGPathElement*>(mContent)->
+                    GetPathLengthScale(nsSVGPathElement::eForStroking);
       if (pathScale <= 0) {
         return NS_OK;
       }
     }
 
     dashes = new gfxFloat[count];
     if (dashes) {
       for (PRUint32 i = 0; i < count; i++) {
--- a/layout/svg/base/src/nsSVGTextPathFrame.cpp
+++ b/layout/svg/base/src/nsSVGTextPathFrame.cpp
@@ -172,17 +172,17 @@ nsSVGTextPathFrame::GetStartOffset()
 gfxFloat
 nsSVGTextPathFrame::GetOffsetScale()
 {
   nsIFrame *pathFrame = GetPathFrame();
   if (!pathFrame)
     return 1.0;
 
   return static_cast<nsSVGPathElement*>(pathFrame->GetContent())->
-    GetPathLengthScale();
+    GetPathLengthScale(nsSVGPathElement::eForTextPath);
 }
 
 //----------------------------------------------------------------------
 // nsIFrame methods
 
 NS_IMETHODIMP
 nsSVGTextPathFrame::AttributeChanged(PRInt32         aNameSpaceID,
                                      nsIAtom*        aAttribute,
--- a/layout/xul/base/public/nsXULPopupManager.h
+++ b/layout/xul/base/public/nsXULPopupManager.h
@@ -76,17 +76,16 @@
  */
 
 class nsMenuFrame;
 class nsMenuPopupFrame;
 class nsMenuBarFrame;
 class nsMenuParent;
 class nsIDOMKeyEvent;
 class nsIDocShellTreeItem;
-class nsIView;
 
 // when a menu command is executed, the closemenu attribute may be used
 // to define how the menu should be closed up
 enum CloseMenuMode {
   CloseMenuMode_Auto, // close up the chain of menus, default value
   CloseMenuMode_None, // don't close up any menus
   CloseMenuMode_Single // close up only the menu the command is inside
 };
@@ -473,19 +472,20 @@ public:
    */
   void HidePopup(nsIContent* aPopup,
                  bool aHideChain,
                  bool aDeselectMenu,
                  bool aAsynchronous,
                  nsIContent* aLastPopup = nsnull);
 
   /**
-   * Hide the popup associated the view aView
+   * Hide the popup aFrame. This method is called by the view manager when the
+   * close button is pressed.
    */
-  void HidePopup(nsIView* aView);
+  void HidePopup(nsIFrame* aFrame);
 
   /**
    * Hide a popup after a short delay. This is used when rolling over menu items.
    * This timer is stored in mCloseTimer. The timer may be cancelled and the popup
    * closed by calling KillMenuTimer.
    */
   void HidePopupAfterDelay(nsMenuPopupFrame* aPopup);
 
@@ -548,23 +548,23 @@ public:
    * focused, or if it is a submenu of another menu that isn't open.
    */
   bool MayShowPopup(nsMenuPopupFrame* aFrame);
 
   /**
    * Indicate that the popup associated with aView has been moved to the
    * specified screen coordiates.
    */
-  void PopupMoved(nsIView* aView, nsIntPoint aPoint);
+  void PopupMoved(nsIFrame* aFrame, nsIntPoint aPoint);
 
   /**
    * Indicate that the popup associated with aView has been resized to the
    * specified screen width and height.
    */
-  void PopupResized(nsIView* aView, nsIntSize ASize);
+  void PopupResized(nsIFrame* aFrame, nsIntSize ASize);
 
   /**
    * Called when a popup frame is destroyed. In this case, just remove the
    * item and later popups from the list. No point going through HidePopup as
    * the frames have gone away.
    */
   void PopupDestroyed(nsMenuPopupFrame* aFrame);
 
--- a/layout/xul/base/src/nsXULPopupManager.cpp
+++ b/layout/xul/base/src/nsXULPopupManager.cpp
@@ -331,34 +331,33 @@ nsXULPopupManager::AdjustPopupsOnWindowC
       }
     }
 
     item = item->GetParent();
   }
 }
 
 static
-nsMenuPopupFrame* GetPopupToMoveOrResize(nsIView* aView)
+nsMenuPopupFrame* GetPopupToMoveOrResize(nsIFrame* aFrame)
 {
-  nsIFrame *frame = static_cast<nsIFrame *>(aView->GetClientData());
-  if (!frame || frame->GetType() != nsGkAtoms::menuPopupFrame)
+  if (!aFrame || aFrame->GetType() != nsGkAtoms::menuPopupFrame)
     return nsnull;
 
   // no point moving or resizing hidden popups
-  nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame *>(frame);
+  nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame *>(aFrame);
   if (menuPopupFrame->PopupState() != ePopupOpenAndVisible)
     return nsnull;
 
   return menuPopupFrame;
 }
 
 void
-nsXULPopupManager::PopupMoved(nsIView* aView, nsIntPoint aPnt)
+nsXULPopupManager::PopupMoved(nsIFrame* aFrame, nsIntPoint aPnt)
 {
-  nsMenuPopupFrame* menuPopupFrame = GetPopupToMoveOrResize(aView);
+  nsMenuPopupFrame* menuPopupFrame = GetPopupToMoveOrResize(aFrame);
   if (!menuPopupFrame)
     return;
 
   // Don't do anything if the popup is already at the specified location. This
   // prevents recursive calls when a popup is positioned.
   nsIntPoint currentPnt = menuPopupFrame->ScreenPosition();
   if (aPnt.x != currentPnt.x || aPnt.y != currentPnt.y) {
     // Update the popup's position using SetPopupPosition if the popup is
@@ -371,19 +370,19 @@ nsXULPopupManager::PopupMoved(nsIView* a
     }
     else {
       menuPopupFrame->MoveTo(aPnt.x, aPnt.y, false);
     }
   }
 }
 
 void
-nsXULPopupManager::PopupResized(nsIView* aView, nsIntSize aSize)
+nsXULPopupManager::PopupResized(nsIFrame* aFrame, nsIntSize aSize)
 {
-  nsMenuPopupFrame* menuPopupFrame = GetPopupToMoveOrResize(aView);
+  nsMenuPopupFrame* menuPopupFrame = GetPopupToMoveOrResize(aFrame);
   if (!menuPopupFrame)
     return;
 
   nsPresContext* presContext = menuPopupFrame->PresContext();
 
   nsSize currentSize = menuPopupFrame->GetSize();
   if (aSize.width != presContext->AppUnitsToDevPixels(currentSize.width) ||
       aSize.height != presContext->AppUnitsToDevPixels(currentSize.height)) {
@@ -993,23 +992,20 @@ nsXULPopupManager::HidePopupCallback(nsI
       FirePopupHidingEvent(popupToHide, nextPopup, aLastPopup,
                            popupFrame->PresContext(),
                            foundMenu->PopupType(), aDeselectMenu);
     }
   }
 }
 
 void
-nsXULPopupManager::HidePopup(nsIView* aView)
+nsXULPopupManager::HidePopup(nsIFrame* aFrame)
 {
-  nsIFrame *frame = static_cast<nsIFrame *>(aView->GetClientData());
-  if (!frame || frame->GetType() != nsGkAtoms::menuPopupFrame)
-    return;
-
-  HidePopup(frame->GetContent(), false, true, false);
+  if (aFrame && aFrame->GetType() == nsGkAtoms::menuPopupFrame)
+    HidePopup(aFrame->GetContent(), false, true, false);
 }
 
 void
 nsXULPopupManager::HidePopupAfterDelay(nsMenuPopupFrame* aPopup)
 {
   // Don't close up immediately.
   // Kick off a close timer.
   KillMenuTimer();
--- a/media/libvpx/Makefile.in
+++ b/media/libvpx/Makefile.in
@@ -523,13 +523,12 @@ else
 endif
 
 endif
 
 # Workaround a bug of Sun Studio (CR 6963410)
 ifdef SOLARIS_SUNPRO_CC
 ifeq (86,$(findstring 86,$(OS_TEST)))
 filter.o: filter.c Makefile.in
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(CC) -o $@ -c $(patsubst -xO[45],-xO3,$(COMPILE_CFLAGS)) $<
 endif
 endif
--- a/memory/jemalloc/jemalloc.c
+++ b/memory/jemalloc/jemalloc.c
@@ -984,20 +984,20 @@ struct arena_bin_s {
 
 #ifdef MALLOC_STATS
 	/* Bin statistics. */
 	malloc_bin_stats_t stats;
 #endif
 };
 
 struct arena_s {
-#ifdef MALLOC_DEBUG
+	/* For bug 703087, we're temporarily adding arena.magic to release
+	   builds. */
 	uint32_t		magic;
 #  define ARENA_MAGIC 0x947d3d24
-#endif
 
 	/* All operations on this arena require that lock be locked. */
 #ifdef MOZ_MEMORY
 	malloc_spinlock_t	lock;
 #else
 	pthread_mutex_t		lock;
 #endif
 
@@ -4327,17 +4327,25 @@ isalloc_validate(const void *ptr)
 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
 	if (chunk == NULL)
 		return (0);
 
 	if (malloc_rtree_get(chunk_rtree, (uintptr_t)chunk) == NULL)
 		return (0);
 
 	if (chunk != ptr) {
-		assert(chunk->arena->magic == ARENA_MAGIC);
+		/* For bug 703087, we've temporarily made what is normally a
+		   debug-only assertion here into a fatal assertion. */
+		if (chunk->arena->magic != ARENA_MAGIC) {
+			char* boom = (char*) 0;
+			_malloc_message("isalloc_validate called with invalid pointer. "
+			                "Crashing...\n", "", "", "");
+			*boom = 1;
+		}
+
 		return (arena_salloc(ptr));
 	} else {
 		size_t ret;
 		extent_node_t *node;
 		extent_node_t key;
 
 		/* Chunk. */
 		key.addr = (void *)chunk;
@@ -4837,20 +4845,19 @@ arena_new(arena_t *arena)
 
 		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
 
 #ifdef MALLOC_STATS
 		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
 #endif
 	}
 
-#ifdef MALLOC_DEBUG
+        /* For bug 703087, we're temporarily adding arena->magic for release
+           builds. */
 	arena->magic = ARENA_MAGIC;
-#endif
-
 	return (false);
 }
 
 /* Create a new arena and insert it into the arenas array at index ind. */
 static arena_t *
 arenas_extend(unsigned ind)
 {
 	arena_t *ret;
@@ -6058,23 +6065,26 @@ MALLOC_OUT:
 
 #ifdef MOZ_MEMORY_DARWIN
 	/*
 	* Overwrite the default memory allocator to use jemalloc everywhere.
 	*/
 	default_zone = malloc_default_zone();
 
 	/*
-	 * We only use jemalloc with versions of MacOS we've seen (10.5, 10.6, and
-	 * 10.7).  We'll have to update our code to work with newer versions,
-	 * because the malloc zone layout is likely to change.
+	 * We only use jemalloc with MacOS 10.6 and 10.7.  jemalloc is disabled
+	 * on 32-bit builds (10.5 and 32-bit 10.6) due to bug 702250, an
+	 * apparent MacOS bug.  In fact, this code isn't even compiled on
+	 * 32-bit builds.
+	 *
+	 * We'll have to update our code to work with newer versions, because
+	 * the malloc zone layout is likely to change.
 	 */
 
-	osx_use_jemalloc = (default_zone->version == LEOPARD_MALLOC_ZONE_T_VERSION ||
-			    default_zone->version == SNOW_LEOPARD_MALLOC_ZONE_T_VERSION ||
+	osx_use_jemalloc = (default_zone->version == SNOW_LEOPARD_MALLOC_ZONE_T_VERSION ||
 			    default_zone->version == LION_MALLOC_ZONE_T_VERSION);
 
 	/* Allow us dynamically turn off jemalloc for testing. */
 	if (getenv("NO_MAC_JEMALLOC")) {
 		osx_use_jemalloc = false;
 #ifdef __i386__
 		malloc_printf("Warning: NO_MAC_JEMALLOC has no effect on "
 			      "i386 machines (such as this one).\n");
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -169,17 +169,17 @@ public:
         return TemporaryRef<T>(tmp, dontRef());
     }
 
     T* get() const { return ptr; }
     operator T*() const { return ptr; }
     T* operator->() const { return ptr; }
     T& operator*() const { return *ptr; }
     template<typename U>
-    operator TemporaryRef<U>() { return forget(); }
+    operator TemporaryRef<U>() { return TemporaryRef<U>(ptr); }
 
 private:
     void assign(T* t) {
         unref(ptr);
         ptr = t;
     }
 
     T* ptr;
--- a/mobile/android/app/Makefile.in
+++ b/mobile/android/app/Makefile.in
@@ -40,27 +40,27 @@ topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = profile/extensions
 
 PREF_JS_EXPORTS = $(srcdir)/mobile.js
-DIST_FILES = application.ini
 
 ifndef LIBXUL_SDK
 ifneq (Android,$(OS_TARGET))
 PROGRAM=$(MOZ_APP_NAME)$(BIN_SUFFIX)
 
 CPPSRCS = nsBrowserApp.cpp
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
+LOCAL_INCLUDES += -I$(DEPTH)/build
 
 DEFINES += -DXPCOM_GLUE
 STL_FLAGS=
 
 LIBS += \
   $(EXTRA_DSO_LIBS) \
   $(XPCOM_STANDALONE_GLUE_LDOPTS) \
   $(NULL)
@@ -85,53 +85,23 @@ endif
 endif
 endif #LIBXUL_SDK
 
 # Make sure the standalone glue doesn't try to get libxpcom.so from mobile/app.
 NSDISTMODE = copy
 
 include $(topsrcdir)/config/rules.mk
 
-GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
-GRE_BUILDID = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build BuildID)
-ifndef MOZ_BUILD_DATE
-APP_BUILDID = $(shell $(PYTHON) $(topsrcdir)/toolkit/xre/make-platformini.py --print-buildid)
-else
-APP_BUILDID = $(MOZ_BUILD_DATE)
-endif
 APP_ICON = mobile
 
-DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) \
-           -DGRE_BUILDID=$(GRE_BUILDID) \
-           -DAPP_BUILDID=$(APP_BUILDID) \
-           -DAPP_NAME=$(MOZ_APP_NAME) \
-           -DAPP_VERSION=$(MOZ_APP_VERSION) \
-           -DMOZ_UPDATER=$(MOZ_UPDATER) \
-           -DAPP_ID=$(MOZ_APP_ID) \
-           $(NULL)
-
-ifdef MOZILLA_OFFICIAL
-DEFINES += -DMOZILLA_OFFICIAL
-endif
-
-SOURCE_STAMP := $(shell cd $(srcdir)/.. && hg identify 2>/dev/null | cut -f1 -d' ')
-ifdef SOURCE_STAMP
-DEFINES += -DMOZ_SOURCE_STAMP="$(SOURCE_STAMP)"
-endif
-
-# strip a trailing slash from the repo URL because it's not always present,
-# and we want to construct a working URL in buildconfig.html
-# make+shell+sed = awful
-_dollar=$$
-SOURCE_REPO := $(shell cd $(srcdir)/.. && hg showconfig paths.default 2>/dev/null | head -n1 | sed -e "s/^ssh:/http:/" -e "s/\/$(_dollar)//" )
-# extra sanity check for old versions of hg
-# that don't support showconfig
-ifeq (http,$(patsubst http%,http,$(SOURCE_REPO)))
-DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
-endif
+DEFINES += \
+  -DAPP_NAME=$(MOZ_APP_NAME) \
+  -DAPP_VERSION=$(MOZ_APP_VERSION) \
+  -DMOZ_UPDATER=$(MOZ_UPDATER) \
+  $(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
 REDIT_PATH = $(LIBXUL_DIST)/bin
 endif
 
 APP_BINARY = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
@@ -151,17 +121,17 @@ clean clobber repackage::
 	rm -rf $(DIST)/$(APP_NAME).app
 
 ifdef LIBXUL_SDK
 APPFILES = Resources
 else
 APPFILES = MacOS
 endif
 
-libs repackage:: application.ini
+libs repackage::
 	mkdir -p $(DIST)/$(APP_NAME).app/Contents/MacOS
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
 	mkdir -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" -e "s/%APP_BINARY%/$(APP_BINARY)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
 	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
 	$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
deleted file mode 100644
--- a/mobile/android/app/application.ini
+++ /dev/null
@@ -1,26 +0,0 @@
-#filter substitution
-[App]
-Vendor=Mozilla
-Name=Fennec
-Version=@APP_VERSION@
-BuildID=@APP_BUILDID@
-#ifdef MOZ_SOURCE_REPO
-SourceRepository=@MOZ_SOURCE_REPO@
-#endif
-#ifdef MOZ_SOURCE_STAMP
-SourceStamp=@MOZ_SOURCE_STAMP@
-#endif
-ID=@APP_ID@
-
-[Gecko]
-MinVersion=1.9.2b5pre
-MaxVersion=@GRE_MILESTONE@
-
-[XRE]
-EnableExtensionManager=1
-
-[Crash Reporter]
-#if MOZILLA_OFFICIAL
-Enabled=1
-#endif
-ServerURL=https://crash-reports.mozilla.com/submit
--- a/mobile/android/app/nsBrowserApp.cpp
+++ b/mobile/android/app/nsBrowserApp.cpp
@@ -31,18 +31,18 @@
  * 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 "application.ini.h"
 #include "nsXPCOMGlue.h"
-#include "nsXULAppAPI.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
 #elif defined(XP_UNIX)
 #include <sys/time.h>
 #include <sys/resource.h>
 #endif
 
@@ -142,30 +142,17 @@ static const nsDynamicFunctionLoad kXULF
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { nsnull, nsnull }
 };
 
 static int do_main(const char *exePath, int argc, char* argv[])
 {
   nsCOMPtr<nsILocalFile> appini;
-#ifdef XP_WIN
-  // exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
-  // encoded path, so it is safe to convert it
-  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
-                                getter_AddRefs(appini));
-#else
-  nsresult rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
-                                      getter_AddRefs(appini));
-#endif
-  if (NS_FAILED(rv)) {
-    return 255;
-  }
-
-  appini->SetNativeLeafName(NS_LITERAL_CSTRING("application.ini"));
+  nsresult rv;
 
   // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
   // Note that -app must be the *first* argument.
   const char *appDataFile = getenv("XUL_APP_FILE");
   if (appDataFile && *appDataFile) {
     rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
     if (NS_FAILED(rv)) {
       Output("Invalid path found: '%s'", appDataFile);
@@ -190,25 +177,42 @@ static int do_main(const char *exePath, 
       Output("Couldn't set %s.\n", appEnv);
       return 255;
     }
     argv[2] = argv[0];
     argv += 2;
     argc -= 2;
   }
 
-  nsXREAppData *appData;
-  rv = XRE_CreateAppData(appini, &appData);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't read application.ini");
-    return 255;
+  int result;
+  if (appini) {
+    nsXREAppData *appData;
+    rv = XRE_CreateAppData(appini, &appData);
+    if (NS_FAILED(rv)) {
+      Output("Couldn't read application.ini");
+      return 255;
+    }
+    result = XRE_main(argc, argv, appData);
+    XRE_FreeAppData(appData);
+  } else {
+#ifdef XP_WIN
+    // exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
+    // encoded path, so it is safe to convert it
+    rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), PR_FALSE,
+                         getter_AddRefs(appini));
+#else
+    rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_FALSE,
+                               getter_AddRefs(appini));
+#endif
+    if (NS_FAILED(rv)) {
+      return 255;
+    }
+    result = XRE_main(argc, argv, &sAppData);
   }
 
-  int result = XRE_main(argc, argv, appData);
-  XRE_FreeAppData(appData);
   return result;
 }
 
 #if MOZ_PLATFORM_MAEMO == 6
 static bool
 GeckoPreLoader(const char* execPath)
 {
   nsresult rv = XPCOMGlueStartup(execPath);
@@ -264,16 +268,18 @@ int main(int argc, char* argv[])
   nsFastStartup startup;
   startup.CreateFastStartup(argc, argv, exePath, GeckoPreLoader);
 #else
   rv = XPCOMGlueStartup(exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XPCOM.\n");
     return 255;
   }
+  // Reset exePath so that it is the directory name and not the xpcom dll name
+  *lastSlash = 0;
 
   rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XRE functions.\n");
     return 255;
   }
 #endif
 
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -102,20 +102,22 @@ abstract public class GeckoApp
     public static SurfaceView cameraView;
     public static GeckoApp mAppContext;
     public static boolean mFullScreen = false;
     public static File sGREDir = null;
     public static Menu sMenu;
     public Handler mMainHandler;
     private IntentFilter mConnectivityFilter;
     private BroadcastReceiver mConnectivityReceiver;
+
     public static BrowserToolbar mBrowserToolbar;
     public static DoorHangerPopup mDoorHangerPopup;
     public Favicons mFavicons;
     private IntentFilter mBatteryFilter;
+
     private BroadcastReceiver mBatteryReceiver;
     private Geocoder mGeocoder;
     private Address  mLastGeoAddress;
     private static LayerController mLayerController;
     private static PlaceholderLayerClient mPlaceholderLayerClient;
     private static GeckoSoftwareLayerClient mSoftwareLayerClient;
     boolean mUserDefinedProfile = false;
 
@@ -1239,19 +1241,20 @@ abstract public class GeckoApp
         GeckoAppShell.registerGeckoEventListener("PanZoom:Resize", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("ToggleChrome:Hide", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
 
         mConnectivityFilter = new IntentFilter();
         mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         mConnectivityReceiver = new GeckoConnectivityReceiver();
 
-        mBatteryFilter = new IntentFilter();
-        mBatteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        IntentFilter batteryFilter = new IntentFilter();
+        batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
         mBatteryReceiver = new GeckoBatteryManager();
+        registerReceiver(mBatteryReceiver, batteryFilter);
                 
         final GeckoApp self = this;
  
         mMainHandler.postDelayed(new Runnable() {
             public void run() {
                 
                 Log.w(LOGTAG, "zerdatime " + new Date().getTime() + " - pre checkLaunchState");
 
@@ -1354,17 +1357,16 @@ abstract public class GeckoApp
 
         // Whatever we do here should be fast, because we're blocking
         // the next activity from showing up until we finish.
 
         // onPause will be followed by either onResume or onStop.
         super.onPause();
 
         unregisterReceiver(mConnectivityReceiver);
-        unregisterReceiver(mBatteryReceiver);
     }
 
     @Override
     public void onResume()
     {
         Log.i(LOGTAG, "resume");
         if (checkLaunchState(LaunchState.GeckoRunning))
             GeckoAppShell.onResume();
@@ -1372,17 +1374,16 @@ abstract public class GeckoApp
         // Undo whatever we did in onPause.
         super.onResume();
 
         // Just in case. Normally we start in onNewIntent
         if (checkLaunchState(LaunchState.Launching))
             onNewIntent(getIntent());
 
         registerReceiver(mConnectivityReceiver, mConnectivityFilter);
-        registerReceiver(mBatteryReceiver, mBatteryFilter);
     }
 
     @Override
     public void onStop()
     {
         Log.i(LOGTAG, "stop");
         // We're about to be stopped, potentially in preparation for
         // being destroyed.  We're killable after this point -- as I
@@ -1444,16 +1445,18 @@ abstract public class GeckoApp
         GeckoAppShell.unregisterGeckoEventListener("Gecko:Ready", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Toast:Show", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Hide", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
 
         mFavicons.close();
 
         super.onDestroy();
+
+        unregisterReceiver(mBatteryReceiver);
     }
 
     @Override
     public void onConfigurationChanged(android.content.res.Configuration newConfig)
     {
         Log.i(LOGTAG, "configuration changed");
         // nothing, just ignore
         super.onConfigurationChanged(newConfig);
--- a/mobile/android/confvars.sh
+++ b/mobile/android/confvars.sh
@@ -30,18 +30,18 @@
 # 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 *****
 
-MOZ_APP_NAME=fennec
-MOZ_APP_UA_NAME=Fennec
+MOZ_APP_BASENAME=Fennec
+MOZ_APP_VENDOR=Mozilla
 
 MOZ_APP_VERSION=11.0a1
 
 MOZ_BRANDING_DIRECTORY=mobile/android/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/android/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
@@ -66,8 +66,11 @@ MOZ_APP_COMPONENT_LIBS="browsercomps"
 MOZ_APP_COMPONENT_INCLUDE=nsBrowserComponents.h
 
 # use custom widget for html:select
 MOZ_USE_NATIVE_POPUP_WINDOWS=1
 
 MOZ_APP_ID={aa3c5121-dab2-40e2-81ca-7ea25febc110}
 
 MOZ_JAVA_COMPOSITOR=1
+MOZ_EXTENSION_MANAGER=1
+MOZ_APP_STATIC_INI=1
+
--- a/mobile/android/installer/removed-files.in
+++ b/mobile/android/installer/removed-files.in
@@ -1,8 +1,9 @@
+update.locale
 README.txt
 components/nsTryToClose.js
 #if MOZ_UPDATE_CHANNEL != beta
 extensions/feedback@mobile.mozilla.org.xpi
 #endif
 #ifdef XP_WIN
   #if _MSC_VER != 1400
     @BINPATH@/Microsoft.VC80.CRT.manifest
--- a/mobile/xul/app/Makefile.in
+++ b/mobile/xul/app/Makefile.in
@@ -40,27 +40,27 @@ topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = profile/extensions
 
 PREF_JS_EXPORTS = $(srcdir)/mobile.js
-DIST_FILES = application.ini
 
 ifndef LIBXUL_SDK
 ifneq (Android,$(OS_TARGET))
 PROGRAM=$(MOZ_APP_NAME)$(BIN_SUFFIX)
 
 CPPSRCS = nsBrowserApp.cpp
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
+LOCAL_INCLUDES += -I$(DEPTH)/build
 
 DEFINES += -DXPCOM_GLUE
 STL_FLAGS=
 
 LIBS += \
   $(EXTRA_DSO_LIBS) \
   $(XPCOM_STANDALONE_GLUE_LDOPTS) \
   $(NULL)
@@ -85,52 +85,23 @@ endif
 endif
 endif #LIBXUL_SDK
 
 # Make sure the standalone glue doesn't try to get libxpcom.so from mobile/app.
 NSDISTMODE = copy
 
 include $(topsrcdir)/config/rules.mk
 
-GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
-GRE_BUILDID = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build BuildID)
-ifndef MOZ_BUILD_DATE
-APP_BUILDID = $(shell $(PYTHON) $(topsrcdir)/toolkit/xre/make-platformini.py --print-buildid)
-else
-APP_BUILDID = $(MOZ_BUILD_DATE)
-endif
 APP_ICON = mobile
 
-DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) \
-           -DGRE_BUILDID=$(GRE_BUILDID) \
-           -DAPP_BUILDID=$(APP_BUILDID) \
-           -DAPP_NAME=$(MOZ_APP_NAME) \
-           -DAPP_VERSION=$(MOZ_APP_VERSION) \
-           -DMOZ_UPDATER=$(MOZ_UPDATER) \
-           $(NULL)
-
-ifdef MOZILLA_OFFICIAL
-DEFINES += -DMOZILLA_OFFICIAL
-endif
-
-SOURCE_STAMP := $(shell cd $(srcdir)/.. && hg identify 2>/dev/null | cut -f1 -d' ')
-ifdef SOURCE_STAMP
-DEFINES += -DMOZ_SOURCE_STAMP="$(SOURCE_STAMP)"
-endif
-
-# strip a trailing slash from the repo URL because it's not always present,
-# and we want to construct a working URL in buildconfig.html
-# make+shell+sed = awful
-_dollar=$$
-SOURCE_REPO := $(shell cd $(srcdir)/.. && hg showconfig paths.default 2>/dev/null | head -n1 | sed -e "s/^ssh:/http:/" -e "s/\/$(_dollar)//" )
-# extra sanity check for old versions of hg
-# that don't support showconfig
-ifeq (http,$(patsubst http%,http,$(SOURCE_REPO)))
-DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
-endif
+DEFINES += \
+  -DAPP_NAME=$(MOZ_APP_NAME) \
+  -DAPP_VERSION=$(MOZ_APP_VERSION) \
+  -DMOZ_UPDATER=$(MOZ_UPDATER) \
+  $(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
 REDIT_PATH = $(LIBXUL_DIST)/bin
 endif
 
 APP_BINARY = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
@@ -150,17 +121,17 @@ clean clobber repackage::
 	rm -rf $(DIST)/$(APP_NAME).app
 
 ifdef LIBXUL_SDK
 APPFILES = Resources
 else
 APPFILES = MacOS
 endif
 
-libs repackage:: application.ini
+libs repackage::
 	mkdir -p $(DIST)/$(APP_NAME).app/Contents/MacOS
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
 	mkdir -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" -e "s/%APP_BINARY%/$(APP_BINARY)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
 	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
 	$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
deleted file mode 100644
--- a/mobile/xul/app/application.ini
+++ /dev/null
@@ -1,26 +0,0 @@
-#filter substitution
-[App]
-Vendor=Mozilla
-Name=Fennec
-Version=@APP_VERSION@
-BuildID=@APP_BUILDID@
-#ifdef MOZ_SOURCE_REPO
-SourceRepository=@MOZ_SOURCE_REPO@
-#endif
-#ifdef MOZ_SOURCE_STAMP
-SourceStamp=@MOZ_SOURCE_STAMP@
-#endif
-ID={a23983c0-fd0e-11dc-95ff-0800200c9a66}
-
-[Gecko]
-MinVersion=1.9.2b5pre
-MaxVersion=@GRE_MILESTONE@
-
-[XRE]
-EnableExtensionManager=1
-
-[Crash Reporter]
-#if MOZILLA_OFFICIAL
-Enabled=1
-#endif
-ServerURL=https://crash-reports.mozilla.com/submit
--- a/mobile/xul/app/nsBrowserApp.cpp
+++ b/mobile/xul/app/nsBrowserApp.cpp
@@ -31,18 +31,18 @@
  * 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 "application.ini.h"
 #include "nsXPCOMGlue.h"
-#include "nsXULAppAPI.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
 #elif defined(XP_UNIX)
 #include <sys/time.h>
 #include <sys/resource.h>
 #endif
 
@@ -142,30 +142,17 @@ static const nsDynamicFunctionLoad kXULF
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { nsnull, nsnull }
 };
 
 static int do_main(const char *exePath, int argc, char* argv[])
 {
   nsCOMPtr<nsILocalFile> appini;
-#ifdef XP_WIN
-  // exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
-  // encoded path, so it is safe to convert it
-  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
-                                getter_AddRefs(appini));
-#else
-  nsresult rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
-                                      getter_AddRefs(appini));
-#endif
-  if (NS_FAILED(rv)) {
-    return 255;
-  }
-
-  appini->SetNativeLeafName(NS_LITERAL_CSTRING("application.ini"));
+  nsresult rv;
 
   // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
   // Note that -app must be the *first* argument.
   const char *appDataFile = getenv("XUL_APP_FILE");
   if (appDataFile && *appDataFile) {
     rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
     if (NS_FAILED(rv)) {
       Output("Invalid path found: '%s'", appDataFile);
@@ -190,25 +177,42 @@ static int do_main(const char *exePath, 
       Output("Couldn't set %s.\n", appEnv);
       return 255;
     }
     argv[2] = argv[0];
     argv += 2;
     argc -= 2;
   }
 
-  nsXREAppData *appData;
-  rv = XRE_CreateAppData(appini, &appData);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't read application.ini");
-    return 255;
+  int result;
+  if (appini) {
+    nsXREAppData *appData;
+    rv = XRE_CreateAppData(appini, &appData);
+    if (NS_FAILED(rv)) {
+      Output("Couldn't read application.ini");
+      return 255;
+    }
+    result = XRE_main(argc, argv, appData);
+    XRE_FreeAppData(appData);
+  } else {
+#ifdef XP_WIN
+    // exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
+    // encoded path, so it is safe to convert it
+    rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), PR_FALSE,
+                         getter_AddRefs(appini));
+#else
+    rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_FALSE,
+                               getter_AddRefs(appini));
+#endif
+    if (NS_FAILED(rv)) {
+      return 255;
+    }
+    result = XRE_main(argc, argv, &sAppData);
   }
 
-  int result = XRE_main(argc, argv, appData);
-  XRE_FreeAppData(appData);
   return result;
 }
 
 #if MOZ_PLATFORM_MAEMO == 6
 static bool
 GeckoPreLoader(const char* execPath)
 {
   nsresult rv = XPCOMGlueStartup(execPath);
@@ -264,16 +268,18 @@ int main(int argc, char* argv[])
   nsFastStartup startup;
   startup.CreateFastStartup(argc, argv, exePath, GeckoPreLoader);
 #else
   rv = XPCOMGlueStartup(exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XPCOM.\n");
     return 255;
   }
+  // Reset exePath so that it is the directory name and not the xpcom dll name
+  *lastSlash = 0;
 
   rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XRE functions.\n");
     return 255;
   }
 #endif
 
--- a/mobile/xul/confvars.sh
+++ b/mobile/xul/confvars.sh
@@ -30,18 +30,18 @@
 # 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 *****
 
-MOZ_APP_NAME=fennec
-MOZ_APP_UA_NAME=Fennec
+MOZ_APP_BASENAME=Fennec
+MOZ_APP_VENDOR=Mozilla
 
 MOZ_APP_VERSION=11.0a1
 
 MOZ_BRANDING_DIRECTORY=mobile/xul/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/xul/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
@@ -62,8 +62,12 @@ MOZ_RAW=1
 fi
 
 # Needed for building our components as part of libxul
 MOZ_APP_COMPONENT_LIBS="browsercomps"
 MOZ_APP_COMPONENT_INCLUDE=nsBrowserComponents.h
 
 # use custom widget for html:select
 MOZ_USE_NATIVE_POPUP_WINDOWS=1
+
+MOZ_APP_ID={a23983c0-fd0e-11dc-95ff-0800200c9a66}
+MOZ_EXTENSION_MANAGER=1
+MOZ_APP_STATIC_INI=1
--- a/mobile/xul/installer/removed-files.in
+++ b/mobile/xul/installer/removed-files.in
@@ -1,8 +1,9 @@
+update.locale
 README.txt
 components/nsTryToClose.js
 #if MOZ_UPDATE_CHANNEL != beta
 extensions/feedback@mobile.mozilla.org.xpi
 #endif
 #ifdef XP_WIN
   #if _MSC_VER != 1400
     @BINPATH@/Microsoft.VC80.CRT.manifest
--- a/modules/libpref/src/Makefile.in
+++ b/modules/libpref/src/Makefile.in
@@ -72,17 +72,16 @@ GARBAGE		+= $(addprefix $(DIST)/bin/defa
 
 GARBAGE		+= greprefs.js
 
 GREPREF_FILES = $(topsrcdir)/netwerk/base/public/security-prefs.js $(srcdir)/init/all.js
 
 # Optimizer bug with GCC 3.2.2 on OS/2
 ifeq ($(OS_ARCH), OS2)
 nsPrefService.$(OBJ_SUFFIX): nsPrefService.cpp
-	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS:-O2=-O1) $(_VPATH_SRCS)
 endif
 
 
 greprefs.js: $(GREPREF_FILES)
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $^ > $@
 
--- a/netwerk/dns/effective_tld_names.dat
+++ b/netwerk/dns/effective_tld_names.dat
@@ -691,22 +691,24 @@ org.co
 rec.co
 web.co
 
 // com : http://en.wikipedia.org/wiki/.com
 com
 
 // CentralNic names : http://www.centralnic.com/names/domains
 // Confirmed by registry <gavin.brown@centralnic.com> 2008-06-09
+// Updated by registry <gavin.brown@centralnic.com> 2011-05-27
 ar.com
 br.com
 cn.com
 de.com
 eu.com
 gb.com
+gr.com
 hu.com
 jpn.com
 kr.com
 no.com
 qc.com
 ru.com
 sa.com
 se.com
@@ -757,16 +759,20 @@ gov.cx
 // cz : http://en.wikipedia.org/wiki/.cz
 cz
 
 // de : http://en.wikipedia.org/wiki/.de
 // Confirmed by registry <ops@denic.de> (with technical
 // reservations) 2008-07-01
 de
 
+// CentralNic names : http://www.centralnic.com/names/domains
+// Submitted by registry <gavin.brown@centralnic.com> 2011-05-27
+com.de
+
 // dj : http://en.wikipedia.org/wiki/.dj
 dj
 
 // dk : http://en.wikipedia.org/wiki/.dk
 // Confirmed by registry <robert@dk-hostmaster.dk> 2008-06-17
 dk
 
 // dm : http://en.wikipedia.org/wiki/.dm
@@ -3486,17 +3492,19 @@ nu
 !songfest.om
 !statecouncil.om
 
 // org : http://en.wikipedia.org/wiki/.org
 org
 
 // CentralNic names : http://www.centralnic.com/names/domains
 // Submitted by registry <gavin.brown@centralnic.com> 2008-06-17
+// Updated by registry <gavin.brown@centralnic.com> 2011-05-27
 ae.org
+us.org
 
 // ZaNiC names : http://www.za.net/
 // Confirmed by registry <hostmaster@nic.za.net> 2009-10-03
 za.org
 
 // pa : http://www.nic.pa/
 // Some additional second level "domains" resolve directly as hostnames, such as
 // pannet.pa, so we add a rule for "pa".
--- a/netwerk/dns/nsHostResolver.h
+++ b/netwerk/dns/nsHostResolver.h
@@ -66,29 +66,19 @@ class nsResolveHostCallback;
     PRInt32 Release() {                                                      \
         PRInt32 n = NS_AtomicDecrementRefcnt(_refc);                         \
         NS_LOG_RELEASE(this, n, #classname);                                 \
         if (n == 0)                                                          \
             delete this;                                                     \
         return n;                                                            \
     }
 
-#ifdef ANDROID
-// See bug 687367 - pre gingerbread android has race conditions involving stdio.
-// stdio is used as part of the getaddrinfo() implementation. In order to reduce
-// that race window limit ourselves to 1 lookup at a time on android.
-
-#define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY  0
-#define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 1
-#define MAX_NON_PRIORITY_REQUESTS 0
-#else
 #define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY  3
 #define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 5
 #define MAX_NON_PRIORITY_REQUESTS 150
-#endif
 
 #define MAX_RESOLVER_THREADS (MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
                               MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
 
 struct nsHostKey
 {
     const char *host;
     PRUint16    flags;
--- a/other-licenses/android/Makefile.in
+++ b/other-licenses/android/Makefile.in
@@ -66,18 +66,24 @@ CPPSRCS = \
   nsGeckoUtils.cpp \
   APKOpen.cpp \
   $(NULL)
 
 CSRCS = \
   ba.c \
   debugger.c \
   dlfcn.c \
+  getaddrinfo.c \
   linker.c \
   linker_format.c \
+  res_debug.c \
+  res_init.c \
+  res_mkquery.c \
+  res_send.c \
+  res_state.c \
   rt.c \
   $(NULL)
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/startup
 
 EXPORTS = APKOpen.h
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/arpa_nameser.h
@@ -0,0 +1,587 @@
+/*	$NetBSD: nameser.h,v 1.19 2005/12/26 19:01:47 perry Exp $	*/
+
+/*
+ * Copyright (c) 1983, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *	Id: nameser.h,v 1.2.2.4.4.1 2004/03/09 08:33:30 marka Exp
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#ifndef _ARPA_NAMESER_H_
+#define _ARPA_NAMESER_H_
+
+#define BIND_4_COMPAT
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+/*
+ * Revision information.  This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__NAMESER > 19931104)".  Do not
+ * compare for equality; rather, use it to determine whether your libbind.a
+ * contains a new enough lib/nameser/ to support the feature you need.
+ */
+
+#define __NAMESER	19991006	/* New interface version stamp. */
+
+/*
+ * Define constants based on RFC 883, RFC 1034, RFC 1035
+ */
+#define NS_PACKETSZ	512	/* default UDP packet size */
+#define NS_MAXDNAME	1025	/* maximum domain name */
+#define NS_MAXMSG	65535	/* maximum message size */
+#define NS_MAXCDNAME	255	/* maximum compressed domain name */
+#define NS_MAXLABEL	63	/* maximum length of domain label */
+#define NS_HFIXEDSZ	12	/* #/bytes of fixed data in header */
+#define NS_QFIXEDSZ	4	/* #/bytes of fixed data in query */
+#define NS_RRFIXEDSZ	10	/* #/bytes of fixed data in r record */
+#define NS_INT32SZ	4	/* #/bytes of data in a uint32_t */
+#define NS_INT16SZ	2	/* #/bytes of data in a uint16_t */
+#define NS_INT8SZ	1	/* #/bytes of data in a uint8_t */
+#define NS_INADDRSZ	4	/* IPv4 T_A */
+#define NS_IN6ADDRSZ	16	/* IPv6 T_AAAA */
+#define NS_CMPRSFLGS	0xc0	/* Flag bits indicating name compression. */
+#define NS_DEFAULTPORT	53	/* For both TCP and UDP. */
+
+/*
+ * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord()
+ * in synch with it.
+ */
+typedef enum __ns_sect {
+	ns_s_qd = 0,		/* Query: Question. */
+	ns_s_zn = 0,		/* Update: Zone. */
+	ns_s_an = 1,		/* Query: Answer. */
+	ns_s_pr = 1,		/* Update: Prerequisites. */
+	ns_s_ns = 2,		/* Query: Name servers. */
+	ns_s_ud = 2,		/* Update: Update. */
+	ns_s_ar = 3,		/* Query|Update: Additional records. */
+	ns_s_max = 4
+} ns_sect;
+
+/*
+ * This is a message handle.  It is caller allocated and has no dynamic data.
+ * This structure is intended to be opaque to all but ns_parse.c, thus the
+ * leading _'s on the member names.  Use the accessor functions, not the _'s.
+ */
+typedef struct __ns_msg {
+	const u_char	*_msg, *_eom;
+	uint16_t	_id, _flags, _counts[ns_s_max];
+	const u_char	*_sections[ns_s_max];
+	ns_sect		_sect;
+	int		_rrnum;
+	const u_char	*_msg_ptr;
+} ns_msg;
+
+/* Private data structure - do not use from outside library. */
+struct _ns_flagdata {  int mask, shift;  };
+extern const struct _ns_flagdata _ns_flagdata[];
+
+/* Accessor macros - this is part of the public interface. */
+
+#define ns_msg_id(handle) ((handle)._id + 0)
+#define ns_msg_base(handle) ((handle)._msg + 0)
+#define ns_msg_end(handle) ((handle)._eom + 0)
+#define ns_msg_size(handle) ((size_t)((handle)._eom - (handle)._msg))
+#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
+
+/*
+ * This is a parsed record.  It is caller allocated and has no dynamic data.
+ */
+typedef	struct __ns_rr {
+	char		name[NS_MAXDNAME];
+	uint16_t	type;
+	uint16_t	rr_class;
+	uint32_t	ttl;
+	uint16_t	rdlength;
+	const u_char *	rdata;
+} ns_rr;
+
+/* Accessor macros - this is part of the public interface. */
+#define ns_rr_name(rr)	(((rr).name[0] != '\0') ? (rr).name : ".")
+#define ns_rr_type(rr)	((ns_type)((rr).type + 0))
+#define ns_rr_class(rr)	((ns_class)((rr).rr_class + 0))
+#define ns_rr_ttl(rr)	((u_long)(rr).ttl + 0)
+#define ns_rr_rdlen(rr)	((size_t)(rr).rdlength + 0)
+#define ns_rr_rdata(rr)	((rr).rdata + 0)
+
+/*
+ * These don't have to be in the same order as in the packet flags word,
+ * and they can even overlap in some cases, but they will need to be kept
+ * in synch with ns_parse.c:ns_flagdata[].
+ */
+typedef enum __ns_flag {
+	ns_f_qr,		/* Question/Response. */
+	ns_f_opcode,		/* Operation code. */
+	ns_f_aa,		/* Authoritative Answer. */
+	ns_f_tc,		/* Truncation occurred. */
+	ns_f_rd,		/* Recursion Desired. */
+	ns_f_ra,		/* Recursion Available. */
+	ns_f_z,			/* MBZ. */
+	ns_f_ad,		/* Authentic Data (DNSSEC). */
+	ns_f_cd,		/* Checking Disabled (DNSSEC). */
+	ns_f_rcode,		/* Response code. */
+	ns_f_max
+} ns_flag;
+
+/*
+ * Currently defined opcodes.
+ */
+typedef enum __ns_opcode {
+	ns_o_query = 0,		/* Standard query. */
+	ns_o_iquery = 1,	/* Inverse query (deprecated/unsupported). */
+	ns_o_status = 2,	/* Name server status query (unsupported). */
+				/* Opcode 3 is undefined/reserved. */
+	ns_o_notify = 4,	/* Zone change notification. */
+	ns_o_update = 5,	/* Zone update message. */
+	ns_o_max = 6
+} ns_opcode;
+
+/*
+ * Currently defined response codes.
+ */
+typedef	enum __ns_rcode {
+	ns_r_noerror = 0,	/* No error occurred. */
+	ns_r_formerr = 1,	/* Format error. */
+	ns_r_servfail = 2,	/* Server failure. */
+	ns_r_nxdomain = 3,	/* Name error. */
+	ns_r_notimpl = 4,	/* Unimplemented. */
+	ns_r_refused = 5,	/* Operation refused. */
+	/* these are for BIND_UPDATE */
+	ns_r_yxdomain = 6,	/* Name exists */
+	ns_r_yxrrset = 7,	/* RRset exists */
+	ns_r_nxrrset = 8,	/* RRset does not exist */
+	ns_r_notauth = 9,	/* Not authoritative for zone */
+	ns_r_notzone = 10,	/* Zone of record different from zone section */
+	ns_r_max = 11,
+	/* The following are EDNS extended rcodes */
+	ns_r_badvers = 16,
+	/* The following are TSIG errors */
+	ns_r_badsig = 16,
+	ns_r_badkey = 17,
+	ns_r_badtime = 18
+} ns_rcode;
+
+/* BIND_UPDATE */
+typedef enum __ns_update_operation {
+	ns_uop_delete = 0,
+	ns_uop_add = 1,
+	ns_uop_max = 2
+} ns_update_operation;
+
+/*
+ * This structure is used for TSIG authenticated messages
+ */
+struct ns_tsig_key {