Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Thu, 19 Jul 2012 14:34:36 -0700
changeset 106621 af4c7ab588896e7ee0f038cb3cd601e58f534a69
parent 106620 8b0a7122b1aacd1588ef3dbd8753fa7824bc128b (current diff)
parent 99862 01929e390ba54dfd34fec8514abaa6e20c37ee2a (diff)
child 106623 616b34b63dda70535c4f7f02e53d01301e558168
push id14706
push usereakhgari@mozilla.com
push dateTue, 11 Sep 2012 20:39:52 +0000
treeherdermozilla-inbound@d50bf1edaabe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge from mozilla-central.
accessible/src/generic/Accessible.h
accessible/src/html/HTMLTableAccessible.cpp
accessible/src/xul/XULMenuAccessible.cpp
browser/app/macbuild/Contents/Info.plist.in
browser/app/profile/firefox.js
browser/base/content/browser.js
browser/base/content/browser.xul
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/winstripe/browser.css
build/mobile/devicemanagerSUT.py
build/mobile/robocop/robotium-solo-3.2.1.jar
configure.in
content/base/public/nsContentUtils.h
content/base/public/nsIDocument.h
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsFrameLoader.h
content/base/src/nsGenericElement.cpp
content/base/src/nsNodeUtils.cpp
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsStyledElement.cpp
content/canvas/src/WebGLContext.h
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventStateManager.cpp
content/events/src/nsEventStateManager.h
content/media/nsBuiltinDecoder.h
content/media/nsBuiltinDecoderReader.h
content/media/nsBuiltinDecoderStateMachine.cpp
content/media/nsMediaDecoder.h
content/svg/content/src/nsSVGGraphicElement.cpp
content/xbl/src/nsXBLPrototypeHandler.cpp
content/xbl/src/nsXBLPrototypeHandler.h
content/xul/content/src/nsXULElement.cpp
content/xul/content/src/nsXULElement.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsIScriptEventHandlerOwner.h
dom/base/nsLocation.cpp
dom/bindings/Codegen.py
dom/ipc/PBrowser.ipdl
dom/ipc/TabChild.cpp
dom/plugins/ipc/PluginModuleParent.cpp
editor/libeditor/base/nsEditor.cpp
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/text/nsPlaintextEditor.cpp
extensions/cookie/nsPermissionManager.cpp
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderEGL.cpp
gfx/layers/ImageLayers.h
gfx/layers/Layers.h
gfx/layers/basic/BasicCanvasLayer.cpp
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/d3d10/ImageLayerD3D10.cpp
gfx/layers/d3d10/LayerManagerD3D10.cpp
gfx/layers/d3d10/LayerManagerD3D10.h
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/opengl/ImageLayerOGL.cpp
gfx/thebes/gfxPlatformGtk.cpp
ipc/chromium/src/base/process_util_linux.cc
js/src/Makefile.in
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/SemanticAnalysis.cpp
js/src/ion/CodeGenerator.cpp
js/src/jsatom.cpp
js/src/jsatom.h
js/src/jsdbgapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsgc.cpp
js/src/jsinfer.cpp
js/src/jsinferinlines.h
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsinterpinlines.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsreflect.cpp
js/src/jsscope.cpp
js/src/jsscript.h
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jswrapper.cpp
js/src/jswrapper.h
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/FastOps.cpp
js/src/shell/js.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCMaps.cpp
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/wrappers/WrapperFactory.cpp
js/xpconnect/wrappers/WrapperFactory.h
js/xpconnect/wrappers/XrayWrapper.cpp
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/forms/nsListControlFrame.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsHTMLReflowState.h
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
layout/reftests/svg/reftest.list
layout/svg/base/src/nsSVGUtils.cpp
layout/xul/base/src/nsBoxFrame.cpp
layout/xul/base/src/nsMenuBarListener.cpp
layout/xul/base/src/nsMenuFrame.cpp
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/chrome/content/browser.js
modules/libpref/src/init/all.js
security/manager/ssl/src/nsCertOverrideService.h
security/manager/ssl/src/nsCertTree.h
security/manager/ssl/src/nsClientAuthRemember.h
security/manager/ssl/src/nsNSSCallbacks.h
security/manager/ssl/src/nsRecentBadCerts.h
toolkit/components/commandlines/nsCommandLine.cpp
toolkit/components/startup/nsAppStartup.h
toolkit/components/telemetry/Telemetry.cpp
toolkit/components/telemetry/TelemetryPing.js
toolkit/content/tests/chrome/test_arrowpanel.xul
toolkit/mozapps/installer/packager.mk
toolkit/system/osxproxy/nsOSXSystemProxySettings.mm
widget/android/nsWindow.cpp
widget/android/nsWindow.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.h
widget/gtk2/nsWindow.cpp
widget/nsGUIEvent.h
widget/nsIWidget.h
widget/qt/nsWindow.cpp
widget/windows/KeyboardLayout.cpp
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
widget/windows/nsWindowGfx.cpp
widget/xpwidgets/PuppetWidget.cpp
widget/xpwidgets/PuppetWidget.h
widget/xpwidgets/nsBaseWidget.cpp
widget/xpwidgets/nsBaseWidget.h
xpfe/appshell/src/nsAppShellService.h
--- a/accessible/src/base/nsAccessiblePivot.h
+++ b/accessible/src/base/nsAccessiblePivot.h
@@ -7,28 +7,29 @@
 #ifndef _nsAccessiblePivot_H_
 #define _nsAccessiblePivot_H_
 
 #include "nsIAccessiblePivot.h"
 
 #include "nsAutoPtr.h"
 #include "nsTObserverArray.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/Attributes.h"
 
 class Accessible;
 class nsIAccessibleTraversalRule;
 
 // raised when current pivot's position is needed but it is not in the tree.
 #define NS_ERROR_NOT_IN_TREE \
 NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL, 0x26)
 
 /**
  * Class represents an accessible pivot.
  */
-class nsAccessiblePivot: public nsIAccessiblePivot
+class nsAccessiblePivot MOZ_FINAL : public nsIAccessiblePivot
 {
 public:
   nsAccessiblePivot(Accessible* aRoot);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsAccessiblePivot, nsIAccessiblePivot)
 
   NS_DECL_NSIACCESSIBLEPIVOT
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -913,16 +913,17 @@ class KeyBinding
 public:
   /**
    * Modifier mask values.
    */
   static const PRUint32 kShift = 1;
   static const PRUint32 kControl = 2;
   static const PRUint32 kAlt = 4;
   static const PRUint32 kMeta = 8;
+  static const PRUint32 kOS = 16;
 
   KeyBinding() : mKey(0), mModifierMask(0) {}
   KeyBinding(PRUint32 aKey, PRUint32 aModifierMask) :
     mKey(aKey), mModifierMask(aModifierMask) {};
 
   inline bool IsEmpty() const { return !mKey; }
   inline PRUint32 Key() const { return mKey; }
   inline PRUint32 ModifierMask() const { return mModifierMask; }
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -761,17 +761,17 @@ HTMLTableAccessible::ColExtentAt(PRUint3
   if (!tableLayout)
     return 0;
 
   nsCOMPtr<nsIDOMElement> domElement;
   PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan;
   bool isSelected;
   PRInt32 columnExtent = 0;
 
-  nsresult rv = tableLayout->
+  tableLayout->
     GetCellDataAt(aRowIdx, aColIdx, *getter_AddRefs(domElement),
                   startRowIndex, startColIndex, rowSpan, colSpan,
                   actualRowSpan, columnExtent, isSelected);
 
   return columnExtent;
 }
 
 PRUint32
@@ -781,17 +781,17 @@ HTMLTableAccessible::RowExtentAt(PRUint3
   if (!tableLayout)
     return 0;
 
   nsCOMPtr<nsIDOMElement> domElement;
   PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualColSpan;
   bool isSelected;
   PRInt32 rowExtent = 0;
 
-  nsresult rv = tableLayout->
+  tableLayout->
     GetCellDataAt(aRowIdx, aColIdx, *getter_AddRefs(domElement),
                   startRowIndex, startColIndex, rowSpan, colSpan,
                   rowExtent, actualColSpan, isSelected);
 
   return rowExtent;
 }
 
 bool
--- a/accessible/src/xul/XULMenuAccessible.cpp
+++ b/accessible/src/xul/XULMenuAccessible.cpp
@@ -179,16 +179,19 @@ XULMenuitemAccessible::AccessKey() const
           modifierKey = KeyBinding::kControl;
           break;
         case nsIDOMKeyEvent::DOM_VK_ALT:
           modifierKey = KeyBinding::kAlt;
           break;
         case nsIDOMKeyEvent::DOM_VK_META:
           modifierKey = KeyBinding::kMeta;
           break;
+        case nsIDOMKeyEvent::DOM_VK_WIN:
+          modifierKey = KeyBinding::kOS;
+          break;
       }
     }
   }
 
   return KeyBinding(accesskey[0], modifierKey);
 }
 
 KeyBinding
@@ -221,25 +224,31 @@ XULMenuitemAccessible::KeyboardShortcut(
 
   PRUint32 modifierMask = 0;
   if (modifiersStr.Find("shift") != -1)
     modifierMask |= KeyBinding::kShift;
   if (modifiersStr.Find("alt") != -1)
     modifierMask |= KeyBinding::kAlt;
   if (modifiersStr.Find("meta") != -1)
     modifierMask |= KeyBinding::kMeta;
+  if (modifiersStr.Find("os") != -1)
+    modifierMask |= KeyBinding::kOS;
   if (modifiersStr.Find("control") != -1)
     modifierMask |= KeyBinding::kControl;
   if (modifiersStr.Find("accel") != -1) {
     // Get the accelerator key value from prefs, overriding the default.
     switch (Preferences::GetInt("ui.key.accelKey", 0)) {
       case nsIDOMKeyEvent::DOM_VK_META:
         modifierMask |= KeyBinding::kMeta;
         break;
 
+      case nsIDOMKeyEvent::DOM_VK_WIN:
+        modifierMask |= KeyBinding::kOS;
+        break;
+
       case nsIDOMKeyEvent::DOM_VK_ALT:
         modifierMask |= KeyBinding::kAlt;
         break;
 
       case nsIDOMKeyEvent::DOM_VK_CONTROL:
         modifierMask |= KeyBinding::kControl;
         break;
 
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -53,24 +53,27 @@ function getContentWindow() {
 // XXX never grant 'content-camera' to non-gaia apps
 function addPermissions(urls) {
   let permissions = [
     'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'pin-app',
     'websettings-read', 'websettings-readwrite',
     'content-camera', 'webcontacts-manage', 'wifi-manage', 'desktop-notification',
     'geolocation', 'device-storage', 'alarms'
   ];
+
   urls.forEach(function(url) {
     url = url.trim();
-    let uri = Services.io.newURI(url, null, null);
-    let allow = Ci.nsIPermissionManager.ALLOW_ACTION;
+    if (url) {
+      let uri = Services.io.newURI(url, null, null);
+      let allow = Ci.nsIPermissionManager.ALLOW_ACTION;
 
-    permissions.forEach(function(permission) {
-      Services.perms.add(uri, permission, allow);
-    });
+      permissions.forEach(function(permission) {
+        Services.perms.add(uri, permission, allow);
+      });
+    }
   });
 }
 
 var shell = {
   get contentBrowser() {
     delete this.contentBrowser;
     return this.contentBrowser = document.getElementById('homescreen');
   },
--- a/browser/app/macbuild/Contents/Info.plist.in
+++ b/browser/app/macbuild/Contents/Info.plist.in
@@ -199,21 +199,21 @@
 			</array>
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
 	<string>%MAC_BUNDLE_VERSION%</string>
 	<key>NSAppleScriptEnabled</key>
 	<true/>
 	<key>LSMinimumSystemVersion</key>
-	<string>10.5</string>
+	<string>10.6</string>
 	<key>LSMinimumSystemVersionByArchitecture</key>
 	<dict>
 		<key>i386</key>
-		<string>10.5.0</string>
+		<string>10.6.0</string>
 		<key>x86_64</key>
 		<string>10.6.0</string>
 	</dict>
   <key>NSSupportsAutomaticGraphicsSwitching</key>
   <true/>
   <key>NSPrincipalClass</key>
   <string>GeckoNSApplication</string>
 </dict>
--- a/browser/base/content/test/browser_bug553455.js
+++ b/browser/base/content/test/browser_bug553455.js
@@ -706,19 +706,19 @@ function test_renotify_installed() {
 function test_cancel_restart() {
   // Wait for the progress notification
   wait_for_notification(function(aPanel) {
     let notification = aPanel.childNodes[0];
     is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
 
     // Close the notification
     let anchor = document.getElementById("addons-notification-icon");
-    EventUtils.synthesizeMouseAtCenter(anchor, {});
+    anchor.click();
     // Reopen the notification
-    EventUtils.synthesizeMouseAtCenter(anchor, {});
+    anchor.click();
 
     ok(PopupNotifications.isPanelOpen, "Notification should still be open");
     is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
     isnot(notification, aPanel.childNodes[0], "Should have reconstructed the notification UI");
     notification = aPanel.childNodes[0];
     is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
     let button = document.getAnonymousElementByAttribute(notification, "anonid", "cancel");
 
--- a/browser/base/content/test/browser_popupNotification.js
+++ b/browser/base/content/test/browser_popupNotification.js
@@ -733,16 +733,20 @@ function triggerMainCommand(popup) {
 }
 
 function triggerSecondaryCommand(popup, index) {
   info("[Test #" + gTestIndex + "] triggering secondary command");
   let notifications = popup.childNodes;
   ok(notifications.length > 0, "at least one notification displayed");
   let notification = notifications[0];
 
+  // Cancel the arrow panel slide-in transition (bug 767133) such that
+  // it won't interfere with us interacting with the dropdown.
+  document.getAnonymousNodes(popup)[0].style.transition = "none";
+
   notification.button.focus();
 
   popup.addEventListener("popupshown", function () {
     popup.removeEventListener("popupshown", arguments.callee, false);
 
     // Press down until the desired command is selected
     for (let i = 0; i <= index; i++)
       EventUtils.synthesizeKey("VK_DOWN", {});
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -468,17 +468,17 @@ function openAboutDialog() {
 #else
   var features = "chrome,centerscreen,dependent,dialog=no";
 #endif
   window.openDialog("chrome://browser/content/aboutDialog.xul", "", features);
 }
 
 function openPreferences(paneID, extraArgs)
 {
-  if (Services.prefs.getBoolPref("browser.preferences.inContent")) {  
+  if (Services.prefs.getBoolPref("browser.preferences.inContent")) {
     openUILinkIn("about:preferences", "tab");
   } else {
     var instantApply = getBoolPref("browser.preferences.instantApply", false);
     var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal");
 
     var win = Services.wm.getMostRecentWindow("Browser:Preferences");
     if (win) {
       win.focus();
@@ -487,27 +487,27 @@ function openPreferences(paneID, extraAr
         win.document.documentElement.showPane(pane);
       }
 
       if (extraArgs && extraArgs["advancedTab"]) {
         var advancedPaneTabs = win.document.getElementById("advancedPrefs");
         advancedPaneTabs.selectedTab = win.document.getElementById(extraArgs["advancedTab"]);
       }
 
-     return win;
+     return;
     }
 
-    return openDialog("chrome://browser/content/preferences/preferences.xul",
-                      "Preferences", features, paneID, extraArgs);
+    openDialog("chrome://browser/content/preferences/preferences.xul",
+               "Preferences", features, paneID, extraArgs);
   }
 }
 
 function openAdvancedPreferences(tabID)
 {
-  return openPreferences("paneAdvanced", { "advancedTab" : tabID });
+  openPreferences("paneAdvanced", { "advancedTab" : tabID });
 }
 
 /**
  * Opens the troubleshooting information (about:support) page for this version
  * of the application.
  */
 function openTroubleshootingPage()
 {
--- a/browser/components/sessionstore/test/browser_461743_sample.html
+++ b/browser/components/sessionstore/test/browser_461743_sample.html
@@ -20,17 +20,17 @@
     frames[0].removeEventListener("DOMContentLoaded", handleLoad, false);
     frames[1].removeEventListener("DOMContentLoaded", handleLoad, false);
 
     var flip = 0;
     MutationEvent.prototype.toString = function() {
       return flip++ == 0 ? chromeUrl : exploitUrl;
     };
 
-    var href = Components.lookupMethod(frames[1].location, "href");
+    var href = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(frames[1].location), "href").get;
     var loadChrome = { handleEvent: href };
     var loadExploit = { handleEvent: href };
 
     function delay() {
       var xhr = new XMLHttpRequest();
       xhr.open("GET", location.href, false);
       xhr.send(null);
     }
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -144,16 +144,18 @@ function ScriptsView() {
 
 ScriptsView.prototype = {
 
   /**
    * Removes all elements from the scripts container, leaving it empty.
    */
   empty: function DVS_empty() {
     this._scripts.selectedIndex = -1;
+    this._scripts.setAttribute("label", L10N.getStr("noScriptsText"));
+    this._scripts.removeAttribute("tooltiptext");
 
     while (this._scripts.firstChild) {
       this._scripts.removeChild(this._scripts.firstChild);
     }
   },
 
   /**
    * Removes the input in the searchbox and unhides all the scripts.
@@ -420,56 +422,71 @@ ScriptsView.prototype = {
    * The click listener for the scripts container.
    */
   _onScriptsChange: function DVS__onScriptsChange() {
     let selectedItem = this._scripts.selectedItem;
     if (!selectedItem) {
       return;
     }
 
-    let script = selectedItem.getUserData("sourceScript");
-    this._preferredScript = script;
-    DebuggerController.SourceScripts.showScript(script);
+    this._preferredScript = selectedItem;
+    this._scripts.setAttribute("tooltiptext", selectedItem.value);
+    DebuggerController.SourceScripts.showScript(selectedItem.getUserData("sourceScript"));
   },
 
   /**
    * The search listener for the scripts search box.
    */
   _onScriptsSearch: function DVS__onScriptsSearch(e) {
     let editor = DebuggerView.editor;
     let scripts = this._scripts;
     let [file, line, token] = this._getSearchboxInfo();
 
+    // If the webpage has no scripts, searching is redundant.
+    if (!scripts.itemCount) {
+      return;
+    }
+
     // Presume we won't find anything.
     scripts.selectedItem = this._preferredScript;
+    scripts.setAttribute("label", this._preferredScript.label);
+    scripts.setAttribute("tooltiptext", this._preferredScript.value);
 
     // If we're not searching for a file anymore, unhide all the scripts.
     if (!file) {
       for (let i = 0, l = scripts.itemCount; i < l; i++) {
         scripts.getItemAtIndex(i).hidden = false;
       }
     } else {
-      for (let i = 0, l = scripts.itemCount, found = false; i < l; i++) {
+      let found = false;
+
+      for (let i = 0, l = scripts.itemCount; i < l; i++) {
         let item = scripts.getItemAtIndex(i);
         let target = item.label.toLowerCase();
 
         // Search is not case sensitive, and is tied to the label not the url.
         if (target.match(file)) {
           item.hidden = false;
 
           if (!found) {
             found = true;
             scripts.selectedItem = item;
+            scripts.setAttribute("label", item.label);
+            scripts.setAttribute("tooltiptext", item.value);
           }
         }
         // Hide what doesn't match our search.
         else {
           item.hidden = true;
         }
       }
+      if (!found) {
+        scripts.setAttribute("label", L10N.getStr("noMatchingScriptsText"));
+        scripts.removeAttribute("tooltiptext");
+      }
     }
     if (line > -1) {
       editor.setCaretPosition(line - 1);
     }
     if (token.length) {
       let offset = editor.find(token, { ignoreCase: true });
       if (offset > -1) {
         editor.setSelection(offset, offset + token.length)
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -59,16 +59,17 @@
                        tooltiptext="&debuggerUI.stepInButton.tooltip;"
                        tabindex="0"/>
         <toolbarbutton id="step-out"
                        class="devtools-toolbarbutton"
                        tooltiptext="&debuggerUI.stepOutButton.tooltip;"
                        tabindex="0"/>
       </hbox>
       <menulist id="scripts" class="devtools-menulist"
+                sizetopopup="always"
                 label="&debuggerUI.emptyScriptText;"/>
       <textbox id="scripts-search" type="search"
                class="devtools-searchinput"
                emptytext="&debuggerUI.emptyFilterText;"/>
       <checkbox id="pause-exceptions"
                 type="checkbox"
                 tabindex="0"
                 label="&debuggerUI.pauseExceptions;"/>
--- a/browser/devtools/debugger/test/browser_dbg_location-changes-blank.js
+++ b/browser/devtools/debugger/test/browser_dbg_location-changes-blank.js
@@ -62,16 +62,23 @@ function testLocationChange()
 
         // Wait for the initial resume...
         gDebugger.gClient.addOneTimeListener("resumed", function() {
           is(gDebugger.DebuggerView.Scripts.selected, null,
             "There should be no selected script.");
           is(gDebugger.editor.getText().length, 0,
             "The source editor not have any text displayed.");
 
+          let menulist = gDebugger.DebuggerView.Scripts._scripts;
+          let noScripts = gDebugger.L10N.getStr("noScriptsText");
+          is(menulist.getAttribute("label"), noScripts,
+            "The menulist should display a notice that there are no scripts availalble.");
+          is(menulist.getAttribute("tooltiptext"), "",
+            "The menulist shouldn't have any tooltip text attributed when there are no scripts available.");
+
           closeDebuggerAndFinish();
         });
       });
     });
     content.location = "about:blank";
   });
 }
 
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-02.js
@@ -119,20 +119,51 @@ function finalCheck(i, string, token) {
 
   if (string[i]) {
     EventUtils.sendChar(string[i]);
     finalCheck(i + 1, string, token);
     return;
   }
 
   clear();
+  ok(gEditor.getCaretPosition().line == 5 &&
+     gEditor.getCaretPosition().col == 8 + token.length + i,
+    "The editor didn't remain at the correct token. (4)");
 
   executeSoon(function() {
+    let noMatchingScripts = gDebugger.L10N.getStr("noMatchingScriptsText");
+
     is(gScripts.visibleItemsCount, 2,
       "Not all the scripts are shown after the searchbox was emptied.");
+    is(gMenulist.selectedIndex, 1,
+      "The menulist should have retained its selected index after the searchbox was emptied.");
+
+    write("BOGUS");
+    ok(gEditor.getCaretPosition().line == 5 &&
+       gEditor.getCaretPosition().col == 8 + token.length + i,
+      "The editor didn't remain at the correct token. (5)");
+
+    is(gMenulist.getAttribute("label"), noMatchingScripts,
+      "The menulist should display a notice that no scripts match the searched token.");
+    is(gScripts.visibleItemsCount, 0,
+      "No scripts should be displayed in the menulist after a bogus search.");
+    is(gMenulist.selectedIndex, 1,
+      "The menulist should retain its selected index after a bogus search.");
+
+    clear();
+    ok(gEditor.getCaretPosition().line == 5 &&
+       gEditor.getCaretPosition().col == 8 + token.length + i,
+      "The editor didn't remain at the correct token. (6)");
+
+    isnot(gMenulist.getAttribute("label"), noMatchingScripts,
+      "The menulist should not display a notice after the searchbox was emptied.");
+    is(gScripts.visibleItemsCount, 2,
+      "Not all the scripts are shown after the searchbox was emptied.");
+    is(gMenulist.selectedIndex, 1,
+      "The menulist should have retained its selected index after the searchbox was emptied of a bogus search.");
 
     closeDebuggerAndFinish();
   });
 }
 
 function clear() {
   gSearchBox.focus();
   gSearchBox.value = "";
--- a/browser/devtools/tilt/TiltUtils.jsm
+++ b/browser/devtools/tilt/TiltUtils.jsm
@@ -436,17 +436,17 @@ TiltUtils.DOM = {
         if (coord.width > aMinSize && coord.height > aMinSize) {
 
           // save the necessary details into a list to be returned later
           store.info.push({ depth: depth, coord: coord, name: name });
           store.nodes.push(node);
         }
 
         // prepare the queue array
-        Array.prototype.push.apply(queue, name === "iframe" ?
+        Array.prototype.push.apply(queue, name === "iframe" || name === "frame" ?
                                           node.contentDocument.childNodes :
                                           node.childNodes);
       }
       nodes = queue;
       depth++;
     }
 
     return store;
--- a/browser/devtools/tilt/test/Makefile.in
+++ b/browser/devtools/tilt/test/Makefile.in
@@ -51,14 +51,15 @@ MOCHITEST_BROWSER_FILES += \
 	browser_tilt_picking_highlight03.js \
 	browser_tilt_picking_miv.js \
 	browser_tilt_utils01.js \
 	browser_tilt_utils02.js \
 	browser_tilt_utils03.js \
 	browser_tilt_utils04.js \
 	browser_tilt_utils05.js \
 	browser_tilt_utils06.js \
+	browser_tilt_utils07.js \
 	browser_tilt_visualizer.js \
 	browser_tilt_zoom.js \
 	$(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/browser/devtools/tilt/test/browser_tilt_utils07.js
@@ -0,0 +1,192 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function init(callback) {
+  let iframe = gBrowser.ownerDocument.createElement("iframe");
+
+  iframe.addEventListener("load", function onLoad() {
+    iframe.removeEventListener("load", onLoad, true);
+    callback(iframe);
+
+    gBrowser.parentNode.removeChild(iframe);
+    finish();
+  }, true);
+
+  iframe.setAttribute("src", ["data:text/html,",
+    "<!DOCTYPE html>",
+    "<html>",
+      "<body style='margin: 0;'>",
+        "<frameset cols='50%,50%'>",
+          "<frame src='",
+          ["data:text/html,",
+           "<!DOCTYPE html>",
+           "<html>",
+           "<body style='margin: 0;'>",
+           "<div id='test-div' style='width: 123px; height: 456px;'></div>",
+           "</body>",
+           "</html>"
+          ].join(""),
+          "' />",
+          "<frame src='",
+          ["data:text/html,",
+           "<!DOCTYPE html>",
+           "<html>",
+           "<body style='margin: 0;'>",
+           "<span></span>",
+           "</body>",
+           "</html>"
+          ].join(""),
+          "' />",
+        "</frameset>",
+        "<iframe src='",
+        ["data:text/html,",
+         "<!DOCTYPE html>",
+         "<html>",
+         "<body>",
+         "<span></span>",
+         "</body>",
+         "</html>"
+        ].join(""),
+        "'></iframe>",
+        "<frame src='",
+        ["data:text/html,",
+         "<!DOCTYPE html>",
+         "<html>",
+         "<body style='margin: 0;'>",
+         "<span></span>",
+         "</body>",
+         "</html>"
+        ].join(""),
+        "' />",
+        "<frame src='",
+        ["data:text/html,",
+         "<!DOCTYPE html>",
+         "<html>",
+         "<body style='margin: 0;'>",
+         "<iframe src='",
+         ["data:text/html,",
+          "<!DOCTYPE html>",
+          "<html>",
+          "<body>",
+          "<div></div>",
+          "</body>",
+          "</html>"
+         ].join(""),
+         "'></iframe>",
+         "</body>",
+         "</html>"
+        ].join(""),
+        "' />",
+      "</body>",
+    "</html>"
+  ].join(""));
+
+  gBrowser.parentNode.appendChild(iframe);
+}
+
+function test() {
+  waitForExplicitFinish();
+  ok(TiltUtils, "The TiltUtils object doesn't exist.");
+
+  let dom = TiltUtils.DOM;
+  ok(dom, "The TiltUtils.DOM wasn't found.");
+
+  init(function(iframe) {
+    let cwDimensions = dom.getContentWindowDimensions(iframe.contentWindow);
+
+    is(cwDimensions.width - iframe.contentWindow.scrollMaxX,
+      iframe.contentWindow.innerWidth,
+      "The content window width wasn't calculated correctly.");
+    is(cwDimensions.height - iframe.contentWindow.scrollMaxY,
+      iframe.contentWindow.innerHeight,
+      "The content window height wasn't calculated correctly.");
+
+    let nodeCoordinates = LayoutHelpers.getRect(
+      iframe.contentDocument.getElementById("test-div"), iframe.contentWindow);
+
+    let frameOffset = LayoutHelpers.getIframeContentOffset(iframe);
+    let frameRect = iframe.getBoundingClientRect();
+
+    is(nodeCoordinates.top, frameRect.top + frameOffset[0],
+      "The node coordinates top value wasn't calculated correctly.");
+    is(nodeCoordinates.left, frameRect.left + frameOffset[1],
+      "The node coordinates left value wasn't calculated correctly.");
+    is(nodeCoordinates.width, 123,
+      "The node coordinates width value wasn't calculated correctly.");
+    is(nodeCoordinates.height, 456,
+      "The node coordinates height value wasn't calculated correctly.");
+
+
+    let store = dom.traverse(iframe.contentWindow);
+
+    is(store.nodes.length, 16,
+      "The traverse() function didn't walk the correct number of nodes.");
+    is(store.info.length, 16,
+      "The traverse() function didn't examine the correct number of nodes.");
+    is(store.info[0].name, "html",
+      "the 1st traversed node isn't the expected one.");
+    is(store.info[0].depth, 0,
+      "the 1st traversed node doesn't have the expected depth.");
+    is(store.info[1].name, "head",
+      "the 2nd traversed node isn't the expected one.");
+    is(store.info[1].depth, 1,
+      "the 2nd traversed node doesn't have the expected depth.");
+    is(store.info[2].name, "body",
+      "the 3rd traversed node isn't the expected one.");
+    is(store.info[2].depth, 1,
+      "the 3rd traversed node doesn't have the expected depth.");
+    is(store.info[3].name, "div",
+      "the 4th traversed node isn't the expected one.");
+    is(store.info[3].depth, 2,
+      "the 4th traversed node doesn't have the expected depth.");
+    is(store.info[4].name, "span",
+      "the 5th traversed node isn't the expected one.");
+    is(store.info[4].depth, 2,
+      "the 5th traversed node doesn't have the expected depth.");
+    is(store.info[5].name, "iframe",
+      "the 6th traversed node isn't the expected one.");
+    is(store.info[5].depth, 2,
+      "the 6th traversed node doesn't have the expected depth.");
+    is(store.info[6].name, "span",
+      "the 7th traversed node isn't the expected one.");
+    is(store.info[6].depth, 2,
+      "the 7th traversed node doesn't have the expected depth.");
+    is(store.info[7].name, "iframe",
+      "the 8th traversed node isn't the expected one.");
+    is(store.info[7].depth, 2,
+      "the 8th traversed node doesn't have the expected depth.");
+    is(store.info[8].name, "html",
+      "the 9th traversed node isn't the expected one.");
+    is(store.info[8].depth, 3,
+      "the 9th traversed node doesn't have the expected depth.");
+    is(store.info[9].name, "html",
+      "the 10th traversed node isn't the expected one.");
+    is(store.info[9].depth, 3,
+      "the 10th traversed node doesn't have the expected depth.");
+    is(store.info[10].name, "head",
+      "the 11th traversed node isn't the expected one.");
+    is(store.info[10].depth, 4,
+      "the 11th traversed node doesn't have the expected depth.");
+    is(store.info[11].name, "body",
+      "the 12th traversed node isn't the expected one.");
+    is(store.info[11].depth, 4,
+      "the 12th traversed node doesn't have the expected depth.");
+    is(store.info[12].name, "head",
+      "the 13th traversed node isn't the expected one.");
+    is(store.info[12].depth, 4,
+      "the 13th traversed node doesn't have the expected depth.");
+    is(store.info[13].name, "body",
+      "the 14th traversed node isn't the expected one.");
+    is(store.info[13].depth, 4,
+      "the 14th traversed node doesn't have the expected depth.");
+    is(store.info[14].name, "span",
+      "the 15th traversed node isn't the expected one.");
+    is(store.info[14].depth, 5,
+      "the 15th traversed node doesn't have the expected depth.");
+    is(store.info[15].name, "div",
+      "the 16th traversed node isn't the expected one.");
+    is(store.info[15].depth, 5,
+      "the 16th traversed node doesn't have the expected depth.");
+  });
+}
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
@@ -62,9 +62,9 @@
 <!ENTITY debuggerUI.propertiesTitle  "Scope variables">
 
 <!-- LOCALIZATION NOTE (debuggerUI.emptyFilterText): This is the text that
   -  appears in the filter text box when it is empty. -->
 <!ENTITY debuggerUI.emptyFilterText  "Filter scripts">
 
 <!-- LOCALIZATION NOTE (emptyScriptText): The text to display in the menulist when
   - there are no scripts. -->
-<!ENTITY debuggerUI.emptyScriptText  "No scripts.">
+<!ENTITY debuggerUI.emptyScriptText  "No scripts">
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.properties
@@ -54,16 +54,24 @@ resumeTooltip=Click to resume
 # LOCALIZATION NOTE (emptyStackText): The text that is displayed in the stack
 # frames list when there are no frames to display.
 emptyStackText=No stacks to display.
 
 # LOCALIZATION NOTE (emptyBreakpointsText): The text that is displayed in the
 # breakpoints list when there are no breakpoints to display.
 emptyBreakpointsText=No breakpoints to display.
 
+# LOCALIZATION NOTE (noScriptsText): The text to display in the menulist when
+# there are no scripts.
+noScriptsText=No scripts
+
+# LOCALIZATION NOTE (noMatchingScriptsText): The text to display in the
+# menulist when there are no matching scripts after filtering.
+noMatchingScriptsText=No matching scripts
+
 # LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that
 # are displayed in the breakpoints menu item popup.
 breakpointMenuItem.enableSelf=Enable breakpoint
 breakpointMenuItem.disableSelf=Disable breakpoint
 breakpointMenuItem.deleteSelf=Remove breakpoint
 breakpointMenuItem.enableOthers=Enable others
 breakpointMenuItem.disableOthers=Disable others
 breakpointMenuItem.deleteOthers=Remove others
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1900,41 +1900,16 @@ toolbar[mode="text"] toolbarbutton.chevr
 #appmenu-editmenu-paste {
   list-style-image: url("moz-icon://stock/gtk-paste?size=menu");
 }
 #wrapper-appmenu-toolbar-button,
 .appmenu-edit-button[disabled="true"] {
   opacity: .3;
 }
 
-/* Inspector / Highlighter */
-
-#highlighter-panel {
-  -moz-appearance: none;
-  -moz-window-shadow: none;
-  background: -moz-linear-gradient(top -1deg, #ffdd88, #ffeeaa);
-  border: none;
-  opacity: 0.35;
-}
-
-listitem.style-selector {
-  background-color: DarkGray;
-  color: white;
-}
-
-listitem.style-section {
-  background-color: LightGray;
-  color: black;
-  font-weight: bold;
-}
-
-panel[dimmed="true"] {
-  opacity: 0.5;
-}
-
 /* Add-on bar */
 
 #addon-bar {
   box-shadow: 0 1px 0 rgba(0,0,0,.15) inset;
   padding: 0;
   min-height: 20px;
 }
 
--- a/browser/themes/gnomestripe/devtools/debugger.css
+++ b/browser/themes/gnomestripe/devtools/debugger.css
@@ -13,16 +13,17 @@
  */
 
 #dbg-content {
   padding: 0;
 }
 
 #scripts {
   max-width: 350px;
+  min-width: 150px;
 }
 
 /**
  * Lists and headers
  */
 
 .list-item {
   padding: 2px;
@@ -247,21 +248,21 @@
   -moz-appearance: treetwistyopen;
 }
 
 /**
  * Animations
  */
 
 .details[open][animated] {
-  -moz-animation-duration: 0.25s;
-  -moz-animation-name: showblock;
+  animation-duration: 0.25s;
+  animation-name: showblock;
 }
 
-@-moz-keyframes showblock {
+@keyframes showblock {
   from {
     opacity: 0;
     transform-origin: top;
     transform: scaleY(0);
   }
 
   to {
     opacity: 1;
--- a/browser/themes/gnomestripe/downloads/downloads.css
+++ b/browser/themes/gnomestripe/downloads/downloads.css
@@ -199,35 +199,35 @@ richlistitem[type="download"][state="1"]
 
 #downloads-indicator-notification {
   opacity: 0;
   background: url("chrome://browser/skin/downloads/download-notification.png")
               center no-repeat;
   background-size: 16px;
 }
 
-@-moz-keyframes downloadsIndicatorNotificationRight {
+@keyframes downloadsIndicatorNotificationRight {
   from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
-  20%  { opacity: .85; -moz-animation-timing-function: ease-out; }
+  20%  { opacity: .85; animation-timing-function: ease-out; }
   to   { opacity: 0; transform: translate(0) scale(1); }
 }
 
-@-moz-keyframes downloadsIndicatorNotificationLeft {
+@keyframes downloadsIndicatorNotificationLeft {
   from { opacity: 0; transform: translate(128px, 128px) scale(8); }
-  20%  { opacity: .85; -moz-animation-timing-function: ease-out; }
+  20%  { opacity: .85; animation-timing-function: ease-out; }
   to   { opacity: 0; transform: translate(0) scale(1); }
 }
 
 #downloads-indicator[notification] > #downloads-indicator-anchor > #downloads-indicator-notification {
-  -moz-animation-name: downloadsIndicatorNotificationRight;
-  -moz-animation-duration: 1s;
+  animation-name: downloadsIndicatorNotificationRight;
+  animation-duration: 1s;
 }
 
 #downloads-indicator[notification]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
-  -moz-animation-name: downloadsIndicatorNotificationLeft;
+  animation-name: downloadsIndicatorNotificationLeft;
 }
 
 /*** Progress bar and text ***/
 
 #downloads-indicator-counter {
   height: 12px;
   margin: 0;
   color: hsl(0,0%,30%);
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -2619,41 +2619,16 @@ toolbarbutton.chevron > .toolbarbutton-m
 .allTabs-preview:not(:hover):not([closebuttonhover]) > html|canvas {
   opacity: .8;
 }
 
 .allTabs-preview:focus > * > .allTabs-preview-inner {
   box-shadow: @focusRingShadow@;
 }
 
-/* Inspector / Highlighter */
-
-#highlighter-panel {
-  -moz-appearance: none;
-  -moz-window-shadow: none;
-  background: -moz-linear-gradient(top -1deg, #ffdd88, #ffeeaa);
-  border: none;
-  opacity: 0.35;
-}
-
-listitem.style-selector {
-  background-color: DarkGray;
-  color: white;
-}
-
-listitem.style-section {
-  background-color: LightGray;
-  color: black;
-  font-weight: bold;
-}
-
-panel[dimmed="true"] {
-  opacity: 0.5;
-}
-
 /* Add-on bar */
 
 #addon-bar {
   min-height: 18px;
   padding-right: 16px; /* replace with -moz-padding-end when/if bug 631729 gets fixed */
 }
 
 #addon-bar:not(:-moz-lwtheme) {
--- a/browser/themes/pinstripe/devtools/debugger.css
+++ b/browser/themes/pinstripe/devtools/debugger.css
@@ -15,16 +15,17 @@
  */
 
 #dbg-content {
   padding: 0;
 }
 
 #scripts {
   max-width: 350px;
+  min-width: 150px;
 }
 
 /**
  * Lists and headers
  */
 
 .list-item {
   padding: 2px;
@@ -247,21 +248,21 @@
   -moz-appearance: treetwistyopen;
 }
 
 /**
  * Animations
  */
 
 .details[open][animated] {
-  -moz-animation-duration: 0.25s;
-  -moz-animation-name: showblock;
+  animation-duration: 0.25s;
+  animation-name: showblock;
 }
 
-@-moz-keyframes showblock {
+@keyframes showblock {
   from {
     opacity: 0;
     transform-origin: top;
     transform: scaleY(0);
   }
 
   to {
     opacity: 1;
--- a/browser/themes/pinstripe/downloads/downloads.css
+++ b/browser/themes/pinstripe/downloads/downloads.css
@@ -220,35 +220,35 @@ richlistitem[type="download"][state="1"]
 
 #downloads-indicator-notification {
   opacity: 0;
   background: url("chrome://browser/skin/downloads/download-notification.png")
               center no-repeat;
   background-size: 16px;
 }
 
-@-moz-keyframes downloadsIndicatorNotificationRight {
+@keyframes downloadsIndicatorNotificationRight {
   from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
-  20%  { opacity: .85; -moz-animation-timing-function: ease-out; }
+  20%  { opacity: .85; animation-timing-function: ease-out; }
   to   { opacity: 0; transform: translate(0) scale(1); }
 }
 
-@-moz-keyframes downloadsIndicatorNotificationLeft {
+@keyframes downloadsIndicatorNotificationLeft {
   from { opacity: 0; transform: translate(128px, 128px) scale(8); }
-  20%  { opacity: .85; -moz-animation-timing-function: ease-out; }
+  20%  { opacity: .85; animation-timing-function: ease-out; }
   to   { opacity: 0; transform: translate(0) scale(1); }
 }
 
 #downloads-indicator[notification] > #downloads-indicator-anchor > #downloads-indicator-notification {
-  -moz-animation-name: downloadsIndicatorNotificationRight;
-  -moz-animation-duration: 1s;
+  animation-name: downloadsIndicatorNotificationRight;
+  animation-duration: 1s;
 }
 
 #downloads-indicator[notification]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
-  -moz-animation-name: downloadsIndicatorNotificationLeft;
+  animation-name: downloadsIndicatorNotificationLeft;
 }
 
 /*** Progress bar and text ***/
 
 #downloads-indicator-counter {
   height: 12px;
   margin: 0;
   color: hsl(0,0%,30%);
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -2563,41 +2563,16 @@ toolbarbutton.bookmark-item[dragover="tr
 .allTabs-preview:not(:hover):not([closebuttonhover]) > html|canvas {
   opacity: .8;
 }
 
 .allTabs-preview:focus > * > .allTabs-preview-inner {
   outline: 1px dotted -moz-dialogText;
 }
 
-/* Inspector / Highlighter */
-
-#highlighter-panel {
-  -moz-appearance: none;
-  -moz-window-shadow: none;
-  background: -moz-linear-gradient(top -1deg, #ffdd88, #ffeeaa);
-  border: none;
-  opacity: 0.35;
-}
-
-listitem.style-selector {
-  background-color: DarkGray;
-  color: white;
-}
-
-listitem.style-section {
-  background-color: LightGray;
-  color: black;
-  font-weight: bold;
-}
-
-panel[dimmed="true"] {
-  opacity: 0.5;
-}
-
 /* Add-on bar */
 
 #addon-bar {
   -moz-appearance: none;
   min-height: 20px;
   border-top-style: none;
   border-bottom-style: none;
   padding-top: 1px;
--- a/browser/themes/winstripe/devtools/debugger.css
+++ b/browser/themes/winstripe/devtools/debugger.css
@@ -13,16 +13,17 @@
  */
 
 #dbg-content {
   padding: 0;
 }
 
 #scripts {
   max-width: 350px;
+  min-width: 150px;
 }
 
 /**
  * This hardcoded width likely due to a toolkit Windows specific bug.
  * See http://hg.mozilla.org/mozilla-central/annotate/f38d6df93cad/toolkit/themes/winstripe/global/textbox-aero.css#l7
  */
 #scripts-search {
   width: 200px;
@@ -258,21 +259,21 @@
   background-image: url("chrome://global/skin/tree/twisty-open.png");
 }
 
 /**
  * Animations
  */
 
 .details[open][animated] {
-  -moz-animation-duration: 0.25s;
-  -moz-animation-name: showblock;
+  animation-duration: 0.25s;
+  animation-name: showblock;
 }
 
-@-moz-keyframes showblock {
+@keyframes showblock {
   from {
     opacity: 0;
     transform-origin: top;
     transform: scaleY(0);
   }
 
   to {
     opacity: 1;
--- a/browser/themes/winstripe/downloads/downloads.css
+++ b/browser/themes/winstripe/downloads/downloads.css
@@ -219,35 +219,35 @@ richlistitem[type="download"][state="1"]
 
 #downloads-indicator-notification {
   opacity: 0;
   background: url("chrome://browser/skin/downloads/download-notification.png")
               center no-repeat;
   background-size: 16px;
 }
 
-@-moz-keyframes downloadsIndicatorNotificationRight {
+@keyframes downloadsIndicatorNotificationRight {
   from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
-  20%  { opacity: .85; -moz-animation-timing-function: ease-out; }
+  20%  { opacity: .85; animation-timing-function: ease-out; }
   to   { opacity: 0; transform: translate(0) scale(1); }
 }
 
-@-moz-keyframes downloadsIndicatorNotificationLeft {
+@keyframes downloadsIndicatorNotificationLeft {
   from { opacity: 0; transform: translate(128px, 128px) scale(8); }
-  20%  { opacity: .85; -moz-animation-timing-function: ease-out; }
+  20%  { opacity: .85; animation-timing-function: ease-out; }
   to   { opacity: 0; transform: translate(0) scale(1); }
 }
 
 #downloads-indicator[notification] > #downloads-indicator-anchor > #downloads-indicator-notification {
-  -moz-animation-name: downloadsIndicatorNotificationRight;
-  -moz-animation-duration: 1s;
+  animation-name: downloadsIndicatorNotificationRight;
+  animation-duration: 1s;
 }
 
 #downloads-indicator[notification]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
-  -moz-animation-name: downloadsIndicatorNotificationLeft;
+  animation-name: downloadsIndicatorNotificationLeft;
 }
 
 /*** Progress bar and text ***/
 
 #downloads-indicator-counter {
   height: 12px;
   margin: 0;
   color: hsl(0,0%,30%);
--- a/build/mobile/devicemanagerSUT.py
+++ b/build/mobile/devicemanagerSUT.py
@@ -217,17 +217,17 @@ class DeviceManagerSUT(DeviceManager):
             if select.select([self._sock], [], [], 1)[0]:
                 temp = self._sock.recv(1024)
             if (self.debug >= 4): print "response: " + str(temp)
           except socket.error, err:
             self._sock.close()
             self._sock = None
             # This error shows up with we have our tegra rebooted.
             if err[0] == errno.ECONNRESET:
-              raise AgentError("Automation error: Error receiving data from socket (possible reboot). cmd=%s; err=%s" % (cmd, err), True)
+              raise AgentError("Automation error: Error receiving data from socket (possible reboot). cmd=%s; err=%s" % (cmd, err))
             raise AgentError("Error receiving data from socket. cmd=%s; err=%s" % (cmd, err))
 
           data += temp
 
           # If something goes wrong in the agent it will send back a string that
           # starts with '##AGENT-WARNING##'
           errorMatch = self.agentErrorRE.match(data)
           if errorMatch:
--- a/build/mobile/robocop/Makefile.in
+++ b/build/mobile/robocop/Makefile.in
@@ -7,17 +7,17 @@ topsrcdir   = @top_srcdir@
 srcdir      = @srcdir@
 VPATH       = @srcdir@
 TESTPATH    = $(topsrcdir)/mobile/android/base/tests
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = robocop
 
-ROBOTIUM_PATH = $(srcdir)/robotium-solo-3.2.1.jar
+ROBOTIUM_PATH = $(srcdir)/robotium-solo-3.3.jar
 
 JAVAFILES = \
   R.java \
 
 _JAVA_HARNESS = \
   Actions.java \
   Assert.java \
   Driver.java \
--- a/build/mobile/robocop/README
+++ b/build/mobile/robocop/README
@@ -1,9 +1,9 @@
 Robocop is a Mozilla project which uses Robotium to test Firefox on Android devices.
 
 Robotium is an open source tool licensed under the Apache 2.0 license and the original 
 source can be found here:
 http://code.google.com/p/robotium/
 
-We are including robotium-solo-3.2.1.jar as a binary and are not modifying it in anyway 
+We are including robotium-solo-3.3.jar as a binary and are not modifying it in anyway 
 from the original download found at: 
 http://code.google.com/p/robotium/
deleted file mode 100644
index f4107c7496ec18d7a5fc2fe56742036ef3861bb7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0fd9421101ed0dc10a00a2b85c4b0811abd2bd2a
GIT binary patch
literal 55662
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%0A%1ye!~0l$d$K~~1G`#%`9tYJMee9Q2ehaT
zk`A&c?Ih9K2_m)n{LQZWKg9&5caWx9^F}J)Gt3z&#-s-z++A-RU8vf%JV`pa6LfRN
zX=aU6$k*kse5()_z}Z=yX)Z_Dm;4#bulgu2WCoZIFU9YTG*k65Y#(x=ehbp0(-y*i
zP=;zSHlBb_QM0d&`nF4PsGTvs_)B?GJ~)h1{jUcLUP`_7Es^A!gJ$jT0dbY_J%+%?
z<?se1PNK;m#k@kARFplx(%hxHcex3snuez~Qr*j9Suyistoh#6agXam7&2%Z-6caP
zMM7-(beThI0;7%wa!Y8it#qRts7Eo@=0K+rfpo)Aj!{xb^6Q4npwE{;pJiziB-@cl
ztpy;l6$VYCj8rm_RR3p#f~*h&dm=hxqN|!CvO2-gc)*-u4H6(WzMzw`GC`~^fAM7O
z%rVCAkc;9j{^Bx9$^lSY^(^)`GXXO8Fa?=jER%z(R|LXn5E1yWF8&BL)&G!dT;(3`
zq%Nukm1|U$0(>(~R>9W~q(hm<j$h?Q^Q;8<G@U}3LP_2|Q-Xm#B=PGB`VP~c(mOW3
z0t46L&mCA5mGfQL-$&PTxIq_{Gc~to7<${z8nD1X^sI#WoPmTn>N3QLQg6_2gjAsD
zJ}FC=pO-v({3A^<&E9dGrTr*N_YnxavU?T~x?obcuV$wq+en=_Z$1T!ib_VAbW9CJ
zebfadww6fbyXiPYre#}>BIzj1+bS!VO{^ZmGiKd-B$ITK?o3H_t|hW~CjObxl73s$
zc%=fpG078!{w~||ZJo(bm?t}yIhbI^L0H#HOfPzDf|+2Jh=t>kdZAaLf|0-|l5HIZ
z=dY(htQR4Bjzh?@5{vSyGGWTi1i7B^Opvr2E#v%ABXe3`1d>FWx-b;%7?UH6|1;-t
z0WoW$Vj5Ysm4U--=ZPfOFauz+PB>HG9h2RtNj1Ao(!4&h5ptMKj#?JFlIbdaL&Q*I
zUE;Hw(3CWv3X~;-o4f<zig`@!MT4imL0|8YzHm<qt>w@9=+BiTNxiwX&Pc!|mgd@3
zy|%xvO})pMKF^7E9+K!FeqMoezJ>UiKh(ZeP~pllr-z|69E&KEIXoNNI>*{PPg*cE
zdxCIG@un3j$J}AQ?O<_^mUS=@+Kxu7T!#C=DB`^h$fzY!Zj@tOoi_1~L&TRSI7&)Z
z$Qry#pq++$YXVcShv6qIrl&0dBqK{(8@1!wjc@4hp@XMC{eEXQ7S-ZV!Lm9hE?wIM
z+!qn}J4(2Uo%+vaDjtHX4+vDpZtRO2>JvUpqWnm~CPUpKjhoo6p3tj1{^o&`AkUnr
z4q=?!Ahwpc4z);ckoohUuY@FrOAtmI-j?#~anLEHzhRt<u!<oQ6`~jZ=%wtt*!^Wv
zkg($Ef>oL~)jRJJt^Y+9C6INzXt3sF;v#?*f_*LzQL(F;cVi+YmTa31nuZQt*z5hw
zkcI30(LBhQR<Z0}7P4`Yzcu<qntye&5F3GUk*My4D?YnoXm=Hedz?fc%zXvZy(`FF
z{c!z5e+)86q(K$#^kGWY35;<QV~~a_clro5`xII*j<Zeb3Y_V~<V+*-fSV6VQ}%U#
zs4IhoHJvb<*LD-5TD-qSW%IsUXU>>!_Q#qDjPJ&vTvWDdVoGAluoL&OJDjPy<SGYY
zE}?KYJR-b_0M7`dLlF#PM0gl8K`RGgZ9E}gQ23mwfVGKDyzjSikiFTaqSM?I9JB;?
z*kaNT99)O0K<$7|^cX^8;bIV1u8DX{t(z*~mT3LjaQxMKPWYZlWVd4W%*DI+Q)cMj
z(jdTVMK?}KTG5{^@%T<`Me;~p=-*{$@47LjjnSd9Ouh|gxvTgkPYYcEVXS74aJ3-G
zUF|S~9Ri+X<yGSS!o&Ww*NG7E*<7X565>5s*ZB*E4Q^pyxG7K3&WtfR<O@?gZd@zx
zuG!gstUaBk7-#L!={aMwjDxKq$|>^z`oLbI^FKo2sqaEK`AzT}!R4Zary7cXnV4VT
zI|H7j2-1j-Ar;4EtN#e(5<LbpIm{{RDu4h>u79&U7bF{Osg89`8h$Y?$(Wp8U%LTc
zrvSK_0>EYPB_i-Owjc8Cnj!j+hXGV_fC+#y`e4jT4yJZ}2nEClS{IAu;-`Dg`Agl2
zmA~dfj=2Y+L84_L(U_V+LxQcF5)Q<3aMM*Gdcr#Nggyf&hVS$g%3tEP;v^PViMQ0J
z<C$FJIACdww$6Jnn(<PokAYrMwpKR?WzUM(WE8!5&v&B>bi4^g0Vv4;mev!Z9RSHN
zf~FfnF^r%POooO42sU_8Gdkm+cET?y{B*d^ya_e9<&iR|E2=6zA-UG-YY!S4qQ*A1
z>$4NAr$|1_3QgDEz?R<tvb@Ehm8v?CuZJ_db(D6%mTJuu`}Ih;M8V=7X^(M`0YY{~
zx(Ow`(Mem=vUQ+lQK2>25J9d_wnF2TMLid?=roW-ufKRgym(?rb;qf5q-17GZNRlA
zIZ?54-Z-wBQm>g(KW><=ok}jBRzz=Rn>}*u#jtJNY<7oldc(GSbOy1Z*F%S}ft5wA
zk4<0ySqsH6ERZ(`RWl#yCb_Pseg<|9U8Ausc8W8z;>wC*rf9Brr9syz&?^w?6ARh3
zmp?zcM(z|ME0flyYF?_H*OM>k>r_2Qa)Y{QrhX=*dZwos&_7Tuke+$pCIs^H=oAX+
zS_~UM3uDrYC4EiJ@}8VI_oLi`9VKlT(^eh5Gypz}e3ue<N)f84n>O%RKsC5#D&u+K
zk<7i!g5>Pgz<gZhy>@h>t|eAPW0IZoo)b4(XQJ5i{wN87Y)`vM0<K*KRNDkhGX>}l
z)S(2oo(IIf_MgE7s58t<2F@)5&NTzq&H}u*e5K^v*Tl82!M%@;rqVMq&FoA&g-W?_
ziiW<nKY+o$qF!%FwH`AHsY>p*nQ5+IvrBkw{3+$WbUck}ICYc)`!b9wzi49!cFz&8
zMlQ?@PjMWsqFJ20bAhpVtG_x~tVLKX{rHr{EZ!NijhF5clE?~mkF&CXug50**-EiE
zS3uts#CKV@*e2P&0O-=NPVl5H13gJ;!MKH(dK?Iu`*etTDeiBNLnjAK#diCfj{T+;
zzgKg5vufCYeE&qB*8NPGAp4p|6VW#?_e~M8V@iZ8Ee7~tgCMs;qHP@JIRlhp6k^!s
zL~-<0nvyy%DQ_Mcx6$BB4WG3dm$oh_(laF4kBS7i=YVp*1o47NULN3FPLoHxoCD#K
zhOFENQaO)!X&c-*26<@+xeOy-?uB^SBu6|?fEiF7LMOJ*C&GJ7vOh)&lzUFGe}-`B
zOJ1IWRIY?mfG1E6o|At`DqqGW#2YLR&n=ik7y!j7#2Y9d$0cZ!EHHvoAcjbF0n(xh
z<WfMqY!K`@4QVL>)G~*7=@9(cjl5hBa_LXJj12JtN?u-rRNjSC&>JrQhf8pTR6dSF
zh&M$3PZl`(DkqB;zsyhYO*7He1<b_W(kVK%D@%4l+WLa7V|v1<<$H9JHMU7(PpV+6
zS&ng4+Qh3E*ha2PVvR1@))uC**QjJ`4AO@3KabC3nty<5RQNf%nju`Hf|#9Cr57|3
z?Kf(8#?oV=UvU8P-r|29+a4Mv(2dz42lu=b4{-#?LMy?NRwm?YP6cZ;0RUSN<P@T4
ziCQ!Nd*h@3iBAn~->$uxhIwn9YodoNPokX|zlPf0yJ<0^9d|~xyuIqRwvJYhK)BE6
zaO=YJ_uJPD_A3L-L7jJq@r7H1`{dLn{$&Ng)w+1;d0&h0LtlJ@|0t1McVl;c@Pw?Z
zJAEP2)f>GU>DC>)g6;MtsdIbu#H?d~<dXgAICuV1>}pYw_h+IDB6|@rS5XrP>qPQg
z_T<p9369?c$y!mdukFM_vILk_Tk99KguYhLGRWJ6`&xl(7rY7HT5&-e!e@zbiT4rZ
zxKS&4yW8LhRa<9^z0_ckgykYh8Fl%EUgY%m+G)j<Y+vL{48r7tb07G|o4G_iNfs+J
zxN*LZycjh}eQ!)%_?wm1PV3X+l0ti3*@e6O(^<bOy*TujCit^>$8)Xl<(0c1mv&#*
zR6K%o;Il^76{)thXa}y+li^1T`xUl&DdUX&;STj8jXV66l6#Xk+_mm`Dn~7cp|-(@
zCmJJ8g0a`c&>5O|;R0&zG11-z>9sBXsc1~cj2l3q55VIRy+FoC(Qz;_%=L?H?h{4K
z4)s;%opOGo9f)7Gwf_%+mImO*Br0{;H~xP-+f^jBzyJjX0KfzLFB&!}o47lR+B%y!
z{`-1kEu|%SgkK>mrAq~AQN(*XDT*}z$Uut15-Lr>fPsXCuy{N|j6}~w|8JB$pZg8W
zirCqA;BST4E(=7k;{s+=vaYl1+l{B2lk2*@JwG6fL2YKu`KjVKN&ch&7)J(XjA4YN
zD$M77O)PY#_E>||?Rf`g-~l!uVi_?FZ|Sl0*e$MGbA+qZEz&7D4*I<?tWD`uHPv1v
zHumhtMwl5x9oAC9nNkDmRO%YdtJDk4-9}Dysxd7xpVSvr(luOuD9c;LgGgj&SW66w
zjo-`;OB-ADtkYN2Nxes5a!qF7y%$+Ng=e9PVj{DOt=O~RBP^bxh9YpVdi+OU$+^H#
z;{keU*fFVC^0J~9(u&g>QZ>i<UYic+R7ZC`bTUpM*nAl|k6dNYH7Fp-#DP$KH&}&f
zNK_9ISh0kRCt{N+a5%lh9TU#}d`R7eCLMl)`9CJ@hiNX+(Ay)y0^D36nhrwyB%2^|
zj2FWuxNji0MFb2Hh5f)h%MTLzP;sES`Nah`c5Juev0AB8`;?`iruQ=YoTe42F`#1i
zZai}|HBwpF=He{a9=fz?J~14t_8jpB4|Zp87_iE@%-gR1oGOVpe>_qsviGX(BVs69
z(NQaQ-z{tQxn8&0WulbHrdmw|X!#^$f8YIDsPxiypfh)az0o!3UREKCn%PT?qQ%Jf
zTM)S1v`|!OSjEjs%%;}eCM%VT)mG>2zKPktL|(-95fMJO^fhCCLU}+Sga{P_>d><L
zD|iu&8q5ICEc8##GjPP2vQB<M!j+;%zm;>8o)+7!3j2`DCO%<m$SnNA-Nk#|pf!8#
zpk+UPX-OV$CTK~X^c>EeyiaKsP;vlc`kX{WyKnQe=mYT0(dpKBeMN{?duIIvl?o$K
zo~WMDhgo&~gfrEN*0e=Wfi=~Kzo_8+gmT^Z33Po&5H-oFI5d}VYYs6qmVHd!1aw3)
z&t(gV#|@K(x<YKD4KUmo;vBjMhw1w3uKbbPk-W}B1$iW!c>m=3!)UY+{Qmx@8h*a@
zrQroY001xG|A%Guuf~p3wo3viyvSkgjG@6mv?m$_{>YW>^@0$?rBI6T1&YWf{0-t4
zBC|3kaaxZW5-22S-T?R^?MGlGSu}<dPG+}9+fMj?zrUZb`>0$l+5<jbJooZL!tinR
zSBDKz<aD`A?`1qT5h9rd@0J*@M74=BQzSe|6C&yLZ45m|<rzj9ZLgS}3e{!@$#Zk>
zJl}VD7Y%HU=^-6*F6P3Xli@PPY>z$4i{AS0DAnkliLze9^1SmA`sN~v5%eS0G>wG#
zWyKrO&eKbXbHzUN$tqL1fXa?~lnJ=SJaeEHuWN<Np0Y0-8U^PtG|+bWQ8Z}yC9;d%
z#~V41N^;MhRB|qKE5}U?V_Xgkj}I_&KJM+8M!+uke68Bu_lWtjJ34W2q%9GH$yJi>
z9J!I{qwO8axTsP(&iZz^`k}DQ{D|mU3$UtiM4F~p>Cu%m;!Qn+IhlFTOKRjHm`Gf*
zq~~qo>m@JM3&z^YnX+3*{v<D9s_jC3aaP7Xa&2wTt`clq^m7ATUT5XbzJnjCTx{pf
z4E=<eCh0xw_P}lW;C|Rz(CO^QHa0J_ZpzvC<#d4EOh<?f7}`J;^a426X}NCo!i|w#
z?O|CaC`DM4cmGLw)5qIDJ3#;d{(Eiuf9bEG|89!>i|(pwsbQ<2{E`8Jg<3#Swk@hE
zg<vK22W#4us8TAHz~;lEN2GCO;Oq-Hf|-#OKMa`p1^pdt0nzSEog&BoR-k+1OcJ1I
zYfSavFq`A^y1Uy-<4p4V{rUL=kmPQl4}p)-9{Z(3B0F&spv}i}kAOcB6j#Es6Cn;}
zdLI$10lf1*-H(%d?rupCnjPRlBQaALF!vxzo{KqdBstdjtiw1Tr-G|@slGHn8iH@$
zp3)>b;p8#V=;m6@x#+P1g&cruuO?$LpTp$Vno&lW;<O#vVzOrCx?{=ZVY>k9-eUM+
zyU}7Qq~+LU$PKu6BIv`pZ=xssYIt^`3J<mL;17+*vwSc7s2!UY^L=R%T_c}ix{b7C
z&pHOGRjwL2t<@N1vN-HiYm}yD9XE9r+DN;8oP0Apf+2k^%0LZtTH)yOMUzhZAYeK1
zLvesbZ&TlInJatJdabiXwPiRo366)39a-FQ)Sz>#`ZLe(yC@}0&K>RdGkwnlY_f>C
z?51wMbCs-<ce3-cPg#Yovqf#u?!hKJK|V>13VRgB)|I_NL+4s47y_DQ8{sMO*qwN0
zV_;WKgwcA$u!lck+Ju!$La#RD^dX{ae8MD&;n8-<dCi!%b7=v|KqzfGD6}d91d2S=
zZg9xjZF@*&d+|Owy!Jji+~#h3$i1#C3YidpB4y7{xJ@t+oE^AmgDZ**S1yN~HenF_
z9+1gN4)SC=*?PyUmuSGXDr>F()c9~Kb?3#^9zkoJMNw2JoNnJB%utCxHxzpQz8egV
zwew8sX-XupGE8TQ#gt|sR>Ge-KXQoXWIkIcxluX5{3*eX$jf%h&gr^ttKnxtB27QW
zV?UIzHZN{k)(xSvod=6u!T^m0)>`Sjq<)pFW5Bw$)mmEdtV=+y2q~?bQfflr!K5ju
zi1v4_JU80!^UC)q`zpRxw~h*Jq<coRmky`Wochj8rNB|mA+gRASyBE4Qys-)%qUtQ
zG;vJt7FDwp%8AKx+N=<z5f<_}Pm#mI{ej^R{@?K73QcB}xgzZ>az_j(qp@E28DdM9
zJqu4PzR0AyFTkqfjJ7FU%iEkKj#FJcMJP<-Jrz1BTbqfU)D#SJOtH1LQ@n+O&RH;a
z4@sS@%Mp+3j+FU3^#@I!(^07BPPm0Myl^5qdV<8m$4>?B9nt2tCD??18_m7^GA1JP
zq8@q|e+jCdFmtM=u-4^wyiGqs9}v4mE&*MFJGRGbqCJcc-J&GK#Zn=^=tH=Cl87ow
zNg}ai5>64xFSJD1<Gg(8Ihjwp;>EA?^{`$6ud})HNH<ZxpoCA<1^)S-R4KDjc>UX>
zNyH)p=XowcM4I$*q%6tFFPq|vI@zQY$#WwTQPN4mK9~(-ls=fz3l^crVZthW$|dt8
z6$t_{5IFmk{fiD>+?d-UaZ47D><#g|sp?ZmuK-8g(r-11KB;i4NR>k&I>Zk^3;PW+
zD+_)p0h?efyW6S<tFQAf=$|J{s&#-0Fts>|;bf(R@nneP7JxWBpg1=FunYWsl3Sw1
zCCQPlHGtl_Z~$DYnWAyrNXxoN4g}5p9I;`z?kXa&``ku9{JhG7C<LMRsE{qc|EPp6
z+_$cj@Bjes`2R&ERJAa16EkuCH<OMObx3dJF^|7-ukMSN7XkzWKu8!y-J2@`{n|iA
z!-T}xk{A>EzyUN>DbM$oYP-Pln_TD)bmX$v>yXQ&5lPAoSEKvGgR#g!7LhqDvRluQ
zPHPrRr8b)+vX{k@!hiR=+x}2nfWF?9<z%ow&A90m)qTG<p#wBmWC5KIE19eZGy%e$
z0o@;10OzH~&0)BY_6O6<VY{oIp22vt0U-aG7<&TaBY!$GISZ`rC0M5evxn598OZ~?
zC;iT_)<dhNAHOez(M#>A1CbBmPdli3{6KfSXT|(g<oiqI-#5Aj{Eq!?!}$y6hu_aX
zegWq#9GW)yAnRR)vp4Ey{9cRjoeQ&vF4s%C_-#a~o0@|^KE@AvKlfe$^Vg8Tc3%%z
zJqRE3y$xV>;`<KJI{t$nXgwT1<zVc6PVrlf(pNDu4=OPa^W6@ZA6_5Z*I?fdrn^uc
zF~+3ENY(XvwmM~;qIw%uI;I&fCKfj?wnZ!n_#&BgK2r`?(xhfv!ip?KqQw<ucfFk9
ztvv-t0{1SKtVsC5S&z+zGz`Vk6*mSis+Fv8qCnLvE+17%0QD3Fz(!hxIk2{R4oga`
zsl!>@VE6e+_Fx9&!LBh;)wOBxa^A|M&7m&PP0P}MyvkK$!u^l!u>{W!K5t?;^jw8H
zO9Ojm>+#mcvuPMDRq4rQ@~h^<QO<+4HAgO4(y2VpRvy+4uIyNnMu@z*+V3jkpv8Vn
zjOeR`0$=%BVOWdE7P@p9QpD~v9d**ok(zN!tAGx--0)$M26f7Dj^ply1PKT*sRqL4
zo;mPodE#oUGZz<GI)u6WONFzy|2fTXC(3DAVnjpl_I^HUlLR?q>)NEcCcR}};9Yu*
z<8DA<cdD39VM~*IwM1#+)=`7<W<XVzWnjZXH|F37f;E+pDo(Kn8lqWHT|waMuo24q
ziD&_%vP|V6nUXjv5HP5tjNx{wlxfj3OQ)BHwWAJSd@K`I=w}V0!l@0^O7|kO3iiPv
z&2*v7uG_6>B<EJO>RTKapRz6er;?lL_)@A`oH1KZsyH}UE38%oV4;dRG^&aI>5kS?
z#WsZ`qpA;MhujM8)ZJ2mSy#clMzV;*Yps-9Z%RUr(A*ui9Bvtkizsl$z&<~tDYx7N
zAeh`mM1!|E7>KReHWpSY$Bi;XCnL@F%@QZ0pDqqBea2W>zY5}5tF|TuhZuZ_sqxYV
zjV@}^(XVn@%J}G#))>icsoCbQugzes?9a`}GJ8<EPeHpEM?2f>alLsks#)i-=B+A-
z&${St(MB@KR-_=Uq<8;<s0(1alh45lN0$NCw>6y4eT&7>id34JaP($ItXb$$M)i&K
z!6Bm(53~w-IuGgD8`*`fLj<SN?3a?)Ax-)BbA0^ZW|g!;beouu1Kmf{j*HYR+)Qdh
zwJ{mC?C7D=R=_T?_z@$cq>n)yLfpwB%~FVqmBoO^pGtak?AzwUhybDZ6Ho%32oZ0J
z%yS9&6EO_55dEo0{}ICnnNkFaF$=LI{b;mpi7{~G<8~GNh_;gxNBt`%j}{rLKpw&g
z(vmDg$T9;Bww*toiW{@abey840(w+wXvd0gmC&7$XdTvt=zr4NQMqM#=&JM%)vk+8
z&-aFPuZy<M;A6Fbn{}<m5~9^tUTgQ8g}Es=+TNyaIz+Lckj?H7z894B7!yQeKPhrG
zWWV8j*M|Qdu8|>OFg{>^=LPI#whuOkw_Mk0W=GMgCN5-0lWB@6K~l4=8piz7b%ifW
zbkLfc()r7r%%l>Lk3%YTqM)nvVSG<LG<;=0u3S<%tqiDQdpP4BC28-gS}uir*Ut^B
zVp3_zIwsFrnpt&<S-Gn0V%b}OmhR5JYj%hsL2O<bVwq5YmQ|@6&t6Vis##gfyu#$t
z6S370_2DNn7F3a1g)QTJz$RS7uo6RMTq)+#Ggw%~(N!_%E>v)E`78IgqqU9My7uHM
z)RIYsx)3TQ!$*nxaWcUI8`dK!oK~w8$8~|CRI_5UG@j;m)p=Mlp0~p|)#gut_)Db<
zlx$tekg2iE9K|)#`S3?&7lks3<YrhjBRn^<Ye_+dg``wRv!W(kr$>3iIB|*PCYqMn
z#ctu^)J&G+kk6O$pS_~7;ky~plNA$n%(5>1QG%bzgL0$vS!Eh=e<{N~-E{_}SX!fy
zdrH_vHY)Baw+&B_$1dE?ymKmD8WFV*Q=!MtTFjOqbgp^QkE)ZFo`&nwwF}ut@@dw^
zq_aA4aq%7LV-wv5pDyCu+t{TVt`lz~!QL#7Ng7JaXm~NFh-+7B=FITe2`6(bv9sd%
znn52dBg;Ahm)Q#uXIh%wg5~M$k{ye)+;_;rd$Jdn6}N364I2|KCQJ|XC)(u<xfqD!
zY1_EmqZrYUBGeI_E(+5c#MYqeoNUWgoXm^f7`2MfCo|4MuSUAfiZNd%PvOqC*LX5v
z^W^j<pAGZt++SxFH1=gnEaJKc<x&@`Sh{ZSyI5WyogUuhlrE;OL~kLBj3Xo-pDjE7
z?Ukju6@4n3v3=OJctZR!XsCnFu%(KlLW3W@z{`tjeM;ASWPfm0Mc)pp1eQ5Y0#tw2
zYOT8$eYmxr^_d5_+h_Z_U?-Dz9%YV47^(LA?4^1yj@ACDhFl}y$$Ajf;^na%t}nDt
z2l9M1Ar(tf>aL(K{~#|(W1!tBh)HM2UZrxVsYfDj<ompsY?la?M4$W!n%4N^NgyF<
zZ6RrU^xM_o*REj4;0JS|H2rL{0%;1~m`q736SJ-q1Ve9v@Q~#Q*?Ks>*f#sNpf0Tj
zh%JeBC1hQx<R}O?0B|#t0McwTV?o^FP$>^r8lHg1+cSe*A3RjvgVLvR>o+!?(SuTG
zv--WJRlO^CPkNrv()_m7zRDeRTewfULdyjY<+!0WTM(Z##Qj~6(`)VvwIj7&Jljlx
z85jXSLj5NV$Aw7OZJCK%A()_SUd=%{D&*ub@muQgzdX5XN-l(xD^kB(4(V-h3gC5R
zdDmq$;t-7a4lqQq1~3hFjm=^pSG3viO2lAx^h=)i3Q9KJxFLD-uN8UZQ8`MN!z<g2
zhH(mZeB07k4vsp4+d;(#gl6LI{BpdS!7Pv_dAKJTH(hV?Xs@QR3wbBKc~7O|A#+1(
zHyhU)S5+^f<y+XqExjr?yZLTFPUH-ArLI6OW%9eq_|LC7&*e#cl`q(anIB2DZGpSA
zvB%_bB^X6}eSpyG$f5UM=A%B&qm0!iab%wBGUcGr;0be4jw12J&qNnwYKyX(e5ne%
zQWlcZ4oRztBIo7QBcg^39Cm6uCR#0C;UHH;o1DX=)WgHjas`5?`;^NQ-S?gF*#Vf(
zE?03in+m$tnRGK=?=QNCe*8aQf|qZE)uZ6!b3@0sKhLl59gEXO{Tr)H^$QK89*!j&
zw-QQ&T5m|T!Rl=UG0~}^J}tyEW;j{ZekyF7ygOvfB<~mvKG~Vr<SBm?&*GNw{A9d%
zB)y`Q63c20;$CV&u5`Sr9d8;I8^RL#He-#liNQKHQsEEAp(&v0bNdUM5?t+??)lC1
z;w`E#QJl#7Fq5J%lV;3Z9#L1*E=24Djz~Kn&?i3A<fEow!qFRW^i21?RhoQ~WXDY!
zV9A{|6H<aB>enS&NjWS%ykw%%;NiZknK*X)@$(pBG3b#MVH&oYR<*87z%;%wxUwuK
ze0;j<a&=MA<}5fuBExfpMin&tumI1f&z(S`&x@7*0RHi`D0n*4rW}$1>z6)0$#TxK
zJL2*Vi~NgM^2G=H#1!)gjFz9KZt1JOZ)$}hcW8>2N}|w<lD1O|=4xe;qPr8ue%aim
zbv1Z2X(Np50==1)j`Hs8h;vUK3yk;dLpMK@mp*sqkr<*s@pILqh%mY7gLr9VG5-ei
zRJOLn9ov{+m%%N&oBDO;MV%-Pa@`p=H!kW{mk}k7mqL4&RGVZghB}t_&qi|rkDuJH
zPrtlJ$m%EY^%K?Q(TeNQ?z~>DJ`;WbcQQyT1>TL4|Fud{jsAFTWk9g3-JP=!mAnQ0
z`N&2)0)0F3>%ldb*7QARK2!No(RrwDSWcLz2d%a21C$2NX^%O;1iAf}lSVDQA69vk
z<CKkk!%*pywC*hRGUM(inL6jyXar1PMpR&>P;uoztOY^V5^=S{(^?+37G!E-r;Ei*
zDM?>9^+huf>2sQDrVadRyuwHLf%eP)sBMP_u?qVjJhMM?BL6Y!LZvvLltG&bj5)`d
zBZ-cP`_4t@_>DE<jgv%|P;8>zCrLEZz@g~4^bA2UzWECW3stT_RMlXFgcfwo4-=YL
zuuo1O5lp=4*L-oo>BK5>!ys`7jIdy}K)FV|Wz%1EC6?Bb*mK!*yTEqA@OoKvnJ&q<
zmDDOd8Grfp%1QLfNhE0nGRIw7qZEIUvmkS3k^s3g2RZc;u6z!0JJfSM#4}jFm5FcM
z{R6?IX)6`1%!ZQ$ugG(9)q_-jomw_uL&O!OK|?i`C_2AjXLRY2;`<++!e&tqyzHit
zXlc}T1Vi<-%3(Kuj@IkQcSSuf$$0>5$>MVX|F(pmRK}-L=C54V6<O9XSNgip0-vwd
z4YPHD__<^tK7oL%Os{H!;1*fP7;s-Na3Mo<9$(oYB#(06n9W|*CBGTRH?N~6j!v$T
z%-LASTcIOl$6pl{+Q)Zsy25w7gW<Cl&*;=m<IjJyXkKoX(?6l3!!WYZb`?LDuF8BC
z0N33?Hn6Vg4bOUaYYn?<IZ`Kh`gBm9+UAQ@%wVr*!m^;QTEyb5GYcQ@2E~5vPD<H;
zo8D4a%)c#q+zt1*l!d5dFB0qtDfm&XRwl0)ZZnAS1h`uHfmv)jGOcYZcgq*<NuoRl
zyjH#wO7mn#{l=?V=5-D@iO!DOFGA^v@y6*l(zcneigQ>gP{Ti~l&<3|$f;RV@WAYv
z<~QU$9g5@eO{Bi~!XHBhwS#du0R3}xdKnov2(xDG3uYtJeUPcup8mQi56@(cH;D5B
zaasj$33pSjyFX8D0v|u-qrGOQuP~Epw(wxlT(8pp<6+&EHJ5&)*PgTUzUjoJlibL-
zUU{ZT)m}^>MVlyHpuGdEL@Hk;CSR7QUM{v{Y@|30?5^myF^L%ZS0pY^kv3jDbudmv
zgth4U?|*W(XlQ@O0fzwqIK}!eR)4D*SUCS1b9;E>m|*&nc}<%#&lhuU&Z8viStMC6
zf>5x`rw+3$l95W5NNQ1*G|tFvS+I8*#1#ux0tHfNqAFN-2u2fG3L-(N2s{7*B7&aW
z_eTlKp^ikockfNxvTe}HK8~^Pc|YaOdHH08?RC8I0gxZ!@~0k7dS?gDO*p2|<fWZJ
zH)_*Pp_^=+oi*;oS=ra%uN`<AbPdE|J0#(=AEDvuJsP3aJ|C%iZ^R*bkHpm-vcWIw
zxfIy@$);|d9Id%{55+kW{w0GOzl{ajj<B0>Op8_Ej~z-M+R~x4cAIjPALAYLt)mGG
ze%tc(27in2|1$9q7;|&+o{JkH@?^w&KKOe44uI!RK8yQ)XT)24sE^Gv=b&0os|TwY
zzW)qHjkV$^XrkZTYiH)*LBX+w5ff@CN41O=Z4*OQZR}&jgB8ctV&+V>qQGdLE>JNo
zv<t&rnzuIw#3nnRsC{#F&S`M<sROGCdTkaZeh^_uTt|Q*mrZN09XP+Ryt#Hh*9Iy9
z)7yp_wN7ynSKT;5phq9=RcFD;r7IGq2^}3O<s|S9u(;o7Hh!wDCsHlc7<yu59&t65
zp9KiPeCPF1vtl>5Zxa<R4b{j|9ln-(wPQ8v8K^PHoxY8J1s%c;WR%{`5q2{S8_BNX
zZH$c(q%N4xW*y$CG^YVg4qeQg%^4WbH{!t9*j-Nw*GRaTvSL?oCt0sUG4olGPYo&)
zPJa$wu@g&zgsqiu4yWu0H8Ukywu-0*67R^bHIOTfZ?$K@)7x#ZNRpUHi<BqFifjyL
zaj%vb-<~O(q_8B6Ta%Nfk`$|cN-8}Mhfa*-o$%IwM>3|{M3WU0(h&s9G2JRnmKAez
zCkV0MP`;t|^h#q_lA18?s5tt@v+^QImlz%IG8VmSoK@x+CQh-L%4*tf&A{DrDp)M&
zomS4BF)`Mc<3Tfxn&U!X^Wy>`w<w=oluw&N`0R5qWs_5?#TZVW`YnERmJg}t7&8ko
zeQlUr?%?dB7?)BGZ59h9Czs^=vZOIEbJUO(w~-6k%n#+cdY^z?9N2^=D^&FJP!0Fs
zHU}?a2`XhpgNAd{bdX#SsC_~W3*b>v?m4{;ZU%YbSl#B;e<hukN6#|zYuvjfwQ8e`
zn|@Dbkyg3K0#C=$Lt!}S;IFXbtN5PRr2H8~@ik10(Gg@p!rRp!p;b{4tsp~ztYO2A
zyv&Tf7MX@@pf`kbS%)Rq+ukvQBdInI&d3?4<y%T^*;0+9d|*~IUIhFSakX<!K{ZuZ
zZ3IRW$8laYbB#4}1RJPuLeINXOwg!Z_il-t+C!Ed{gk;(OEq^p1uI~$$BM&Hk3|L3
zG`1M50FxVH0<KZF$cMdSwFgthJRjx4jl*(>;a_=Z56C-!1m+*3cjmF!r~FnNtApW*
zF@tysM!p$%hij$6ox@s>7I)?`+h2Q+iQU6m58T6C4}Y6NN-_e{%pUT?ox^_T{ng)(
zdrykx$94y#$8v|HS5iSk0{abAgSj3MZPcEwmQH}tD7Y~#WK1C_d{6<dgM7Ji7aq$3
z`;F|weDBKc4)HTrXNWmh99aI=&S)MaOrrZiwrj#vh0}<@O|kS=p4{l;*r%#-HzCO^
zCn-ZsZPhc`-wQnOgZW1PYh)?s)XnrnzFfD{nFKm6Q<2c2n|c^EitQD81liO_i*vIj
z8kGpF$f2XkK~t2yoShEK+;uh&9=MSjJu)p}Xjng2lTn_x-!G6UE+uh(^PwqIc@4>J
zHHk={YJAb~2|j4r)`^}hb11zB167vmz?5}H9%Oh@oD~`qce&5H)I;=8$$Z0|`E1o<
zlDA;*J(KJu@EVUQT}sI3^Wm~ak@}gj&8Tq~+`x+C>N&lgDccg30mwIniN$1X=>(s&
zu~F7-djm1rwSu6}RN<BFnSnzO?h{M2xrC_L{QV;TRofP%Jl2Noi^<vL#5${iJaL}A
zY#ha#y(KR9<1(9-^hwIt#Ls2!Dgt(MaadkmH&L-~Z@J@e1w_^oRVtn9dOSQiMRlm7
zI&`S5c3Mqb_7dM<*w|l@=M!OGsXFQU_?l_Hjb;=BD{9n*rFG=MESB{x*m4m=I<viY
zC)<K8Ke5*){o$lGW}Sh%J(K!Skef|4Z_oASVSef*J^JPKJ_}iN&SAWq<P<t5v{)_1
zy$092Bc@582OH2;02<jzEuMf*QAvjrLM_h@<(BV@lG}f%;0}Cpt8gCRI7i{_MuBV9
zPA9~-hSkmp4w^1a+p-NRAHbztfVcAP(SrfYk)%A+O6FWB{S#~_k7r>?&UaFgqkf~v
z-LO^TYS<B$yrX`#?!#pf%*QV;ZZ#I~=e0>vhvbo|s9}m+qH=oV!x6P7y38fMEUR4j
zwBd~Ko1%i62A0JW(6x^zJb)3+h@-+DTJ%;_UODZw(sB>IF#i7Znl<LrWhL~`AT@0n
zX%&`Nh`t!?Nu?`fQYK%6;mmaW7hTpOC=(~hcx~wYB*6>Pvmy6)qK}Nto;=qn{wXW{
zE6~XHig23i%NB+1X?hQwpY}DTAROMVqpa2trYX%+y60<nQ1Oiq<uT|MOZdUpU7Kfv
z|F@iJy95Sa9@U<10rHT-S`<<UW|s}jja%4?QGy#YmjSt2k8{BmJKnVr)yyc#u@Lo)
zg50<*14+lSErgrBBrg(vpQlr4q#5pUT3V+9BO;n_vc5v7m<hFhEBR>)_iRtq(OhuT
zW7LRG`1GV{dMcjfRA5l;QkszQR|YB~hWIGX#K4}g<W3NgFVM&y@uoX?!i^Hx5fj**
zlkuGc`2i|qfb0F;ruK2Dj6t$sAy=%3H%6=rs#f|&(Y%?%9EI^2=~RYgbIH6}M#u<!
zjz(-q>_{+InyY3011T9q?NLJ%Mh;@RL;JZw#sjx}&Rf#suAc=Hq${(oR9FU6JIJFQ
z?a2W+X<rP;nK__6B*m=?h#=pxiS))*dh-VD`j9S8(Rxf9Gq!~zc0<`9cO&+tia|U(
z(Yn;S;I*l<i&`VnsWkO12lM3S&(^*;3UFmN`=Ph^D%B*?zE41Bq;}%1S|XKAW;011
zv81c3PULht@sk2MEa*F#TSgZVGw>A?Q+$t+E!U5FnV8rsZ^8l>);f=9b=aF9a9mOH
z+g~W%zvu^&Y>Q><5V@lf?xC3PG{E=Tolxivsz-8QrlCY8-cd%~*RAEA&+=k{f(}Y^
zNaT0JEyYKh+_6?#a0S_@t}<ztk%>C8idNQMYXvrg!tgm6YbyMqktUuUzVN43GC5Kk
zxK#&$IBnBva+8xD?1N=4DPM5W(fsU8zICnyIgYJo^ov1h<_l94r|{8G-GQL)DKk&3
zo*!J;$JozDvaZQ(i@9w_<}i!W_;QEwn1i+}Nv*|<>wyNWa6ZouK;H2f7}XoWQe%cv
z4cJvAr3s~-@*y67Jja_6um@`WUz7u>Oy>eAH;PV7jtvAgJplQRqceCf7?%X$(rBv>
z83v)46&bbCulcTv5Aj?nw5~OdQ}Fr))f1G?9WYliIU$sUo^T5quN3aX-=lCI&X82=
zj9gSIM84iDps<+0wz@QExwQhWNw9gPRz_kg%_#pk7N~Tp*Gr~ZFV%J8b$Wr=t}T8q
ze)}+WGgVe$KwnWw@s{i|(r8}Nzf@6SWBNfP*^+BAJJ+B(HK&x%Z>FbJ)yrFnC$)l6
zH#09(yHJ9&CAq>WT_CYSWSzf>cRU$A=1X&~WV%+e-Y8ccC12C29LbtBNETikcfjB`
zZMC8i#w4%rO4@vJeJb<M%^;-Sgt-}it324ltVo}*9U6qJ;E3EX*>TPRmE>kIn(0=E
z_XG<`zbO7-xl6yGVpYv^+rhXfdVWG!rhdQ~FkZC>0L5YnA6+B2$L|kskUKDklGX-s
zXcVdc0N7~H1uTy>Hc2;OHksdWR&URU+-NIXX-RnDAwnC*w4z$I@KrCh8uYXRpILOx
zmuWDx<g{x;A3@dd$6R8iuAPWTo7L&{BYr}z)V`J~>{N{wm%6HPBporCIVw9n`z7k}
z%GAqN#`o~>%d&Flq}1uq4Q`0bWnC&+RQ5<!9S@aN957qHZT$ULZ$|)t*nfxu;NM;F
z|J<^o%7V0#a$@v02CgQy^#A8z>i<3X9~z<ipEN@EFEm2;uQc+1PQ>|tm*{_WX#WS_
z{2Ly*{*zYw)#;575CDJ|7yv-v|0k{eKauV>)-_6kazhLVJY{v^o^iP5e-b8eD^SCw
z!nIn~$y_3O5^l(D?ig*8$dDl7?`=%Y++4+(tY~gY-!2r^Mt5f1cG*Eourw_oSo+-(
z^J~tJhBE0S<sLsYG;ngTmUY$=Y!O}BJbZ=qR;y&qm*XjqcrfUM)09G@j-fc+Lr&36
z|Jz=ccX_0|Et;KQTvU=2cTQ+o;E7+6QQ~dWH_pGvDQ+_LsB^KtSKq8R53d~TY!DQi
zsvs7BadmUr7I9YFi1qgxemDH8dbYvM&3)>EY<)5AO$l4}{%W0ie__xvt?vnvdk+N|
zFG&4aGIN%g>#ojbWn1sV+;_vI>e(j#xc$rdws^P?zr>XI`-0wE?yDs_nO)+@+%ZY-
zfnedUmdi7=kF1*Zci!WY$)5X~6DH*xdQtMDzA81&>VNY?j$_%*e9!fR&)K0Zu<G~!
z`>zDZs{vwnO5>)WD8C@Js3bGB*!0v!u0sX_3>R$U3oq<Exa7vd3!Y0NUM#UM$o1>I
zVZBpr>Yu%O>-xiak1Uy?aUdq)(A*m#lMQ-i9<(gTE&nn%|6$3#dk5s_m|MRTYyEx9
z?AgLe_orXb-*iiT8oyY#Oi0oOt<6hjgg4K6Bs={}cKvGe%Fdrm0p5&EBFxxRGbfxS
z!0^_Q0okJnZIBRoJ^6fN1(3H9h((Z$SkkDDtj*Wa&(qB{I7H9a4cX#eG>chKEWQXG
z9Kff88%4)w29)6hd>VyOG|Dhy9f!bYfDDQOzSs>wDmrkRq=;ftI{}lRMFwg#m?^b{
z^#BVD6%GalGn8mJMvQTe$t9U(nI)B>C7C(Jum!g0b~JC`@aN=XU|?2&tS&^@v5b{e
zJFweuAWlL|k&S_Ykq>e>CBg<q5n^m8E(Yc&*hmq&;ggxJIo1Omn#2P+fec}Iz7!FL
zJ7=UOXX7$Ebf5lY9U%q=3pI4JtrUncJ0}yj*-N~B_)KMDU|7upS*L<9dy^3nX1io2
z=H#d23G{DG1-5&E;WC#8G8~66f4V6V=DQ;u&4>{!Q$4xWfkr>zL=Tqv*2E<8qEt|f
zVmEu`jakiWfo4DDLQnBRjzpLp1m)pP@qOaHf#E>6&k#jV@xtz;+JPfa9ddi|1eimo
zK<{Bk*sv#nlzWVEcmVyHcZBipgUGn_9o=~Jo4^sqYll*BFF3k2=+`?Vtl1k*-eu3|
zHlSbJi?G2pisWm2(G5qxSq))0V=5W<tf3o^e$y1f_<#(O@0~(79Q_=BgyH_hB%kV!
zZaDgp><GgjmXdrxJG$ZM=Vv1fpIAZiY1-(9qo1OTF#JUo$!98~8;*WDF2eBKS`yF7
zMK>D#6i$TE35}$l$%$?@`gx5AvnMr^bb2GY!RVWX5C-QhByZ~wx((?2CJ;6pT|(Y2
z3UnLLm)#>Jm}TTF!bdkBeK9M-{7<XNS=x$jKKh&;!u;&rB+lUB>v-_PSpp3I|L;AH
zr7MqHvo?z6SD2ddckOW-Y>8s9@d=8$`iOAF*4amdYZoQfK)e3vv54M%McAfxifWzN
V0B=?{kfEAD7zu31|33xd0RVv90Gj{+
--- a/configure.in
+++ b/configure.in
@@ -7067,17 +7067,17 @@ 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 -lmozglue"
     if test -n "$MOZ_OLD_LINKER"; then
         WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=dlopen,--wrap=dlclose,--wrap=dlerror,--wrap=dlsym,--wrap=dladdr"
     fi
     WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=getaddrinfo,--wrap=freeaddrinfo,--wrap=gai_strerror"
-    WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=fork,--wrap=pthread_atfork,--wrap=raise"
+    WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=fork,--wrap=pthread_atfork,--wrap=raise,--wrap=PR_GetEnv,--wrap=PR_SetEnv"
 fi
 
 dnl ========================================================
 dnl = Use malloc wrapper lib
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(wrap-malloc,
 [  --enable-wrap-malloc    Wrap malloc calls (gnu linker only)],
     _WRAP_MALLOC=1,
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1865,16 +1865,17 @@ public:
    * nsEventStateManager::IsHandlingUserInput() stops returning true.
    * This enables us to detect long running user-generated event handlers.
    */
   static TimeDuration HandlingUserInputTimeout();
 
   static void GetShiftText(nsAString& text);
   static void GetControlText(nsAString& text);
   static void GetMetaText(nsAString& text);
+  static void GetOSText(nsAString& text);
   static void GetAltText(nsAString& text);
   static void GetModifierSeparatorText(nsAString& text);
 
   /**
    * Returns if aContent has a tabbable subdocument.
    * A sub document isn't tabbable when it's a zombie document.
    *
    * @param aElement element to test.
@@ -2169,16 +2170,17 @@ private:
   /**
    * True if there's a fragment parser activation on the stack.
    */
   static bool sFragmentParsingActive;
 
   static nsString* sShiftText;
   static nsString* sControlText;
   static nsString* sMetaText;
+  static nsString* sOSText;
   static nsString* sAltText;
   static nsString* sModifierSeparator;
 };
 
 typedef nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
                                                     HTMLSplitOnSpacesTokenizer;
 
 #define NS_HOLD_JS_OBJECTS(obj, clazz)                                         \
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -14,17 +14,16 @@
 #include "nsILoadGroup.h"
 #include "nsCRT.h"
 #include "mozFlushType.h"
 #include "nsIAtom.h"
 #include "nsCompatibility.h"
 #include "nsTObserverArray.h"
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
-#include "nsNodeInfoManager.h"
 #include "nsIVariant.h"
 #include "nsIObserver.h"
 #include "nsGkAtoms.h"
 #include "nsAutoPtr.h"
 #include "nsPIDOMWindow.h"
 #include "nsSMILAnimationController.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIDocumentEncoder.h"
@@ -121,38 +120,19 @@ class nsIDocument : public nsINode
 {
 public:
   typedef mozilla::dom::Element Element;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_IID)
   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
 
 #ifdef MOZILLA_INTERNAL_API
-  nsIDocument()
-    : nsINode(nsnull),
-      mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
-      mNodeInfoManager(nsnull),
-      mCompatMode(eCompatibility_FullStandards),
-      mIsInitialDocumentInWindow(false),
-      mMayStartLayout(true),
-      mVisible(true),
-      mRemovedFromDocShell(false),
-      // mAllowDNSPrefetch starts true, so that we can always reliably && it
-      // with various values that might disable it.  Since we never prefetch
-      // unless we get a window, and in that case the docshell value will get
-      // &&-ed in, this is safe.
-      mAllowDNSPrefetch(true),
-      mIsBeingUsedAsImage(false),
-      mHasLinksToUpdate(false),
-      mPartID(0)
-  {
-    SetInDocument();
-  }
+  nsIDocument();
 #endif
-  
+
   /**
    * Let the document know that we're starting to load data into it.
    * @param aCommand The parser command. Must not be null.
    *                 XXXbz It's odd to have that here.
    * @param aChannel The channel the data will come from. The channel must be
    *                 able to report its Content-Type.
    * @param aLoadGroup The loadgroup this document should use from now on.
    *                   Note that the document might not be the only thing using
@@ -1200,16 +1180,21 @@ public:
     return mMarkedCCGeneration;
   }
 
   bool IsLoadedAsData()
   {
     return mLoadedAsData;
   }
 
+  bool IsLoadedAsInteractiveData()
+  {
+    return mLoadedAsInteractiveData;
+  }
+
   bool MayStartLayout()
   {
     return mMayStartLayout;
   }
 
   void SetMayStartLayout(bool aMayStartLayout)
   {
     mMayStartLayout = aMayStartLayout;
@@ -1678,24 +1663,17 @@ public:
       --mInSyncOperationCount;
     }
   }
 
 private:
   PRUint64 mWarnedAbout;
 
 protected:
-  ~nsIDocument()
-  {
-    // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
-    //     releasing it) happens in the nsDocument destructor. We'd prefer to
-    //     do it here but nsNodeInfoManager is a concrete class that we don't
-    //     want to expose to users of the nsIDocument API outside of Gecko.
-  }
-
+  ~nsIDocument();
   nsPropertyTable* GetExtraPropertyTable(PRUint16 aCategory);
 
   // Never ever call this. Only call GetWindow!
   virtual nsPIDOMWindow *GetWindowInternal() const = 0;
 
   // Never ever call this. Only call GetInnerWindow!
   virtual nsPIDOMWindow *GetInnerWindowInternal() = 0;
 
@@ -1742,29 +1720,27 @@ protected:
   PRInt32 mCharacterSetSource;
 
   // This is just a weak pointer; the parent document owns its children.
   nsIDocument* mParentDocument;
 
   // A reference to the element last returned from GetRootElement().
   mozilla::dom::Element* mCachedRootElement;
 
-  // We'd like these to be nsRefPtrs, but that'd require us to include
-  // additional headers that we don't want to expose.
-  // The cleanup is handled by the nsDocument destructor.
+  // We hold a strong reference to mNodeInfoManager through mNodeInfo
   nsNodeInfoManager* mNodeInfoManager; // [STRONG]
-  mozilla::css::Loader* mCSSLoader; // [STRONG]
+  nsRefPtr<mozilla::css::Loader> mCSSLoader;
   nsHTMLStyleSheet* mAttrStyleSheet;
 
   // The set of all object, embed, applet, video and audio elements for
   // which this is the owner document. (They might not be in the document.)
   // These are non-owning pointers, the elements are responsible for removing
   // themselves when they go away.
   nsAutoPtr<nsTHashtable<nsPtrHashKey<nsIContent> > > mFreezableElements;
-  
+
   // The set of all links that need their status resolved.  Links must add themselves
   // to this set by calling RegisterPendingLinkUpdate when added to a document and must
   // remove themselves by calling UnregisterPendingLinkUpdate when removed from a document.
   nsTHashtable<nsPtrHashKey<mozilla::dom::Link> > mLinksToUpdate;
 
   // SMIL Animation Controller, lazily-initialized in GetAnimationController
   nsRefPtr<nsSMILAnimationController> mAnimationController;
 
@@ -1794,16 +1770,21 @@ protected:
     eTriFalse,
     eTriTrue
   } mAllowXULXBL;
 
   // True if we're loaded as data and therefor has any dangerous stuff, such
   // as scripts and plugins, disabled.
   bool mLoadedAsData;
 
+  // This flag is only set in nsXMLDocument, for e.g. documents used in XBL. We
+  // don't want animations to play in such documents, so we need to store the
+  // flag here so that we can check it in nsDocument::GetAnimationController.
+  bool mLoadedAsInteractiveData;
+
   // If true, whoever is creating the document has gotten it to the
   // point where it's safe to start layout on it.
   bool mMayStartLayout;
   
   // True iff we've ever fired a DOMTitleChanged event for this document
   bool mHaveFiredTitleChange;
 
   // True iff IsShowing() should be returning true
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -211,16 +211,17 @@ PRUint32 nsContentUtils::sRunnersCountAt
 nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nsnull;
 
 bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
 bool nsContentUtils::sAllowXULXBL_for_file = false;
 
 nsString* nsContentUtils::sShiftText = nsnull;
 nsString* nsContentUtils::sControlText = nsnull;
 nsString* nsContentUtils::sMetaText = nsnull;
+nsString* nsContentUtils::sOSText = nsnull;
 nsString* nsContentUtils::sAltText = nsnull;
 nsString* nsContentUtils::sModifierSeparator = nsnull;
 
 bool nsContentUtils::sInitialized = false;
 bool nsContentUtils::sIsFullScreenApiEnabled = false;
 bool nsContentUtils::sTrustedFullScreenOnly = true;
 bool nsContentUtils::sIsIdleObserverAPIEnabled = false;
 
@@ -431,16 +432,25 @@ void
 nsContentUtils::GetMetaText(nsAString& text)
 {
   if (!sMetaText)
     InitializeModifierStrings();
   text.Assign(*sMetaText);
 }
 
 void
+nsContentUtils::GetOSText(nsAString& text)
+{
+  if (!sOSText) {
+    InitializeModifierStrings();
+  }
+  text.Assign(*sOSText);
+}
+
+void
 nsContentUtils::GetAltText(nsAString& text)
 {
   if (!sAltText)
     InitializeModifierStrings();
   text.Assign(*sAltText);
 }
 
 void
@@ -462,30 +472,33 @@ nsContentUtils::InitializeModifierString
   if (bundleService) {
     rv = bundleService->CreateBundle( "chrome://global-platform/locale/platformKeys.properties",
                                       getter_AddRefs(bundle));
   }
   
   NS_ASSERTION(NS_SUCCEEDED(rv) && bundle, "chrome://global/locale/platformKeys.properties could not be loaded");
   nsXPIDLString shiftModifier;
   nsXPIDLString metaModifier;
+  nsXPIDLString osModifier;
   nsXPIDLString altModifier;
   nsXPIDLString controlModifier;
   nsXPIDLString modifierSeparator;
   if (bundle) {
     //macs use symbols for each modifier key, so fetch each from the bundle, which also covers i18n
     bundle->GetStringFromName(NS_LITERAL_STRING("VK_SHIFT").get(), getter_Copies(shiftModifier));
     bundle->GetStringFromName(NS_LITERAL_STRING("VK_META").get(), getter_Copies(metaModifier));
+    bundle->GetStringFromName(NS_LITERAL_STRING("VK_WIN").get(), getter_Copies(osModifier));
     bundle->GetStringFromName(NS_LITERAL_STRING("VK_ALT").get(), getter_Copies(altModifier));
     bundle->GetStringFromName(NS_LITERAL_STRING("VK_CONTROL").get(), getter_Copies(controlModifier));
     bundle->GetStringFromName(NS_LITERAL_STRING("MODIFIER_SEPARATOR").get(), getter_Copies(modifierSeparator));
   }
   //if any of these don't exist, we get  an empty string
   sShiftText = new nsString(shiftModifier);
   sMetaText = new nsString(metaModifier);
+  sOSText = new nsString(osModifier);
   sAltText = new nsString(altModifier);
   sControlText = new nsString(controlModifier);
   sModifierSeparator = new nsString(modifierSeparator);  
 }
 
 bool nsContentUtils::sImgLoaderInitialized;
 
 void
@@ -1448,16 +1461,18 @@ nsContentUtils::Shutdown()
   sBlockedScriptRunners = nsnull;
 
   delete sShiftText;
   sShiftText = nsnull;
   delete sControlText;  
   sControlText = nsnull;
   delete sMetaText;  
   sMetaText = nsnull;
+  delete sOSText;
+  sOSText = nsnull;
   delete sAltText;  
   sAltText = nsnull;
   delete sModifierSeparator;
   sModifierSeparator = nsnull;
 
   NS_IF_RELEASE(sSameOriginChecker);
   
   nsTextEditorState::ShutDown();
@@ -2769,38 +2784,30 @@ bool
 nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
   nsCOMPtr<nsIURI> absURI;
   return aContent->IsLink(getter_AddRefs(absURI));
 }
 
 static bool
 TestSitePerm(nsIPrincipal* aPrincipal, const char* aType, PRUint32 aPerm)
 {
-  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
-    // System principal is always allowed and never denied permission.
-    return aPerm == nsIPermissionManager::ALLOW_ACTION;
-  }
-
-  nsCOMPtr<nsIURI> uri;
-  if (NS_FAILED(!aPrincipal ||
-      aPrincipal->GetURI(getter_AddRefs(uri))) ||
-      !uri) {
-    // We always deny (i.e. don't allow) the permission if we don't
-    // have a principal or we don't know the URI.
+  if (!aPrincipal) {
+    // We always deny (i.e. don't allow) the permission if we don't have a
+    // principal.
     return aPerm != nsIPermissionManager::ALLOW_ACTION;
   }
 
   nsCOMPtr<nsIPermissionManager> permMgr =
     do_GetService("@mozilla.org/permissionmanager;1");
   NS_ENSURE_TRUE(permMgr, false);
 
   PRUint32 perm;
-  nsresult rv = permMgr->TestPermission(uri, aType, &perm);
+  nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
   NS_ENSURE_SUCCESS(rv, false);
-  
+
   return perm == aPerm;
 }
 
 bool
 nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal, const char* aType)
 {
   return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION);
 }
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1489,54 +1489,82 @@ nsDOMImplementation::CreateHTMLDocument(
   document.forget(aReturn);
 
   return NS_OK;
 }
 
 // ==================================================================
 // =
 // ==================================================================
-
-  // NOTE! nsDocument::operator new() zeroes out all members, so don't
-  // bother initializing members to 0.
+nsIDocument::nsIDocument()
+  : nsINode(nsnull),
+    mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
+    mNodeInfoManager(nsnull),
+    mCompatMode(eCompatibility_FullStandards),
+    mIsInitialDocumentInWindow(false),
+    mMayStartLayout(true),
+    mVisible(true),
+    mRemovedFromDocShell(false),
+    // mAllowDNSPrefetch starts true, so that we can always reliably && it
+    // with various values that might disable it.  Since we never prefetch
+    // unless we get a window, and in that case the docshell value will get
+    // &&-ed in, this is safe.
+    mAllowDNSPrefetch(true),
+    mIsBeingUsedAsImage(false),
+    mHasLinksToUpdate(false),
+    mPartID(0)
+{
+  SetInDocument();
+}
+
+// NOTE! nsDocument::operator new() zeroes out all members, so don't
+// bother initializing members to 0.
 
 nsDocument::nsDocument(const char* aContentType)
   : nsIDocument()
   , mAnimatingImages(true)
   , mVisibilityState(eHidden)
 {
   SetContentTypeInternal(nsDependentCString(aContentType));
-  
+
 #ifdef PR_LOGGING
   if (!gDocumentLeakPRLog)
     gDocumentLeakPRLog = PR_NewLogModule("DocumentLeak");
 
   if (gDocumentLeakPRLog)
     PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG,
            ("DOCUMENT %p created", this));
 
   if (!gCspPRLog)
     gCspPRLog = PR_NewLogModule("CSP");
 #endif
 
   // Start out mLastStyleSheetSet as null, per spec
   SetDOMStringToNull(mLastStyleSheetSet);
-  
+
   mLinksToUpdate.Init();
 }
 
 static PLDHashOperator
 ClearAllBoxObjects(nsIContent* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
 {
   if (aBoxObject) {
     aBoxObject->Clear();
   }
   return PL_DHASH_NEXT;
 }
 
+nsIDocument::~nsIDocument()
+{
+  if (mNodeInfoManager) {
+    mNodeInfoManager->DropDocumentReference();
+  }
+}
+
+
 nsDocument::~nsDocument()
 {
 #ifdef PR_LOGGING
   if (gDocumentLeakPRLog)
     PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG,
            ("DOCUMENT %p destroyed", this));
 #endif
 
@@ -1608,22 +1636,16 @@ nsDocument::~nsDocument()
 
   if (mScriptLoader) {
     mScriptLoader->DropDocumentReference();
   }
 
   if (mCSSLoader) {
     // Could be null here if Init() failed
     mCSSLoader->DropDocumentReference();
-    NS_RELEASE(mCSSLoader);
-  }
-
-  // XXX Ideally we'd do this cleanup in the nsIDocument destructor.
-  if (mNodeInfoManager) {
-    mNodeInfoManager->DropDocumentReference();
   }
 
   delete mHeaderData;
 
   if (mBoxObjectTable) {
     mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nsnull);
     delete mBoxObjectTable;
   }
@@ -1905,17 +1927,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImageMaps)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedEncoder)
 
   tmp->mParentDocument = nsnull;
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPreloadingImages)
 
-  
+
   if (tmp->mBoxObjectTable) {
    tmp->mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nsnull);
    delete tmp->mBoxObjectTable;
    tmp->mBoxObjectTable = nsnull;
  }
 
   if (tmp->mListenerManager) {
     tmp->mListenerManager->Disconnect();
@@ -1926,29 +1948,29 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   if (tmp->mSubDocuments) {
     PL_DHashTableDestroy(tmp->mSubDocuments);
     tmp->mSubDocuments = nsnull;
   }
 
   tmp->mFrameRequestCallbacks.Clear();
 
   tmp->mRadioGroups.Clear();
-  
+
   // nsDocument has a pretty complex destructor, so we're going to
   // assume that *most* cycles you actually want to break somewhere
   // else, and not unlink an awful lot here.
 
   tmp->mIdentifierMap.Clear();
 
   if (tmp->mAnimationController) {
     tmp->mAnimationController->Unlink();
   }
 
   tmp->mPendingTitleChangeEvent.Revoke();
-  
+
   tmp->mInUnlinkOrDeletion = false;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 nsresult
 nsDocument::Init()
 {
   if (mCSSLoader || mNodeInfoManager || mScriptLoader) {
@@ -1956,59 +1978,51 @@ nsDocument::Init()
   }
 
   mIdentifierMap.Init();
   mStyledLinks.Init();
   mRadioGroups.Init();
 
   // Force initialization.
   nsINode::nsSlots* slots = GetSlots();
-  NS_ENSURE_TRUE(slots,NS_ERROR_OUT_OF_MEMORY);
 
   // Prepend self as mutation-observer whether we need it or not (some
   // subclasses currently do, other don't). This is because the code in
   // nsNodeUtils always notifies the first observer first, expecting the
   // first observer to be the document.
   NS_ENSURE_TRUE(slots->mMutationObservers.PrependElementUnlessExists(static_cast<nsIMutationObserver*>(this)),
                  NS_ERROR_OUT_OF_MEMORY);
 
 
   mOnloadBlocker = new nsOnloadBlocker();
-  NS_ENSURE_TRUE(mOnloadBlocker, NS_ERROR_OUT_OF_MEMORY);
-
   mCSSLoader = new mozilla::css::Loader(this);
-  NS_ENSURE_TRUE(mCSSLoader, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(mCSSLoader);
   // Assume we're not quirky, until we know otherwise
   mCSSLoader->SetCompatibilityMode(eCompatibility_FullStandards);
 
   mNodeInfoManager = new nsNodeInfoManager();
-  NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);
-
   nsresult  rv = mNodeInfoManager->Init(this);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // mNodeInfo keeps NodeInfoManager alive!
   mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo();
   NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY);
   NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
                     "Bad NodeType in aNodeInfo");
 
   NS_ASSERTION(OwnerDoc() == this, "Our nodeinfo is busted!");
 
   mScriptLoader = new nsScriptLoader(this);
-  NS_ENSURE_TRUE(mScriptLoader, NS_ERROR_OUT_OF_MEMORY);
 
   mImageTracker.Init();
   mPlugins.Init();
 
   return NS_OK;
 }
 
-void 
+void
 nsIDocument::DeleteAllProperties()
 {
   for (PRUint32 i = 0; i < GetPropertyTableCount(); ++i) {
     PropertyTable(i)->DeleteAllProperties();
   }
 }
 
 void
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1168,21 +1168,16 @@ protected:
   bool mSynchronousDOMContentLoaded:1;
 
   // If true, we have an input encoding.  If this is false, then the
   // document was created entirely in memory
   bool mHaveInputEncoding:1;
 
   bool mInXBLUpdate:1;
 
-  // This flag is only set in nsXMLDocument, for e.g. documents used in XBL. We
-  // don't want animations to play in such documents, so we need to store the
-  // flag here so that we can check it in nsDocument::GetAnimationController.
-  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.
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -14,19 +14,19 @@
 #include "nsIDocShell.h"
 #include "nsStringFwd.h"
 #include "nsIFrameLoader.h"
 #include "nsPoint.h"
 #include "nsSize.h"
 #include "nsIURI.h"
 #include "nsAutoPtr.h"
 #include "nsFrameMessageManager.h"
-#include "Layers.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Attributes.h"
+#include "Layers.h"
 
 class nsIURI;
 class nsSubDocumentFrame;
 class nsIView;
 class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
 class nsITabParent;
 
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1531,39 +1531,30 @@ nsGenericElement::GetTagName(nsAString& 
   aTagName = NodeName();
   return NS_OK;
 }
 
 nsresult
 nsGenericElement::GetAttribute(const nsAString& aName,
                                nsAString& aReturn)
 {
-  // I hate XUL
-  if (IsXUL()) {
-    const nsAttrValue* val =
-      nsXULElement::FromContent(this)->GetAttrValue(aName);
-    if (val) {
-      val->ToString(aReturn);
-    }
-    else {
-      // XXX should be SetDOMStringToNull(aReturn);
-      // See bug 232598
-      aReturn.Truncate();
-    }
-    return NS_OK;
-  }
-  
   const nsAttrValue* val =
     mAttrsAndChildren.GetAttr(aName,
                               IsHTML() && IsInHTMLDocument() ?
                                 eIgnoreCase : eCaseMatters);
   if (val) {
     val->ToString(aReturn);
   } else {
-    SetDOMStringToNull(aReturn);
+    if (IsXUL()) {
+      // XXX should be SetDOMStringToNull(aReturn);
+      // See bug 232598
+      aReturn.Truncate();
+    } else {
+      SetDOMStringToNull(aReturn);
+    }
   }
 
   return NS_OK;
 }
 
 nsresult
 nsGenericElement::SetAttribute(const nsAString& aName,
                                const nsAString& aValue)
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -570,18 +570,17 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
   // precondition in nsXULElement::UnbindFromTree and remove the line in
   // nsXULElement.h that makes nsNodeUtils a friend of nsXULElement.
   // Note: Make sure to do this witchery _after_ we've done any deep
   // cloning, so kids of the new node aren't confused about whether they're
   // in a document.
 #ifdef MOZ_XUL
   if (aClone && !aParent && aNode->IsElement() &&
       aNode->AsElement()->IsXUL()) {
-    nsXULElement *xulElem = static_cast<nsXULElement*>(elem);
-    if (!xulElem->mPrototype || xulElem->IsInDoc()) {
+    if (!aNode->OwnerDoc()->IsLoadedAsInteractiveData()) {
       clone->SetFlags(NODE_FORCE_XBL_BINDINGS);
     }
   }
 #endif
 
   if (aNode->HasProperties()) {
     bool ok = aNodesWithProperties.AppendObject(aNode);
     if (aClone) {
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -188,25 +188,16 @@ nsStyledElementNotElementCSSInlineStyle:
 }
 
 // ---------------------------------------------------------------
 // Others and helpers
 
 nsIDOMCSSStyleDeclaration*
 nsStyledElementNotElementCSSInlineStyle::GetStyle(nsresult* retval)
 {
-  nsXULElement* xulElement = nsXULElement::FromContent(this);
-  if (xulElement) {
-    nsresult rv = xulElement->EnsureLocalStyle();
-    if (NS_FAILED(rv)) {
-      *retval = rv;
-      return nsnull;
-    }
-  }
-    
   nsGenericElement::nsDOMSlots *slots = DOMSlots();
 
   if (!slots->mStyle) {
     // Just in case...
     ReparseStyleAttribute(true);
 
     slots->mStyle = new nsDOMCSSAttributeDeclaration(this, false);
     SetMayHaveStyle();
new file mode 100644
--- /dev/null
+++ b/content/canvas/crashtests/767337-1.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="c" width="500" height="1000">
+</canvas>
+<script>
+var ctxt = document.getElementById('c').getContext('2d');
+for (var k = 0; k < 100; ++j) {
+  for (var j = 0; j < 10; ++j) {
+    for (var i = 0; i < 1000; ++i) {
+      gradient = ctxt.createLinearGradient(0,0,200,i);
+      gradient.addColorStop(0,'black');
+      gradient.addColorStop(1,'rgba(0, 255*k/100, 0, 0.1)');
+      ctxt.fillStyle = gradient;
+      ctxt.fillRect(j*50, 2*i, 50, 2);
+    }
+  }
+}
+</script>
+</body>
+</html>
\ No newline at end of file
--- a/content/canvas/crashtests/crashtests.list
+++ b/content/canvas/crashtests/crashtests.list
@@ -5,8 +5,9 @@ load 647480.html
 load 0px-size-font-667225.html
 load texImage2D.html
 load 729116.html
 load 745699-1.html
 load 746813-1.html
 # this test crashes in a bunch places still
 #load 745818-large-source.html
 load 743499-negative-size.html
+load 767337-1.html
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -20,17 +20,16 @@
 #include "nsHTMLCanvasElement.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIMemoryReporter.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsWrapperCache.h"
 #include "nsIObserver.h"
 
 #include "GLContextProvider.h"
-#include "Layers.h"
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/ImageData.h"
 
 #ifdef XP_MACOSX
 #include "ForceDiscreteGPUHelperCGL.h"
 #endif
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -35,17 +35,16 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsDOMError.h"
 #include "nsIJSContextStack.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsMutationEvent.h"
 #include "nsIXPConnect.h"
 #include "nsDOMCID.h"
-#include "nsIScriptEventHandlerOwner.h"
 #include "nsFocusManager.h"
 #include "nsIDOMElement.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsContentCID.h"
 #include "nsEventDispatcher.h"
 #include "nsDOMJSUtils.h"
 #include "nsDOMScriptObjectHolder.h"
@@ -657,31 +656,18 @@ nsEventListenerManager::CompileEventHand
                   "Why are we compiling a non-string JS listener?");
 
   nsresult result = NS_OK;
 
   nsIJSEventListener *listener = aListenerStruct->GetJSListener();
   NS_ASSERTION(!listener->GetHandler(), "What is there to compile?");
 
   nsIScriptContext *context = listener->GetEventContext();
-  nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =
-    do_QueryInterface(mTarget);
   nsScriptObjectHolder<JSObject> handler(context);
 
-  if (handlerOwner) {
-    result = handlerOwner->GetCompiledEventHandler(aListenerStruct->mTypeAtom,
-                                                   handler);
-    if (NS_SUCCEEDED(result) && handler) {
-      aListenerStruct->mHandlerIsString = false;
-    } else {
-      // Make sure there's nothing in the holder in the failure case
-      handler.set(nsnull);
-    }
-  }
-
   if (aListenerStruct->mHandlerIsString) {
     // OK, we didn't find an existing compiled event handler.  Flag us
     // as not a string so we don't keep trying to compile strings
     // which can't be compiled
     aListenerStruct->mHandlerIsString = false;
 
     // mTarget may not be an nsIContent if it's a window and we're
     // getting an inline event listener forwarded from <html:body> or
@@ -740,51 +726,39 @@ nsEventListenerManager::CompileEventHand
       }
     }
 
     nsCxPusher pusher;
     if (aNeedsCxPush && !pusher.Push(context->GetNativeContext())) {
       return NS_ERROR_FAILURE;
     }
 
+    PRUint32 argCount;
+    const char **argNames;
+    // If no content, then just use kNameSpaceID_None for the
+    // namespace ID.  In practice, it doesn't matter since SVG is
+    // the only thing with weird arg names and SVG doesn't map event
+    // listeners to the window.
+    nsContentUtils::GetEventArgNames(content ?
+                                       content->GetNameSpaceID() :
+                                       kNameSpaceID_None,
+                                     aListenerStruct->mTypeAtom,
+                                     &argCount, &argNames);
 
-    if (handlerOwner) {
-      // Always let the handler owner compile the event
-      // handler, as it may want to use a special
-      // context or scope object.
-      result = handlerOwner->CompileEventHandler(context,
-                                                 aListenerStruct->mTypeAtom,
-                                                 *body,
-                                                 url.get(), lineNo,
-                                                 handler);
-    } else {
-      PRUint32 argCount;
-      const char **argNames;
-      // If no content, then just use kNameSpaceID_None for the
-      // namespace ID.  In practice, it doesn't matter since SVG is
-      // the only thing with weird arg names and SVG doesn't map event
-      // listeners to the window.
-      nsContentUtils::GetEventArgNames(content ?
-                                         content->GetNameSpaceID() :
-                                         kNameSpaceID_None,
-                                       aListenerStruct->mTypeAtom,
-                                       &argCount, &argNames);
-
-      result = context->CompileEventHandler(aListenerStruct->mTypeAtom,
-                                            argCount, argNames,
-                                            *body,
-                                            url.get(), lineNo,
-                                            SCRIPTVERSION_DEFAULT, // for now?
-                                            handler);
-      if (result == NS_ERROR_ILLEGAL_VALUE) {
-        NS_WARNING("Probably a syntax error in the event handler!");
-        return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
-      }
-      NS_ENSURE_SUCCESS(result, result);
+    result = context->CompileEventHandler(aListenerStruct->mTypeAtom,
+                                          argCount, argNames,
+                                          *body,
+                                          url.get(), lineNo,
+                                          SCRIPTVERSION_DEFAULT, // for now?
+                                          handler);
+    if (result == NS_ERROR_ILLEGAL_VALUE) {
+      NS_WARNING("Probably a syntax error in the event handler!");
+      return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
     }
+    NS_ENSURE_SUCCESS(result, result);
   }
 
   if (handler) {
     // Bind it
     nsScriptObjectHolder<JSObject> boundHandler(context);
     context->BindCompiledEventHandler(mTarget, listener->GetEventScope(),
                                       handler.get(), boundHandler);
     listener->SetHandler(boundHandler.get());
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -261,16 +261,17 @@ enum {
  MOUSE_SCROLL_PIXELS
 };
 
 // mask values for ui.key.chromeAccess and ui.key.contentAccess
 #define NS_MODIFIER_SHIFT    1
 #define NS_MODIFIER_CONTROL  2
 #define NS_MODIFIER_ALT      4
 #define NS_MODIFIER_META     8
+#define NS_MODIFIER_OS       16
 
 static nsIDocument *
 GetDocumentFromWindow(nsIDOMWindow *aWindow)
 {
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aWindow);
   nsCOMPtr<nsIDocument> doc;
 
   if (win) {
@@ -285,16 +286,17 @@ GetAccessModifierMaskFromPref(PRInt32 aI
 {
   PRInt32 accessKey = Preferences::GetInt("ui.key.generalAccessKey", -1);
   switch (accessKey) {
     case -1:                             break; // use the individual prefs
     case nsIDOMKeyEvent::DOM_VK_SHIFT:   return NS_MODIFIER_SHIFT;
     case nsIDOMKeyEvent::DOM_VK_CONTROL: return NS_MODIFIER_CONTROL;
     case nsIDOMKeyEvent::DOM_VK_ALT:     return NS_MODIFIER_ALT;
     case nsIDOMKeyEvent::DOM_VK_META:    return NS_MODIFIER_META;
+    case nsIDOMKeyEvent::DOM_VK_WIN:     return NS_MODIFIER_OS;
     default:                             return 0;
   }
 
   switch (aItemType) {
   case nsIDocShellTreeItem::typeChrome:
     return Preferences::GetInt("ui.key.chromeAccess", 0);
   case nsIDocShellTreeItem::typeContent:
     return Preferences::GetInt("ui.key.contentAccess", 0);
@@ -1162,16 +1164,18 @@ nsEventStateManager::PreHandleEvent(nsPr
       if (keyEvent->IsShift())
         modifierMask |= NS_MODIFIER_SHIFT;
       if (keyEvent->IsControl())
         modifierMask |= NS_MODIFIER_CONTROL;
       if (keyEvent->IsAlt())
         modifierMask |= NS_MODIFIER_ALT;
       if (keyEvent->IsMeta())
         modifierMask |= NS_MODIFIER_META;
+      if (keyEvent->IsOS())
+        modifierMask |= NS_MODIFIER_OS;
 
       // Prevent keyboard scrolling while an accesskey modifier is in use.
       if (modifierMask && (modifierMask == sChromeAccessModifier ||
                            modifierMask == sContentAccessModifier))
         HandleAccessKey(aPresContext, keyEvent, aStatus, nsnull,
                         eAccessKeyProcessingNormal, modifierMask);
     }
     // then fall through...
@@ -1519,16 +1523,20 @@ nsEventStateManager::GetAccessKeyLabelPr
   if (modifier & NS_MODIFIER_CONTROL) {
     nsContentUtils::GetControlText(modifierText);
     aPrefix.Append(modifierText + separator);
   }
   if (modifier & NS_MODIFIER_META) {
     nsContentUtils::GetMetaText(modifierText);
     aPrefix.Append(modifierText + separator);
   }
+  if (modifier & NS_MODIFIER_OS) {
+    nsContentUtils::GetOSText(modifierText);
+    aPrefix.Append(modifierText + separator);
+  }
   if (modifier & NS_MODIFIER_ALT) {
     nsContentUtils::GetAltText(modifierText);
     aPrefix.Append(modifierText + separator);
   }
   if (modifier & NS_MODIFIER_SHIFT) {
     nsContentUtils::GetShiftText(modifierText);
     aPrefix.Append(modifierText + separator);
   }
@@ -1632,20 +1640,19 @@ nsEventStateManager::HandleAccessKey(nsP
         esm->HandleAccessKey(parentPC, aEvent, aStatus, docShell,
                              eAccessKeyProcessingUp, aModifierMask);
     }
   }// if end. bubble up process
 }// end of HandleAccessKey
 
 bool
 nsEventStateManager::DispatchCrossProcessEvent(nsEvent* aEvent,
-                                               nsIFrameLoader* aFrameLoader,
+                                               nsFrameLoader* aFrameLoader,
                                                nsEventStatus *aStatus) {
-  nsFrameLoader* fml = static_cast<nsFrameLoader*>(aFrameLoader);
-  PBrowserParent* remoteBrowser = fml->GetRemoteBrowser();
+  PBrowserParent* remoteBrowser = aFrameLoader->GetRemoteBrowser();
   TabParent* remote = static_cast<TabParent*>(remoteBrowser);
   if (!remote) {
     return false;
   }
 
   switch (aEvent->eventStructType) {
   case NS_MOUSE_EVENT: {
     nsMouseEvent* mouseEvent = static_cast<nsMouseEvent*>(aEvent);
@@ -1783,39 +1790,67 @@ nsEventStateManager::HandleCrossProcessE
       }
       nsCOMPtr<nsIContent> target = do_QueryInterface(targetPtr);
       if (IsRemoteTarget(target) && !targets.Contains(target)) {
         targets.AppendElement(target);
       }
     }
   }
 
+  if (targets.Length() == 0) {
+    return false;
+  }
+
   // Look up the frame loader for all the remote targets we found, and
   // then dispatch the event to the remote content they represent.
   bool dispatched = false;
   for (PRUint32 i = 0; i < targets.Length(); ++i) {
     nsIContent* target = targets[i];
     nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(target);
     if (!loaderOwner) {
-      return false;
+      continue;
     }
 
     nsRefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader();
     if (!frameLoader) {
-      return false;
+      continue;
     }
 
     PRUint32 eventMode;
     frameLoader->GetEventMode(&eventMode);
     if (eventMode == nsIFrameLoader::EVENT_MODE_DONT_FORWARD_TO_CHILD) {
-      return false;
+      continue;
     }
 
-    nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, aTargetFrame);
-    aEvent->refPoint = pt.ToNearestPixels(mPresContext->AppUnitsPerDevPixel());
+    // The "toplevel widget" in content processes is always at position
+    // 0,0.  Map the event coordinates to match that.
+    if (aEvent->eventStructType != NS_TOUCH_EVENT) {
+      nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
+                                                                aTargetFrame);
+      aEvent->refPoint =
+        pt.ToNearestPixels(mPresContext->AppUnitsPerDevPixel());
+    } else {
+      nsIFrame* targetFrame = frameLoader->GetPrimaryFrameOfOwningContent();
+      aEvent->refPoint = nsIntPoint();
+      // Find out how far we're offset from the nearest widget.
+      nsPoint offset =
+        nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, targetFrame);
+      nsIntPoint intOffset =
+        offset.ToNearestPixels(mPresContext->AppUnitsPerDevPixel());
+      nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
+      // Then offset all the touch points by that distance, to put them
+      // in the space where top-left is 0,0.
+      const nsTArray<nsCOMPtr<nsIDOMTouch> >& touches = touchEvent->touches;
+      for (PRUint32 i = 0; i < touches.Length(); ++i) {
+        nsIDOMTouch* touch = touches[i];
+        if (touch) {
+          touch->mRefPoint += intOffset;
+        }
+      }
+    }
 
     dispatched |= DispatchCrossProcessEvent(aEvent, frameLoader, aStatus);
   }
   return dispatched;
 }
 
 //
 // CreateClickHoldTimer
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -442,17 +442,17 @@ protected:
   void DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
                                nsIFrame* aTargetFrame);
   void DoQuerySelectedText(nsQueryContentEvent* aEvent);
 
   bool RemoteQueryContentEvent(nsEvent *aEvent);
   mozilla::dom::TabParent *GetCrossProcessTarget();
   bool IsTargetCrossProcess(nsGUIEvent *aEvent);
 
-  bool DispatchCrossProcessEvent(nsEvent* aEvent, nsIFrameLoader* remote,
+  bool DispatchCrossProcessEvent(nsEvent* aEvent, nsFrameLoader* remote,
                                  nsEventStatus *aStatus);
   bool HandleCrossProcessEvent(nsEvent *aEvent,
                                  nsIFrame* aTargetFrame,
                                  nsEventStatus *aStatus);
 
 private:
   static inline void DoStateChange(mozilla::dom::Element* aElement,
                                    nsEventStates aState, bool aAddState);
--- a/content/media/gstreamer/nsGStreamerReader.cpp
+++ b/content/media/gstreamer/nsGStreamerReader.cpp
@@ -125,18 +125,23 @@ nsresult nsGStreamerReader::Init(nsBuilt
   gst_app_sink_set_callbacks(mVideoAppSink, &mSinkCallbacks,
       (gpointer) this, NULL);
   GstPad *sinkpad = gst_element_get_pad(GST_ELEMENT(mVideoAppSink), "sink");
   gst_pad_add_event_probe(sinkpad,
       G_CALLBACK(&nsGStreamerReader::EventProbeCb), this);
   gst_object_unref(sinkpad);
 
   mAudioSink = gst_parse_bin_from_description("capsfilter name=filter ! "
+#ifdef MOZ_SAMPLE_TYPE_FLOAT32
         "appsink name=audiosink sync=true caps=audio/x-raw-float,"
         "channels={1,2},rate=44100,width=32,endianness=1234", TRUE, NULL);
+#else
+        "appsink name=audiosink sync=true caps=audio/x-raw-int,"
+        "channels={1,2},rate=48000,width=16,endianness=1234", TRUE, NULL);
+#endif
   mAudioAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mAudioSink),
         "audiosink"));
   gst_app_sink_set_callbacks(mAudioAppSink, &mSinkCallbacks,
       (gpointer) this, NULL);
   sinkpad = gst_element_get_pad(GST_ELEMENT(mAudioAppSink), "sink");
   gst_pad_add_event_probe(sinkpad,
       G_CALLBACK(&nsGStreamerReader::EventProbeCb), this);
   gst_object_unref(sinkpad);
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -191,18 +191,21 @@ destroying the nsBuiltinDecoder object.
 #include "nsSize.h"
 #include "prlog.h"
 #include "gfxContext.h"
 #include "gfxRect.h"
 #include "MediaResource.h"
 #include "nsMediaDecoder.h"
 #include "nsHTMLMediaElement.h"
 #include "mozilla/ReentrantMonitor.h"
+#include "ImageLayers.h"
+class nsAudioStream;
 
-class nsAudioStream;
+typedef mozilla::layers::Image Image;
+typedef mozilla::layers::ImageContainer ImageContainer;
 
 static inline bool IsCurrentThread(nsIThread* aThread) {
   return NS_GetCurrentThread() == aThread;
 }
 
 // Decoder backends must implement this class to perform the codec
 // specific parts of decoding the video/audio format.
 class nsDecoderStateMachine : public nsRunnable
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -2,17 +2,16 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(nsBuiltinDecoderReader_h_)
 #define nsBuiltinDecoderReader_h_
 
 #include <nsDeque.h>
-#include "ImageLayers.h"
 #include "nsSize.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "MediaStreamGraph.h"
 #include "SharedBuffer.h"
 
 // Stores info relevant to presenting media frames.
 class nsVideoInfo {
 public:
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -545,21 +545,21 @@ void nsBuiltinDecoderStateMachine::SendO
   nsRefPtr<SharedBuffer> buffer = aAudio->mAudioBuffer;
   aOutput->AppendFrames(buffer.forget(), aAudio->mFrames, PRInt32(offset), aAudio->mFrames,
                         MOZ_AUDIO_DATA_FORMAT);
   LOG(PR_LOG_DEBUG, ("%p Decoder writing %d frames of data to MediaStream for AudioData at %lld",
                      mDecoder.get(), aAudio->mFrames - PRInt32(offset), aAudio->mTime));
   aStream->mAudioFramesWritten += aAudio->mFrames - PRInt32(offset);
 }
 
-static void WriteVideoToMediaStream(Image* aImage,
+static void WriteVideoToMediaStream(mozilla::layers::Image* aImage,
                                     PRInt64 aDuration, const gfxIntSize& aIntrinsicSize,
                                     VideoSegment* aOutput)
 {
-  nsRefPtr<Image> image = aImage;
+  nsRefPtr<mozilla::layers::Image> image = aImage;
   aOutput->AppendFrame(image.forget(), aDuration, aIntrinsicSize);
 }
 
 static const TrackID TRACK_AUDIO = 1;
 static const TrackID TRACK_VIDEO = 2;
 static const TrackRate RATE_VIDEO = USECS_PER_S;
 
 void nsBuiltinDecoderStateMachine::SendOutputStreamData()
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(nsMediaDecoder_h_)
 #define nsMediaDecoder_h_
 
-#include "ImageLayers.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "VideoFrameContainer.h"
 #include "MediaStreamGraph.h"
 
 class nsHTMLMediaElement;
 class nsIStreamListener;
 class nsTimeRanges;
 class nsIMemoryReporter;
@@ -33,18 +32,16 @@ static const PRUint32 FRAMEBUFFER_LENGTH
 static const PRUint32 FRAMEBUFFER_LENGTH_MAX = 16384;
 
 // All methods of nsMediaDecoder must be called from the main thread only
 // with the exception of GetVideoFrameContainer and GetStatistics,
 // which can be called from any thread.
 class nsMediaDecoder : public nsIObserver
 {
 public:
-  typedef mozilla::layers::Image Image;
-  typedef mozilla::layers::ImageContainer ImageContainer;
   typedef mozilla::MediaResource MediaResource;
   typedef mozilla::ReentrantMonitor ReentrantMonitor;
   typedef mozilla::SourceMediaStream SourceMediaStream;
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
   typedef mozilla::VideoFrameContainer VideoFrameContainer;
 
   nsMediaDecoder();
@@ -336,17 +333,17 @@ public:
   virtual void Resume(bool aForceBuffering) = 0;
 
   // Returns a weak reference to the media element we're decoding for,
   // if it's available.
   nsHTMLMediaElement* GetMediaElement();
 
   // Returns the current size of the framebuffer used in
   // MozAudioAvailable events.
-  PRUint32 GetFrameBufferLength() { return mFrameBufferLength; };
+  PRUint32 GetFrameBufferLength() { return mFrameBufferLength; }
 
   // Sets the length of the framebuffer used in MozAudioAvailable events.
   // The new size must be between 512 and 16384.
   virtual nsresult RequestFrameBufferLength(PRUint32 aLength);
 
   // Moves any existing channel loads into the background, so that they don't
   // block the load event. This is called when we stop delaying the load
   // event. Any new loads initiated (for example to seek) will also be in the
@@ -363,17 +360,17 @@ public:
   bool CanPlayThrough();
 
   // Returns the size, in bytes, of the heap memory used by the currently
   // queued decoded video and audio data.
   virtual PRInt64 VideoQueueMemoryInUse() = 0;
   virtual PRInt64 AudioQueueMemoryInUse() = 0;
 
   VideoFrameContainer* GetVideoFrameContainer() { return mVideoFrameContainer; }
-  ImageContainer* GetImageContainer()
+  mozilla::layers::ImageContainer* GetImageContainer()
   {
     return mVideoFrameContainer ? mVideoFrameContainer->GetImageContainer() : nsnull;
   }
 
 protected:
 
   // Start timer to update download progress information.
   nsresult StartProgress();
--- a/content/svg/content/src/DOMSVGLengthList.cpp
+++ b/content/svg/content/src/DOMSVGLengthList.cpp
@@ -36,19 +36,24 @@ void UpdateListIndicesFromIndex(nsTArray
 namespace mozilla {
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedLengthList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGLengthList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGLengthList)
-  // No need to null check tmp - script/SMIL can't detach us from mAList
-  ( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) = nsnull;
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  if (tmp->mAList) {
+    if (tmp->IsAnimValList()) {
+      tmp->mAList->mAnimVal = nsnull;
+    } else {
+      tmp->mAList->mBaseVal = nsnull;
+    }
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGLengthList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGLengthList)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
--- a/content/svg/content/src/DOMSVGNumberList.cpp
+++ b/content/svg/content/src/DOMSVGNumberList.cpp
@@ -36,19 +36,24 @@ void UpdateListIndicesFromIndex(nsTArray
 } // namespace
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedNumberList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumberList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumberList)
-  // No need to null check tmp - script/SMIL can't detach us from mAList
-  ( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) = nsnull;
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  if (tmp->mAList) {
+    if (tmp->IsAnimValList()) {
+      tmp->mAList->mAnimVal = nsnull;
+    } else {
+      tmp->mAList->mBaseVal = nsnull;
+    }
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumberList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGNumberList)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
--- a/content/svg/content/src/DOMSVGTransformList.cpp
+++ b/content/svg/content/src/DOMSVGTransformList.cpp
@@ -32,20 +32,24 @@ void UpdateListIndicesFromIndex(
 namespace mozilla {
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedTransformList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGTransformList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransformList)
-  // No need to null check tmp - script/SMIL can't detach us from mAList
-  ( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) =
-    nsnull;
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  if (tmp->mAList) {
+    if (tmp->IsAnimValList()) {
+      tmp->mAList->mAnimVal = nsnull;
+    } else {
+      tmp->mAList->mBaseVal = nsnull;
+    }
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGTransformList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGTransformList)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
--- a/content/svg/content/src/nsSVGGraphicElement.cpp
+++ b/content/svg/content/src/nsSVGGraphicElement.cpp
@@ -232,17 +232,17 @@ nsSVGGraphicElement::GetAnimateMotionTra
 {
   return mAnimateMotionTransform.get();
 }
 
 void
 nsSVGGraphicElement::SetAnimateMotionTransform(const gfxMatrix* aMatrix)
 {
   if ((!aMatrix && !mAnimateMotionTransform) ||
-      aMatrix && mAnimateMotionTransform && *aMatrix == *mAnimateMotionTransform) {
+      (aMatrix && mAnimateMotionTransform && *aMatrix == *mAnimateMotionTransform)) {
     return;
   }
   mAnimateMotionTransform = aMatrix ? new gfxMatrix(*aMatrix) : nsnull;
   DidAnimateTransformList();
 }
 
 SVGAnimatedTransformList*
 nsSVGGraphicElement::GetAnimatedTransformList()
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -56,23 +56,26 @@ PRUint32 nsXBLPrototypeHandler::gRefCnt 
 
 PRInt32 nsXBLPrototypeHandler::kMenuAccessKey = -1;
 PRInt32 nsXBLPrototypeHandler::kAccelKey = -1;
 
 const PRInt32 nsXBLPrototypeHandler::cShift = (1<<0);
 const PRInt32 nsXBLPrototypeHandler::cAlt = (1<<1);
 const PRInt32 nsXBLPrototypeHandler::cControl = (1<<2);
 const PRInt32 nsXBLPrototypeHandler::cMeta = (1<<3);
+const PRInt32 nsXBLPrototypeHandler::cOS = (1<<4);
 
-const PRInt32 nsXBLPrototypeHandler::cShiftMask = (1<<4);
-const PRInt32 nsXBLPrototypeHandler::cAltMask = (1<<5);
-const PRInt32 nsXBLPrototypeHandler::cControlMask = (1<<6);
-const PRInt32 nsXBLPrototypeHandler::cMetaMask = (1<<7);
+const PRInt32 nsXBLPrototypeHandler::cShiftMask = (1<<5);
+const PRInt32 nsXBLPrototypeHandler::cAltMask = (1<<6);
+const PRInt32 nsXBLPrototypeHandler::cControlMask = (1<<7);
+const PRInt32 nsXBLPrototypeHandler::cMetaMask = (1<<8);
+const PRInt32 nsXBLPrototypeHandler::cOSMask = (1<<9);
 
-const PRInt32 nsXBLPrototypeHandler::cAllModifiers = cShiftMask | cAltMask | cControlMask | cMetaMask;
+const PRInt32 nsXBLPrototypeHandler::cAllModifiers =
+  cShiftMask | cAltMask | cControlMask | cMetaMask | cOSMask;
 
 nsXBLPrototypeHandler::nsXBLPrototypeHandler(const PRUnichar* aEvent,
                                              const PRUnichar* aPhase,
                                              const PRUnichar* aAction,
                                              const PRUnichar* aCommand,
                                              const PRUnichar* aKeyCode,
                                              const PRUnichar* aCharCode,
                                              const PRUnichar* aModifiers,
@@ -491,16 +494,18 @@ nsXBLPrototypeHandler::DispatchXULKeyCom
 
   // Copy the modifiers from the key event.
   nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
   if (!keyEvent) {
     NS_ERROR("Trying to execute a key handler for a non-key event!");
     return NS_ERROR_FAILURE;
   }
 
+  // XXX We should use widget::Modifiers for supporting all modifiers.
+
   bool isAlt = false;
   bool isControl = false;
   bool isShift = false;
   bool isMeta = false;
   keyEvent->GetAltKey(&isAlt);
   keyEvent->GetCtrlKey(&isControl);
   keyEvent->GetShiftKey(&isShift);
   keyEvent->GetMetaKey(&isMeta);
@@ -641,21 +646,22 @@ PRInt32 nsXBLPrototypeHandler::GetMatchi
 }
 
 PRInt32 nsXBLPrototypeHandler::KeyToMask(PRInt32 key)
 {
   switch (key)
   {
     case nsIDOMKeyEvent::DOM_VK_META:
       return cMeta | cMetaMask;
-      break;
+
+    case nsIDOMKeyEvent::DOM_VK_WIN:
+      return cOS | cOSMask;
 
     case nsIDOMKeyEvent::DOM_VK_ALT:
       return cAlt | cAltMask;
-      break;
 
     case nsIDOMKeyEvent::DOM_VK_CONTROL:
     default:
       return cControl | cControlMask;
   }
   return cControl | cControlMask;  // for warning avoidance
 }
 
@@ -752,24 +758,26 @@ nsXBLPrototypeHandler::ConstructPrototyp
     char* token = nsCRT::strtok( str, ", \t", &newStr );
     while( token != NULL ) {
       if (PL_strcmp(token, "shift") == 0)
         mKeyMask |= cShift | cShiftMask;
       else if (PL_strcmp(token, "alt") == 0)
         mKeyMask |= cAlt | cAltMask;
       else if (PL_strcmp(token, "meta") == 0)
         mKeyMask |= cMeta | cMetaMask;
+      else if (PL_strcmp(token, "os") == 0)
+        mKeyMask |= cOS | cOSMask;
       else if (PL_strcmp(token, "control") == 0)
         mKeyMask |= cControl | cControlMask;
       else if (PL_strcmp(token, "accel") == 0)
         mKeyMask |= KeyToMask(kAccelKey);
       else if (PL_strcmp(token, "access") == 0)
         mKeyMask |= KeyToMask(kMenuAccessKey);
       else if (PL_strcmp(token, "any") == 0)
-        mKeyMask &= ~(mKeyMask << 4);
+        mKeyMask &= ~(mKeyMask << 5);
     
       token = nsCRT::strtok( newStr, ", \t", &newStr );
     }
 
     nsMemory::Free(str);
   }
 
   nsAutoString key(aCharCode);
@@ -848,59 +856,65 @@ nsXBLPrototypeHandler::ReportKeyConflict
                                   params, ArrayLength(params),
                                   nsnull, EmptyString(), mLineNumber);
 }
 
 bool
 nsXBLPrototypeHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent,
                                           bool aIgnoreShiftKey)
 {
-  nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
-  nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
+  nsEvent* event = aEvent->GetInternalNSEvent();
+  NS_ENSURE_TRUE(event && NS_IS_INPUT_EVENT(event), false);
+  nsInputEvent* inputEvent = static_cast<nsInputEvent*>(event);
 
-  bool keyPresent;
   if (mKeyMask & cMetaMask) {
-    key ? key->GetMetaKey(&keyPresent) : mouse->GetMetaKey(&keyPresent);
-    if (keyPresent != ((mKeyMask & cMeta) != 0))
+    if (inputEvent->IsMeta() != ((mKeyMask & cMeta) != 0)) {
       return false;
+    }
+  }
+
+  if (mKeyMask & cOSMask) {
+    if (inputEvent->IsOS() != ((mKeyMask & cOS) != 0)) {
+      return false;
+    }
   }
 
   if (mKeyMask & cShiftMask && !aIgnoreShiftKey) {
-    key ? key->GetShiftKey(&keyPresent) : mouse->GetShiftKey(&keyPresent);
-    if (keyPresent != ((mKeyMask & cShift) != 0))
+    if (inputEvent->IsShift() != ((mKeyMask & cShift) != 0)) {
       return false;
+    }
   }
 
   if (mKeyMask & cAltMask) {
-    key ? key->GetAltKey(&keyPresent) : mouse->GetAltKey(&keyPresent);
-    if (keyPresent != ((mKeyMask & cAlt) != 0))
+    if (inputEvent->IsAlt() != ((mKeyMask & cAlt) != 0)) {
       return false;
+    }
   }
 
   if (mKeyMask & cControlMask) {
-    key ? key->GetCtrlKey(&keyPresent) : mouse->GetCtrlKey(&keyPresent);
-    if (keyPresent != ((mKeyMask & cControl) != 0))
+    if (inputEvent->IsControl() != ((mKeyMask & cControl) != 0)) {
       return false;
+    }
   }
 
   return true;
 }
 
 nsresult
 nsXBLPrototypeHandler::Read(nsIScriptContext* aContext, nsIObjectInputStream* aStream)
 {
   nsresult rv = aStream->Read8(&mPhase);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = aStream->Read8(&mKeyMask);
-  NS_ENSURE_SUCCESS(rv, rv);
   rv = aStream->Read8(&mType);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = aStream->Read8(&mMisc);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  rv = aStream->Read32(reinterpret_cast<PRUint32*>(&mKeyMask));
+  NS_ENSURE_SUCCESS(rv, rv);
   PRUint32 detail; 
   rv = aStream->Read32(&detail);
   NS_ENSURE_SUCCESS(rv, rv);
   mDetail = detail;
 
   nsAutoString name;
   rv = aStream->ReadString(name);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -926,22 +940,22 @@ nsXBLPrototypeHandler::Write(nsIScriptCo
   if ((mType & NS_HANDLER_TYPE_XUL) || !mEventName)
     return NS_OK;
 
   XBLBindingSerializeDetails type = XBLBinding_Serialize_Handler;
 
   nsresult rv = aStream->Write8(type);
   rv = aStream->Write8(mPhase);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = aStream->Write8(mKeyMask);
-  NS_ENSURE_SUCCESS(rv, rv);
   rv = aStream->Write8(mType);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = aStream->Write8(mMisc);
   NS_ENSURE_SUCCESS(rv, rv);
+  rv = aStream->Write32(static_cast<PRUint32>(mKeyMask));
+  NS_ENSURE_SUCCESS(rv, rv);
   rv = aStream->Write32(mDetail);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aStream->WriteWStringZ(nsDependentAtomString(mEventName).get());
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aStream->Write32(mLineNumber);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/xbl/src/nsXBLPrototypeHandler.h
+++ b/content/xbl/src/nsXBLPrototypeHandler.h
@@ -167,47 +167,50 @@ protected:
   static PRInt32 kAccelKey;
   static PRInt32 kMenuAccessKey;
   static void InitAccessKeys();
 
   static const PRInt32 cShift;
   static const PRInt32 cAlt;
   static const PRInt32 cControl;
   static const PRInt32 cMeta;
+  static const PRInt32 cOS;
 
   static const PRInt32 cShiftMask;
   static const PRInt32 cAltMask;
   static const PRInt32 cControlMask;
   static const PRInt32 cMetaMask;
+  static const PRInt32 cOSMask;
 
   static const PRInt32 cAllModifiers;
 
 protected:
   union {
     nsIWeakReference* mHandlerElement;  // For XUL <key> element handlers. [STRONG]
     PRUnichar*        mHandlerText;     // For XBL handlers (we don't build an
                                         // element for the <handler>, and instead
                                         // we cache the JS text or command name
                                         // that we should use.
   };
 
   PRUint32 mLineNumber;  // The line number we started at in the XBL file
   
   // The following four values make up 32 bits.
   PRUint8 mPhase;            // The phase (capturing, bubbling)
-  PRUint8 mKeyMask;          // Which modifier keys this event handler expects to have down
-                             // in order to be matched.
   PRUint8 mType;             // The type of the handler.  The handler is either a XUL key
                              // handler, an XBL "command" event, or a normal XBL event with
                              // accompanying JavaScript.  The high bit is used to indicate
                              // whether this handler should prevent the default action.
   PRUint8 mMisc;             // Miscellaneous extra information.  For key events,
                              // stores whether or not we're a key code or char code.
                              // For mouse events, stores the clickCount.
 
+  PRInt32 mKeyMask;          // Which modifier keys this event handler expects to have down
+                             // in order to be matched.
+ 
   // The primary filter information for mouse/key events.
   PRInt32 mDetail;           // For key events, contains a charcode or keycode. For
                              // mouse events, stores the button info.
 
   // Prototype handlers are chained. We own the next handler in the chain.
   nsXBLPrototypeHandler* mNextHandler;
   nsCOMPtr<nsIAtom> mEventName; // The type of the event, e.g., "keypress"
   nsRefPtr<nsXBLEventHandler> mHandler;
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -99,52 +99,25 @@
 #include "nsEventDispatcher.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIDOMXULCommandEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsCCUncollectableMarker.h"
 
 namespace css = mozilla::css;
 
-/**
- * A tearoff class for nsXULElement to implement nsIScriptEventHandlerOwner.
- */
-class nsScriptEventHandlerOwnerTearoff MOZ_FINAL : public nsIScriptEventHandlerOwner
-{
-public:
-    nsScriptEventHandlerOwnerTearoff(nsXULElement* aElement)
-    : mElement(aElement) {}
-
-    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-    NS_DECL_CYCLE_COLLECTION_CLASS(nsScriptEventHandlerOwnerTearoff)
-
-    // nsIScriptEventHandlerOwner
-    virtual nsresult CompileEventHandler(nsIScriptContext* aContext,
-                                         nsIAtom *aName,
-                                         const nsAString& aBody,
-                                         const char* aURL,
-                                         PRUint32 aLineNo,
-                                         nsScriptObjectHolder<JSObject>& aHandler);
-    virtual nsresult GetCompiledEventHandler(nsIAtom *aName,
-                                             nsScriptObjectHolder<JSObject>& aHandler);
-
-private:
-    nsRefPtr<nsXULElement> mElement;
-};
-
 //----------------------------------------------------------------------
 
 static NS_DEFINE_CID(kXULPopupListenerCID,        NS_XULPOPUPLISTENER_CID);
 
 //----------------------------------------------------------------------
 
 #ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
 PRUint32             nsXULPrototypeAttribute::gNumElements;
 PRUint32             nsXULPrototypeAttribute::gNumAttributes;
-PRUint32             nsXULPrototypeAttribute::gNumEventHandlers;
 PRUint32             nsXULPrototypeAttribute::gNumCacheTests;
 PRUint32             nsXULPrototypeAttribute::gNumCacheHits;
 PRUint32             nsXULPrototypeAttribute::gNumCacheSets;
 PRUint32             nsXULPrototypeAttribute::gNumCacheFills;
 #endif
 
 class nsXULElementTearoff MOZ_FINAL : public nsIDOMElementCSSInlineStyle,
                                       public nsIFrameLoaderOwner
@@ -230,27 +203,27 @@ already_AddRefed<nsXULElement>
 nsXULElement::Create(nsXULPrototypeElement* aPrototype, nsINodeInfo *aNodeInfo,
                      bool aIsScriptable)
 {
     nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
     nsXULElement *element = new nsXULElement(ni.forget());
     if (element) {
         NS_ADDREF(element);
 
-        element->mPrototype = aPrototype;
         if (aPrototype->mHasIdAttribute) {
             element->SetHasID();
         }
         if (aPrototype->mHasClassAttribute) {
             element->SetFlags(NODE_MAY_HAVE_CLASS);
         }
         if (aPrototype->mHasStyleAttribute) {
             element->SetMayHaveStyle();
         }
 
+        element->MakeHeavyweight(aPrototype);
         if (aIsScriptable) {
             // Check each attribute on the prototype to see if we need to do
             // any additional processing and hookup that would otherwise be
             // done 'automagically' by SetAttr().
             for (PRUint32 i = 0; i < aPrototype->mNumAttributes; ++i) {
                 element->AddListenerFor(aPrototype->mAttributes[i].mName,
                                         true);
             }
@@ -288,17 +261,17 @@ nsXULElement::Create(nsXULPrototypeEleme
     }
 
     nsRefPtr<nsXULElement> element = Create(aPrototype, nodeInfo,
                                             aIsScriptable);
     if (!element) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    NS_ADDREF(*aResult = element.get());
+    element.forget(aResult);
 
     return NS_OK;
 }
 
 nsresult
 NS_NewXULElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo)
 {
     NS_PRECONDITION(aNodeInfo.get(), "need nodeinfo for non-proto Create");
@@ -324,17 +297,16 @@ NS_TrustedNewXULElement(nsIContent** aRe
 }
 
 //----------------------------------------------------------------------
 // nsISupports interface
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULElement,
                                                   nsStyledElement)
-    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrototype)
     {
         nsXULSlots* slots = static_cast<nsXULSlots*>(tmp->GetExistingSlots());
         if (slots) {
             slots->Traverse(cb);
         }
     }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
@@ -345,59 +317,83 @@ DOMCI_NODE_DATA(XULElement, nsXULElement
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULElement)
     NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsXULElement)
         NS_INTERFACE_TABLE_ENTRY(nsXULElement, nsIDOMNode)
         NS_INTERFACE_TABLE_ENTRY(nsXULElement, nsIDOMElement)
         NS_INTERFACE_TABLE_ENTRY(nsXULElement, nsIDOMXULElement)
     NS_OFFSET_AND_INTERFACE_TABLE_END
     NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
-    NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIScriptEventHandlerOwner,
-                                   new nsScriptEventHandlerOwnerTearoff(this))
     NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMElementCSSInlineStyle,
                                    new nsXULElementTearoff(this))
     NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIFrameLoaderOwner,
                                    new nsXULElementTearoff(this))
     NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULElement)
 NS_ELEMENT_INTERFACE_MAP_END
 
 //----------------------------------------------------------------------
 // nsIDOMNode interface
 
 nsresult
 nsXULElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
 {
     *aResult = nsnull;
 
-    // If we have a prototype, so will our clone.
-    nsRefPtr<nsXULElement> element;
-    if (mPrototype) {
-        element = nsXULElement::Create(mPrototype, aNodeInfo, true);
-    }
-    else {
-        nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
-        element = new nsXULElement(ni.forget());
-    }
-
-    if (!element) {
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
+    nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
+    nsRefPtr<nsXULElement> element = new nsXULElement(ni.forget());
 
     // XXX TODO: set up RDF generic builder n' stuff if there is a
     // 'datasources' attribute? This is really kind of tricky,
     // because then we'd need to -selectively- copy children that
     // -weren't- generated from RDF. Ugh. Forget it.
 
     // Note that we're _not_ copying mControllers.
 
-    nsresult rv = const_cast<nsXULElement*>(this)->CopyInnerTo(element);
-    if (NS_SUCCEEDED(rv)) {
-        NS_ADDREF(*aResult = element);
+    PRUint32 count = mAttrsAndChildren.AttrCount();
+    nsresult rv = NS_OK;
+    for (PRUint32 i = 0; i < count; ++i) {
+        const nsAttrName* originalName = mAttrsAndChildren.AttrNameAt(i);
+        const nsAttrValue* originalValue = mAttrsAndChildren.AttrAt(i);
+        nsAttrValue attrValue;
+
+        // Style rules need to be cloned.
+        if (originalValue->Type() == nsAttrValue::eCSSStyleRule) {
+            nsRefPtr<css::Rule> ruleClone =
+                originalValue->GetCSSStyleRuleValue()->Clone();
+
+            nsString stringValue;
+            originalValue->ToString(stringValue);
+
+            nsRefPtr<css::StyleRule> styleRule = do_QueryObject(ruleClone);
+            attrValue.SetTo(styleRule, &stringValue);
+        } else {
+            attrValue.SetTo(*originalValue);
+        }
+
+        if (originalName->IsAtom()) {
+           rv = element->mAttrsAndChildren.SetAndTakeAttr(originalName->Atom(),
+                                                          attrValue);
+        } else {
+            rv = element->mAttrsAndChildren.SetAndTakeAttr(originalName->NodeInfo(),
+                                                           attrValue);
+        }
+        NS_ENSURE_SUCCESS(rv, rv);
+        element->AddListenerFor(*originalName, true);
+        if (originalName->Equals(nsGkAtoms::id)) {
+            element->SetHasID();
+        }
+        if (originalName->Equals(nsGkAtoms::_class)) {
+            element->SetFlags(NODE_MAY_HAVE_CLASS);
+        }
+        if (originalName->Equals(nsGkAtoms::style)) {
+            element->SetMayHaveStyle();
+        }
     }
 
+    element.forget(aResult);
     return rv;
 }
 
 //----------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsXULElement::GetElementsByAttribute(const nsAString& aAttribute,
                                      const nsAString& aValue,
@@ -638,140 +634,17 @@ nsXULElement::PerformAccesskey(bool aKey
           elm->ClickWithInputSource(nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD);
         }
     }
     else {
         content->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
     }
 }
 
-
 //----------------------------------------------------------------------
-// nsIScriptEventHandlerOwner interface
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsScriptEventHandlerOwnerTearoff)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsScriptEventHandlerOwnerTearoff)
-  tmp->mElement = nsnull;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsScriptEventHandlerOwnerTearoff)
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mElement");
-  cb.NoteXPCOMChild(static_cast<nsIContent*>(tmp->mElement));
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScriptEventHandlerOwnerTearoff)
-  NS_INTERFACE_MAP_ENTRY(nsIScriptEventHandlerOwner)
-NS_INTERFACE_MAP_END_AGGREGATED(mElement)
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsScriptEventHandlerOwnerTearoff)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsScriptEventHandlerOwnerTearoff)
-
-nsresult
-nsScriptEventHandlerOwnerTearoff::GetCompiledEventHandler(
-                                                nsIAtom *aName,
-                                                nsScriptObjectHolder<JSObject>& aHandler)
-{
-    XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheTests);
-    aHandler.drop();
-
-    nsXULPrototypeAttribute *attr =
-        mElement->FindPrototypeAttribute(kNameSpaceID_None, aName);
-    if (attr) {
-        XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheHits);
-        aHandler.set(attr->mEventHandler);
-    }
-
-    return NS_OK;
-}
-
-nsresult
-nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
-                                                nsIScriptContext* aContext,
-                                                nsIAtom *aName,
-                                                const nsAString& aBody,
-                                                const char* aURL,
-                                                PRUint32 aLineNo,
-                                                nsScriptObjectHolder<JSObject>& aHandler)
-{
-    nsresult rv;
-
-    XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheSets);
-
-    // XXX sXBL/XBL2 issue! Owner or current document?
-    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->OwnerDoc());
-
-    nsIScriptContext* context = NULL;
-    nsXULPrototypeElement* elem = mElement->mPrototype;
-    if (elem && xuldoc) {
-        // It'll be shared among the instances of the prototype.
-
-        // Use the prototype document's special context.  Because
-        // scopeObject is null, the JS engine has no other source of
-        // <the-new-shared-event-handler>.__proto__ than to look in
-        // cx->globalObject for Function.prototype.  That prototype
-        // keeps the global object alive, so if we use this document's
-        // global object, we'll be putting something in the prototype
-        // that protects this document's global object from GC.
-        nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner;
-        rv = xuldoc->GetScriptGlobalObjectOwner(getter_AddRefs(globalOwner));
-        NS_ENSURE_SUCCESS(rv, rv);
-        NS_ENSURE_TRUE(globalOwner, NS_ERROR_UNEXPECTED);
-
-        nsIScriptGlobalObject* global = globalOwner->GetScriptGlobalObject();
-        NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
-
-        context = global->GetScriptContext();
-        // It could be possible the language has been setup on aContext but
-        // not on the global - we don't demand-create language contexts on the
-        // nsGlobalWindow
-        NS_ASSERTION(context,
-                     "Failed to get a language context from the global!?");
-        NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
-    }
-    else {
-        context = aContext;
-    }
-
-    // Compile the event handler
-    PRUint32 argCount;
-    const char **argNames;
-    nsContentUtils::GetEventArgNames(kNameSpaceID_XUL, aName, &argCount,
-                                     &argNames);
-
-    nsCxPusher pusher;
-    if (!pusher.Push(context->GetNativeContext())) {
-      return NS_ERROR_FAILURE;
-    }
-
-    rv = context->CompileEventHandler(aName, argCount, argNames,
-                                      aBody, aURL, aLineNo,
-                                      SCRIPTVERSION_DEFAULT,  // for now?
-                                      aHandler);
-    if (NS_FAILED(rv)) return rv;
-
-    nsXULPrototypeAttribute *attr =
-        mElement->FindPrototypeAttribute(kNameSpaceID_None, aName);
-    if (attr) {
-        XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
-        // take a copy of the event handler, and tell the language about it.
-        if (aHandler) {
-            NS_ASSERTION(!attr->mEventHandler, "Leaking handler.");
-
-            if (!elem->mHoldsScriptObject) {
-                rv = nsContentUtils::HoldJSObjects(
-                    elem, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
-                NS_ENSURE_SUCCESS(rv, rv);
-            }
-
-            elem->mHoldsScriptObject = true;
-        }
-        attr->mEventHandler = aHandler.get();
-    }
-
-    return NS_OK;
-}
 
 void
 nsXULElement::AddListenerFor(const nsAttrName& aName,
                              bool aCompileEventHandlers)
 {
     // If appropriate, add a popup listener and/or compile the event
     // handler. Called when we change the element's document, create a
     // new element, change an attribute's value, etc.
@@ -997,20 +870,18 @@ nsXULElement::UnregisterAccessKey(const 
 }
 
 nsresult
 nsXULElement::BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                             const nsAttrValueOrString* aValue, bool aNotify)
 {
     if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::accesskey &&
         IsInDoc()) {
-        const nsAttrValue* attrVal = FindLocalOrProtoAttr(aNamespaceID, aName);
-        if (attrVal) {
-            nsAutoString oldValue;
-            attrVal->ToString(oldValue);
+        nsAutoString oldValue;
+        if (GetAttr(aNamespaceID, aName, oldValue)) {
             UnregisterAccessKey(oldValue);
         }
     } 
     else if (aNamespaceID == kNameSpaceID_None && (aName ==
              nsGkAtoms::command || aName == nsGkAtoms::observes) && IsInDoc()) {
 //         XXX sXBL/XBL2 issue! Owner or current document?
         nsAutoString oldValue;
         GetAttr(kNameSpaceID_None, nsGkAtoms::observes, oldValue);
@@ -1037,86 +908,122 @@ nsXULElement::BeforeSetAttr(PRInt32 aNam
                                           aValue, aNotify);
 }
 
 nsresult
 nsXULElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                            const nsAttrValue* aValue, bool aNotify)
 {
     if (aNamespaceID == kNameSpaceID_None) {
-        // XXX UnsetAttr handles more attributes than we do. See bug 233642.
-
-        // Add popup and event listeners. We can't call AddListenerFor since
-        // the attribute isn't set yet.
-        MaybeAddPopupListener(aName);
-        if (nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL) && aValue) {
-            if (aValue->Type() == nsAttrValue::eString) {
-                AddScriptEventListener(aName, aValue->GetStringValue(), true);
-            } else {
-                nsAutoString body;
-                aValue->ToString(body);
-                AddScriptEventListener(aName, body, true);
-            }
-        }
-
-        // Hide chrome if needed
-        if (mNodeInfo->Equals(nsGkAtoms::window) && aValue) {
-            if (aName == nsGkAtoms::hidechrome) {
-                HideWindowChrome(
-                  aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
-            }
-            else if (aName == nsGkAtoms::chromemargin) {
-                SetChromeMargins(aValue);
+        if (aValue) {
+            // Add popup and event listeners. We can't call AddListenerFor since
+            // the attribute isn't set yet.
+            MaybeAddPopupListener(aName);
+            if (nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL)) {
+                if (aValue->Type() == nsAttrValue::eString) {
+                    AddScriptEventListener(aName, aValue->GetStringValue(), true);
+                } else {
+                    nsAutoString body;
+                    aValue->ToString(body);
+                    AddScriptEventListener(aName, body, true);
+                }
             }
-        }
-
-        // title, (in)activetitlebarcolor and drawintitlebar are settable on
-        // any root node (windows, dialogs, etc)
-        nsIDocument *document = GetCurrentDoc();
-        if (document && document->GetRootElement() == this) {
-            if (aName == nsGkAtoms::title) {
-                document->NotifyPossibleTitleChange(false);
-            }
-            else if ((aName == nsGkAtoms::activetitlebarcolor ||
-                      aName == nsGkAtoms::inactivetitlebarcolor) && aValue) {
-                nscolor color = NS_RGBA(0, 0, 0, 0);
-                if (aValue->Type() == nsAttrValue::eColor) {
-                    aValue->GetColorValue(color);
-                } else {
-                    nsAutoString tmp;
-                    nsAttrValue attrValue;
-                    aValue->ToString(tmp);
-                    attrValue.ParseColor(tmp);
-                    attrValue.GetColorValue(color);
+    
+            // Hide chrome if needed
+            if (mNodeInfo->Equals(nsGkAtoms::window)) {
+                if (aName == nsGkAtoms::hidechrome) {
+                    HideWindowChrome(
+                      aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
                 }
-                SetTitlebarColor(color, aName == nsGkAtoms::activetitlebarcolor);
-            }
-            else if (aName == nsGkAtoms::drawintitlebar) {
-                SetDrawsInTitlebar(aValue &&
-                    aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
-            }
-            else if (aName == nsGkAtoms::localedir) {
-                // if the localedir changed on the root element, reset the document direction
-                nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
-                if (xuldoc) {
-                    xuldoc->ResetDocumentDirection();
+                else if (aName == nsGkAtoms::chromemargin) {
+                    SetChromeMargins(aValue);
                 }
             }
-            else if (aName == nsGkAtoms::lwtheme ||
-                     aName == nsGkAtoms::lwthemetextcolor) {
-                // if the lwtheme changed, make sure to reset the document lwtheme cache
-                nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
-                if (xuldoc) {
-                    xuldoc->ResetDocumentLWTheme();
+    
+            // title, (in)activetitlebarcolor and drawintitlebar are settable on
+            // any root node (windows, dialogs, etc)
+            nsIDocument *document = GetCurrentDoc();
+            if (document && document->GetRootElement() == this) {
+                if (aName == nsGkAtoms::title) {
+                    document->NotifyPossibleTitleChange(false);
+                }
+                else if ((aName == nsGkAtoms::activetitlebarcolor ||
+                          aName == nsGkAtoms::inactivetitlebarcolor)) {
+                    nscolor color = NS_RGBA(0, 0, 0, 0);
+                    if (aValue->Type() == nsAttrValue::eColor) {
+                        aValue->GetColorValue(color);
+                    } else {
+                        nsAutoString tmp;
+                        nsAttrValue attrValue;
+                        aValue->ToString(tmp);
+                        attrValue.ParseColor(tmp);
+                        attrValue.GetColorValue(color);
+                    }
+                    SetTitlebarColor(color, aName == nsGkAtoms::activetitlebarcolor);
+                }
+                else if (aName == nsGkAtoms::drawintitlebar) {
+                    SetDrawsInTitlebar(
+                        aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
+                }
+                else if (aName == nsGkAtoms::localedir) {
+                    // if the localedir changed on the root element, reset the document direction
+                    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
+                    if (xuldoc) {
+                        xuldoc->ResetDocumentDirection();
+                    }
+                }
+                else if (aName == nsGkAtoms::lwtheme ||
+                         aName == nsGkAtoms::lwthemetextcolor) {
+                    // if the lwtheme changed, make sure to reset the document lwtheme cache
+                    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
+                    if (xuldoc) {
+                        xuldoc->ResetDocumentLWTheme();
+                    }
                 }
             }
-        }
-
-        if (aName == nsGkAtoms::src && document) {
-            LoadSrc();
+    
+            if (aName == nsGkAtoms::src && document) {
+                LoadSrc();
+            }
+        } else  {
+            if (mNodeInfo->Equals(nsGkAtoms::window)) {
+                if (aName == nsGkAtoms::hidechrome) {
+                    HideWindowChrome(false);
+                }
+                else if (aName == nsGkAtoms::chromemargin) {
+                    ResetChromeMargins();
+                }
+            }
+    
+            nsIDocument* doc = GetCurrentDoc();
+            if (doc && doc->GetRootElement() == this) {
+                if ((aName == nsGkAtoms::activetitlebarcolor ||
+                     aName == nsGkAtoms::inactivetitlebarcolor)) {
+                    // Use 0, 0, 0, 0 as the "none" color.
+                    SetTitlebarColor(NS_RGBA(0, 0, 0, 0), aName == nsGkAtoms::activetitlebarcolor);
+                }
+                else if (aName == nsGkAtoms::localedir) {
+                    // if the localedir changed on the root element, reset the document direction
+                    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
+                    if (xuldoc) {
+                        xuldoc->ResetDocumentDirection();
+                    }
+                }
+                else if ((aName == nsGkAtoms::lwtheme ||
+                          aName == nsGkAtoms::lwthemetextcolor)) {
+                    // if the lwtheme changed, make sure to restyle appropriately
+                    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
+                    if (xuldoc) {
+                        xuldoc->ResetDocumentLWTheme();
+                    }
+                }
+                else if (aName == nsGkAtoms::drawintitlebar) {
+                    SetDrawsInTitlebar(false);
+                }
+            }
         }
 
         // XXX need to check if they're changing an event handler: if
         // so, then we need to unhook the old one.  Or something.
     }
 
     return nsStyledElement::AfterSetAttr(aNamespaceID, aName,
                                          aValue, aNotify);
@@ -1133,426 +1040,31 @@ nsXULElement::ParseAttribute(PRInt32 aNa
                                          aResult)) {
         // Fall back to parsing as atom for short values
         aResult.ParseStringOrAtom(aValue);
     }
 
     return true;
 }
 
-const nsAttrName*
-nsXULElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
-{
-    const nsAttrName* attrName =
-        mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
-    if (attrName) {
-        return attrName;
-    }
-
-    if (mPrototype) {
-        PRUint32 i;
-        for (i = 0; i < mPrototype->mNumAttributes; ++i) {
-            attrName = &mPrototype->mAttributes[i].mName;
-            if (attrName->QualifiedNameEquals(aStr)) {
-                return attrName;
-            }
-        }
-    }
-
-    return nsnull;
-}
-
-const nsAttrValue*
-nsXULElement::GetAttrValue(const nsAString& aName)
-{
-  const nsAttrValue* val =
-      mAttrsAndChildren.GetAttr(aName, eCaseMatters);
-  if (val) {
-      return val;
-  }
-
-  if (mPrototype) {
-      PRUint32 i, count = mPrototype->mNumAttributes;
-      for (i = 0; i < count; ++i) {
-          nsXULPrototypeAttribute *protoAttr = &mPrototype->mAttributes[i];
-          if (protoAttr->mName.QualifiedNameEquals(aName)) {
-              return &protoAttr->mValue;
-          }
-      }
-  }
-
-  return nsnull;
-}
-
-bool
-nsXULElement::GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
-                      nsAString& aResult) const
-{
-    NS_ASSERTION(nsnull != aName, "must have attribute name");
-    NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
-                 "must have a real namespace ID!");
-
-    const nsAttrValue* val = FindLocalOrProtoAttr(aNameSpaceID, aName);
-
-    if (!val) {
-        // Since we are returning a success code we'd better do
-        // something about the out parameters (someone may have
-        // given us a non-empty string).
-        aResult.Truncate();
-        return false;
-    }
-
-    val->ToString(aResult);
-
-    return true;
-}
-
-bool
-nsXULElement::HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const
-{
-    NS_ASSERTION(nsnull != aName, "must have attribute name");
-    NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
-                 "must have a real namespace ID!");
-
-    return mAttrsAndChildren.GetAttr(aName, aNameSpaceID) ||
-           FindPrototypeAttribute(aNameSpaceID, aName);
-}
-
-bool
-nsXULElement::AttrValueIs(PRInt32 aNameSpaceID,
-                          nsIAtom* aName,
-                          const nsAString& aValue,
-                          nsCaseTreatment aCaseSensitive) const
-{
-  NS_ASSERTION(aName, "Must have attr name");
-  NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
-
-  const nsAttrValue* val = FindLocalOrProtoAttr(aNameSpaceID, aName);
-  return val && val->Equals(aValue, aCaseSensitive);
-}
-
-bool
-nsXULElement::AttrValueIs(PRInt32 aNameSpaceID,
-                          nsIAtom* aName,
-                          nsIAtom* aValue,
-                          nsCaseTreatment aCaseSensitive) const
-{
-  NS_ASSERTION(aName, "Must have attr name");
-  NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
-  NS_ASSERTION(aValue, "Null value atom");
-
-  const nsAttrValue* val = FindLocalOrProtoAttr(aNameSpaceID, aName);
-  return val && val->Equals(aValue, aCaseSensitive);
-}
-
-PRInt32
-nsXULElement::FindAttrValueIn(PRInt32 aNameSpaceID,
-                              nsIAtom* aName,
-                              AttrValuesArray* aValues,
-                              nsCaseTreatment aCaseSensitive) const
-{
-  NS_ASSERTION(aName, "Must have attr name");
-  NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
-  NS_ASSERTION(aValues, "Null value array");
-  
-  const nsAttrValue* val = FindLocalOrProtoAttr(aNameSpaceID, aName);
-  if (val) {
-    for (PRInt32 i = 0; aValues[i]; ++i) {
-      if (val->Equals(*aValues[i], aCaseSensitive)) {
-        return i;
-      }
-    }
-    return ATTR_VALUE_NO_MATCH;
-  }
-  return ATTR_MISSING;
-}
-
-nsresult
-nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, bool aNotify)
-{
-    // This doesn't call BeforeSetAttr/AfterSetAttr for now.
-    
-    NS_ASSERTION(nsnull != aName, "must have attribute name");
-    nsresult rv;
-
-    // Because It's Hard to maintain a magic ``unset'' value in
-    // the local attributes, we'll fault all the attributes,
-    // unhook ourselves from the prototype, and then remove the
-    // local copy of the attribute that we want to unset. In
-    // other words, we'll become ``heavyweight''.
-    //
-    // We can avoid this if the attribute isn't in the prototype,
-    // then we just need to remove it locally
-
-    nsXULPrototypeAttribute *protoattr =
-        FindPrototypeAttribute(aNameSpaceID, aName);
-    if (protoattr) {
-        // We've got an attribute on the prototype, so we need to
-        // fully fault and remove the local copy.
-        rv = MakeHeavyweight();
-        NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    nsIDocument* doc = GetCurrentDoc();
-    mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
-
-    bool isId = false;
-    if (aName == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) {
-      // Have to do this before clearing flag. See RemoveFromIdTable
-      RemoveFromIdTable();
-      isId = true;
-    }
-
-    PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID);
-    if (index < 0) {
-        NS_ASSERTION(!protoattr, "we used to have a protoattr, we should now "
-                                 "have a normal one");
-
-        return NS_OK;
-    }
-
-    nsAutoString oldValue;
-    GetAttr(aNameSpaceID, aName, oldValue);
-
-    if (aNotify) {
-        nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
-                                         nsIDOMMutationEvent::REMOVAL);
-    }
-
-    bool hasMutationListeners = aNotify &&
-        nsContentUtils::HasMutationListeners(this,
-            NS_EVENT_BITS_MUTATION_ATTRMODIFIED, this);
-
-    nsCOMPtr<nsIDOMAttr> attrNode;
-    if (hasMutationListeners) {
-        nsAutoString ns;
-        nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
-        GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
-                                   getter_AddRefs(attrNode));
-    }
-
-    nsDOMSlots *slots = GetExistingDOMSlots();
-    if (slots && slots->mAttributeMap) {
-      slots->mAttributeMap->DropAttribute(aNameSpaceID, aName);
-    }
-
-    // The id-handling code, and in the future possibly other code, need to
-    // react to unexpected attribute changes.
-    nsMutationGuard::DidMutate();
-
-    nsAttrValue ignored;
-    rv = mAttrsAndChildren.RemoveAttrAt(index, ignored);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // XXX if the RemoveAttrAt() call fails, we might end up having removed
-    // the attribute from the attribute map even though the attribute is still
-    // on the element
-    // https://bugzilla.mozilla.org/show_bug.cgi?id=296205
-
-    // Deal with modification of magical attributes that side-effect
-    // other things.
-    // XXX Know how to remove POPUP event listeners when an attribute is unset?
-
-    if (isId) {
-        ClearHasID();
-    }
-
-    if (aNameSpaceID == kNameSpaceID_None) {
-        if (mNodeInfo->Equals(nsGkAtoms::window)) {
-            if (aName == nsGkAtoms::hidechrome) {
-                HideWindowChrome(false);
-            }
-            else if (aName == nsGkAtoms::chromemargin) {
-                ResetChromeMargins();
-            }
-        }
-
-        if (doc && doc->GetRootElement() == this) {
-            if ((aName == nsGkAtoms::activetitlebarcolor ||
-                 aName == nsGkAtoms::inactivetitlebarcolor)) {
-                // Use 0, 0, 0, 0 as the "none" color.
-                SetTitlebarColor(NS_RGBA(0, 0, 0, 0), aName == nsGkAtoms::activetitlebarcolor);
-            }
-            else if (aName == nsGkAtoms::localedir) {
-                // if the localedir changed on the root element, reset the document direction
-                nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
-                if (xuldoc) {
-                    xuldoc->ResetDocumentDirection();
-                }
-            }
-            else if ((aName == nsGkAtoms::lwtheme ||
-                      aName == nsGkAtoms::lwthemetextcolor)) {
-                // if the lwtheme changed, make sure to restyle appropriately
-                nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
-                if (xuldoc) {
-                    xuldoc->ResetDocumentLWTheme();
-                }
-            }
-            else if (aName == nsGkAtoms::drawintitlebar) {
-                SetDrawsInTitlebar(false);
-            }
-        }
-
-        // If the accesskey attribute is removed, unregister it here
-        // Also see nsXULLabelFrame, nsBoxFrame and nsTextBoxFrame's AttributeChanged
-        if (aName == nsGkAtoms::accesskey || aName == nsGkAtoms::control) {
-            UnregisterAccessKey(oldValue);
-        }
-
-        // Check to see if the OBSERVES attribute is being unset.  If so, we
-        // need to remove our broadcaster goop completely.
-        if (doc && (aName == nsGkAtoms::observes ||
-                          aName == nsGkAtoms::command)) {
-            RemoveBroadcaster(oldValue);
-        }
-    }
-
-    if (doc) {
-        nsRefPtr<nsXBLBinding> binding =
-            doc->BindingManager()->GetBinding(this);
-        if (binding)
-            binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
-
-    }
-
-    UpdateState(aNotify);
-
-    if (aNotify) {
-        nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
-                                      nsIDOMMutationEvent::REMOVAL);
-    }
-
-    if (hasMutationListeners) {
-        nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
-
-        mutation.mRelatedNode = attrNode;
-        mutation.mAttrName = aName;
-
-        if (!oldValue.IsEmpty())
-          mutation.mPrevAttrValue = do_GetAtom(oldValue);
-        mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
-
-        mozAutoSubtreeModified subtree(OwnerDoc(), this);
-        (new nsAsyncDOMEvent(this, mutation))->RunDOMEventWhenSafe();
-    }
-
-    return NS_OK;
-}
-
 void
 nsXULElement::RemoveBroadcaster(const nsAString & broadcasterId)
 {
     nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(OwnerDoc());
     if (xuldoc) {
         nsCOMPtr<nsIDOMElement> broadcaster;
         nsCOMPtr<nsIDOMDocument> domDoc (do_QueryInterface(xuldoc));
         domDoc->GetElementById(broadcasterId, getter_AddRefs(broadcaster));
         if (broadcaster) {
             xuldoc->RemoveBroadcastListenerFor(broadcaster, this,
               NS_LITERAL_STRING("*"));
         }
     }
 }
 
-const nsAttrName*
-nsXULElement::GetAttrNameAt(PRUint32 aIndex) const
-{
-    PRUint32 localCount = mAttrsAndChildren.AttrCount();
-    PRUint32 protoCount = mPrototype ? mPrototype->mNumAttributes : 0;
-
-    if (localCount > protoCount) {
-        // More local than proto, put local first
-
-        // Is the index low enough to just grab a local attr?
-        if (aIndex < localCount) {
-            return mAttrsAndChildren.AttrNameAt(aIndex);
-        }
-
-        aIndex -= localCount;
-
-        // Search though prototype attributes while skipping names that exist in
-        // the local array.
-        for (PRUint32 i = 0; i < protoCount; i++) {
-            const nsAttrName* name = &mPrototype->mAttributes[i].mName;
-            if (mAttrsAndChildren.GetAttr(name->LocalName(), name->NamespaceID())) {
-                aIndex++;
-            }
-            if (i == aIndex) {
-                return name;
-            }
-        }
-    }
-    else {
-        // More proto than local, put proto first
-
-        // Is the index low enough to just grab a proto attr?
-        if (aIndex < protoCount) {
-            return &mPrototype->mAttributes[aIndex].mName;
-        }
-
-        aIndex -= protoCount;
-
-        // Search though local attributes while skipping names that exist in
-        // the prototype array.
-        for (PRUint32 i = 0; i < localCount; i++) {
-            const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
-
-            for (PRUint32 j = 0; j < protoCount; j++) {
-                if (mPrototype->mAttributes[j].mName.Equals(*name)) {
-                    aIndex++;
-                    break;
-                }
-            }
-            if (i == aIndex) {
-                return name;
-            }
-        }
-    }
-
-    return nsnull;
-}
-
-PRUint32
-nsXULElement::GetAttrCount() const
-{
-    PRUint32 localCount = mAttrsAndChildren.AttrCount();
-    PRUint32 protoCount = mPrototype ? mPrototype->mNumAttributes : 0;
-
-    if (localCount > protoCount) {
-        // More local than proto, remove dups from proto array
-        PRUint32 count = localCount;
-
-        for (PRUint32 i = 0; i < protoCount; i++) {
-            const nsAttrName* name = &mPrototype->mAttributes[i].mName;
-            if (!mAttrsAndChildren.GetAttr(name->LocalName(), name->NamespaceID())) {
-                count++;
-            }
-        }
-
-        return count;
-    }
-
-    // More proto than local, remove dups from local array
-    PRUint32 count = protoCount;
-
-    for (PRUint32 i = 0; i < localCount; i++) {
-        const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
-
-        count++;
-        for (PRUint32 j = 0; j < protoCount; j++) {
-            if (mPrototype->mAttributes[j].mName.Equals(*name)) {
-                count--;
-                break;
-            }
-        }
-    }
-
-    return count;
-}
-
 void
 nsXULElement::DestroyContent()
 {
     nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
     if (slots) {
         NS_IF_RELEASE(slots->mControllers);
         if (slots->mFrameLoader) {
             slots->mFrameLoader->Destroy();
@@ -1706,63 +1218,22 @@ nsXULElement::GetBuilder(nsIXULTemplateB
 
     return NS_OK;
 }
 
 
 //----------------------------------------------------------------------
 // Implementation methods
 
-// XXX DoGetID and DoGetClasses must be defined here because we have proto
-// attributes.
-nsIAtom*
-nsXULElement::DoGetID() const
-{
-    NS_ASSERTION(HasID(), "Unexpected call");
-    const nsAttrValue* attr =
-        FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::id);
-
-    // We need the nullcheck here because during unlink the prototype loses
-    // all of its attributes. We might want to change that.
-    // The nullcheck would also be needed if we make UnsetAttr use
-    // nsGenericElement::UnsetAttr as that calls out to various code between
-    // removing the attribute and calling ClearHasID().
-
-    return attr ? attr->GetAtomValue() : nsnull;
-}
-
-const nsAttrValue*
-nsXULElement::DoGetClasses() const
-{
-    NS_ASSERTION(HasFlag(NODE_MAY_HAVE_CLASS), "Unexpected call");
-    return FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::_class);
-}
-
 NS_IMETHODIMP
 nsXULElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
 {
     return NS_OK;
 }
 
-css::StyleRule*
-nsXULElement::GetInlineStyleRule()
-{
-    if (!MayHaveStyle()) {
-        return nsnull;
-    }
-    // Fetch the cached style rule from the attributes.
-    const nsAttrValue* attrVal = FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::style);
-
-    if (attrVal && attrVal->Type() == nsAttrValue::eCSSStyleRule) {
-        return attrVal->GetCSSStyleRuleValue();
-    }
-
-    return nsnull;
-}
-
 nsChangeHint
 nsXULElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                      PRInt32 aModType) const
 {
     nsChangeHint retval(NS_STYLE_HINT_NONE);
 
     if (aAttribute == nsGkAtoms::value &&
         (aModType == nsIDOMMutationEvent::REMOVAL ||
@@ -1884,45 +1355,16 @@ NS_IMPL_XUL_STRING_ATTR(Persist, persist
 NS_IMPL_XUL_STRING_ATTR(Left, left)
 NS_IMPL_XUL_STRING_ATTR(Top, top)
 NS_IMPL_XUL_STRING_ATTR(Datasources, datasources)
 NS_IMPL_XUL_STRING_ATTR(Ref, ref)
 NS_IMPL_XUL_STRING_ATTR(TooltipText, tooltiptext)
 NS_IMPL_XUL_STRING_ATTR(StatusText, statustext)
 
 nsresult
-nsXULElement::EnsureLocalStyle()
-{
-    // Clone the prototype rule, if we don't have a local one.
-    if (mPrototype &&
-        !mAttrsAndChildren.GetAttr(nsGkAtoms::style, kNameSpaceID_None)) {
-
-        nsXULPrototypeAttribute *protoattr =
-                  FindPrototypeAttribute(kNameSpaceID_None, nsGkAtoms::style);
-        if (protoattr && protoattr->mValue.Type() == nsAttrValue::eCSSStyleRule) {
-            nsRefPtr<css::Rule> ruleClone =
-                protoattr->mValue.GetCSSStyleRuleValue()->Clone();
-
-            nsString stringValue;
-            protoattr->mValue.ToString(stringValue);
-
-            nsAttrValue value;
-            nsRefPtr<css::StyleRule> styleRule = do_QueryObject(ruleClone);
-            value.SetTo(styleRule, &stringValue);
-
-            nsresult rv =
-                mAttrsAndChildren.SetAndTakeAttr(nsGkAtoms::style, value);
-            NS_ENSURE_SUCCESS(rv, rv);
-        }
-    }
-
-    return NS_OK;
-}
-
-nsresult
 nsXULElement::LoadSrc()
 {
     // Allow frame loader only on objects for which a container box object
     // can be obtained.
     nsIAtom* tag = Tag();
     if (tag != nsGkAtoms::browser &&
         tag != nsGkAtoms::editor &&
         tag != nsGkAtoms::iframe) {
@@ -2190,86 +1632,27 @@ nsXULElement::IntrinsicState() const
         state &= ~NS_EVENT_STATE_MOZ_READONLY;
     }
 
     return state;
 }
 
 //----------------------------------------------------------------------
 
-nsGenericElement::nsAttrInfo
-nsXULElement::GetAttrInfo(PRInt32 aNamespaceID, nsIAtom *aName) const
+nsresult
+nsXULElement::MakeHeavyweight(nsXULPrototypeElement* aPrototype)
 {
-
-    nsAttrInfo info(nsStyledElement::GetAttrInfo(aNamespaceID, aName));
-    if (!info.mValue) {
-        nsXULPrototypeAttribute *protoattr =
-            FindPrototypeAttribute(aNamespaceID, aName);
-        if (protoattr) {
-            return nsAttrInfo(&protoattr->mName, &protoattr->mValue);
-        }
-    }
-
-    return info;
-}
-
-
-nsXULPrototypeAttribute *
-nsXULElement::FindPrototypeAttribute(PRInt32 aNamespaceID,
-                                     nsIAtom* aLocalName) const
-{
-    if (!mPrototype) {
-        return nsnull;
+    if (!aPrototype) {
+        return NS_OK;
     }
 
-    PRUint32 i, count = mPrototype->mNumAttributes;
-    if (aNamespaceID == kNameSpaceID_None) {
-        // Common case so optimize for this
-        for (i = 0; i < count; ++i) {
-            nsXULPrototypeAttribute *protoattr = &mPrototype->mAttributes[i];
-            if (protoattr->mName.Equals(aLocalName)) {
-                return protoattr;
-            }
-        }
-    }
-    else {
-        for (i = 0; i < count; ++i) {
-            nsXULPrototypeAttribute *protoattr = &mPrototype->mAttributes[i];
-            if (protoattr->mName.Equals(aLocalName, aNamespaceID)) {
-                return protoattr;
-            }
-        }
-    }
-
-    return nsnull;
-}
-
-nsresult nsXULElement::MakeHeavyweight()
-{
-    if (!mPrototype)
-        return NS_OK;           // already heavyweight
-
-    nsRefPtr<nsXULPrototypeElement> proto;
-    proto.swap(mPrototype);
-
-    bool hadAttributes = mAttrsAndChildren.AttrCount() > 0;
-
     PRUint32 i;
     nsresult rv;
-    for (i = 0; i < proto->mNumAttributes; ++i) {
-        nsXULPrototypeAttribute* protoattr = &proto->mAttributes[i];
-
-        // We might have a local value for this attribute, in which case
-        // we don't want to copy the prototype's value.
-        if (hadAttributes &&
-            mAttrsAndChildren.GetAttr(protoattr->mName.LocalName(),
-                                      protoattr->mName.NamespaceID())) {
-            continue;
-        }
-
+    for (i = 0; i < aPrototype->mNumAttributes; ++i) {
+        nsXULPrototypeAttribute* protoattr = &aPrototype->mAttributes[i];
         nsAttrValue attrValue;
         
         // Style rules need to be cloned.
         if (protoattr->mValue.Type() == nsAttrValue::eCSSStyleRule) {
             nsRefPtr<css::Rule> ruleClone =
                 protoattr->mValue.GetCSSStyleRuleValue()->Clone();
 
             nsString stringValue;
@@ -2441,27 +1824,26 @@ nsXULElement::ResetChromeMargins()
     // See nsIWidget
     nsContentUtils::AddScriptRunner(new MarginSetter(mainWidget));
 }
 
 bool
 nsXULElement::BoolAttrIsTrue(nsIAtom* aName)
 {
     const nsAttrValue* attr =
-        FindLocalOrProtoAttr(kNameSpaceID_None, aName);
+        GetAttrInfo(kNameSpaceID_None, aName).mValue;
 
     return attr && attr->Type() == nsAttrValue::eAtom &&
            attr->GetAtomValue() == nsGkAtoms::_true;
 }
 
 void
 nsXULElement::RecompileScriptEventListeners()
 {
     PRInt32 i, count = mAttrsAndChildren.AttrCount();
-    bool haveLocalAttributes = (count > 0);
     for (i = 0; i < count; ++i) {
         const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
 
         // Eventlistenener-attributes are always in the null namespace
         if (!name->IsAtom()) {
             continue;
         }
 
@@ -2469,44 +1851,16 @@ nsXULElement::RecompileScriptEventListen
         if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
             continue;
         }
 
         nsAutoString value;
         GetAttr(kNameSpaceID_None, attr, value);
         AddScriptEventListener(attr, value, true);
     }
-
-    if (mPrototype) {
-
-        count = mPrototype->mNumAttributes;
-        for (i = 0; i < count; ++i) {
-            const nsAttrName &name = mPrototype->mAttributes[i].mName;
-
-            // Eventlistenener-attributes are always in the null namespace
-            if (!name.IsAtom()) {
-                continue;
-            }
-
-            nsIAtom *attr = name.Atom();
-
-            // Don't clobber a locally modified attribute.
-            if (haveLocalAttributes && mAttrsAndChildren.GetAttr(attr)) {
-                continue;
-            }
-
-            if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
-                continue;
-            }
-
-            nsAutoString value;
-            GetAttr(kNameSpaceID_None, attr, value);
-            AddScriptEventListener(attr, value, true);
-        }
-    }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeNode)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeNode)
     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
         static_cast<nsXULPrototypeElement*>(tmp)->Unlink();
     }
     else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
@@ -2531,29 +1885,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
         for (i = 0; i < elem->mChildren.Length(); ++i) {
             NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildren[i]");
             cb.NoteXPCOMChild(elem->mChildren[i]);
         }
     }
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXULPrototypeNode)
-    if (tmp->mType == nsXULPrototypeNode::eType_Element) {
-        nsXULPrototypeElement *elem =
-            static_cast<nsXULPrototypeElement*>(tmp);
-        if (elem->mHoldsScriptObject) {
-            PRUint32 i;
-            for (i = 0; i < elem->mNumAttributes; ++i) {
-                JSObject* handler = elem->mAttributes[i].mEventHandler;
-                NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(handler,
-                                                           "mAttributes[i].mEventHandler")
-            }
-        }
-    }
-    else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
+    if (tmp->mType == nsXULPrototypeNode::eType_Script) {
         nsXULPrototypeScript *script =
             static_cast<nsXULPrototypeScript*>(tmp);
         NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(script->mScriptObject.mObject,
                                                    "mScriptObject.mObject")
     }
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULPrototypeNode)
@@ -2839,20 +2181,16 @@ nsXULPrototypeElement::SetAttrAt(PRUint3
     mAttributes[aPos].mValue.ParseStringOrAtom(aValue);
 
     return NS_OK;
 }
 
 void
 nsXULPrototypeElement::Unlink()
 {
-    if (mHoldsScriptObject) {
-        nsContentUtils::DropJSObjects(this);
-        mHoldsScriptObject = false;
-    }
     mNumAttributes = 0;
     delete[] mAttributes;
     mAttributes = nsnull;
 }
 
 //----------------------------------------------------------------------
 //
 // nsXULPrototypeScript
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -20,17 +20,16 @@
 #include "nsIControllers.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsEventListenerManager.h"
 #include "nsIRDFCompositeDataSource.h"
 #include "nsIRDFResource.h"
-#include "nsIScriptEventHandlerOwner.h"
 #include "nsBindingManager.h"
 #include "nsIURI.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsIBoxObject.h"
 #include "nsLayoutCID.h"
 #include "nsAttrAndChildArray.h"
 #include "nsGkAtoms.h"
 #include "nsAutoPtr.h"
@@ -69,88 +68,42 @@ class StyleRule;
   A prototype attribute for an nsXULPrototypeElement.
 
  */
 
 class nsXULPrototypeAttribute
 {
 public:
     nsXULPrototypeAttribute()
-        : mName(nsGkAtoms::id),  // XXX this is a hack, but names have to have a value
-          mEventHandler(nsnull)
+        : mName(nsGkAtoms::id)  // XXX this is a hack, but names have to have a value
     {
         XUL_PROTOTYPE_ATTRIBUTE_METER(gNumAttributes);
         MOZ_COUNT_CTOR(nsXULPrototypeAttribute);
     }
 
     ~nsXULPrototypeAttribute();
 
     nsAttrName mName;
     nsAttrValue mValue;
-    // mEventHandler is only valid for the language ID specified in the
-    // containing nsXULPrototypeElement.  We would ideally use
-    // nsScriptObjectHolder, but want to avoid the extra lang ID.
-    JSObject* mEventHandler;
 
 #ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
-    /**
-      If enough attributes, on average, are event handlers, it pays to keep
-      mEventHandler here, instead of maintaining a separate mapping in each
-      nsXULElement associating those mName values with their mEventHandlers.
-      Assume we don't need to keep mNameSpaceID along with mName in such an
-      event-handler-only name-to-function-pointer mapping.
-
-      Let
-        minAttrSize  = sizeof(mNodeInof) + sizeof(mValue)
-        mappingSize  = sizeof(mNodeInfo) + sizeof(mEventHandler)
-        elemOverhead = nElems * sizeof(MappingPtr)
-
-      Then
-        nAttrs * minAttrSize + nEventHandlers * mappingSize + elemOverhead
-        > nAttrs * (minAttrSize + mappingSize - sizeof(mNodeInfo))
-      which simplifies to
-        nEventHandlers * mappingSize + elemOverhead
-        > nAttrs * (mappingSize - sizeof(mNodeInfo))
-      or
-        nEventHandlers + (nElems * sizeof(MappingPtr)) / mappingSize
-        > nAttrs * (1 - sizeof(mNodeInfo) / mappingSize)
-
-      If nsCOMPtr and all other pointers are the same size, this reduces to
-        nEventHandlers + nElems / 2 > nAttrs / 2
-
-      To measure how many attributes are event handlers, compile XUL source
-      with XUL_PROTOTYPE_ATTRIBUTE_METERING and watch the counters below.
-      Plug into the above relation -- if true, it pays to put mEventHandler
-      in nsXULPrototypeAttribute rather than to keep a separate mapping.
-
-      Recent numbers after opening four browser windows:
-        nElems 3537, nAttrs 2528, nEventHandlers 1042
-      giving 1042 + 3537/2 > 2528/2 or 2810 > 1264.
-
-      As it happens, mEventHandler also makes this struct power-of-2 sized,
-      8 words on most architectures, which makes for strength-reduced array
-      index-to-pointer calculations.
-     */
     static PRUint32   gNumElements;
     static PRUint32   gNumAttributes;
-    static PRUint32   gNumEventHandlers;
     static PRUint32   gNumCacheTests;
     static PRUint32   gNumCacheHits;
     static PRUint32   gNumCacheSets;
     static PRUint32   gNumCacheFills;
 #endif /* !XUL_PROTOTYPE_ATTRIBUTE_METERING */
 };
 
 
 /**
 
   A prototype content model element that holds the "primordial" values
-  that have been parsed from the original XUL document. A
-  'lightweight' nsXULElement may delegate its representation to this
-  structure, which is shared.
+  that have been parsed from the original XUL document.
 
  */
 
 class nsXULPrototypeNode : public nsISupports
 {
 public:
     enum Type { eType_Element, eType_Script, eType_Text, eType_PI };
 
@@ -190,21 +143,20 @@ protected:
 };
 
 class nsXULPrototypeElement : public nsXULPrototypeNode
 {
 public:
     nsXULPrototypeElement()
         : nsXULPrototypeNode(eType_Element),
           mNumAttributes(0),
-          mAttributes(nsnull),
           mHasIdAttribute(false),
           mHasClassAttribute(false),
           mHasStyleAttribute(false),
-          mHoldsScriptObject(false)
+          mAttributes(nsnull)
     {
     }
 
     virtual ~nsXULPrototypeElement()
     {
         Unlink();
     }
 
@@ -234,24 +186,21 @@ public:
     nsresult SetAttrAt(PRUint32 aPos, const nsAString& aValue, nsIURI* aDocumentURI);
 
     void Unlink();
 
     nsPrototypeArray         mChildren;
 
     nsCOMPtr<nsINodeInfo>    mNodeInfo;           // [OWNER]
 
-    PRUint32                 mNumAttributes;
+    PRUint32                 mNumAttributes:29;
+    PRUint32                 mHasIdAttribute:1;
+    PRUint32                 mHasClassAttribute:1;
+    PRUint32                 mHasStyleAttribute:1;
     nsXULPrototypeAttribute* mAttributes;         // [OWNER]
-    
-    bool                     mHasIdAttribute:1;
-    bool                     mHasClassAttribute:1;
-    bool                     mHasStyleAttribute:1;
-    bool                     mHoldsScriptObject:1;
-
 };
 
 class nsXULDocument;
 
 class nsXULPrototypeScript : public nsXULPrototypeNode
 {
 public:
     nsXULPrototypeScript(PRUint32 aLineNo, PRUint32 version);
@@ -404,54 +353,34 @@ public:
     virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 
     // nsIContent
     virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                 nsIContent* aBindingParent,
                                 bool aCompileEventHandlers);
     virtual void UnbindFromTree(bool aDeep, bool aNullParent);
     virtual void RemoveChildAt(PRUint32 aIndex, bool aNotify);
-    virtual bool GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
-                           nsAString& aResult) const;
-    virtual bool HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const;
-    virtual bool AttrValueIs(PRInt32 aNameSpaceID, nsIAtom* aName,
-                               const nsAString& aValue,
-                               nsCaseTreatment aCaseSensitive) const;
-    virtual bool AttrValueIs(PRInt32 aNameSpaceID, nsIAtom* aName,
-                               nsIAtom* aValue,
-                               nsCaseTreatment aCaseSensitive) const;
-    virtual PRInt32 FindAttrValueIn(PRInt32 aNameSpaceID,
-                                    nsIAtom* aName,
-                                    AttrValuesArray* aValues,
-                                    nsCaseTreatment aCaseSensitive) const;
-    virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
-                               bool aNotify);
-    virtual const nsAttrName* GetAttrNameAt(PRUint32 aIndex) const;
-    virtual PRUint32 GetAttrCount() const;
     virtual void DestroyContent();
 
 #ifdef DEBUG
     virtual void List(FILE* out, PRInt32 aIndent) const;
     virtual void DumpContent(FILE* out, PRInt32 aIndent,bool aDumpAll) const
     {
     }
 #endif
 
     virtual void PerformAccesskey(bool aKeyCausesActivation,
                                   bool aIsTrustedEvent);
     nsresult ClickWithInputSource(PRUint16 aInputSource);
 
     virtual nsIContent *GetBindingParent() const;
     virtual bool IsNodeOfType(PRUint32 aFlags) const;
     virtual bool IsFocusable(PRInt32 *aTabIndex = nsnull, bool aWithMouse = false);
-    virtual nsIAtom* DoGetID() const;
-    virtual const nsAttrValue* DoGetClasses() const;
 
     NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
-    virtual mozilla::css::StyleRule* GetInlineStyleRule();
     virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                                 PRInt32 aModType) const;
     NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
     // XUL element methods
     /**
      * The template-generated flag is used to indicate that a
      * template-generated element has already had its children generated.
@@ -467,48 +396,34 @@ public:
     NS_FORWARD_NSIDOMELEMENT(nsGenericElement::)
 
     // nsIDOMXULElement
     NS_DECL_NSIDOMXULELEMENT
 
     virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
     virtual nsEventStates IntrinsicState() const;
 
-    nsresult EnsureLocalStyle();
-
     nsresult GetFrameLoader(nsIFrameLoader** aFrameLoader);
     already_AddRefed<nsFrameLoader> GetFrameLoader();
     nsresult SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner);
 
     virtual void RecompileScriptEventListeners();
 
     // This function should ONLY be used by BindToTree implementations.
     // The function exists solely because XUL elements store the binding
     // parent as a member instead of in the slots, as nsGenericElement does.
     void SetXULBindingParent(nsIContent* aBindingParent)
     {
       mBindingParent = aBindingParent;
     }
 
-    const nsAttrValue* GetAttrValue(const nsAString& aName);
-
-    /**
-     * Get the attr info for the given namespace ID and attribute name.
-     * The namespace ID must not be kNameSpaceID_Unknown and the name
-     * must not be null.
-     */
-    virtual nsAttrInfo GetAttrInfo(PRInt32 aNamespaceID, nsIAtom* aName) const;
-
     virtual nsXPCClassInfo* GetClassInfo();
 
     virtual nsIDOMNode* AsDOMNode() { return this; }
 protected:
-    // XXX This can be removed when nsNodeUtils::CloneAndAdopt doesn't need
-    //     access to mPrototype anymore.
-    friend class nsNodeUtils;
 
     // This can be removed if EnsureContentsGenerated dies.
     friend class nsNSElementTearoff;
 
     // Implementation methods
     nsresult EnsureContentsGenerated(void) const;
 
     nsresult ExecuteOnBroadcastHandler(nsIDOMElement* anElement, const nsAString& attrName);
@@ -531,34 +446,26 @@ protected:
 
         nsRefPtr<nsFrameLoader> mFrameLoader;
     };
 
     virtual nsINode::nsSlots* CreateSlots();
 
     nsresult LoadSrc();
 
-    // Required fields
-    nsRefPtr<nsXULPrototypeElement>     mPrototype;
-
     /**
      * The nearest enclosing content node with a binding
      * that created us. [Weak]
      */
     nsIContent*                         mBindingParent;
 
     /**
      * Abandon our prototype linkage, and copy all attributes locally
      */
-    nsresult MakeHeavyweight();
-
-    const nsAttrValue* FindLocalOrProtoAttr(PRInt32 aNameSpaceID,
-                                            nsIAtom *aName) const {
-        return nsXULElement::GetAttrInfo(aNameSpaceID, aName).mValue;
-    }
+    nsresult MakeHeavyweight(nsXULPrototypeElement* aPrototype);
 
     virtual nsresult BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                    const nsAttrValueOrString* aValue,
                                    bool aNotify);
     virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                   const nsAttrValue* aValue, bool aNotify);
 
     virtual void UpdateEditableState(bool aNotify);
@@ -567,39 +474,32 @@ protected:
                                   nsIAtom* aAttribute,
                                   const nsAString& aValue,
                                   nsAttrValue& aResult);
 
     virtual nsEventListenerManager*
       GetEventListenerManagerForAttr(nsIAtom* aAttrName, bool* aDefer);
   
     /**
-     * Return our prototype's attribute, if one exists.
-     */
-    nsXULPrototypeAttribute *FindPrototypeAttribute(PRInt32 aNameSpaceID,
-                                                    nsIAtom *aName) const;
-    /**
      * Add a listener for the specified attribute, if appropriate.
      */
     void AddListenerFor(const nsAttrName& aName,
                         bool aCompileEventHandlers);
     void MaybeAddPopupListener(nsIAtom* aLocalName);
 
     nsIWidget* GetWindowWidget();
 
     // attribute setters for widget
     nsresult HideWindowChrome(bool aShouldHide);
     void SetChromeMargins(const nsAttrValue* aValue);
     void ResetChromeMargins();
     void SetTitlebarColor(nscolor aColor, bool aActive);
 
     void SetDrawsInTitlebar(bool aState);
 
-    const nsAttrName* InternalGetExistingAttrNameFromQName(const nsAString& aStr) const;
-
     void RemoveBroadcaster(const nsAString & broadcasterId);
 
 protected:
     // Internal accessor. This shadows the 'Slots', and returns
     // appropriate value.
     nsIControllers *Controllers() {
       nsDOMSlots* slots = GetExistingDOMSlots();
       return slots ? slots->mControllers : nsnull; 
@@ -612,18 +512,16 @@ protected:
     NS_NewXULElement(nsIContent** aResult, nsINodeInfo *aNodeInfo);
     friend void
     NS_TrustedNewXULElement(nsIContent** aResult, nsINodeInfo *aNodeInfo);
 
     static already_AddRefed<nsXULElement>
     Create(nsXULPrototypeElement* aPrototype, nsINodeInfo *aNodeInfo,
            bool aIsScriptable);
 
-    friend class nsScriptEventHandlerOwnerTearoff;
-
     bool IsReadWriteTextElement() const
     {
         const nsIAtom* tag = Tag();
         return
             GetNameSpaceID() == kNameSpaceID_XUL &&
             (tag == nsGkAtoms::textbox || tag == nsGkAtoms::textarea) &&
             !HasAttr(kNameSpaceID_None, nsGkAtoms::readonly);
     }
--- a/dom/apps/src/AppsService.js
+++ b/dom/apps/src/AppsService.js
@@ -9,17 +9,16 @@ function debug(s) {
 }
 
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Webapps.jsm");
 
-const APPS_SERVICE_CONTRACTID = "@mozilla.org/AppsService;1";
 const APPS_SERVICE_CID        = Components.ID("{05072afa-92fe-45bf-ae22-39b69c117058}");
 
 function AppsService()
 {
   debug("AppsService Constructor");
 }
 
 AppsService.prototype = {
@@ -30,17 +29,11 @@ AppsService.prototype = {
 
   getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aManifestURL) {
     debug("getAppLocalIdByManifestURL( " + aManifestURL + " )");
     return DOMApplicationRegistry.getAppLocalIdByManifestURL(aManifestURL);
   },
 
   classID : APPS_SERVICE_CID,
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService]),
-
-  classInfo : XPCOMUtils.generateCI({classID: APPS_SERVICE_CID,
-                                     contractID: APPS_SERVICE_CONTRACTID,
-                                     classDescription: "AppsService",
-                                     interfaces: [Ci.nsIAppsService],
-                                     flags: Ci.nsIClassInfo.DOM_OBJECT})
 }
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([AppsService])
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -51,17 +51,16 @@ EXPORTS = \
   nsIDOMScriptObjectFactory.h \
   nsIJSEventListener.h \
   nsIJSNativeInitializer.h \
   nsIScriptContext.h	\
   nsIScriptExternalNameSet.h \
   nsIScriptGlobalObject.h \
   nsIScriptGlobalObjectOwner.h \
   nsIScriptNameSpaceManager.h \
-  nsIScriptEventHandlerOwner.h \
   nsIScriptObjectPrincipal.h \
   nsIScriptRuntime.h \
   nsIScriptTimeoutHandler.h \
   nsPIDOMWindow.h \
   nsPIWindowRoot.h \
   nsFocusManager.h \
   nsWrapperCache.h \
   nsContentPermissionHelper.h \
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -153,16 +153,20 @@ Navigator::Invalidate()
     mSmsManager->Shutdown();
     mSmsManager = nsnull;
   }
 
 #ifdef MOZ_B2G_RIL
   if (mTelephony) {
     mTelephony = nsnull;
   }
+
+  if (mVoicemail) {
+    mVoicemail = nsnull;
+  }
 #endif
 
   if (mConnection) {
     mConnection->Shutdown();
     mConnection = nsnull;
   }
 
   if (mMobileConnection) {
@@ -1175,16 +1179,47 @@ Navigator::GetMozTelephony(nsIDOMTelepho
     // mTelephony may be null here!
     telephony = mTelephony;
   }
 
   telephony.forget(aTelephony);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+Navigator::GetMozVoicemail(nsIDOMMozVoicemail** aVoicemail)
+{
+  *aVoicemail = nsnull;
+
+  if (!mVoicemail) {
+    nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+    NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK);
+
+    // Chrome is always allowed access, so do the permission check only
+    // for non-chrome pages.
+    if (!nsContentUtils::IsCallerChrome()) {
+      nsCOMPtr<nsIDocument> doc = do_QueryInterface(window->GetExtantDocument());
+      NS_ENSURE_TRUE(doc, NS_OK);
+
+      nsCOMPtr<nsIURI> uri;
+      doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
+
+      if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.voicemail.whitelist")) {
+        return NS_OK;
+      }
+    }
+
+    nsresult rv = NS_NewVoicemail(window, getter_AddRefs(mVoicemail));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  NS_ADDREF(*aVoicemail = mVoicemail);
+  return NS_OK;
+}
+
 #endif // MOZ_B2G_RIL
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorNetwork
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozConnection(nsIDOMMozConnection** aConnection)
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -27,16 +27,17 @@ class nsIDOMMozConnection;
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 #include "nsIDOMNavigatorUserMedia.h"
 #endif
 
 #ifdef MOZ_B2G_RIL
 #include "nsIDOMNavigatorTelephony.h"
 class nsIDOMTelephony;
+class nsIDOMMozVoicemail;
 #endif
 
 #ifdef MOZ_B2G_BT
 #include "nsIDOMNavigatorBluetooth.h"
 #endif
 
 #include "nsIDOMNavigatorSystemMessages.h"
 
@@ -142,16 +143,17 @@ private:
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<nsGeolocation> mGeolocation;
   nsRefPtr<nsDesktopNotificationCenter> mNotification;
   nsRefPtr<battery::BatteryManager> mBatteryManager;
   nsRefPtr<power::PowerManager> mPowerManager;
   nsRefPtr<sms::SmsManager> mSmsManager;
 #ifdef MOZ_B2G_RIL
   nsCOMPtr<nsIDOMTelephony> mTelephony;
+  nsCOMPtr<nsIDOMMozVoicemail> mVoicemail;
 #endif
   nsRefPtr<network::Connection> mConnection;
   nsRefPtr<network::MobileConnection> mMobileConnection;
 #ifdef MOZ_B2G_BT
   nsCOMPtr<nsIDOMBluetoothManager> mBluetooth;
 #endif
   nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager;
   nsWeakPtr mWindow;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -80,17 +80,16 @@
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIScriptExternalNameSet.h"
 #include "nsJSUtils.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsScriptNameSpaceManager.h"
-#include "nsIScriptEventHandlerOwner.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsJSEnvironment.h"
 
 // DOM base includes
 #include "nsIDOMPluginArray.h"
 #include "nsIDOMPlugin.h"
 #include "nsIDOMMimeTypeArray.h"
 #include "nsIDOMMimeType.h"
@@ -507,16 +506,18 @@ using mozilla::dom::indexedDB::IDBWrappe
 #include "nsIDOMMobileConnection.h"
 #include "USSDReceivedEvent.h"
 #include "mozilla/dom/network/Utils.h"
 
 #ifdef MOZ_B2G_RIL
 #include "Telephony.h"
 #include "TelephonyCall.h"
 #include "CallEvent.h"
+#include "nsIDOMVoicemail.h"
+#include "nsIDOMVoicemailEvent.h"
 #endif
 
 #ifdef MOZ_B2G_BT
 #include "BluetoothManager.h"
 #include "BluetoothAdapter.h"
 #include "BluetoothDevice.h"
 #include "BluetoothDeviceEvent.h"
 #endif
@@ -1662,16 +1663,20 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(MozWifiConnectionInfoEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(Telephony, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(TelephonyCall, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CallEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(MozVoicemail, nsEventTargetSH,
+                           EVENTTARGET_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(MozVoicemailEvent, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
 #ifdef MOZ_B2G_BT
   NS_DEFINE_CLASSINFO_DATA(BluetoothManager, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)  
   NS_DEFINE_CLASSINFO_DATA(BluetoothDevice, nsEventTargetSH,
@@ -4475,16 +4480,26 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMTelephonyCall)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(CallEvent, nsIDOMCallEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCallEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
   DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(MozVoicemail, nsIDOMMozVoicemail)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozVoicemail)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(MozVoicemailEvent, nsIDOMMozVoicemailEvent)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozVoicemailEvent)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
+  DOM_CLASSINFO_MAP_END
 #endif
 
 #ifdef MOZ_B2G_BT
   DOM_CLASSINFO_MAP_BEGIN(BluetoothManager, nsIDOMBluetoothManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothManager)
   DOM_CLASSINFO_MAP_END  
 
   DOM_CLASSINFO_MAP_BEGIN(BluetoothAdapter, nsIDOMBluetoothAdapter)
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -518,16 +518,18 @@ DOMCI_CLASS(MozContactChangeEvent)
 DOMCI_CLASS(MozApplicationEvent)
 
 #ifdef MOZ_B2G_RIL
 DOMCI_CLASS(MozWifiStatusChangeEvent)
 DOMCI_CLASS(MozWifiConnectionInfoEvent)
 DOMCI_CLASS(Telephony)
 DOMCI_CLASS(TelephonyCall)
 DOMCI_CLASS(CallEvent)
+DOMCI_CLASS(MozVoicemail)
+DOMCI_CLASS(MozVoicemailEvent)
 #endif
 
 #ifdef MOZ_B2G_BT
 DOMCI_CLASS(BluetoothManager)
 DOMCI_CLASS(BluetoothAdapter)
 DOMCI_CLASS(BluetoothDevice)
 DOMCI_CLASS(BluetoothDeviceEvent)
 #endif
deleted file mode 100644
--- a/dom/base/nsIScriptEventHandlerOwner.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsIScriptEventHandlerOwner_h__
-#define nsIScriptEventHandlerOwner_h__
-
-#include "nsISupports.h"
-#include "nsIScriptContext.h"
-#include "nsAString.h"
-
-template<class> class nsScriptObjectHolder;
-
-class nsIAtom;
-
-#define NS_ISCRIPTEVENTHANDLEROWNER_IID \
-{ 0xc8f35f71, 0x07d1, 0x4ff3, \
-  { 0xa3, 0x2f, 0x65, 0xcb, 0x35, 0x64, 0xac, 0xe0 } }
-
-/**
- * Associate a compiled event handler with its target object, which owns it
- * This is an adjunct to nsIScriptObjectOwner that nsEventListenerManager's
- * implementation queries for, in order to avoid recompiling a recurrent or
- * prototype-inherited event handler.
- */
-class nsIScriptEventHandlerOwner : public nsISupports
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTEVENTHANDLEROWNER_IID)
-
-  /**
-   * Compile the specified event handler.  This does NOT bind it to
-   * anything.  That's the caller's responsibility.
-   *
-   * @param aContext the context to use when creating event handler
-   * @param aName the name of the handler
-   * @param aBody the handler script body
-   * @param aURL the URL or filename for error messages
-   * @param aLineNo the starting line number of the script for error messages
-   * @param aHandler the holder for the compiled handler object
-   */
-  virtual nsresult CompileEventHandler(nsIScriptContext* aContext,
-                                       nsIAtom *aName,
-                                       const nsAString& aBody,
-                                       const char* aURL,
-                                       PRUint32 aLineNo,
-                                       nsScriptObjectHolder<JSObject>& aHandler) = 0;
-
-  /**
-   * Retrieve an already-compiled event handler that can be bound to a
-   * target object using a script context.
-   *
-   * @param aName the name of the event handler to retrieve
-   * @param aHandler the holder for the compiled event handler.
-   */
-  virtual nsresult GetCompiledEventHandler(nsIAtom *aName,
-                                           nsScriptObjectHolder<JSObject>& aHandler) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptEventHandlerOwner,
-                              NS_ISCRIPTEVENTHANDLEROWNER_IID)
-
-#endif // nsIScriptEventHandlerOwner_h__
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -32,16 +32,17 @@
 #include "nsDOMError.h"
 #include "nsDOMClassInfoID.h"
 #include "nsCRT.h"
 #include "nsIProtocolHandler.h"
 #include "nsReadableUtils.h"
 #include "nsITextToSubURI.h"
 #include "nsJSUtils.h"
 #include "jsfriendapi.h"
+#include "nsContentUtils.h"
 
 static nsresult
 GetContextFromStack(nsIJSContextStack *aStack, JSContext **aContext)
 {
   nsCOMPtr<nsIJSContextStackIterator>
     iterator(do_CreateInstance("@mozilla.org/js/xpc/ContextStackIterator;1"));
   NS_ENSURE_TRUE(iterator, NS_ERROR_FAILURE);
 
@@ -163,28 +164,34 @@ GetFrameDocument(JSContext *cx, JSStackF
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
   return doc.forget();
 }
 
 nsresult
 nsLocation::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
 {
   *aLoadInfo = nsnull;
+  JSContext* cx;
+  if ((cx = nsContentUtils::GetCurrentJSContext())) {
+    nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+    NS_ENSURE_STATE(ssm);
+    // Check to see if URI is allowed.
+    nsresult rv = ssm->CheckLoadURIFromScript(cx, aURI);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
   NS_ENSURE_TRUE(docShell, NS_ERROR_NOT_AVAILABLE);
 
   nsresult rv;
   // Get JSContext from stack.
   nsCOMPtr<nsIJSContextStack>
     stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  JSContext *cx;
-
   NS_ENSURE_SUCCESS(GetContextFromStack(stack, &cx), NS_ERROR_FAILURE);
 
   nsCOMPtr<nsISupports> owner;
   nsCOMPtr<nsIURI> sourceURI;
 
   if (cx) {
     // No cx means that there's no JS running, or at least no JS that
     // was run through code that properly pushed a context onto the
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -420,10 +420,152 @@ ThrowingConstructor(JSContext* cx, unsig
 }
 
 JSBool
 ThrowingConstructorWorkers(JSContext* cx, unsigned argc, JS::Value* vp)
 {
   return Throw<false>(cx, NS_ERROR_FAILURE);
 }
 
+bool
+XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
+                    JSPropertyDescriptor* desc,
+                    // And the things we need to determine the descriptor
+                    Prefable<JSFunctionSpec>* methods,
+                    jsid* methodIds,
+                    JSFunctionSpec* methodSpecs,
+                    size_t methodCount,
+                    Prefable<JSPropertySpec>* attributes,
+                    jsid* attributeIds,
+                    JSPropertySpec* attributeSpecs,
+                    size_t attributeCount,
+                    Prefable<ConstantSpec>* constants,
+                    jsid* constantIds,
+                    ConstantSpec* constantSpecs,
+                    size_t constantCount)
+{
+  for (size_t prefIdx = 0; prefIdx < methodCount; ++prefIdx) {
+    MOZ_ASSERT(methods[prefIdx].specs);
+    if (methods[prefIdx].enabled) {
+      // Set i to be the index into our full list of ids/specs that we're
+      // looking at now.
+      size_t i = methods[prefIdx].specs - methodSpecs;
+      for ( ; methodIds[i] != JSID_VOID; ++i) {
+        if (id == methodIds[i]) {
+          JSFunction *fun = JS_NewFunctionById(cx, methodSpecs[i].call,
+                                               methodSpecs[i].nargs, 0,
+                                               wrapper, id);
+          if (!fun)
+              return false;
+          JSObject *funobj = JS_GetFunctionObject(fun);
+          desc->value.setObject(*funobj);
+          desc->attrs = methodSpecs[i].flags;
+          desc->obj = wrapper;
+          desc->setter = nsnull;
+          desc->getter = nsnull;
+          return true;
+        }
+      }
+    }
+  }
+
+  for (size_t prefIdx = 0; prefIdx < attributeCount; ++prefIdx) {
+    MOZ_ASSERT(attributes[prefIdx].specs);
+    if (attributes[prefIdx].enabled) {
+      // Set i to be the index into our full list of ids/specs that we're
+      // looking at now.
+      size_t i = attributes[prefIdx].specs - attributeSpecs;
+      for ( ; attributeIds[i] != JSID_VOID; ++i) {
+        if (id == attributeIds[i]) {
+          desc->attrs = attributeSpecs[i].flags;
+          desc->obj = wrapper;
+          desc->setter = attributeSpecs[i].setter;
+          desc->getter = attributeSpecs[i].getter;
+          return true;
+        }
+      }
+    }
+  }
+
+  for (size_t prefIdx = 0; prefIdx < constantCount; ++prefIdx) {
+    MOZ_ASSERT(constants[prefIdx].specs);
+    if (constants[prefIdx].enabled) {
+      // Set i to be the index into our full list of ids/specs that we're
+      // looking at now.
+      size_t i = constants[prefIdx].specs - constantSpecs;
+      for ( ; constantIds[i] != JSID_VOID; ++i) {
+        if (id == constantIds[i]) {
+          desc->attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
+          desc->obj = wrapper;
+          desc->value = constantSpecs[i].value;
+          return true;
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
+bool
+XrayEnumerateProperties(JS::AutoIdVector& props,
+                        Prefable<JSFunctionSpec>* methods,
+                        jsid* methodIds,
+                        JSFunctionSpec* methodSpecs,
+                        size_t methodCount,
+                        Prefable<JSPropertySpec>* attributes,
+                        jsid* attributeIds,
+                        JSPropertySpec* attributeSpecs,
+                        size_t attributeCount,
+                        Prefable<ConstantSpec>* constants,
+                        jsid* constantIds,
+                        ConstantSpec* constantSpecs,
+                        size_t constantCount)
+{
+  for (size_t prefIdx = 0; prefIdx < methodCount; ++prefIdx) {
+    MOZ_ASSERT(methods[prefIdx].specs);
+    if (methods[prefIdx].enabled) {
+      // Set i to be the index into our full list of ids/specs that we're
+      // looking at now.
+      size_t i = methods[prefIdx].specs - methodSpecs;
+      for ( ; methodIds[i] != JSID_VOID; ++i) {
+        if ((methodSpecs[i].flags & JSPROP_ENUMERATE) &&
+            !props.append(methodIds[i])) {
+          return false;
+        }
+      }
+    }
+  }
+
+  for (size_t prefIdx = 0; prefIdx < attributeCount; ++prefIdx) {
+    MOZ_ASSERT(attributes[prefIdx].specs);
+    if (attributes[prefIdx].enabled) {
+      // Set i to be the index into our full list of ids/specs that we're
+      // looking at now.
+      size_t i = attributes[prefIdx].specs - attributeSpecs;
+      for ( ; attributeIds[i] != JSID_VOID; ++i) {
+        if ((attributeSpecs[i].flags & JSPROP_ENUMERATE) &&
+            !props.append(attributeIds[i])) {
+          return false;
+        }
+      }
+    }
+  }
+
+  for (size_t prefIdx = 0; prefIdx < constantCount; ++prefIdx) {
+    MOZ_ASSERT(constants[prefIdx].specs);
+    if (constants[prefIdx].enabled) {
+      // Set i to be the index into our full list of ids/specs that we're
+      // looking at now.
+      size_t i = constants[prefIdx].specs - constantSpecs;
+      for ( ; constantIds[i] != JSID_VOID; ++i) {
+        if (!props.append(constantIds[i])) {
+          return false;
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1003,12 +1003,45 @@ public:
     const T& Value() const {
       return *storage.addr();
     }
     void Destroy() {
       storage.addr()->~T();
     }
 };
 
+// Implementation of the bits that XrayWrapper needs
+bool
+XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
+                    JSPropertyDescriptor* desc,
+                    // And the things we need to determine the descriptor
+                    Prefable<JSFunctionSpec>* methods,
+                    jsid* methodIds,
+                    JSFunctionSpec* methodSpecs,
+                    size_t methodCount,
+                    Prefable<JSPropertySpec>* attributes,
+                    jsid* attributeIds,
+                    JSPropertySpec* attributeSpecs,
+                    size_t attributeCount,
+                    Prefable<ConstantSpec>* constants,
+                    jsid* constantIds,
+                    ConstantSpec* constantSpecs,
+                    size_t constantCount);
+
+bool
+XrayEnumerateProperties(JS::AutoIdVector& props,
+                        Prefable<JSFunctionSpec>* methods,
+                        jsid* methodIds,
+                        JSFunctionSpec* methodSpecs,
+                        size_t methodCount,
+                        Prefable<JSPropertySpec>* attributes,
+                        jsid* attributeIds,
+                        JSPropertySpec* attributeSpecs,
+                        size_t attributeCount,
+                        Prefable<ConstantSpec>* constants,
+                        jsid* constantIds,
+                        ConstantSpec* constantSpecs,
+                        size_t constantCount);
+
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_BindingUtils_h__ */
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -764,21 +764,22 @@ class PropertyDefiner:
         return len(self.regular) > 0
     def variableName(self, chrome):
         if chrome and self.hasChromeOnly():
             return "sChrome" + self.name
         if self.hasNonChromeOnly():
             return "s" + self.name
         return "NULL"
     def usedForXrays(self, chrome):
-        # We only need Xrays for methods and attributes.  And we only need them
-        # for the non-chrome ones if we have no chromeonly things.  Otherwise
-        # (we have chromeonly attributes) we need Xrays for the chrome
-        # methods/attributes.  Finally, in workers there are no Xrays.
-        return ((self.name is "Methods" or self.name is "Attributes") and
+        # We only need Xrays for methods, attributes and constants.  And we only
+        # need them for the non-chrome ones if we have no chromeonly things.
+        # Otherwise (we have chromeonly attributes) we need Xrays for the chrome
+        # methods/attributes/constants.  Finally, in workers there are no Xrays.
+        return ((self.name is "Methods" or self.name is "Attributes" or
+                 self.name is "Constants") and
                 chrome == self.hasChromeOnly() and
                 not self.descriptor.workers)
 
     def __str__(self):
         # We only need to generate id arrays for things that will end
         # up used via ResolveProperty or EnumerateProperties.
         str = self.generateArray(self.regular, self.variableName(False),
                                  self.usedForXrays(False))
@@ -1007,17 +1008,17 @@ class PropertyArrays():
         self.consts = ConstDefiner(descriptor, "Constants")
 
     @staticmethod
     def arrayNames():
         return [ "staticMethods", "methods", "attrs", "consts" ]
 
     @staticmethod
     def xrayRelevantArrayNames():
-        return [ "methods", "attrs" ]
+        return [ "methods", "attrs", "consts" ]
 
     def hasChromeOnly(self):
         return reduce(lambda b, a: b or getattr(self, a).hasChromeOnly(),
                       self.arrayNames(), False)
     def variableNames(self, chrome):
         names = {}
         for array in self.arrayNames():
             names[array] = getattr(self, array).variableName(chrome)
@@ -3788,132 +3789,76 @@ class CGClass(CGThing):
         result = ''
         itemCount = 0
         for (memberList, separator) in order:
             (memberString, itemCount) = defineMembers(self, memberList,
                                                       itemCount, separator)
             result = result + memberString
         return result
 
-class CGResolveProperty(CGAbstractMethod):
-    def __init__(self, descriptor, properties):
-        args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
-                Argument('jsid', 'id'), Argument('bool', 'set'),
-                Argument('JSPropertyDescriptor*', 'desc')]
-        CGAbstractMethod.__init__(self, descriptor, "ResolveProperty", "bool", args)
+class CGXrayHelper(CGAbstractMethod):
+    def __init__(self, descriptor, name, args, properties):
+        CGAbstractMethod.__init__(self, descriptor, name, "bool", args)
         self.properties = properties
+
     def definition_body(self):
-        str = ""
-
         varNames = self.properties.variableNames(True)
 
         methods = self.properties.methods
         if methods.hasNonChromeOnly() or methods.hasChromeOnly():
-            str += """  // %(methods)s has an end-of-list marker at the end that we ignore
-  for (size_t prefIdx = 0; prefIdx < ArrayLength(%(methods)s)-1; ++prefIdx) {
-    MOZ_ASSERT(%(methods)s[prefIdx].specs);
-    if (%(methods)s[prefIdx].enabled) {
-      // Set i to be the index into our full list of ids/specs that we're
-      // looking at now.
-      size_t i = %(methods)s[prefIdx].specs - %(methods)s_specs;
-      for ( ; %(methods)s_ids[i] != JSID_VOID; ++i) {
-        if (id == %(methods)s_ids[i]) {
-          JSFunction *fun = JS_NewFunctionById(cx, %(methods)s_specs[i].call, %(methods)s_specs[i].nargs, 0, wrapper, id);
-          if (!fun)
-              return false;
-          JSObject *funobj = JS_GetFunctionObject(fun);
-          desc->value.setObject(*funobj);
-          desc->attrs = %(methods)s_specs[i].flags;
-          desc->obj = wrapper;
-          desc->setter = nsnull;
-          desc->getter = nsnull;
-          return true;
-        }
-      }
-    }
-  }
-
-""" % varNames
+            methodArgs = """// %(methods)s has an end-of-list marker at the end that we ignore
+%(methods)s, %(methods)s_ids, %(methods)s_specs, ArrayLength(%(methods)s) - 1""" % varNames
+        else:
+            methodArgs = "NULL, NULL, NULL, 0"
+        methodArgs = CGGeneric(methodArgs)
 
         attrs = self.properties.attrs
         if attrs.hasNonChromeOnly() or attrs.hasChromeOnly():
-            str += """  // %(attrs)s has an end-of-list marker at the end that we ignore
-  for (size_t prefIdx = 0; prefIdx < ArrayLength(%(attrs)s)-1; ++prefIdx) {
-    MOZ_ASSERT(%(attrs)s[prefIdx].specs);
-    if (%(attrs)s[prefIdx].enabled) {
-      // Set i to be the index into our full list of ids/specs that we're
-      // looking at now.
-      size_t i = %(attrs)s[prefIdx].specs - %(attrs)s_specs;;
-      for ( ; %(attrs)s_ids[i] != JSID_VOID; ++i) {
-        if (id == %(attrs)s_ids[i]) {
-          desc->attrs = %(attrs)s_specs[i].flags;
-          desc->obj = wrapper;
-          desc->setter = %(attrs)s_specs[i].setter;
-          desc->getter = %(attrs)s_specs[i].getter;
-          return true;
-        }
-      }
-    }
-  }
-
-""" % varNames
-
-        return str + "  return true;"
-
-class CGEnumerateProperties(CGAbstractMethod):
+            attrArgs = """// %(attrs)s has an end-of-list marker at the end that we ignore
+%(attrs)s, %(attrs)s_ids, %(attrs)s_specs, ArrayLength(%(attrs)s) - 1""" % varNames
+        else:
+            attrArgs = "NULL, NULL, NULL, 0"
+        attrArgs = CGGeneric(attrArgs)
+
+        consts = self.properties.consts
+        if consts.hasNonChromeOnly() or consts.hasChromeOnly():
+            constArgs = """// %(consts)s has an end-of-list marker at the end that we ignore
+%(consts)s, %(consts)s_ids, %(consts)s_specs, ArrayLength(%(consts)s) - 1""" % varNames
+        else:
+            constArgs = "NULL, NULL, NULL, 0"
+        constArgs = CGGeneric(constArgs)
+
+        prefixArgs = CGGeneric(self.getPrefixArgs())
+
+        return CGIndenter(
+            CGWrapper(CGList([prefixArgs, methodArgs, attrArgs, constArgs], ",\n"),
+                      pre=("return Xray%s(" % self.name),
+                      post=");",
+                      reindent=True)).define()
+
+class CGResolveProperty(CGXrayHelper):
+    def __init__(self, descriptor, properties):
+        args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'wrapper'),
+                Argument('jsid', 'id'), Argument('bool', 'set'),
+                Argument('JSPropertyDescriptor*', 'desc')]
+        CGXrayHelper.__init__(self, descriptor, "ResolveProperty", args,
+                              properties)
+
+    def getPrefixArgs(self):
+        return "cx, wrapper, id, desc"
+
+
+class CGEnumerateProperties(CGXrayHelper):
     def __init__(self, descriptor, properties):
         args = [Argument('JS::AutoIdVector&', 'props')]
-        CGAbstractMethod.__init__(self, descriptor, "EnumerateProperties", "bool", args)
-        self.properties = properties
-    def definition_body(self):
-        str = ""
-
-        varNames = self.properties.variableNames(True)
-
-        methods = self.properties.methods
-        if methods.hasNonChromeOnly() or methods.hasChromeOnly():
-            str += """  // %(methods)s has an end-of-list marker at the end that we ignore
-  for (size_t prefIdx = 0; prefIdx < ArrayLength(%(methods)s)-1; ++prefIdx) {
-    MOZ_ASSERT(%(methods)s[prefIdx].specs);
-    if (%(methods)s[prefIdx].enabled) {
-      // Set i to be the index into our full list of ids/specs that we're
-      // looking at now.
-      size_t i = %(methods)s[prefIdx].specs - %(methods)s_specs;
-      for ( ; %(methods)s_ids[i] != JSID_VOID; ++i) {
-        if ((%(methods)s_specs[i].flags & JSPROP_ENUMERATE) &&
-            !props.append(%(methods)s_ids[i])) {
-          return false;
-        }
-      }
-    }
-  }
-
-""" % varNames
-
-        attrs = self.properties.attrs
-        if attrs.hasNonChromeOnly() or attrs.hasChromeOnly():
-            str += """  // %(attrs)s has an end-of-list marker at the end that we ignore
-  for (size_t prefIdx = 0; prefIdx < ArrayLength(%(attrs)s)-1; ++prefIdx) {
-    MOZ_ASSERT(%(attrs)s[prefIdx].specs);
-    if (%(attrs)s[prefIdx].enabled) {
-      // Set i to be the index into our full list of ids/specs that we're
-      // looking at now.
-      size_t i = %(attrs)s[prefIdx].specs - %(attrs)s_specs;;
-      for ( ; %(attrs)s_ids[i] != JSID_VOID; ++i) {
-        if ((%(attrs)s_specs[i].flags & JSPROP_ENUMERATE) &&
-            !props.append(%(attrs)s_ids[i])) {
-          return false;
-        }
-      }
-    }
-  }
-
-""" % varNames
-
-        return str + "  return true;"
+        CGXrayHelper.__init__(self, descriptor, "EnumerateProperties", args,
+                              properties)
+
+    def getPrefixArgs(self):
+        return "props"
 
 class CGPrototypeTraitsClass(CGClass):
     def __init__(self, descriptor, indent=''):
         templateArgs = [Argument('prototypes::ID', 'PrototypeID')]
         templateSpecialization = ['prototypes::id::' + descriptor.name]
         enums = [ClassEnum('', ['Depth'],
                            [descriptor.interface.inheritanceDepth()])]
         typedefs = [ClassTypedef('NativeType', descriptor.nativeType)]
--- a/dom/bluetooth/BluetoothManager.h
+++ b/dom/bluetooth/BluetoothManager.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_dom_bluetooth_bluetoothmanager_h__
 #define mozilla_dom_bluetooth_bluetoothmanager_h__
 
 #include "BluetoothCommon.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIDOMBluetoothManager.h"
 #include "mozilla/Observer.h"
+#include "nsIEventTarget.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothManager : public nsDOMEventTargetHelper
                        , public nsIDOMBluetoothManager
                        , public BluetoothSignalObserver
 {
 public:
--- a/dom/browser-element/BrowserElementChild.js
+++ b/dom/browser-element/BrowserElementChild.js
@@ -117,16 +117,17 @@ BrowserElementChild.prototype = {
 
     addMsgListener("get-screenshot", this._recvGetScreenshot);
     addMsgListener("set-visible", this._recvSetVisible);
     addMsgListener("get-can-go-back", this._recvCanGoBack);
     addMsgListener("get-can-go-forward", this._recvCanGoForward);
     addMsgListener("go-back", this._recvGoBack);
     addMsgListener("go-forward", this._recvGoForward);
     addMsgListener("reload", this._recvReload);
+    addMsgListener("stop", this._recvStop);
     addMsgListener("unblock-modal-prompt", this._recvStopWaiting);
     addMsgListener("fire-ctx-callback", this._recvFireCtxCallback);
 
     let els = Cc["@mozilla.org/eventlistenerservice;1"]
                 .getService(Ci.nsIEventListenerService);
 
     // We are using the system group for those events so if something in the
     // content called .stopPropagation() this will still be called.
@@ -476,16 +477,21 @@ BrowserElementChild.prototype = {
       webNav.LOAD_FLAGS_NONE;
     try {
       webNav.reload(reloadFlags);
     } catch(e) {
       // Silently swallow errors; these can happen if a used cancels reload
     }
   },
 
+  _recvStop: function(data) {
+    let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
+    webNav.stop(webNav.STOP_NETWORK);
+  },
+
   _keyEventHandler: function(e) {
     if (whitelistedEvents.indexOf(e.keyCode) != -1 && !e.defaultPrevented) {
       sendAsyncMsg('keyevent', {
         type: e.type,
         keyCode: e.keyCode,
         charCode: e.charCode,
       });
     }
--- a/dom/browser-element/BrowserElementParent.js
+++ b/dom/browser-element/BrowserElementParent.js
@@ -164,16 +164,17 @@ function BrowserElementParent(frameLoade
     XPCNativeWrapper.unwrap(self._frameElement)[domName] = self._sendDOMRequest.bind(self, msgName);
   }
 
   // Define methods on the frame element.
   defineMethod('setVisible', this._setVisible);
   defineMethod('goBack', this._goBack);
   defineMethod('goForward', this._goForward);
   defineMethod('reload', this._reload);
+  defineMethod('stop', this._stop);
   defineDOMRequestMethod('getScreenshot', 'get-screenshot');
   defineDOMRequestMethod('getCanGoBack', 'get-can-go-back');
   defineDOMRequestMethod('getCanGoForward', 'get-can-go-forward');
 }
 
 BrowserElementParent.prototype = {
   get _window() {
     return this._frameElement.ownerDocument.defaultView;
@@ -336,16 +337,20 @@ BrowserElementParent.prototype = {
   _goForward: function() {
     this._sendAsyncMsg('go-forward');
   },
 
   _reload: function(hardReload) {
     this._sendAsyncMsg('reload', {hardReload: hardReload});
   },
 
+  _stop: function() {
+    this._sendAsyncMsg('stop');
+  },
+
   _fireKeyEvent: function(data) {
     let evt = this._window.document.createEvent("KeyboardEvent");
     evt.initKeyEvent(data.json.type, true, true, this._window,
                      false, false, false, false, // modifiers
                      data.json.keyCode,
                      data.json.charCode);
 
     this._frameElement.dispatchEvent(evt);
--- a/dom/browser-element/mochitest/Makefile.in
+++ b/dom/browser-element/mochitest/Makefile.in
@@ -76,16 +76,19 @@ MOCHITEST_FILES = \
 		test_browserElement_inproc_OpenWindowRejected.html \
 		file_browserElement_OpenWindowRejected.html \
 		browserElement_SecurityChange.js \
 		test_browserElement_inproc_SecurityChange.html \
 		file_browserElement_SecurityChange.html \
 		browserElement_BackForward.js \
 	        file_bug741717.sjs \
 		browserElement_Reload.js \
+	        file_bug709759.sjs \
+		browserElement_Stop.js \
+                test_browserElement_inproc_Stop.html \
                 browserElement_ContextmenuEvents.js \
                 test_browserElement_inproc_ContextmenuEvents.html \
 		$(NULL)
 
 # Disabled due to https://bugzilla.mozilla.org/show_bug.cgi?id=774100
 #		test_browserElement_inproc_Reload.html \
 
 # OOP tests don't work on Windows (bug 763081) or native-fennec (bug
@@ -114,15 +117,16 @@ MOCHITEST_FILES += \
 		test_browserElement_oop_Close.html \
 		test_browserElement_oop_CloseFromOpener.html \
 		test_browserElement_oop_OpenWindow.html \
 		test_browserElement_oop_OpenWindowInFrame.html \
 		test_browserElement_oop_OpenWindowRejected.html \
 		test_browserElement_oop_SecurityChange.html \
 		test_browserElement_oop_BackForward.html \
 		test_browserElement_oop_Reload.html \
+		test_browserElement_oop_Stop.html \
                 test_browserElement_oop_ContextmenuEvents.html \
 		$(NULL)
 endif #}
 endif #}
 
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/browserElement_Stop.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the public domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Bug 709759 - Test the stop ability of <iframe mozbrowser>.
+
+// The img that is loaded will never be returned and will block
+// the page from loading, the timeout ensures that the page is
+// actually blocked from loading, once stop is called the
+// image load will be cancaelled and mozbrowserloadend should be called.
+
+"use strict";
+SimpleTest.waitForExplicitFinish();
+
+var iframe;
+var stopped = false;
+var imgSrc = 'http://test/tests/dom/browser-element/mochitest/file_bug709759.sjs';
+
+function runTest() {
+  browserElementTestHelpers.setEnabledPref(true);
+  browserElementTestHelpers.addToWhitelist();
+
+  iframe = document.createElement('iframe');
+  iframe.mozbrowser = true;
+
+  iframe.addEventListener('mozbrowserloadend', loadend);
+  iframe.src = 'data:text/html,<html>' +
+    '<body><img src="' + imgSrc + '" /></body></html>';
+
+  document.body.appendChild(iframe);
+
+  setTimeout(function() {
+    stopped = true;
+    iframe.stop();
+  }, 200);
+}
+
+function loadend() {
+  ok(stopped, 'Iframes network connections were stopped');
+  SimpleTest.finish();
+}
+
+runTest();
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/file_bug709759.sjs
@@ -0,0 +1,5 @@
+function handleRequest(request, response)
+{
+  response.processAsync();
+  response.setHeader("Content-Type", "image/jpeg", false);
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/test_browserElement_inproc_Stop.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test of browser element.</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script type="application/javascript;version=1.7" src="browserElement_Stop.js">
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/test_browserElement_oop_Stop.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test of browser element.</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script type="application/javascript;version=1.7" src="browserElement_Stop.js">
+</script>
+</body>
+</html>
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -20,16 +20,20 @@
 #include "nsContentUtils.h"
 #include "nsXULAppAPI.h"
 #include "TabChild.h"
 #include "DeviceStorageRequestChild.h"
 
 // Microsoft's API Name hackery sucks
 #undef CreateEvent
 
+#ifdef MOZ_WIDGET_GONK
+#include "nsIVolumeService.h"
+#endif
+
 using namespace mozilla::dom;
 using namespace mozilla::dom::devicestorage;
 
 #include "nsDirectoryServiceDefs.h"
 
 DeviceStorageFile::DeviceStorageFile(nsIFile* aFile, const nsAString& aPath)
   : mPath(aPath)
   , mEditable(false)
@@ -265,25 +269,36 @@ nsDOMDeviceStorage::SetRootFileForType(c
 {
   PRInt32 typeResult = DEVICE_STORAGE_TYPE_DEFAULT;
 
   nsCOMPtr<nsIFile> f;
   nsCOMPtr<nsIProperties> dirService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
   NS_ASSERTION(dirService, "Must have directory service");
 
 #ifdef MOZ_WIDGET_GONK
-  // check that /sdcard exists, if it doesn't go no further.
-  NS_NewLocalFile(NS_LITERAL_STRING("/sdcard"), false, getter_AddRefs(f));
-  bool check = false;
-  f->Exists(&check);
-  if (!check) {
-    mFile = nsnull;
+  mFile = nsnull;
+
+  nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
+  if (!vs) {
     return typeResult;
   }
-  f = nsnull;
+
+  nsCOMPtr<nsIVolume> v;
+  vs->GetVolumeByPath(NS_LITERAL_STRING("/sdcard"), getter_AddRefs(v));
+  
+  if (!v) {
+    return typeResult;
+  }
+
+  PRInt32 state;
+  v->GetState(&state);
+
+  if (state != nsIVolume::STATE_MOUNTED) {
+    return typeResult;
+  }
 #endif
 
   // Picture directory
   if (aType.Equals(NS_LITERAL_STRING("pictures"))) {
 #ifdef MOZ_WIDGET_GONK
     if (aIndex == 0) {
       NS_NewLocalFile(NS_LITERAL_STRING("/sdcard/DCIM"), false, getter_AddRefs(f));
     }
--- a/dom/file/FileHelper.h
+++ b/dom/file/FileHelper.h
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_filehelper_h__
 #define mozilla_dom_file_filehelper_h__
 
 #include "FileCommon.h"
 
 #include "nsIRequestObserver.h"
+#include "nsThreadUtils.h"
 
 class nsIFileStorage;
 
 BEGIN_FILE_NAMESPACE
 
 class FileHelper;
 class FileRequest;
 class FileOutputStreamWrapper;
--- a/dom/indexedDB/ipc/Makefile.in
+++ b/dom/indexedDB/ipc/Makefile.in
@@ -26,18 +26,17 @@ EXPORTS_mozilla/dom/indexedDB = Serializ
 
 LOCAL_INCLUDES += \
   -I$(topsrcdir)/dom/indexedDB \
   -I$(topsrcdir)/content/events/src \
   $(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
 
-# Bug 770046 - Cannot fail.
-# MOCHITEST_FILES = test_ipc.html
+MOCHITEST_FILES = test_ipc.html
 
 # Need to enable these tests sometime soon.
 #XPCSHELL_TESTS = unit
 
 # We're copying tests from another directory so this check is wrong for us.
 #NO_XPCSHELL_MANIFEST_CHECK = 1
 
 include $(topsrcdir)/config/config.mk
--- a/dom/indexedDB/test/head.js
+++ b/dom/indexedDB/test/head.js
@@ -53,16 +53,20 @@ function triggerMainCommand(popup)
 
 function triggerSecondaryCommand(popup, index)
 {
   info("triggering secondary command, " + index);
   let notifications = popup.childNodes;
   ok(notifications.length > 0, "at least one notification displayed");
   let notification = notifications[0];
 
+  // Cancel the arrow panel slide-in transition (bug 767133) such that
+  // it won't interfere with us interacting with the dropdown.
+  document.getAnonymousNodes(popup)[0].style.transition = "none";
+
   notification.button.focus();
 
   popup.addEventListener("popupshown", function () {
     popup.removeEventListener("popupshown", arguments.callee, false);
 
     // Press down until the desired command is selected
     for (let i = 0; i <= index; i++)
       EventUtils.synthesizeKey("VK_DOWN", {});
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -15,17 +15,17 @@ include protocol PIndexedDB;
 
 include "mozilla/dom/TabMessageUtils.h";
 include "gfxMatrix.h";
 include "mozilla/net/NeckoMessageUtils.h";
 include "IPC/nsGUIEventIPC.h";
 
 using IPC::URI;
 using gfxMatrix;
-using mozilla::LayersBackend;
+using mozilla::layers::LayersBackend;
 using mozilla::WindowsHandle;
 using nscolor;
 using nsCompositionEvent;
 using nsIMEUpdatePreference;
 using nsIntSize;
 using nsKeyEvent;
 using nsMouseEvent;
 using nsMouseScrollEvent;
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1025,17 +1025,17 @@ TabChild::InitWidget(const nsIntSize& si
     }
     mWidget->Create(
         nsnull, 0,              // no parents
         nsIntRect(nsIntPoint(0, 0), size),
         nsnull,                 // HandleWidgetEvent
         nsnull                  // nsDeviceContext
         );
 
-    LayerManager::LayersBackend be;
+    LayersBackend be;
     uint64_t id;
     int32_t maxTextureSize;
     RenderFrameChild* remoteFrame =
         static_cast<RenderFrameChild*>(SendPRenderFrameConstructor(
                                            &be, &maxTextureSize, &id));
     if (!remoteFrame) {
       NS_WARNING("failed to construct RenderFrame");
       return false;
--- a/dom/plugins/ipc/NestedLoopTimer.h
+++ b/dom/plugins/ipc/NestedLoopTimer.h
@@ -31,9 +31,11 @@ public Q_SLOTS:
 private:
     PluginModuleChild *mModule;
     QTimer *mQTimer;
 };
 
 } /* namespace plugins */
 } /* namespace mozilla */
 
+#undef slots
+
 #endif
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -8,16 +8,17 @@
 #include <glib.h>
 #elif XP_MACOSX
 #include "PluginInterposeOSX.h"
 #include "PluginUtilsOSX.h"
 #endif
 #ifdef MOZ_WIDGET_QT
 #include <QtCore/QCoreApplication>
 #include <QtCore/QEventLoop>
+#include "NestedLoopTimer.h"
 #endif
 
 #include "base/process_util.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/unused.h"
 #include "mozilla/ipc/SyncChannel.h"
 #include "mozilla/plugins/PluginModuleParent.h"
--- a/dom/settings/SettingsService.js
+++ b/dom/settings/SettingsService.js
@@ -128,19 +128,17 @@ SettingsServiceLock.prototype = {
 
   classInfo : XPCOMUtils.generateCI({classID: SETTINGSSERVICELOCK_CID,
                                      contractID: SETTINGSSERVICELOCK_CONTRACTID,
                                      classDescription: "SettingsServiceLock",
                                      interfaces: [nsISettingsServiceLock],
                                      flags: nsIClassInfo.DOM_OBJECT})
 };
 
-const SETTINGSSERVICE_CONTRACTID = "@mozilla.org/settingsService;1";
 const SETTINGSSERVICE_CID        = Components.ID("{3458e760-8513-11e1-b0c4-0800200c9a66}");
-const nsISettingsService         = Ci.nsISettingsService;
 
 let myGlobal = this;
 
 function SettingsService()
 {
   debug("settingsService Constructor");
   this._locks = new Queue();
   var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
@@ -166,18 +164,12 @@ SettingsService.prototype = {
       function() { lock.createTransactionAndProcess(); },
       function() { dump("ensureDB error cb!\n"); },
       myGlobal );
     this.nextTick(function() { this._open = false; }, lock);
     return lock;
   },
 
   classID : SETTINGSSERVICE_CID,
-  QueryInterface : XPCOMUtils.generateQI([nsISettingsService]),
-
-  classInfo : XPCOMUtils.generateCI({classID: SETTINGSSERVICE_CID,
-                                     contractID: SETTINGSSERVICE_CONTRACTID,
-                                     classDescription: "SettingsService",
-                                     interfaces: [nsISettingsService],
-                                     flags: nsIClassInfo.DOM_OBJECT})
+  QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService]),
 }
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock])
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -17,27 +17,30 @@ Cu.import("resource://gre/modules/ril_co
 const DEBUG = RIL.DEBUG_CONTENT_HELPER;
 
 const RILCONTENTHELPER_CID =
   Components.ID("{472816e1-1fd6-4405-996c-806f9ea68174}");
 const MOBILECONNECTIONINFO_CID =
   Components.ID("{a35cfd39-2d93-4489-ac7d-396475dacb27}");
 const MOBILENETWORKINFO_CID =
   Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}");
+const VOICEMAILSTATUS_CID=
+  Components.ID("{5467f2eb-e214-43ea-9b89-67711241ec8e}");
 
 const RIL_IPC_MSG_NAMES = [
   "RIL:CardStateChanged",
   "RIL:VoiceInfoChanged",
   "RIL:DataInfoChanged",
   "RIL:EnumerateCalls",
   "RIL:GetAvailableNetworks",
   "RIL:NetworkSelectionModeChanged",
   "RIL:SelectNetwork",
   "RIL:SelectNetworkAuto",
   "RIL:CallStateChanged",
+  "RIL:VoicemailNotification",
   "RIL:CallError",
   "RIL:GetCardLock:Return:OK",
   "RIL:GetCardLock:Return:KO",
   "RIL:SetCardLock:Return:OK",
   "RIL:SetCardLock:Return:KO",
   "RIL:UnlockCardLock:Return:OK",
   "RIL:UnlockCardLock:Return:KO",
   "RIL:UssdReceived",
@@ -93,16 +96,35 @@ MobileNetworkInfo.prototype = {
 
   shortName: null,
   longName: null,
   mcc: 0,
   mnc: 0,
   state: null
 };
 
+function VoicemailStatus() {}
+VoicemailStatus.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozVoicemailStatus]),
+  classID:        VOICEMAILSTATUS_CID,
+  classInfo:      XPCOMUtils.generateCI({
+    classID:          VOICEMAILSTATUS_CID,
+    classDescription: "VoicemailStatus",
+    flags:            Ci.nsIClassInfo.DOM_OBJECT,
+    interfaces:       [Ci.nsIDOMMozVoicemailStatus]
+  }),
+
+  // nsIDOMMozVoicemailStatus
+
+  hasMessages: false,
+  messageCount: Ci.nsIDOMMozVoicemailStatus.MESSAGE_COUNT_UNKNOWN,
+  returnNumber: null,
+  returnMessage: null
+};
+
 function RILContentHelper() {
   this.voiceConnectionInfo = new MobileConnectionInfo();
   this.dataConnectionInfo = new MobileConnectionInfo();
 
   this.initRequests();
   this.initMessageListener(RIL_IPC_MSG_NAMES);
   Services.obs.addObserver(this, "xpcom-shutdown", false);
 
@@ -307,39 +329,62 @@ RILContentHelper.prototype = {
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
     cpmm.sendAsyncMessage("RIL:CancelUSSD", {requestId: requestId});
     return request;
   },
 
   _telephonyCallbacks: null,
-  _enumerationTelephonyCallbacks: null,
+  _voicemailCallbacks: null,
+  _enumerateTelephonyCallbacks: null,
+
+  voicemailStatus: null,
+
+  registerCallback: function registerCallback(callbackType, callback) {
+    let callbacks = this[callbackType];
+    if (!callbacks) {
+      callbacks = this[callbackType] = [];
+    }
+
+    if (callbacks.indexOf(callback) != -1) {
+      throw new Error("Already registered this callback!");
+    }
+
+    callbacks.push(callback);
+    if (DEBUG) debug("Registered " + callbackType + " callback: " + callback);
+  },
+
+  unregisterCallback: function unregisterCallback(callbackType, callback) {
+    let callbacks = this[callbackType];
+    if (!callbacks) {
+      return;
+    }
+
+    let index = callbacks.indexOf(callback);
+    if (index != -1) {
+      callbacks.splice(index, 1);
+      if (DEBUG) debug("Unregistered telephony callback: " + callback);
+    }
+  },
 
   registerTelephonyCallback: function registerTelephonyCallback(callback) {
-    if (this._telephonyCallbacks) {
-      if (this._telephonyCallbacks.indexOf(callback) != -1) {
-        throw new Error("Already registered this callback!");
-      }
-    } else {
-      this._telephonyCallbacks = [];
-    }
-    this._telephonyCallbacks.push(callback);
-    debug("Registered telephony callback: " + callback);
+    this.registerCallback("_telephonyCallbacks", callback);
+  },
+
+  unregisterTelephonyCallback: function unregisteTelephonyCallback(callback) {
+    this.unregisterCallback("_telephonyCallbacks", callback);
   },
 
-  unregisterTelephonyCallback: function unregisterTelephonyCallback(callback) {
-    if (!this._telephonyCallbacks) {
-      return;
-    }
-    let index = this._telephonyCallbacks.indexOf(callback);
-    if (index != -1) {
-      this._telephonyCallbacks.splice(index, 1);
-      debug("Unregistered telephony callback: " + callback);
-    }
+  registerVoicemailCallback: function registerVoicemailCallback(callback) {
+    this.registerCallback("_voicemailCallbacks", callback);
+  },
+
+  unregisterVoicemailCallback: function unregisteVoicemailCallback(callback) {
+    this.unregisterCallback("_voicemailCallbacks", callback);
   },
 
   enumerateCalls: function enumerateCalls(callback) {
     debug("Requesting enumeration of calls for callback: " + callback);
     cpmm.sendAsyncMessage("RIL:EnumerateCalls");
     if (!this._enumerationTelephonyCallbacks) {
       this._enumerationTelephonyCallbacks = [];
     }
@@ -482,24 +527,29 @@ RILContentHelper.prototype = {
         this.handleSelectNetwork(msg.json,
                                  RIL.GECKO_NETWORK_SELECTION_MANUAL);
         break;
       case "RIL:SelectNetworkAuto":
         this.handleSelectNetwork(msg.json,
                                  RIL.GECKO_NETWORK_SELECTION_AUTOMATIC);
         break;
       case "RIL:CallStateChanged":
-        this._deliverTelephonyCallback("callStateChanged",
-                                       [msg.json.callIndex, msg.json.state,
-                                        msg.json.number, msg.json.isActive]);
+        this._deliverCallback("_telephonyCallbacks",
+                              "callStateChanged",
+                              [msg.json.callIndex, msg.json.state,
+                               msg.json.number, msg.json.isActive]);
         break;
       case "RIL:CallError":
-        this._deliverTelephonyCallback("notifyError",
-                                        [msg.json.callIndex,
-                                         msg.json.error]);
+        this._deliverCallback("_telephonyCallbacks",
+                              "notifyError",
+                              [msg.json.callIndex,
+                               msg.json.error]);
+        break;
+      case "RIL:VoicemailNotification":
+        this.handleVoicemailNotification(msg.json);
         break;
       case "RIL:GetCardLock:Return:OK":
       case "RIL:SetCardLock:Return:OK":
       case "RIL:UnlockCardLock:Return:OK":
         this.fireRequestSuccess(msg.json.requestId, msg.json);
         break;
       case "RIL:GetCardLock:Return:KO":
       case "RIL:SetCardLock:Return:KO":
@@ -585,37 +635,71 @@ RILContentHelper.prototype = {
 
     if (message.error) {
       this.fireRequestError(message.requestId, message.error);
     } else {
       this.fireRequestSuccess(message.requestId, null);
     }
   },
 
-  _deliverTelephonyCallback: function _deliverTelephonyCallback(name, args) {
-    if (!this._telephonyCallbacks) {
+  handleVoicemailNotification: function handleVoicemailNotification(message) {
+    let changed = false;
+    if (!this.voicemailStatus) {
+      this.voicemailStatus = new VoicemailStatus();
+    }
+
+    if (this.voicemailStatus.hasMessages != message.active) {
+      changed = true;
+      this.voicemailStatus.hasMessages = message.active;
+    }
+
+    if (this.voicemailStatus.messageCount != message.msgCount) {
+      changed = true;
+      this.voicemailStatus.messageCount = message.msgCount;
+    }
+
+    if (this.voicemailStatus.returnNumber != message.returnNumber) {
+      changed = true;
+      this.voicemailStatus.returnNumber = message.returnNumber;
+    }
+
+    if (this.voicemailStatus.returnMessage != message.returnMessage) {
+      changed = true;
+      this.voicemailStatus.returnMessage = message.returnMessage;
+    }
+
+    if (changed) {
+      this._deliverCallback("_voicemailCallbacks",
+                            "voicemailNotification",
+                            [this.voicemailStatus]);
+    }
+  },
+
+  _deliverCallback: function _deliverCallback(callbackType, name, args) {
+    let thisCallbacks = this[callbackType];
+    if (!thisCallbacks) {
       return;
     }
 
-    let callbacks = this._telephonyCallbacks.slice();
+    let callbacks = thisCallbacks.slice();
     for each (let callback in callbacks) {
-      if (this._telephonyCallbacks.indexOf(callback) == -1) {
+      if (thisCallbacks.indexOf(callback) == -1) {
         continue;
       }
       let handler = callback[name];
       if (typeof handler != "function") {
         throw new Error("No handler for " + name);
       }
       try {
         handler.apply(callback, args);
       } catch (e) {
         debug("callback handler for " + name + " threw an exception: " + e);
       }
     }
-  },
+  }
 };
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([RILContentHelper]);
 
 let debug;
 if (DEBUG) {
   debug = function (s) {
     dump("-*- RILContentHelper: " + s + "\n");
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -775,26 +775,40 @@ RadioInterfaceLayer.prototype = {
       return;
     }
 
     if (message.encoding == RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
       // Don't know how to handle binary data yet.
       return;
     }
 
+    // TODO: Bug #768441
+    // For now we don't store indicators persistently. When the mwi.discard
+    // flag is false, we'll need to persist the indicator to EFmwis.
+    // See TS 23.040 9.2.3.24.2
+
+    let mwi = message.mwi;
+    if (mwi) {
+      mwi.returnNumber = message.sender || null;
+      mwi.returnMessage = message.fullBody || null;
+      ppmm.sendAsyncMessage("RIL:VoicemailNotification", mwi);
+      return;
+    }
+
     let id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
                                                      message.fullBody || null,
                                                      message.timestamp);
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_RECEIVED,
                                            message.sender || null,
                                            message.receiver || null,
                                            message.fullBody || null,
                                            message.timestamp,
                                            false);
+
     Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
   },
 
   /**
    * Local storage for sent SMS messages.
    */
   _sentSmsEnvelopes: null,
   createSmsEnvelope: function createSmsEnvelope(options) {
--- a/dom/system/gonk/nsIRadioInterfaceLayer.idl
+++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsIMobileConnectionProvider.idl"
 
 interface nsIDOMMozMobileConnectionInfo;
 interface nsIDOMDOMRequest;
 interface nsIDOMWindow;
+interface nsIDOMMozVoicemailStatus;
 
 [scriptable, uuid(c14c71b8-afba-403b-8320-94593de9380f)]
 interface nsIRILTelephonyCallback : nsISupports
 {
   /**
    * Notified when a telephony call changes state.
    *
    * @param callIndex
@@ -57,16 +58,28 @@ interface nsIRILTelephonyCallback : nsIS
    *        Call identifier assigned by the RIL. -1 if no connection
    * @param error
    *        Error from RIL.
    */
   void notifyError(in long callIndex,
                    in AString error);
 };
 
+[scriptable, uuid(3ac98987-a63c-4ebe-adbd-ff7a0348d804)]
+interface nsIRILVoicemailCallback : nsISupports
+{
+  /**
+   * Called when a voicemail notification has been received by the network.
+   *
+   * @param status
+   *        The new voicemail status
+   */
+  void voicemailNotification(in nsIDOMMozVoicemailStatus status);
+};
+
 [scriptable, uuid(8a711703-1ee5-4675-9d9a-0b188e944cfe)]
 interface nsIRILDataCallInfo : nsISupports
 {
   /**
    * Current data call state, one of the
    * nsINetworkInterface::NETWORK_STATE_* constants.
    */
   readonly attribute unsigned long state;
@@ -112,22 +125,25 @@ interface nsIRILContactCallback : nsISup
    */
   void receiveContactsList(in DOMString type, in jsval contacts);
 };
 
 /**
  * Helper that runs in the content process and exposes information
  * to the DOM.
  */
-[scriptable, uuid(2f8b0929-2ecf-498c-bfa7-42690509696e)]
+[scriptable, uuid(d2ec602f-9746-4ada-b0c6-f1c1a3cf3578)]
 interface nsIRILContentHelper : nsIMobileConnectionProvider
 {
   void registerTelephonyCallback(in nsIRILTelephonyCallback callback);
   void unregisterTelephonyCallback(in nsIRILTelephonyCallback callback);
 
+  void registerVoicemailCallback(in nsIRILVoicemailCallback callback);
+  void unregisterVoicemailCallback(in nsIRILVoicemailCallback callback);
+
   /**
    * Will continue calling callback.enumerateCallState until the callback
    * returns false.
    */
   void enumerateCalls(in nsIRILTelephonyCallback callback);
 
   /**
    * Functionality for making and managing phone calls.
@@ -140,16 +156,18 @@ interface nsIRILContentHelper : nsIMobil
 
   void answerCall(in unsigned long callIndex);
   void rejectCall(in unsigned long callIndex);
   void holdCall(in unsigned long callIndex);
   void resumeCall(in unsigned long callIndex);
 
   attribute bool microphoneMuted;
   attribute bool speakerEnabled;
+
+  readonly attribute nsIDOMMozVoicemailStatus voicemailStatus;
 };
 
 [scriptable, uuid(fd9e8b38-b839-4d56-8482-3bf1f5c8f2ee)]
 interface nsIICCRecords : nsISupports
 {
   /**
    * Mobile Subscriber ISDN Number
    */
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -510,17 +510,17 @@ const PDU_TOA_NATIONAL_NUM  = 0x88; // N
 const PDU_TOA_PRIVATE_NUM   = 0x89; // Private numbering plan
 const PDU_TOA_ERMES_NUM     = 0x8A; // Ermes numbering plan
 const PDU_TOA_INTERNATIONAL = 0x90; // International number
 const PDU_TOA_NATIONAL      = 0xA0; // National number. Prefix or escape digits
                                     // shall not be included
 const PDU_TOA_NETWORK_SPEC  = 0xB0; // Network specific number This is used to
                                     // indicate administration/service number
                                     // specific to the serving network
-const PDU_TOA_SUSCRIBER     = 0xC0; // Suscriber number. This is used when a
+const PDU_TOA_SUBSCRIBER    = 0xC0; // Subscriber number. This is used when a
                                     // specific short number representation is
                                     // stored in one or more SCs as part of a
                                     // higher layer application
 const PDU_TOA_ALPHANUMERIC  = 0xD0; // Alphanumeric, (coded according to GSM TS
                                     // 03.38 7-bit default alphabet)
 const PDU_TOA_ABBREVIATED   = 0xE0; // Abbreviated number
 
 /**
@@ -652,31 +652,42 @@ const PDU_PID_REPLACE_SHORT_MESSAGE_TYPE
 const PDU_PID_ENHANDED_MESSAGE_SERVICE     = 0x5E;
 const PDU_PID_RETURN_CALL_MESSAGE          = 0x5F
 const PDU_PID_ANSI_136_R_DATA              = 0x7C;
 const PDU_PID_ME_DATA_DOWNLOAD             = 0x7D;
 const PDU_PID_ME_DEPERSONALIZATION         = 0x7E;
 const PDU_PID_USIM_DATA_DOWNLOAD           = 0x7F;
 
 // DCS - Data Coding Scheme
-const PDU_DCS_MSG_CODING_7BITS_ALPHABET = 0x00;
-const PDU_DCS_MSG_CODING_8BITS_ALPHABET = 0x04;
-const PDU_DCS_MSG_CODING_16BITS_ALPHABET= 0x08;
-const PDU_DCS_MSG_CLASS_ME_SPECIFIC     = 0xF1;
-const PDU_DCS_MSG_CLASS_SIM_SPECIFIC    = 0xF2;
-const PDU_DCS_MSG_CLASS_TE_SPECIFIC     = 0xF3;
+const PDU_DCS_MSG_CODING_7BITS_ALPHABET  = 0x00;
+const PDU_DCS_MSG_CODING_8BITS_ALPHABET  = 0x04;
+const PDU_DCS_MSG_CODING_16BITS_ALPHABET = 0x08;
+const PDU_DCS_MSG_CLASS_ME_SPECIFIC      = 0xF1;
+const PDU_DCS_MSG_CLASS_SIM_SPECIFIC     = 0xF2;
+const PDU_DCS_MSG_CLASS_TE_SPECIFIC      = 0xF3;
+const PDU_DCS_CODING_GROUP_BITS          = 0xF0;
+const PDU_DCS_CODING_GROUP_7BITS_DISCARD = 0xC0;
+const PDU_DCS_CODING_GROUP_7BITS_STORE   = 0xD0;
+const PDU_DCS_CODING_GROUP_16BITS_STORE  = 0xE0;
+const PDU_DCS_MWI_ACTIVE_BITS            = 0x08;
+const PDU_DCS_MWI_ACTIVE_VALUE           = 0x08;
+const PDU_DCS_MWI_TYPE_BITS              = 0x03;
+const PDU_DCS_MWI_TYPE_VOICEMAIL         = 0x00;
+const PDU_DCS_MWI_TYPE_FAX               = 0x01;
+const PDU_DCS_MWI_TYPE_EMAIL             = 0x02;
+const PDU_DCS_MWI_TYPE_OTHER             = 0x03;
 
 // Because service center timestamp omit the century. Yay.
 const PDU_TIMESTAMP_YEAR_OFFSET = 2000;
 
 // See 9.2.3.24 TP‑User Data (TP‑UD)
 const PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT         = 0x00;
 const PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION           = 0x01;
-const PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_8BIT  = 0x04;
-const PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_16BIT = 0x05;
+const PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_8BIT  = 0x04;
+const PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_16BIT = 0x05;
 const PDU_IEI_SMSC_CONTROL_PARAMS                      = 0x06;
 const PDU_IEI_UDH_SOURCE_INDICATOR                     = 0x07;
 const PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT        = 0x08;
 const PDU_IEI_WIRELESS_CONTROL_MESSAGE_PROTOCOL        = 0x09;
 const PDU_IEI_TEXT_FORMATING                           = 0x0A;
 const PDU_IEI_PREDEFINED_SOUND                         = 0x0B;
 const PDU_IEI_USER_DATA_SOUND                          = 0x0C;
 const PDU_IEI_PREDEFINED_ANIMATION                     = 0x0D;
@@ -1329,16 +1340,21 @@ const PDU_NL_SINGLE_SHIFT_TABLES = [
   // 0123456789ABCDEF
   + "PQRSTUVWXYZ     "
   // 012345.....6789ABCDEF
   + "     \u20ac          "
   // 0123456789ABCDEF
   + "                "
 ];
 
+// Special SMS Message Indication constants
+const PDU_MWI_STORE_TYPE_BIT     = 0x80;
+const PDU_MWI_STORE_TYPE_DISCARD = 0x00;
+const PDU_MWI_STORE_TYPE_STORE   = 0x80;
+
 const RADIOTECH_FAMILY_3GPP = 1;  // GSM, WCDMA, LTE
 const RADIOTECH_FAMILY_3GPP2 = 2; // CDMA, EVDO
 
 const DATACALL_RADIOTECHNOLOGY_CDMA = 0;
 const DATACALL_RADIOTECHNOLOGY_GSM = 1;
 
 const DATACALL_AUTH_NONE = 0;
 const DATACALL_AUTH_PAP = 1;
@@ -1457,10 +1473,12 @@ const GECKO_RADIO_TECH = [
   "hsupa",
   "hspa",
   "evdob",
   "ehrpd",
   "lte",
   "hspa+",
 ];
 
+const GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN = -1;
+
 // Allow this file to be imported via Components.utils.import().
 const EXPORTED_SYMBOLS = Object.keys(this);
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -3957,71 +3957,81 @@ let GsmPDUHelper = {
     for (let i = 0; i < message.length; ++i) {
       let code = message.charCodeAt(i);
       this.writeHexOctet((code >> 8) & 0xFF);
       this.writeHexOctet(code & 0xFF);
     }
   },
 
   /**
-   * Read 1 + UDHL octets and construct user data header at return.
+   * Read 1 + UDHL octets and construct user data header.
+   *
+   * @param msg
+   *        message object for output.
    *
-   * @return A header object with properties contained in received message.
-   * The properties set include:
-   * <ul>
-   * <li>length: totoal length of the header, default 0.
-   * <li>langIndex: used locking shift table index, default
-   *     PDU_NL_IDENTIFIER_DEFAULT.
-   * <li>langShiftIndex: used locking shift table index, default
-   *     PDU_NL_IDENTIFIER_DEFAULT.
-   * </ul>
+   * @see 3GPP TS 23.040 9.2.3.24
    */
-  readUserDataHeader: function readUserDataHeader() {
+  readUserDataHeader: function readUserDataHeader(msg) {
+    /**
+     * A header object with properties contained in received message.
+     * The properties set include:
+     *
+     * length: totoal length of the header, default 0.
+     * langIndex: used locking shift table index, default
+     * PDU_NL_IDENTIFIER_DEFAULT.
+     * langShiftIndex: used locking shift table index, default
+     * PDU_NL_IDENTIFIER_DEFAULT.
+     *
+     */
     let header = {
       length: 0,
       langIndex: PDU_NL_IDENTIFIER_DEFAULT,
       langShiftIndex: PDU_NL_IDENTIFIER_DEFAULT
     };
 
     header.length = this.readHexOctet();
+    if (DEBUG) debug("Read UDH length: " + header.length);
+
     let dataAvailable = header.length;
     while (dataAvailable >= 2) {
       let id = this.readHexOctet();
       let length = this.readHexOctet();
+      if (DEBUG) debug("Read UDH id: " + id + ", length: " + length);
+
       dataAvailable -= 2;
 
       switch (id) {
         case PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT: {
           let ref = this.readHexOctet();
           let max = this.readHexOctet();
           let seq = this.readHexOctet();
           dataAvailable -= 3;
           if (max && seq && (seq <= max)) {
             header.segmentRef = ref;
             header.segmentMaxSeq = max;
             header.segmentSeq = seq;
           }
           break;
         }
-        case PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_8BIT: {
+        case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_8BIT: {
           let dstp = this.readHexOctet();
           let orip = this.readHexOctet();
           dataAvailable -= 2;
           if ((dstp < PDU_APA_RESERVED_8BIT_PORTS)
               || (orip < PDU_APA_RESERVED_8BIT_PORTS)) {
             // 3GPP TS 23.040 clause 9.2.3.24.3: "A receiving entity shall
             // ignore any information element where the value of the
             // Information-Element-Data is Reserved or not supported"
             break;
           }
           header.destinationPort = dstp;
           header.originatorPort = orip;
           break;
         }
-        case PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_16BIT: {
+        case PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_16BIT: {
           let dstp = (this.readHexOctet() << 8) | this.readHexOctet();
           let orip = (this.readHexOctet() << 8) | this.readHexOctet();
           dataAvailable -= 4;
           // 3GPP TS 23.040 clause 9.2.3.24.4: "A receiving entity shall
           // ignore any information element where the value of the
           // Information-Element-Data is Reserved or not supported"
           if ((dstp < PDU_APA_VALID_16BIT_PORTS)
               && (orip < PDU_APA_VALID_16BIT_PORTS)) {
@@ -4051,16 +4061,51 @@ let GsmPDUHelper = {
           break;
         case PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT:
           let langIndex = this.readHexOctet();
           --dataAvailable;
           if (langIndex < PDU_NL_LOCKING_SHIFT_TABLES.length) {
             header.langIndex = langIndex;
           }
           break;
+        case PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION:
+          let msgInd = this.readHexOctet() & 0xFF;
+          let msgCount = this.readHexOctet();
+          dataAvailable -= 2;
+
+
+          /*
+           * TS 23.040 V6.8.1 Sec 9.2.3.24.2
+           * bits 1 0   : basic message indication type
+           * bits 4 3 2 : extended message indication type
+           * bits 6 5   : Profile id
+           * bit  7     : storage type
+           */
+          let storeType = msgInd & PDU_MWI_STORE_TYPE_BIT;
+          let mwi = msg.mwi;
+          if (!mwi) {
+            mwi = msg.mwi = {};
+          }
+
+          if (storeType == PDU_MWI_STORE_TYPE_STORE) {
+            // Store message because TP_UDH indicates so, note this may override
+            // the setting in DCS, but that is expected
+            mwi.discard = false;
+          } else if (mwi.discard === undefined) {
+            // storeType == PDU_MWI_STORE_TYPE_DISCARD
+            // only override mwi.discard here if it hasn't already been set
+            mwi.discard = true;
+          }
+
+          mwi.msgCount = msgCount & 0xFF;
+          mwi.active = mwi.msgCount > 0;
+
+          if (DEBUG) debug("MWI in TP_UDH received: " + JSON.stringify(mwi));
+
+          break;
         default:
           if (DEBUG) {
             debug("readUserDataHeader: unsupported IEI(" + id
                   + "), " + length + " bytes.");
           }
 
           // Read out unsupported data
           if (length) {
@@ -4078,17 +4123,17 @@ let GsmPDUHelper = {
           break;
       }
     }
 
     if (dataAvailable != 0) {
       throw new Error("Illegal user data header found!");
     }
 
-    return header;
+    msg.header = header;
   },
 
   /**
    * Write out user data header.
    *
    * @param options
    *        Options containing information for user data header write-out. The
    *        `userDataHeaderLength` property must be correctly pre-calculated.
@@ -4253,32 +4298,48 @@ let GsmPDUHelper = {
 
     msg.epid = msg.pid;
     switch (msg.epid & 0xC0) {
       case 0x40:
         // Bit 7..0 = 01xxxxxx
         switch (msg.epid) {
           case PDU_PID_SHORT_MESSAGE_TYPE_0:
             return;
+          case PDU_PID_RETURN_CALL_MESSAGE:
+            // Level 1 of message waiting indication:
+            // Only a return call message is provided
+            let mwi = msg.mwi = {};
+
+            // TODO: When should we de-activate the level 1 indicator?
+            mwi.active = true;
+            mwi.discard = false;
+            mwi.msgCount = GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN;
+            if (DEBUG) debug("TP-PID got return call message: " + msg.sender);
+            return;
         }
         break;
     }
+
     msg.epid = PDU_PID_DEFAULT;
   },
 
   /**
    * Read TP-Data-Coding-Scheme(TP-DCS)
    *
    * @param msg
    *        message object for output.
    *
    * @see 3GPP TS 23.040 9.2.3.10, 3GPP TS 23.038 4.
    */
   readDataCodingScheme: function readDataCodingScheme(msg) {
     let dcs = this.readHexOctet();
+    if (DEBUG) debug("PDU: read dcs: " + dcs);
+
+    // Level 2 of message waiting indication
+    this.readMessageWaitingFromDCS(msg, dcs);
 
     // 7 bit is the default fallback encoding.
     let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
     switch (dcs & 0xC0) {
       case 0x0:
         // bits 7..4 = 00xx
         switch (dcs & 0x0C) {
           case 0x4:
@@ -4308,16 +4369,58 @@ let GsmPDUHelper = {
     }
 
     msg.dcs = dcs;
     msg.encoding = encoding;
 
     if (DEBUG) debug("PDU: message encoding is " + encoding + " bit.");
   },
 
+  readMessageWaitingFromDCS: function readMessageWaitingFromDCS(msg, dcs) {
+    // 0xC0 == 7 bit, don't store
+    // 0xD0 == 7 bit, store
+    // 0xE0 == UCS-2, store
+    let codingGroup = dcs & PDU_DCS_CODING_GROUP_BITS;
+
+    if (codingGroup == PDU_DCS_CODING_GROUP_7BITS_DISCARD ||
+        codingGroup == PDU_DCS_CODING_GROUP_7BITS_STORE ||
+        codingGroup == PDU_DCS_CODING_GROUP_16BITS_STORE) {
+
+      // Indiciates voicemail indicator set or clear
+      let active = (dcs & PDU_DCS_MWI_ACTIVE_BITS) == PDU_DCS_MWI_ACTIVE_VALUE;
+
+      // If TP-UDH is present, these values will be overwritten
+      switch (dcs & PDU_DCS_MWI_TYPE_BITS) {
+        case PDU_DCS_MWI_TYPE_VOICEMAIL:
+          let mwi = msg.mwi;
+          if (!mwi) {
+            mwi = msg.mwi = {};
+          }
+
+          mwi.active = active;
+          mwi.discard = codingGroup == PDU_DCS_CODING_GROUP_7BITS_DISCARD;
+          mwi.msgCount = active ? GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN : 0;
+
+          if (DEBUG) {
+            debug("MWI in DCS received for voicemail: " + JSON.stringify(mwi));
+          }
+          break;
+        case PDU_DCS_MWI_TYPE_FAX:
+          if (DEBUG) debug("MWI in DCS received for fax");
+          break;
+        case PDU_DCS_MWI_TYPE_EMAIL:
+          if (DEBUG) debug("MWI in DCS received for email");
+          break;
+        default:
+          if (DEBUG) debug("MWI in DCS received for \"other\"");
+          break;
+      }
+    }
+  },
+
   /**
    * Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
    *
    * @see 3GPP TS 23.040 9.2.3.11
    */
   readTimestamp: function readTimestamp() {
     let year   = this.readSwappedNibbleBcdNum(1) + PDU_TIMESTAMP_YEAR_OFFSET;
     let month  = this.readSwappedNibbleBcdNum(1) - 1;
@@ -4351,29 +4454,31 @@ let GsmPDUHelper = {
    */
   readUserData: function readUserData(msg, length) {
     if (DEBUG) {
       debug("Reading " + length + " bytes of user data.");
     }
 
     let paddingBits = 0;
     if (msg.udhi) {
-      msg.header = this.readUserDataHeader();
+      this.readUserDataHeader(msg);
 
       if (msg.encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
         let headerBits = (msg.header.length + 1) * 8;
         let headerSeptets = Math.ceil(headerBits / 7);
 
         length -= headerSeptets;
         paddingBits = headerSeptets * 7 - headerBits;
       } else {
         length -= (msg.header.length + 1);
       }
     }
 
+    if (DEBUG) debug("After header, " + length + " septets left of user data");
+
     msg.body = null;
     msg.data = null;
     switch (msg.encoding) {
       case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
         // 7 bit encoding allows 140 octets, which means 160 characters
         // ((140x8) / 7 = 160 chars)
         if (length > PDU_MAX_USER_DATA_7BIT) {
           if (DEBUG) debug("PDU error: user data is too long: " + length);
@@ -4449,23 +4554,25 @@ let GsmPDUHelper = {
     // An empty message object. This gets filled below and then returned.
     let msg = {
       // D:DELIVER, DR:DELIVER-REPORT, S:SUBMIT, SR:SUBMIT-REPORT,
       // ST:STATUS-REPORT, C:COMMAND
       // M:Mandatory, O:Optional, X:Unavailable
       //                  D  DR S  SR ST C
       SMSC:      null, // M  M  M  M  M  M
       mti:       null, // M  M  M  M  M  M
-      udhi:      null, // M  M  X  M  M  M
+      udhi:      null, // M  M  O  M  M  M
       sender:    null, // M  X  X  X  X  X
       recipient: null, // X  X  M  X  M  M
       pid:       null, // M  O  M  O  O  M
       epid:      null, // M  O  M  O  O  M
       dcs:       null, // M  O  M  O  O  X
-      encoding:  null, // M  O  M  O  O  X
+      mwi:       null, // O  O  O  O  O  O
+      replace:  false, // O  O  O  O  O  O
+      header:    null, // M  M  O  M  M  M
       body:      null, // M  O  M  O  O  O
       data:      null, // M  O  M  O  O  O
       timestamp: null, // M  X  X  X  X  X
       status:    null, // X  X  X  X  M  X
       scts:      null, // X  X  X  M  M  X
       dt:        null, // X  X  X  X  M  X
     };
 
--- a/dom/telephony/Makefile.in
+++ b/dom/telephony/Makefile.in
@@ -16,18 +16,23 @@ LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/dom/dom-config.mk
 
 CPPSRCS = \
   Telephony.cpp \
   TelephonyCall.cpp \
   CallEvent.cpp \
+  Voicemail.cpp \
+  VoicemailEvent.cpp \
   $(NULL)
 
 XPIDLSRCS = \
   nsIDOMNavigatorTelephony.idl \
   nsIDOMTelephony.idl \
   nsIDOMTelephonyCall.idl \
   nsIDOMCallEvent.idl \
+  nsIDOMVoicemail.idl \
+  nsIDOMVoicemailEvent.idl \
+  nsIDOMVoicemailStatus.idl \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/telephony/TelephonyFactory.h
+++ b/dom/telephony/TelephonyFactory.h
@@ -3,16 +3,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_telephony_telephonyfactory_h__
 #define mozilla_dom_telephony_telephonyfactory_h__
 
 #include "nsIDOMTelephony.h"
+#include "nsIDOMVoicemail.h"
 #include "nsPIDOMWindow.h"
 
-// Implemented in Telephony.cpp.
+// Implemented in Telephony.cpp / Voicemail.cpp.
 
 nsresult
 NS_NewTelephony(nsPIDOMWindow* aWindow, nsIDOMTelephony** aTelephony);
 
+nsresult
+NS_NewVoicemail(nsPIDOMWindow* aWindow, nsIDOMMozVoicemail** aVoicemail);
+
 #endif // mozilla_dom_telephony_telephonyfactory_h__
new file mode 100644
--- /dev/null
+++ b/dom/telephony/Voicemail.cpp
@@ -0,0 +1,111 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Voicemail.h"
+#include "nsIDOMVoicemailStatus.h"
+
+#include "mozilla/Services.h"
+#include "nsContentUtils.h"
+#include "nsDOMClassInfo.h"
+#include "nsRadioInterfaceLayer.h"
+#include "nsServiceManagerUtils.h"
+
+#include "VoicemailEvent.h"
+
+DOMCI_DATA(MozVoicemail, mozilla::dom::telephony::Voicemail)
+
+USING_TELEPHONY_NAMESPACE
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(Voicemail)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Voicemail,
+                                                  nsDOMEventTargetHelper)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(statuschanged)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Voicemail,
+                                                nsDOMEventTargetHelper)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(statuschanged)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Voicemail)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMMozVoicemail)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozVoicemail)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(Voicemail, nsDOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(Voicemail, nsDOMEventTargetHelper)
+
+NS_IMPL_ISUPPORTS1(Voicemail::RILVoicemailCallback, nsIRILVoicemailCallback)
+
+Voicemail::Voicemail(nsPIDOMWindow* aWindow, nsIRILContentHelper* aRIL)
+  : mRIL(aRIL)
+{
+  BindToOwner(aWindow);
+
+  mRILVoicemailCallback = new RILVoicemailCallback(this);
+
+  nsresult rv = aRIL->RegisterVoicemailCallback(mRILVoicemailCallback);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed registering voicemail callback with RIL");
+  }
+}
+
+Voicemail::~Voicemail()
+{
+  if (mRIL && mRILVoicemailCallback) {
+    mRIL->UnregisterVoicemailCallback(mRILVoicemailCallback);
+  }
+}
+
+// nsIDOMMozVoicemail
+
+NS_IMETHODIMP
+Voicemail::GetStatus(nsIDOMMozVoicemailStatus** aStatus)
+{
+  *aStatus = nsnull;
+
+  NS_ENSURE_STATE(mRIL);
+  return mRIL->GetVoicemailStatus(aStatus);
+}
+
+NS_IMPL_EVENT_HANDLER(Voicemail, statuschanged)
+
+// nsIRILVoicemailCallback
+
+NS_IMETHODIMP
+Voicemail::VoicemailNotification(nsIDOMMozVoicemailStatus* aStatus)
+{
+  nsRefPtr<VoicemailEvent> event = new VoicemailEvent(nsnull, nsnull);
+  nsresult rv = event->InitVoicemailEvent(NS_LITERAL_STRING("statuschanged"),
+                                          false, false, aStatus);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = event->SetTrusted(true);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool dummy;
+  rv = DispatchEvent(static_cast<nsIDOMMozVoicemailEvent*>(event), &dummy);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+nsresult
+NS_NewVoicemail(nsPIDOMWindow* aWindow, nsIDOMMozVoicemail** aVoicemail)
+{
+  nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ?
+    aWindow :
+    aWindow->GetCurrentInnerWindow();
+
+  nsCOMPtr<nsIRILContentHelper> ril =
+    do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+  NS_ENSURE_STATE(ril);
+
+  nsRefPtr<Voicemail> voicemail = new Voicemail(innerWindow, ril);
+  voicemail.forget(aVoicemail);
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/dom/telephony/Voicemail.h
@@ -0,0 +1,61 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_telephony_voicemail_h__
+#define mozilla_dom_telephony_voicemail_h__
+
+#include "TelephonyCommon.h"
+
+#include "nsDOMEvent.h"
+#include "nsDOMEventTargetHelper.h"
+#include "nsIDOMVoicemail.h"
+#include "nsIRadioInterfaceLayer.h"
+
+class nsIRILContentHelper;
+class nsIDOMMozVoicemailStatus;
+
+BEGIN_TELEPHONY_NAMESPACE
+
+class Voicemail : public nsDOMEventTargetHelper,
+                  public nsIDOMMozVoicemail
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIDOMMOZVOICEMAIL
+  NS_DECL_NSIRILVOICEMAILCALLBACK
+
+  NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Voicemail, nsDOMEventTargetHelper)
+
+  Voicemail(nsPIDOMWindow* aWindow, nsIRILContentHelper* aRIL);
+  virtual ~Voicemail();
+
+private:
+  nsCOMPtr<nsIRILContentHelper> mRIL;
+  nsCOMPtr<nsIRILVoicemailCallback> mRILVoicemailCallback;
+
+  NS_DECL_EVENT_HANDLER(statuschanged)
+
+  class RILVoicemailCallback : public nsIRILVoicemailCallback
+  {
+    Voicemail* mVoicemail;
+
+  public:
+    NS_DECL_ISUPPORTS
+    NS_FORWARD_NSIRILVOICEMAILCALLBACK(mVoicemail->)
+
+    RILVoicemailCallback(Voicemail* aVoicemail)
+    : mVoicemail(aVoicemail)
+    {
+      NS_ASSERTION(mVoicemail, "Null pointer!");
+    }
+  };
+};
+
+END_TELEPHONY_NAMESPACE
+
+#endif // mozilla_dom_telephony_voicemail_h__
new file mode 100644
--- /dev/null
+++ b/dom/telephony/VoicemailEvent.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VoicemailEvent.h"
+#include "nsDOMClassInfo.h"
+#include "nsIDOMVoicemailStatus.h"
+
+DOMCI_DATA(MozVoicemailEvent, mozilla::dom::telephony::VoicemailEvent)
+
+USING_TELEPHONY_NAMESPACE
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(VoicemailEvent)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(VoicemailEvent, nsDOMEvent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mStatus)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(VoicemailEvent, nsDOMEvent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStatus)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(VoicemailEvent)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMMozVoicemailEvent)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozVoicemailEvent)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
+
+NS_IMPL_ADDREF_INHERITED(VoicemailEvent, nsDOMEvent)
+NS_IMPL_RELEASE_INHERITED(VoicemailEvent, nsDOMEvent)
+
+nsresult
+VoicemailEvent::InitVoicemailEvent(const nsAString& aEventTypeArg,
+                                   bool aCanBubbleArg, bool aCancelableArg,
+                                   nsIDOMMozVoicemailStatus* aStatus)
+{
+  nsresult rv = nsDOMEvent::InitEvent(aEventTypeArg, aCanBubbleArg,
+                                      aCancelableArg);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mStatus = aStatus;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+VoicemailEvent::GetStatus(nsIDOMMozVoicemailStatus** aStatus)
+{
+  NS_IF_ADDREF(*aStatus = mStatus);
+  return NS_OK;
+}
+
+namespace {
+
+nsresult
+NS_NewDOMVoicemailEvent(nsIDOMEvent** aInstancePtrResult,
+                  nsPresContext* aPresContext,
+                  nsEvent* aEvent)
+{
+  return CallQueryInterface(
+    new mozilla::dom::telephony::VoicemailEvent(aPresContext, aEvent),
+    aInstancePtrResult);
+}
+
+}
new file mode 100644
--- /dev/null
+++ b/dom/telephony/VoicemailEvent.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_telephony_VoicemailEvent_h__
+#define mozilla_dom_telephony_VoicemailEvent_h__
+
+#include "TelephonyCommon.h"
+
+#include "nsIDOMVoicemailEvent.h"
+#include "nsDOMEvent.h"
+
+class nsIDOMMozVoicemailStatus;
+
+BEGIN_TELEPHONY_NAMESPACE
+
+class VoicemailEvent : public nsIDOMMozVoicemailEvent,
+                       public nsDOMEvent
+{
+public:
+  VoicemailEvent(nsPresContext* aPresContext, nsEvent* aEvent)
+    : nsDOMEvent(aPresContext, aEvent) { }
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIDOMMOZVOICEMAILEVENT
+
+  NS_FORWARD_TO_NSDOMEVENT
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(VoicemailEvent, nsDOMEvent)
+
+  nsresult InitVoicemailEvent(const nsAString& aEventTypeArg,
+                              bool aCanBubbleArg, bool aCancelableArg,
+                              nsIDOMMozVoicemailStatus* aStatus);
+
+private:
+  nsCOMPtr<nsIDOMMozVoicemailStatus> mStatus;
+};
+
+END_TELEPHONY_NAMESPACE
+
+#endif // mozilla_dom_telephony_VoicemailEvent_h__
--- a/dom/telephony/nsIDOMNavigatorTelephony.idl
+++ b/dom/telephony/nsIDOMNavigatorTelephony.idl
@@ -2,14 +2,16 @@
 /* vim: set ts=2 et sw=2 tw=40: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMTelephony;
+interface nsIDOMMozVoicemail;
 
-[scriptable, builtinclass, uuid(fb2f5927-41ea-442a-8292-81074f69dc41)]
+[scriptable, builtinclass, uuid(4a297d39-2730-47b8-b406-666b3737aacb)]
 interface nsIDOMNavigatorTelephony : nsISupports
 {
   readonly attribute nsIDOMTelephony mozTelephony;
+  readonly attribute nsIDOMMozVoicemail mozVoicemail;
 };
new file mode 100644
--- /dev/null
+++ b/dom/telephony/nsIDOMVoicemail.idl
@@ -0,0 +1,23 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDOMEventTarget.idl"
+
+interface nsIDOMMozVoicemailStatus;
+
+[scriptable, builtinclass, uuid(db5b727a-daf2-40b9-83e4-cc110eab44ca)]
+interface nsIDOMMozVoicemail : nsIDOMEventTarget
+{
+  /**
+   * The current voicemail status, or null when the status is unknown
+   */
+  readonly attribute nsIDOMMozVoicemailStatus status;
+
+  /**
+   * The current voicemail status has changed
+   */
+  attribute nsIDOMEventListener onstatuschanged;
+};
new file mode 100644
--- /dev/null
+++ b/dom/telephony/nsIDOMVoicemailEvent.idl
@@ -0,0 +1,18 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDOMEvent.idl"
+
+interface nsIDOMMozVoicemailStatus;
+
+[scriptable, builtinclass, uuid(4642f196-1a30-4a9b-986f-7f1574d5cee1)]
+interface nsIDOMMozVoicemailEvent : nsIDOMEvent
+{
+  /**
+   * The voicemail status that caused this event to fire
+   */
+  readonly attribute nsIDOMMozVoicemailStatus status;
+};
new file mode 100644
--- /dev/null
+++ b/dom/telephony/nsIDOMVoicemailStatus.idl
@@ -0,0 +1,50 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(8c58859a-e006-466a-ad76-b188ba0918ab)]
+interface nsIDOMMozVoicemailStatus : nsISupports
+{
+  /**
+   * There are voicemail messages waiting, but the count is unknown.
+   */
+  const long MESSAGE_COUNT_UNKNOWN = -1;
+
+  /**
+   * Whether or not there are messages waiting in the voicemail box
+   */
+  readonly attribute boolean hasMessages;
+
+  /**
+   * The total message count. Some voicemail indicators will only specify that
+   * messages are waiting, but not the actual number. In that case, the value
+   * of messageCount will be MESSAGE_COUNT_UNKNOWN (-1).
+   *
+   * Logic for a voicemail notification might look something like:
+   * if (status.hasMessages) {
+   *   // show new voicemail notification
+   *   if (status.messageCount > 0) {
+   *     // add a label for the message count
+   *   }
+   * } else {
+   *   // hide the voicemail notification
+   * }
+   */
+  readonly attribute long messageCount;
+
+  /**
+   * Return call number received for this voicemail status, or null if one
+   * wasn't provided.
+   */
+  readonly attribute DOMString returnNumber;
+
+  /**
+   * Displayable return call message received for this voicemail status, or null
+   * if one wasn't provided.
+   */
+  readonly attribute DOMString returnMessage;
+};
--- a/dom/telephony/test/marionette/manifest.ini
+++ b/dom/telephony/test/marionette/manifest.ini
@@ -11,8 +11,9 @@ qemu = true
 [test_outgoing_hangup_alerting.js]
 [test_outgoing_hangup_held.js]
 # Bug 761533
 #[test_outgoing_badNumber.js]
 #expectedfailure = true
 #[test_outgoing_busy.js]
 #expectedfailure = true
 [test_outgoing_reject.js]
+[test_voicemail_statuschanged.py]
new file mode 100644
--- /dev/null
+++ b/dom/telephony/test/marionette/pdu_builder.js
@@ -0,0 +1,149 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+// Only bring in what we need from ril_worker/RadioInterfaceLayer here. Reusing
+// that code turns out to be a nightmare, so there is some code duplication.
+let PDUBuilder = {
+  toHexString: function toHexString(n, length) {
+    let str = n.toString(16);
+    if (str.length < length) {
+      for (let i = 0; i < length - str.length; i++) {
+        str = "0" + str;
+      }
+    }
+    return str.toUpperCase();
+  },
+
+  writeUint16: function writeUint16(value) {
+    this.buf += (value & 0xff).toString(16).toUpperCase();
+    this.buf += ((value >> 8) & 0xff).toString(16).toUpperCase();
+  },
+
+  writeHexOctet: function writeHexOctet(octet) {
+    this.buf += this.toHexString(octet, 2);
+  },
+
+  writeSwappedNibbleBCD: function writeSwappedNibbleBCD(data) {
+    data = data.toString();
+    let zeroCharCode = '0'.charCodeAt(0);
+
+    for (let i = 0; i < data.length; i += 2) {
+      let low = data.charCodeAt(i) - zeroCharCode;
+      let high;
+      if (i + 1 < data.length) {
+        high = data.charCodeAt(i + 1) - zeroCharCode;
+      } else {
+        high = 0xF;
+      }
+
+      this.writeHexOctet((high << 4) | low);
+    }
+  },
+
+  writeStringAsSeptets: function writeStringAsSeptets(message,
+                                                      paddingBits,
+                                                      langIndex,
+                                                      langShiftIndex)
+  {
+    const langTable = PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
+    const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
+
+    let dataBits = paddingBits;
+    let data = 0;
+    for (let i = 0; i < message.length; i++) {
+      let septet = langTable.indexOf(message[i]);
+      if (septet == PDU_NL_EXTENDED_ESCAPE) {
+        continue;
+      }
+
+      if (septet >= 0) {
+        data |= septet << dataBits;
+        dataBits += 7;
+      } else {
+        septet = langShiftTable.indexOf(message[i]);
+        if (septet == -1) {
+          throw new Error(message[i] + " not in 7 bit alphabet "
+                          + langIndex + ":" + langShiftIndex + "!");
+        }
+
+        if (septet == PDU_NL_RESERVED_CONTROL) {
+          continue;
+        }
+
+        data |= PDU_NL_EXTENDED_ESCAPE << dataBits;
+        dataBits += 7;
+        data |= septet << dataBits;
+        dataBits += 7;
+      }
+
+      for (; dataBits >= 8; dataBits -= 8) {
+        this.writeHexOctet(data & 0xFF);
+        data >>>= 8;
+      }
+    }
+
+    if (dataBits != 0) {
+      this.writeHexOctet(data & 0xFF);
+    }
+  },
+
+  buildAddress: function buildAddress(address) {
+    let addressFormat = PDU_TOA_ISDN; // 81
+    if (address[0] == '+') {
+      addressFormat = PDU_TOA_INTERNATIONAL | PDU_TOA_ISDN; // 91
+      address = address.substring(1);
+    }
+
+    this.buf = "";
+    this.writeHexOctet(address.length);
+    this.writeHexOctet(addressFormat);
+    this.writeSwappedNibbleBCD(address);
+
+    return this.buf;
+  },
+
+  // assumes 7 bit encoding
+  buildUserData: function buildUserData(options) {
+    let headerLength = 0;
+    this.buf = "";
+    if (options.headers) {
+      for each (let header in options.headers) {
+        headerLength += 2; // id + length octets
+        if (header.octets) {
+          headerLength += header.octets.length;
+        }
+      };
+    }
+
+    let encodedBodyLength = options.body.length;
+    let headerOctets = (headerLength ? headerLength + 1 : 0);
+
+    let paddingBits;
+    let userDataLengthInSeptets;
+    let headerSeptets = Math.ceil(headerOctets * 8 / 7);
+    userDataLengthInSeptets = headerSeptets + encodedBodyLength;
+    paddingBits = headerSeptets * 7 - headerOctets * 8;
+
+    this.writeHexOctet(userDataLengthInSeptets);
+    if (options.headers) {
+      this.writeHexOctet(headerLength);
+
+      for each (let header in options.headers) {
+        this.writeHexOctet(header.id);
+        this.writeHexOctet(header.length);
+
+        if (header.octets) {
+          for each (let octet in header.octets) {
+            this.writeHexOctet(octet);
+          }
+        }
+      }
+    }
+
+    this.writeStringAsSeptets(options.body, paddingBits,
+                              PDU_NL_IDENTIFIER_DEFAULT,
+                              PDU_NL_IDENTIFIER_DEFAULT);
+    return this.buf;
+  }
+};
new file mode 100644
--- /dev/null
+++ b/dom/telephony/test/marionette/test_voicemail_statuschanged.js
@@ -0,0 +1,229 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const WHITELIST_PREF = "dom.voicemail.whitelist";
+let uriPrePath = window.location.protocol + "//" + window.location.host;
+SpecialPowers.setCharPref(WHITELIST_PREF, uriPrePath);
+
+let voicemail = window.navigator.mozVoicemail;
+ok(voicemail instanceof MozVoicemail);
+is(voicemail.status, null);
+
+function sendIndicatorPDU(pdu, listener, nextTest) {
+  let smsCommand = "sms pdu " + pdu;
+  let commandCompleted = false;
+  let sawEvent = false;
+
+ voicemail.addEventListener("statuschanged", function statusChanged(event) {
+    voicemail.removeEventListener("statuschanged", statusChanged);
+
+    try {
+      listener(event);
+    } catch (e) {
+      ok(false, String(e));
+    }
+
+    sawEvent = true;
+    if (commandCompleted) {
+      nextTest();
+    }
+  });
+
+  log("-> " + smsCommand);
+  runEmulatorCmd(smsCommand, function(result) {
+    log("<- " + result);
+    is(result[0], "OK");
+    commandCompleted = true;
+    if (sawEvent) {
+      nextTest();
+    }
+  });
+}
+
+// TODO: Add tests for store/discard once they are implemented
+// See RadioInterfaceLayer.js / Bug #768441
+
+function isVoicemailStatus(status) {
+  is(voicemail.status.hasMessages, status.hasMessages);
+  is(voicemail.status.messageCount, status.messageCount);
+  is(voicemail.status.returnNumber, status.returnNumber);
+  is(voicemail.status.returnMessage, status.returnMessage);
+}
+
+const MWI_PDU_PREFIX = "0000";
+const MWI_PDU_UDH_PREFIX = "0040";
+const MWI_PID_DEFAULT = "00";
+const MWI_PID_RETURN_CALL_MSG = "5F";
+const MWI_DCS_DATA_MSG = "F0";
+const MWI_DCS_DISCARD_INACTIVE = "C0";
+const MWI_DCS_DISCARD_ACTIVE = "C8";
+const MWI_TIMESTAMP = "00000000000000";
+
+const MWI_LEVEL1_SENDER = "+15125551234";
+const MWI_LEVEL1_PDU_ADDRESS = PDUBuilder.buildAddress(MWI_LEVEL1_SENDER);
+const MWI_DEFAULT_BODY = "1 new voicemail";
+const MWI_UD_DEFAULT = PDUBuilder.buildUserData({
+  body: MWI_DEFAULT_BODY
+});
+
+// Level 1 Message Waiting is just a return call message
+const MWI_LEVEL1_PDU =
+  MWI_PDU_PREFIX +
+  MWI_LEVEL1_PDU_ADDRESS +
+  MWI_PID_RETURN_CALL_MSG +
+  MWI_DCS_DATA_MSG +
+  MWI_TIMESTAMP +
+  MWI_UD_DEFAULT;
+
+function testLevel1Indicator() {
+
+  function onLevel1Indicator(event) {
+    let status = event.status;
+    ok(status instanceof MozVoicemailStatus);
+    is(status.hasMessages, true);
+    is(status.messageCount, status.MESSAGE_COUNT_UNKNOWN);
+    is(status.returnNumber, MWI_LEVEL1_SENDER);
+    is(status.returnMessage, MWI_DEFAULT_BODY);
+    isVoicemailStatus(status);
+  }
+
+  sendIndicatorPDU(MWI_LEVEL1_PDU, onLevel1Indicator, testLevel2DiscardActive);
+}
+
+const MWI_LEVEL2_SENDER = "+15125551235";
+const MWI_LEVEL2_PDU_ADDRESS = PDUBuilder.buildAddress(MWI_LEVEL2_SENDER);
+const MWI_LEVEL2_DISCARD_ACTIVE_PDU =
+  MWI_PDU_PREFIX +
+  MWI_LEVEL2_PDU_ADDRESS +
+  MWI_PID_DEFAULT +
+  MWI_DCS_DISCARD_ACTIVE +
+  MWI_TIMESTAMP +
+  MWI_UD_DEFAULT;
+
+function testLevel2DiscardActive() {
+
+  function onLevel2Active(event) {
+    let status = event.status;
+    ok(status instanceof MozVoicemailStatus);
+    is(status.hasMessages, true);
+    is(status.messageCount, status.MESSAGE_COUNT_UNKNOWN);
+    is(status.returnNumber, MWI_LEVEL2_SENDER);
+    is(status.returnMessage, MWI_DEFAULT_BODY);
+    isVoicemailStatus(status);
+  }
+
+  sendIndicatorPDU(MWI_LEVEL2_DISCARD_ACTIVE_PDU,
+                   onLevel2Active,
+                   testLevel2DiscardInactive);
+
+}
+
+const MWI_LEVEL2_DISCARD_INACTIVE_PDU =
+  MWI_PDU_PREFIX +
+  MWI_LEVEL2_PDU_ADDRESS +
+  MWI_PID_DEFAULT +
+  MWI_DCS_DISCARD_INACTIVE +
+  MWI_TIMESTAMP +
+  MWI_UD_DEFAULT;
+
+function testLevel2DiscardInactive() {
+  function onLevel2Inactive(event) {
+    let status = event.status;
+    ok(status instanceof MozVoicemailStatus);
+    is(status.hasMessages, false);
+    is(status.messageCount, 0);
+    is(status.returnNumber, MWI_LEVEL2_SENDER);
+    is(status.returnMessage, MWI_DEFAULT_BODY);
+    isVoicemailStatus(status);
+  }
+
+  sendIndicatorPDU(MWI_LEVEL2_DISCARD_INACTIVE_PDU,
+                   onLevel2Inactive,
+                   testLevel3DiscardActive);
+}
+
+
+// Tests for Level 3 MWI with a message count in the User Data Header
+const MWI_LEVEL3_SENDER = "+15125551236";
+const MWI_LEVEL3_PDU_ADDRESS = PDUBuilder.buildAddress(MWI_LEVEL3_SENDER);
+
+const MWI_LEVEL3_ACTIVE_UDH_MSG_COUNT = 3;
+const MWI_LEVEL3_ACTIVE_BODY = "3 new voicemails";
+const MWI_LEVEL3_ACTIVE_UD = PDUBuilder.buildUserData({
+  headers: [{
+    id: PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION,
+    length: 2,
+    octets: [
+      PDU_MWI_STORE_TYPE_DISCARD,
+      MWI_LEVEL3_ACTIVE_UDH_MSG_COUNT
+    ]
+  }],
+  body: MWI_LEVEL3_ACTIVE_BODY
+});
+
+const MWI_LEVEL3_DISCARD_ACTIVE_PDU =
+  MWI_PDU_UDH_PREFIX +
+  MWI_LEVEL3_PDU_ADDRESS +
+  MWI_PID_DEFAULT +
+  MWI_DCS_DISCARD_ACTIVE +
+  MWI_TIMESTAMP +
+  MWI_LEVEL3_ACTIVE_UD;
+
+function testLevel3DiscardActive() {
+
+  function onLevel3Active(event) {
+    let status = event.status;
+    ok(status instanceof MozVoicemailStatus);
+    is(status.hasMessages, true);
+    is(status.messageCount, MWI_LEVEL3_ACTIVE_UDH_MSG_COUNT);
+    is(status.returnNumber, MWI_LEVEL3_SENDER);
+    is(status.returnMessage, MWI_LEVEL3_ACTIVE_BODY);
+    isVoicemailStatus(status);
+  }
+
+  sendIndicatorPDU(MWI_LEVEL3_DISCARD_ACTIVE_PDU,
+                   onLevel3Active,
+                   testLevel3DiscardInactive);
+}
+
+const MWI_LEVEL3_INACTIVE_BODY = "No unread voicemails";
+const MWI_LEVEL3_INACTIVE_UD = PDUBuilder.buildUserData({
+  headers: [{
+    id: PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION,
+    length: 2,
+    octets: [
+      PDU_MWI_STORE_TYPE_DISCARD,
+      0 // messageCount
+    ]
+  }],
+  body: MWI_LEVEL3_INACTIVE_BODY
+});
+
+const MWI_LEVEL3_DISCARD_INACTIVE_PDU =
+  MWI_PDU_UDH_PREFIX +
+  MWI_LEVEL3_PDU_ADDRESS +
+  MWI_PID_DEFAULT +
+  MWI_DCS_DISCARD_ACTIVE +
+  MWI_TIMESTAMP +
+  MWI_LEVEL3_INACTIVE_UD;
+
+function testLevel3DiscardInactive() {
+  function onLevel3Inactive(event) {
+    let status = event.status;
+    ok(status instanceof MozVoicemailStatus);
+    is(status.hasMessages, false);
+    is(status.messageCount, 0);
+    is(status.returnNumber, MWI_LEVEL3_SENDER);
+    is(status.returnMessage, MWI_LEVEL3_INACTIVE_BODY);
+    isVoicemailStatus(status);
+  }
+
+  sendIndicatorPDU(MWI_LEVEL3_DISCARD_INACTIVE_PDU, onLevel3Inactive, cleanUp);
+}
+
+function cleanUp() {
+  SpecialPowers.clearUserPref(WHITELIST_PREF);
+  finish();
+}
+
+testLevel1Indicator();
new file mode 100644
--- /dev/null
+++ b/dom/telephony/test/marionette/test_voicemail_statuschanged.py
@@ -0,0 +1,20 @@
+from marionette_test import MarionetteTestCase
+import os
+
+class TestVoicemailStatusChanged(MarionetteTestCase):
+
+    def testStatusChanged(self):
+        this_dir = os.path.abspath(os.path.dirname(__file__))
+        system_gonk_dir = os.path.abspath(os.path.join(this_dir,
+            os.path.pardir, os.path.pardir, os.path.pardir, "system", "gonk"))
+
+        ril_consts_path = os.path.join(system_gonk_dir, "ril_consts.js")
+        self.marionette.import_script(ril_consts_path)
+
+        pdu_builder_path = os.path.join(this_dir, "pdu_builder.js")
+        self.marionette.import_script(pdu_builder_path)
+
+        test_path = os.path.join(this_dir, "test_voicemail_statuschanged.js")
+        test = open(test_path, "r").read()
+        self.marionette.set_script_timeout(30000)
+        self.marionette.execute_async_script(test)
--- a/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
+++ b/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
@@ -37,16 +37,22 @@ https://bugzilla.mozilla.org/show_bug.cg
         ok(false, "'EventTarget' shouldn't throw in a sandbox");
       }
       try {
         var xhr = Components.utils.evalInSandbox("XMLHttpRequest()", sandbox);
         is(xhr, "[object XMLHttpRequest]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
       } catch (e) {
         ok(false, "'XMLHttpRequest()' shouldn't throw in a sandbox");
       }
+      try {
+        var canvas = Components.utils.evalInSandbox("document.createElement('canvas').getContext('2d')", sandbox);
+        is(canvas.DRAWWINDOW_DRAW_CARET, CanvasRenderingContext2D.DRAWWINDOW_DRAW_CARET, "Constants should be defined on DOM objects in a sandbox");
+      } catch (e) {
+        ok(false, "'document.createElement('canvas').getContext('2D')' shouldn't throw in a sandbox");
+      }
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   ]]>
   </script>
 </window>
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -5000,35 +5000,37 @@ nsEditor::HandleKeyPressEvent(nsIDOMKeyE
     if (nativeKeyEvent->keyCode == nsIDOMKeyEvent::DOM_VK_BACK_SPACE) {
       aKeyEvent->PreventDefault();
     }
     return NS_OK;
   }
 
   switch (nativeKeyEvent->keyCode) {
     case nsIDOMKeyEvent::DOM_VK_META:
+    case nsIDOMKeyEvent::DOM_VK_WIN:
     case nsIDOMKeyEvent::DOM_VK_SHIFT:
     case nsIDOMKeyEvent::DOM_VK_CONTROL:
     case nsIDOMKeyEvent::DOM_VK_ALT:
       aKeyEvent->PreventDefault(); // consumed
       return NS_OK;
     case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
       if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() ||
-          nativeKeyEvent->IsMeta()) {
+          nativeKeyEvent->IsMeta() || nativeKeyEvent->IsOS()) {
         return NS_OK;
       }
       DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
       aKeyEvent->PreventDefault(); // consumed
       return NS_OK;
     case nsIDOMKeyEvent::DOM_VK_DELETE:
       // on certain platforms (such as windows) the shift key
       // modifies what delete does (cmd_cut in this case).
       // bailing here to allow the keybindings to do the cut.
       if (nativeKeyEvent->IsShift() || nativeKeyEvent->IsControl() ||
-          nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta()) {
+          nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
+          nativeKeyEvent->IsOS()) {
         return NS_OK;
       }
       DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
       aKeyEvent->PreventDefault(); // consumed
       return NS_OK; 
   }
   return NS_OK;
 }
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -594,16 +594,17 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOM
 
   nsKeyEvent* nativeKeyEvent = GetNativeKeyEvent(aKeyEvent);
   NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
   NS_ASSERTION(nativeKeyEvent->message == NS_KEY_PRESS,
                "HandleKeyPressEvent gets non-keypress event");
 
   switch (nativeKeyEvent->keyCode) {
     case nsIDOMKeyEvent::DOM_VK_META:
+    case nsIDOMKeyEvent::DOM_VK_WIN:
     case nsIDOMKeyEvent::DOM_VK_SHIFT:
     case nsIDOMKeyEvent::DOM_VK_CONTROL:
     case nsIDOMKeyEvent::DOM_VK_ALT:
     case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
     case nsIDOMKeyEvent::DOM_VK_DELETE:
       // These keys are handled on nsEditor, so, we can bypass
       // nsPlaintextEditor.
       return nsEditor::HandleKeyPressEvent(aKeyEvent);
@@ -614,17 +615,17 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOM
         return nsPlaintextEditor::HandleKeyPressEvent(aKeyEvent);
       }
 
       if (IsTabbable()) {
         return NS_OK; // let it be used for focus switching
       }
 
       if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() ||
-          nativeKeyEvent->IsMeta()) {
+          nativeKeyEvent->IsMeta() || nativeKeyEvent->IsOS()) {
         return NS_OK;
       }
 
       nsCOMPtr<nsISelection> selection;
       nsresult rv = GetSelection(getter_AddRefs(selection));
       NS_ENSURE_SUCCESS(rv, rv);
       PRInt32 offset;
       nsCOMPtr<nsIDOMNode> node, blockParent;
@@ -664,32 +665,33 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOM
         return NS_OK; // don't type text for shift tabs
       }
       aKeyEvent->PreventDefault();
       return TypedText(NS_LITERAL_STRING("\t"), eTypedText);
     }
     case nsIDOMKeyEvent::DOM_VK_RETURN:
     case nsIDOMKeyEvent::DOM_VK_ENTER:
       if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() ||
-          nativeKeyEvent->IsMeta()) {
+          nativeKeyEvent->IsMeta() || nativeKeyEvent->IsOS()) {
         return NS_OK;
       }
       aKeyEvent->PreventDefault(); // consumed
       if (nativeKeyEvent->IsShift() && !IsPlaintextEditor()) {
         // only inserts a br node
         return TypedText(EmptyString(), eTypedBR);
       }
       // uses rules to figure out what to insert
       return TypedText(EmptyString(), eTypedBreak);
   }
 
   // NOTE: On some keyboard layout, some characters are inputted with Control
   // key or Alt key, but at that time, widget sets FALSE to these keys.
   if (nativeKeyEvent->charCode == 0 || nativeKeyEvent->IsControl() ||
-      nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta()) {
+      nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
+      nativeKeyEvent->IsOS()) {
     // we don't PreventDefault() here or keybindings like control-x won't work
     return NS_OK;
   }
   aKeyEvent->PreventDefault();
   nsAutoString str(nativeKeyEvent->charCode);
   return TypedText(str, eTypedText);
 }
 
--- a/editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html
+++ b/editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html
@@ -132,16 +132,20 @@ function runTests()
     //   Basically, modifier keys shouldn't cause keypress event.  However,
     //   even if it were dispatched by widget's bug, editor should consume
     //   it when editor is editable.
     reset("");
     synthesizeKey("VK_META", { type: "keypress" });
     check(aDescription + "Meta", true, true, !aIsReadonly);
 
     reset("");
+    synthesizeKey("VK_WIN", { type: "keypress" });
+    check(aDescription + "OS", true, true, !aIsReadonly);
+
+    reset("");
     synthesizeKey("VK_SHIFT", { type: "keypress" });
     check(aDescription + "Shift", true, true, !aIsReadonly);
 
     reset("");
     synthesizeKey("VK_CONTROL", { type: "keypress" });
     check(aDescription + "Control", true, true, !aIsReadonly);
 
     // Alt key press event installs menubar key event listener, so,
@@ -171,16 +175,20 @@ function runTests()
     reset("");
     synthesizeKey("VK_BACK_SPACE", { altKey: true });
     check(aDescription + "Alt+Backspace", true, true, aIsReadonly);
 
     reset("");
     synthesizeKey("VK_BACK_SPACE", { metaKey: true });
     check(aDescription + "Meta+Backspace", true, true, aIsReadonly);
 
+    reset("");
+    synthesizeKey("VK_BACK_SPACE", { osKey: true });
+    check(aDescription + "OS+Backspace", true, true, aIsReadonly);
+
     // Delete key:
     //   If editor is readonly, it doesn't consume.
     //   If editor is editable, delete is consumed.
     //   Otherwise, editor doesn't consume the event.
     reset("");
     synthesizeKey("VK_DELETE", { });
     check(aDescription + "Delete", true, true, !aIsReadonly);
 
@@ -195,16 +203,20 @@ function runTests()
     reset("");
     synthesizeKey("VK_DELETE", { altKey: true });
     check(aDescription + "Alt+Delete", true, true, false);
 
     reset("");
     synthesizeKey("VK_DELETE", { metaKey: true });
     check(aDescription + "Meta+Delete", true, true, false);
 
+    reset("");
+    synthesizeKey("VK_DELETE", { osKey: true });
+    check(aDescription + "OS+Delete", true, true, false);
+
     // Return key:
     //   If editor is readonly, it doesn't consume.
     //   If editor is editable and not single line editor, it consumes Return
     //   and Shift+Return.
     //   Otherwise, editor doesn't consume the event.
     reset("a");
     synthesizeKey("VK_RETURN", { });
     check(aDescription + "Return",
@@ -229,16 +241,21 @@ function runTests()
     check(aDescription + "Alt+Return", true, true, false);
     is(aElement.innerHTML, "a", aDescription + "Alt+Return");
 
     reset("a");
     synthesizeKey("VK_RETURN", { metaKey: true });
     check(aDescription + "Meta+Return", true, true, false);
     is(aElement.innerHTML, "a", aDescription + "Meta+Return");
 
+    reset("a");
+    synthesizeKey("VK_RETURN", { osKey: true });
+    check(aDescription + "OS+Return", true, true, false);
+    is(aElement.innerHTML, "a", aDescription + "OS+Return");
+
     // Enter key (same as Return key):
     //   If editor is readonly, it doesn't consume.
     //   If editor is editable and not single line editor, it consumes Return
     //   and Shift+Return.
     //   Otherwise, editor doesn't consume the event.
     reset("a");
     synthesizeKey("VK_ENTER", { });
     check(aDescription + "Enter",
@@ -263,16 +280,21 @@ function runTests()
     check(aDescription + "Alt+Enter", true, true, false);
     is(aElement.innerHTML, "a", aDescription + "Alt+Enter");
 
     reset("a");
     synthesizeKey("VK_ENTER", { metaKey: true });
     check(aDescription + "Meta+Enter", true, true, false);
     is(aElement.innerHTML, "a", aDescription + "Meta+Enter");
 
+    reset("a");
+    synthesizeKey("VK_ENTER", { osKey: true });
+    check(aDescription + "OS+Enter", true, true, false);
+    is(aElement.innerHTML, "a", aDescription + "OS+Enter");
+
     // Tab key:
     //   If editor is tabbable, editor doesn't consume all tab key events.
     //   Otherwise, editor consumes tab key event without any modifier keys.
     reset("a");
     synthesizeKey("VK_TAB", { });
     check(aDescription + "Tab",
           true, true, !aIsTabbable && !aIsReadonly);
     is(aElement.innerHTML,
@@ -306,16 +328,23 @@ function runTests()
 
     reset("a");
     synthesizeKey("VK_TAB", { metaKey: true });
     check(aDescription + "Meta+Tab", true, true, false);
     is(aElement.innerHTML, "a", aDescription + "Meta+Tab");
     is(fm.focusedElement, aElement,
        aDescription + "focus moved unexpectedly (Meta+Tab)");
 
+    reset("a");
+    synthesizeKey("VK_TAB", { osKey: true });
+    check(aDescription + "OS+Tab", true, true, false);
+    is(aElement.innerHTML, "a", aDescription + "OS+Tab");
+    is(fm.focusedElement, aElement,
+       aDescription + "focus moved unexpectedly (OS+Tab)");
+
     // Indent/Outdent tests:
     // UL
     resetForIndent("<ul><li id=\"target\">ul list item</li></ul>");
     synthesizeKey("VK_TAB", { });
     check(aDescription + "Tab on UL",
           true, true, !aIsTabbable && !aIsReadonly);
     is(aElement.innerHTML,
        aIsReadonly || aIsTabbable ?
@@ -367,16 +396,24 @@ function runTests()
     resetForIndent("<ul><li id=\"target\">ul list item</li></ul>");
     synthesizeKey("VK_TAB", { metaKey: true });
     check(aDescription + "Meta+Tab on UL", true, true, false);
     is(aElement.innerHTML, "<ul><li id=\"target\">ul list item</li></ul>",
        aDescription + "Meta+Tab on UL");
     is(fm.focusedElement, aElement,
        aDescription + "focus moved unexpectedly (Meta+Tab on UL)");
 
+    resetForIndent("<ul><li id=\"target\">ul list item</li></ul>");
+    synthesizeKey("VK_TAB", { osKey: true });
+    check(aDescription + "OS+Tab on UL", true, true, false);
+    is(aElement.innerHTML, "<ul><li id=\"target\">ul list item</li></ul>",
+       aDescription + "OS+Tab on UL");
+    is(fm.focusedElement, aElement,
+       aDescription + "focus moved unexpectedly (OS+Tab on UL)");
+
     // OL
     resetForIndent("<ol><li id=\"target\">ol list item</li></ol>");
     synthesizeKey("VK_TAB", { });
     check(aDescription + "Tab on OL",
           true, true, !aIsTabbable && !aIsReadonly);
     is(aElement.innerHTML,
        aIsReadonly || aIsTabbable ?
          "<ol><li id=\"target\">ol list item</li></ol>" :
@@ -427,16 +464,24 @@ function runTests()
     resetForIndent("<ol><li id=\"target\">ol list item</li></ol>");
     synthesizeKey("VK_TAB", { metaKey: true });
     check(aDescription + "Meta+Tab on OL", true, true, false);
     is(aElement.innerHTML, "<ol><li id=\"target\">ol list item</li></ol>",
        aDescription + "Meta+Tab on OL");
     is(fm.focusedElement, aElement,
        aDescription + "focus moved unexpectedly (Meta+Tab on OL)");
 
+    resetForIndent("<ol><li id=\"target\">ol list item</li></ol>");
+    synthesizeKey("VK_TAB", { osKey: true });
+    check(aDescription + "OS+Tab on OL", true, true, false);
+    is(aElement.innerHTML, "<ol><li id=\"target\">ol list item</li></ol>",
+       aDescription + "OS+Tab on OL");
+    is(fm.focusedElement, aElement,
+       aDescription + "focus moved unexpectedly (OS+Tab on OL)");
+
     // TD
     resetForIndent("<table><tr><td id=\"target\">td</td></tr></table>");
     synthesizeKey("VK_TAB", { });
     check(aDescription + "Tab on TD",
           true, true, !aIsTabbable && !aIsReadonly);
     is(aElement.innerHTML,
        aIsTabbable || aIsReadonly ?
          "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>" :
@@ -489,16 +534,25 @@ function runTests()
     synthesizeKey("VK_TAB", { metaKey: true });
     check(aDescription + "Meta+Tab on TD", true, true, false);
     is(aElement.innerHTML,
        "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>",
        aDescription + "Meta+Tab on TD");
     is(fm.focusedElement, aElement,
        aDescription + "focus moved unexpectedly (Meta+Tab on TD)");
 
+    resetForIndent("<table><tr><td id=\"target\">td</td></tr></table>");
+    synthesizeKey("VK_TAB", { osKey: true });
+    check(aDescription + "OS+Tab on TD", true, true, false);
+    is(aElement.innerHTML,
+       "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>",
+       aDescription + "OS+Tab on TD");
+    is(fm.focusedElement, aElement,
+       aDescription + "focus moved unexpectedly (OS+Tab on TD)");
+
     // TH
     resetForIndent("<table><tr><th id=\"target\">th</th></tr></table>");
     synthesizeKey("VK_TAB", { });
     check(aDescription + "Tab on TH",
           true, true, !aIsTabbable && !aIsReadonly);
     is(aElement.innerHTML,
        aIsTabbable || aIsReadonly ?
          "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>" :
@@ -551,16 +605,25 @@ function runTests()
     synthesizeKey("VK_TAB", { metaKey: true });
     check(aDescription + "Meta+Tab on TH", true, true, false);
     is(aElement.innerHTML,
        "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>",
        aDescription + "Meta+Tab on TH");
     is(fm.focusedElement, aElement,
        aDescription + "focus moved unexpectedly (Meta+Tab on TH)");
 
+    resetForIndent("<table><tr><th id=\"target\">th</th></tr></table>");
+    synthesizeKey("VK_TAB", { osKey: true });
+    check(aDescription + "OS+Tab on TH", true, true, false);
+    is(aElement.innerHTML,
+       "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>",
+       aDescription + "OS+Tab on TH");
+    is(fm.focusedElement, aElement,
+       aDescription + "focus moved unexpectedly (OS+Tab on TH)");
+
     // Esc key:
     //   In all cases, esc key events are not consumed
     reset("abc");
     synthesizeKey("VK_ESCAPE", { });
     check(aDescription + "Esc", true, true, false);
 
     reset("abc");
     synthesizeKey("VK_ESCAPE", { shiftKey: true });
@@ -573,16 +636,20 @@ function runTests()
     reset("abc");
     synthesizeKey("VK_ESCAPE", { altKey: true });
     check(aDescription + "Alt+Esc", true, true, false);
 
     reset("abc");
     synthesizeKey("VK_ESCAPE", { metaKey: true });
     check(aDescription + "Meta+Esc", true, true, false);
 
+    reset("abc");
+    synthesizeKey("VK_ESCAPE", { osKey: true });
+    check(aDescription + "OS+Esc", true, true, false);
+
     // typical typing tests:
     reset("");
     synthesizeKey("M", { shiftKey: true });
     check(aDescription + "M", true, true, !aIsReadonly);
     synthesizeKey("o", { });
     check(aDescription + "o", true, true, !aIsReadonly);
     synthesizeKey("z", { });
     check(aDescription + "z", true, true, !aIsReadonly);
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -353,51 +353,55 @@ nsPlaintextEditor::HandleKeyPressEvent(n
 
   nsKeyEvent* nativeKeyEvent = GetNativeKeyEvent(aKeyEvent);
   NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
   NS_ASSERTION(nativeKeyEvent->message == NS_KEY_PRESS,
                "HandleKeyPressEvent gets non-keypress event");
 
   switch (nativeKeyEvent->keyCode) {
     case nsIDOMKeyEvent::DOM_VK_META:
+    case nsIDOMKeyEvent::DOM_VK_WIN:
     case nsIDOMKeyEvent::DOM_VK_SHIFT:
     case nsIDOMKeyEvent::DOM_VK_CONTROL:
     case nsIDOMKeyEvent::DOM_VK_ALT:
     case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
     case nsIDOMKeyEvent::DOM_VK_DELETE:
       // These keys are handled on nsEditor
       return nsEditor::HandleKeyPressEvent(aKeyEvent);
     case nsIDOMKeyEvent::DOM_VK_TAB: {
       if (IsTabbable()) {
         return NS_OK; // let it be used for focus switching
       }
 
       if (nativeKeyEvent->IsShift() || nativeKeyEvent->IsControl() ||
-          nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta()) {
+          nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
+          nativeKeyEvent->IsOS()) {
         return NS_OK;
       }
 
       // else we insert the tab straight through
       aKeyEvent->PreventDefault();
       return TypedText(NS_LITERAL_STRING("\t"), eTypedText);
     }
     case nsIDOMKeyEvent::DOM_VK_RETURN:
     case nsIDOMKeyEvent::DOM_VK_ENTER:
       if (IsSingleLineEditor() || nativeKeyEvent->IsControl() ||
-          nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta()) {
+          nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
+          nativeKeyEvent->IsOS()) {
         return NS_OK;
       }
       aKeyEvent->PreventDefault();
       return TypedText(EmptyString(), eTypedBreak);
   }
 
   // NOTE: On some keyboard layout, some characters are inputted with Control
   // key or Alt key, but at that time, widget sets FALSE to these keys.
   if (nativeKeyEvent->charCode == 0 || nativeKeyEvent->IsControl() ||
-      nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta()) {
+      nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
+      nativeKeyEvent->IsOS()) {
     // we don't PreventDefault() here or keybindings like control-x won't work
     return NS_OK;
   }
   aKeyEvent->PreventDefault();
   nsAutoString str(nativeKeyEvent->charCode);
   return TypedText(str, eTypedText);
 }
 
--- a/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html
+++ b/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html
@@ -119,16 +119,20 @@ function runTests()
     //   Basically, modifier keys shouldn't cause keypress event.  However,
     //   even if it were dispatched by widget's bug, editor should consume
     //   it when editor is editable.
     reset("");
     synthesizeKey("VK_META", { type: "keypress" });
     check(aDescription + "Meta", true, true, !aIsReadonly);
 
     reset("");
+    synthesizeKey("VK_WIN", { type: "keypress" });
+    check(aDescription + "OS", true, true, !aIsReadonly);
+
+    reset("");
     synthesizeKey("VK_SHIFT", { type: "keypress" });
     check(aDescription + "Shift", true, true, !aIsReadonly);
 
     reset("");
     synthesizeKey("VK_CONTROL", { type: "keypress" });
     check(aDescription + "Control", true, true, !aIsReadonly);
 
     // Alt key press event installs menubar key event listener, so,
@@ -164,16 +168,20 @@ function runTests()
     // Mac: cmd_deleteWordBackward
     check(aDescription + "Alt+Backspace",
           true, true, aIsReadonly || kIsWin || kIsMac);
 
     reset("");
     synthesizeKey("VK_BACK_SPACE", { metaKey: true });
     check(aDescription + "Meta+Backspace", true, true, aIsReadonly);
 
+    reset("");
+    synthesizeKey("VK_BACK_SPACE", { osKey: true });
+    check(aDescription + "OS+Backspace", true, true, aIsReadonly);
+
     // Delete key:
     //   If editor is readonly, it doesn't consume.
     //   If editor is editable, delete is consumed.
     //   Otherwise, editor doesn't consume the event but the native key
     //   bindings on nsTextControlFrame may consume it.
     reset("");
     synthesizeKey("VK_DELETE", { });
     // Linux: native handler
@@ -201,16 +209,21 @@ function runTests()
           true, true, kIsMac);
 
     reset("");
     synthesizeKey("VK_DELETE", { metaKey: true });
     // Linux: native handler consumed.
     check(aDescription + "Meta+Delete",
           true, true, kIsLinux);
 
+    reset("");
+    synthesizeKey("VK_DELETE", { osKey: true });
+    check(aDescription + "OS+Delete",
+          true, true, false);
+
     // XXX input.value returns "\n" when it's empty, so, we should use dummy
     // value ("a") for the following tests.
 
     // Return key:
     //   If editor is readonly, it doesn't consume.
     //   If editor is editable and not single line editor, it consumes Return
     //   and Shift+Return.
     //   Otherwise, editor doesn't consume the event.
@@ -238,16 +251,21 @@ function runTests()
     check(aDescription + "Alt+Return", true, true, false);
     is(aElement.value, "a", aDescription + "Alt+Return");
 
     reset("a");
     synthesizeKey("VK_RETURN", { metaKey: true });
     check(aDescription + "Meta+Return", true, true, false);
     is(aElement.value, "a", aDescription + "Meta+Return");
 
+    reset("a");
+    synthesizeKey("VK_RETURN", { osKey: true });
+    check(aDescription + "OS+Return", true, true, false);
+    is(aElement.value, "a", aDescription + "OS+Return");
+
     // Enter key (same as Return key):
     //   If editor is readonly, it doesn't consume.
     //   If editor is editable and not single line editor, it consumes Return
     //   and Shift+Return.
     //   Otherwise, editor doesn't consume the event.
     reset("a");
     synthesizeKey("VK_ENTER", { });
     check(aDescription + "Enter",
@@ -272,16 +290,21 @@ function runTests()
     check(aDescription + "Alt+Enter", true, true, false);
     is(aElement.value, "a", aDescription + "Alt+Enter");
 
     reset("a");
     synthesizeKey("VK_ENTER", { metaKey: true });
     check(aDescription + "Meta+Enter", true, true, false);
     is(aElement.value, "a", aDescription + "Meta+Enter");
 
+    reset("a");
+    synthesizeKey("VK_ENTER", { osKey: true });
+    check(aDescription + "OS+Enter", true, true, false);
+    is(aElement.value, "a", aDescription + "OS+Enter");
+
     // Tab key:
     //   If editor is tabbable, editor doesn't consume all tab key events.
     //   Otherwise, editor consumes tab key event without any modifier keys.
     reset("a");
     synthesizeKey("VK_TAB", { });
     check(aDescription + "Tab",
           true, true, !aIsTabbable && !aIsReadonly);
     is(aElement.value, !aIsTabbable && !aIsReadonly ? "a\t" : "a",
@@ -325,16 +348,23 @@ function runTests()
 
     reset("a");
     synthesizeKey("VK_TAB", { metaKey: true });
     check(aDescription + "Meta+Tab", true, true, false);
     is(aElement.value, "a", aDescription + "Meta+Tab");
     is(fm.focusedElement, aElement,
        aDescription + "focus moved unexpectedly (Meta+Tab)");
 
+    reset("a");
+    synthesizeKey("VK_TAB", { osKey: true });
+    check(aDescription + "OS+Tab", true, true, false);
+    is(aElement.value, "a", aDescription + "OS+Tab");
+    is(fm.focusedElement, aElement,
+       aDescription + "focus moved unexpectedly (OS+Tab)");
+
     // Esc key:
     //   In all cases, esc key events are not consumed
     reset("abc");
     synthesizeKey("VK_ESCAPE", { });
     check(aDescription + "Esc", true, true, false);
 
     reset("abc");
     synthesizeKey("VK_ESCAPE", { shiftKey: true });
@@ -347,16 +377,20 @@ function runTests()
     reset("abc");
     synthesizeKey("VK_ESCAPE", { altKey: true });
     check(aDescription + "Alt+Esc", true, true, false);
 
     reset("abc");
     synthesizeKey("VK_ESCAPE", { metaKey: true });
     check(aDescription + "Meta+Esc", true, true, false);
 
+    reset("abc");
+    synthesizeKey("VK_ESCAPE", { osKey: true });
+    check(aDescription + "OS+Esc", true, true, false);
+
     // typical typing tests:
     reset("");
     synthesizeKey("M", { shiftKey: true });
     check(aDescription + "M", true, true, !aIsReadonly);
     synthesizeKey("o", { });
     check(aDescription + "o", true, true, !aIsReadonly);
     synthesizeKey("z", { });
     check(aDescription + "z", true, true, !aIsReadonly);
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -17,16 +17,17 @@
 #include "nsILineInputStream.h"
 #include "nsIIDNService.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "prprf.h"
 #include "mozilla/storage.h"
 #include "mozilla/Attributes.h"
 #include "nsXULAppAPI.h"
 #include "nsIPrincipal.h"
+#include "nsContentUtils.h"
 
 static nsPermissionManager *gPermissionManager = nsnull;
 
 using mozilla::dom::ContentParent;
 using mozilla::dom::ContentChild;
 using mozilla::unused; // ha!
 
 static bool
@@ -506,16 +507,22 @@ nsPermissionManager::Add(nsIURI     *aUR
 
 NS_IMETHODIMP
 nsPermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal,
                                       const char* aType, PRUint32 aPermission,
                                       PRUint32 aExpireType, PRInt64 aExpireTime)
 {
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
+  // We don't add the system principal because it actually has no URI and we
+  // always allow action for them.
+  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
+    return NS_OK;
+  }
+
   nsCOMPtr<nsIURI> uri;
   aPrincipal->GetURI(getter_AddRefs(uri));
 
   return Add(uri, aType, aPermission, aExpireType, aExpireTime);
 }
 
 nsresult
 nsPermissionManager::AddInternal(const nsAFlatCString &aHost,
@@ -696,16 +703,21 @@ nsPermissionManager::Remove(const nsACSt
 }
 
 NS_IMETHODIMP
 nsPermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal,
                                          const char* aType)
 {
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
+  // System principals are never added to the database, no need to remove them.
+  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
+    return NS_OK;
+  }
+
   nsCOMPtr<nsIURI> uri;
   aPrincipal->GetURI(getter_AddRefs(uri));
   NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
 
   nsCAutoString host;
   uri->GetHost(host);
 
   return Remove(host, aType);
@@ -785,29 +797,43 @@ nsPermissionManager::TestPermission(nsIU
 
 NS_IMETHODIMP
 nsPermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
                                                  const char* aType,
                                                  PRUint32* aPermission)
 {
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
+  // System principals do not have URI so we can't try to get
+  // retro-compatibility here.
+  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
+    *aPermission = nsIPermissionManager::ALLOW_ACTION;
+    return NS_OK;
+  }
+
   nsCOMPtr<nsIURI> uri;
   aPrincipal->GetURI(getter_AddRefs(uri));
 
   return TestPermission(uri, aType, aPermission);
 }
 
 NS_IMETHODIMP
 nsPermissionManager::TestExactPermissionFromPrincipal(nsIPrincipal* aPrincipal,
                                                       const char* aType,
                                                       PRUint32* aPermission)
 {
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
+  // System principals do not have URI so we can't try to get
+  // retro-compatibility here.
+  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
+    *aPermission = nsIPermissionManager::ALLOW_ACTION;
+    return NS_OK;
+  }
+
   nsCOMPtr<nsIURI> uri;
   aPrincipal->GetURI(getter_AddRefs(uri));
 
   return TestExactPermission(uri, aType, aPermission);
 }
 
 nsresult
 nsPermissionManager::CommonTestPermission(nsIURI     *aURI,
--- a/extensions/spellcheck/hunspell/src/affentry.cpp
+++ b/extensions/spellcheck/hunspell/src/affentry.cpp
@@ -592,17 +592,18 @@ inline int SfxEntry::test_condition(cons
                             while (p && *p != ']' && (p = nextchar(p)));
 			    st--;
                         }
                         if (p && *p != ']') p = nextchar(p);
                     } else if (pos) {
                         if (neg) return 0;
                         else if (i == numconds) return 1;
                         ingroup = true;
-			while (p && *p != ']' && (p = nextchar(p)));
+			while (p && *p != ']' && (p = nextchar(p)))
+                          ;
 //			if (p && *p != ']') p = nextchar(p);
                         st--;
                     }
                     if (!pos) {
                         i++;
                         st--;
                     }
                     if (st < beg && p && *p != ']') return 0; // word <= condition
--- a/extensions/spellcheck/hunspell/src/mozHunspellDirProvider.h
+++ b/extensions/spellcheck/hunspell/src/mozHunspellDirProvider.h
@@ -33,29 +33,30 @@
  *
  ******* END LICENSE BLOCK *******/
 
 #ifndef mozHunspellDirProvider_h__
 #define mozHunspellDirProvider_h__
 
 #include "nsIDirectoryService.h"
 #include "nsISimpleEnumerator.h"
+#include "mozilla/Attributes.h"
 
-class mozHunspellDirProvider :
+class mozHunspellDirProvider MOZ_FINAL :
   public nsIDirectoryServiceProvider2
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDIRECTORYSERVICEPROVIDER
   NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
 
   static char const *const kContractID;
 
 private:
-  class AppendingEnumerator : public nsISimpleEnumerator
+  class AppendingEnumerator MOZ_FINAL : public nsISimpleEnumerator
   {
   public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSISIMPLEENUMERATOR
 
     AppendingEnumerator(nsISimpleEnumerator* aBase);
 
   private:
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -1566,17 +1566,19 @@ public:
         nsRefPtr<gfxXlibSurface> xsurface =
             gfxXlibSurface::Create(DefaultScreenOfDisplay(dpy),
                                    renderFMT,
                                    gfxIntSize(aSize.width, aSize.height));
 
         XSync(dpy, False);
         mConfig = nsnull;
 
-        if (sEGLLibrary.HasKHRImagePixmap() && sEGLLibrary.HasKHRImageTexture2D()) {
+        if (sEGLLibrary.HasKHRImagePixmap() &&
+            mGLContext->IsExtensionSupported(GLContext::OES_EGL_image))
+        {
             mEGLImage =
                 sEGLLibrary.fCreateImage(EGL_DISPLAY(),
                                          EGL_NO_CONTEXT,
                                          LOCAL_EGL_NATIVE_PIXMAP_KHR,
                                          (EGLClientBuffer)xsurface->XDrawable(),
                                          nsnull);
 
             if (!mEGLImage) {
--- a/gfx/layers/ImageLayers.h
+++ b/gfx/layers/ImageLayers.h
@@ -11,16 +11,17 @@
 #include "nsISupportsImpl.h"
 #include "gfxPattern.h"
 #include "nsThreadUtils.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/Mutex.h"
 #include "gfxPlatform.h"
+#include "LayersBackend.h"
 
 #ifdef XP_MACOSX
 #include "nsIOSurface.h"
 #endif
 #ifdef XP_WIN
 struct ID3D10Texture2D;
 struct ID3D10Device;
 struct ID3D10ShaderResourceView;
@@ -128,28 +129,28 @@ public:
   };
 
   Format GetFormat() { return mFormat; }
   void* GetImplData() { return mImplData; }
 
   virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
   virtual gfxIntSize GetSize() = 0;
 
-  ImageBackendData* GetBackendData(LayerManager::LayersBackend aBackend)
+  ImageBackendData* GetBackendData(LayersBackend aBackend)
   { return mBackendData[aBackend]; }
-  void SetBackendData(LayerManager::LayersBackend aBackend, ImageBackendData* aData)
+  void SetBackendData(LayersBackend aBackend, ImageBackendData* aData)
   { mBackendData[aBackend] = aData; }
 
 protected:
   Image(void* aImplData, Format aFormat) :
     mImplData(aImplData),
     mFormat(aFormat)
   {}
 
-  nsAutoPtr<ImageBackendData> mBackendData[LayerManager::LAYERS_LAST];
+  nsAutoPtr<ImageBackendData> mBackendData[mozilla::layers::LAYERS_LAST];
 
   void* mImplData;
   Format mFormat;
 };
 
 /**
  * A RecycleBin is owned by an ImageContainer. We store buffers in it that we
  * want to recycle from one image to the next.It's a separate object from 
--- a/gfx/layers/LayerSorter.cpp
+++ b/gfx/layers/LayerSorter.cpp
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "LayerSorter.h"
 #include "DirectedGraph.h"
 #include "limits.h"
 #include "gfxLineSegment.h"
+#include "Layers.h"
 
 namespace mozilla {
 namespace layers {
 
 enum LayerSortOrder {
   Undefined,
   ABeforeB,
   BBeforeA,
--- a/gfx/layers/LayerSorter.h
+++ b/gfx/layers/LayerSorter.h
@@ -1,18 +1,20 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_LAYERSORTER_H
 #define GFX_LAYERSORTER_H
 
-#include "Layers.h"
+#include "nsTArray.h"
 
 namespace mozilla {
 namespace layers {
 
+class Layer;
+
 void SortLayersBy3DZOrder(nsTArray<Layer*>& aLayers);
 
 }
 }
 #endif /* GFX_LAYERSORTER_H */
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -13,17 +13,17 @@
 #include "nsRect.h"
 #include "nsISupportsImpl.h"
 #include "nsAutoPtr.h"
 #include "gfx3DMatrix.h"