Merge mozilla-central into services-central
authorGregory Szorc <gps@mozilla.com>
Fri, 04 Jan 2013 15:36:56 -0800
changeset 126937 302918441b46e8779cd441bf213979c1d844c69f
parent 126936 f1df8615c8f903157232de12245afdd283f75d0f (current diff)
parent 126679 9ea49843366192534b728e78840c2c528556419c (diff)
child 126938 939e3db16cbd1d44ed2204a6a215f32b601a0733
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone20.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 mozilla-central into services-central
content/html/content/public/nsHTMLCanvasElement.h
content/html/content/src/nsHTMLCanvasElement.cpp
content/html/content/src/nsHTMLImageElement.cpp
content/html/content/src/nsHTMLImageElement.h
dom/sms/tests/marionette/test_number_of_messages.js
dom/tests/mochitest/ajax/offline/simpleManifest.notmanifest
dom/tests/mochitest/ajax/offline/test_badManifestMime.html
layout/forms/test/test_bug536567.html
other-licenses/android/ba.c
other-licenses/android/ba.h
other-licenses/android/bionic_tls.h
other-licenses/android/debugger.c
other-licenses/android/dlfcn.c
other-licenses/android/dlfcn.h
other-licenses/android/linker.c
other-licenses/android/linker.h
other-licenses/android/linker_debug.h
other-licenses/android/linker_format.c
other-licenses/android/rt.c
view/public/nsIView.h
view/src/nsView.h
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -77,16 +77,17 @@ include $(topsrcdir)/config/rules.mk
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xpcom \
   -I$(srcdir)/../xul \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/style \
+  -I$(srcdir)/../../../layout/svg \
   -I$(srcdir)/../../../layout/xul/base/src \
   $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../atk \
   $(NULL)
 else
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -112,19 +112,17 @@ public:
   }
 
   /**
    * Return document accessible for the given docshell.
    */
   static DocAccessible* GetDocAccessibleFor(nsIDocShellTreeItem* aContainer)
   {
     nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
-    nsCOMPtr<nsIPresShell> presShell;
-    docShell->GetPresShell(getter_AddRefs(presShell));
-    return GetAccService()->GetDocAccessible(presShell);
+    return GetAccService()->GetDocAccessible(docShell->GetPresShell());
   }
 
   /**
     * Return ancestor in this document with the given role if it exists.
     *
     * @param  aDescendant  [in] descendant to start search with
     * @param  aRole        [in] role to find matching ancestor for
     * @return               the ancestor accessible with the given role, or
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -63,21 +63,16 @@ public:
 
   /**
    * Return node type information of DOM node associated with the accessible.
    */
   bool IsContent() const
   {
     return GetNode() && GetNode()->IsNodeOfType(nsINode::eCONTENT);
   }
-  bool IsElement() const
-  {
-    nsINode* node = GetNode();
-    return node && node->IsElement();
-  }
   bool IsDocumentNode() const
   {
     return GetNode() && GetNode()->IsNodeOfType(nsINode::eDOCUMENT);
   }
 
   /**
    * Return the unique identifier of the accessible.
    */
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -51,16 +51,17 @@
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLObjectElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsImageFrame.h"
 #include "nsIObserverService.h"
 #include "nsLayoutUtils.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsObjectFrame.h"
+#include "nsSVGPathGeometryFrame.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Util.h"
 #include "nsDeckFrame.h"
 
 #ifdef MOZ_XUL
 #include "XULAlertAccessible.h"
@@ -191,19 +192,17 @@ nsAccessibilityService::GetRootDocumentA
   if (documentNode) {
     nsCOMPtr<nsISupports> container = documentNode->GetContainer();
     nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
     if (treeItem) {
       nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
       treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
       if (treeItem != rootTreeItem) {
         nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(rootTreeItem));
-        nsCOMPtr<nsIPresShell> presShell;
-        docShell->GetPresShell(getter_AddRefs(presShell));
-        ps = presShell;
+        ps = docShell->GetPresShell();
       }
 
       return aCanCreate ? GetDocAccessible(ps) : ps->GetDocAccessible();
     }
   }
   return nullptr;
 }
 
@@ -907,18 +906,26 @@ nsAccessibilityService::GetOrCreateAcces
       if (frameType == nsGkAtoms::boxFrame ||
           frameType == nsGkAtoms::scrollFrame) {
         newAcc = new XULTabpanelAccessible(content, document);
       }
     }
   }
 
   if (!newAcc) {
-    if (content->IsSVG(nsGkAtoms::svg)) {
-      newAcc = new EnumRoleAccessible(content, document, roles::DIAGRAM);
+    if (content->IsSVG()) {
+      nsSVGPathGeometryFrame* pathGeometryFrame = do_QueryFrame(frame);
+      if (pathGeometryFrame) {
+        // A graphic elements: rect, circle, ellipse, line, path, polygon,
+        // polyline and image. A 'use' and 'text' graphic elements require
+        // special support.
+        newAcc = new EnumRoleAccessible(content, document, roles::GRAPHIC);
+      } else if (content->Tag() == nsGkAtoms::svg) {
+        newAcc = new EnumRoleAccessible(content, document, roles::DIAGRAM);
+      }
     } else if (content->IsMathML(nsGkAtoms::math)) {
       newAcc = new EnumRoleAccessible(content, document, roles::EQUATION);
     }
   }
 
   // If no accessible, see if we need to create a generic accessible because
   // of some property that makes this object interesting
   // We don't do this for <body>, <html>, <window>, <dialog> etc. which
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -24,17 +24,17 @@
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIScrollableFrame.h"
 #include "nsEventStateManager.h"
 #include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsPIDOMWindow.h"
 #include "nsGUIEvent.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsLayoutUtils.h"
 #include "nsGkAtoms.h"
 
 #include "nsComponentManagerUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "mozilla/dom/Element.h"
 
 #include "nsITreeBoxObject.h"
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -44,17 +44,17 @@
 #include "nsIFormControl.h"
 
 #include "nsDeckFrame.h"
 #include "nsLayoutUtils.h"
 #include "nsIPresShell.h"
 #include "nsIStringBundle.h"
 #include "nsPresContext.h"
 #include "nsIFrame.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIScrollableFrame.h"
 #include "nsFocusManager.h"
 
 #include "nsXPIDLString.h"
 #include "nsUnicharUtils.h"
 #include "nsReadableUtils.h"
 #include "prdtoa.h"
@@ -619,17 +619,17 @@ Accessible::VisibilityState()
   // Walk the parent frame chain to see if there's invisible parent or the frame
   // is in background tab.
   if (!frame->GetStyleVisibility()->IsVisible())
     return states::INVISIBLE;
 
   nsIFrame* curFrame = frame;
   nsPoint framePos(0, 0);
   do {
-    nsIView* view = curFrame->GetView();
+    nsView* view = curFrame->GetView();
     if (view && view->GetVisibility() == nsViewVisibility_kHide)
       return states::INVISIBLE;
 
     // Offscreen state for background tab content and invisible for not selected
     // deck panel.
     nsIFrame* parentFrame = curFrame->GetParent();
     nsDeckFrame* deckFrame = do_QueryFrame(parentFrame);
     if (deckFrame && deckFrame->GetSelectedBox() != curFrame) {
@@ -2010,17 +2010,17 @@ Accessible::RelationByType(uint32_t aTyp
       // If accessible is in its own Window, or is the root of a document,
       // then we should provide NODE_CHILD_OF relation so that MSAA clients
       // can easily get to true parent instead of getting to oleacc's
       // ROLE_WINDOW accessible which will prevent us from going up further
       // (because it is system generated and has no idea about the hierarchy
       // above it).
       nsIFrame *frame = GetFrame();
       if (frame) {
-        nsIView *view = frame->GetViewExternal();
+        nsView *view = frame->GetViewExternal();
         if (view) {
           nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
           if (scrollFrame || view->GetWidget() || !frame->GetParent())
             rel.AppendTarget(Parent());
         }
       }
 
       return rel;
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -23,17 +23,17 @@
 #include "nsRefPtrHashtable.h"
 
 struct nsRoleMapEntry;
 
 struct nsRect;
 class nsIContent;
 class nsIFrame;
 class nsIAtom;
-class nsIView;
+class nsView;
 
 namespace mozilla {
 namespace a11y {
 
 class Accessible;
 class AccEvent;
 class AccGroupInfo;
 class EmbeddedObjCollector;
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -867,17 +867,17 @@ DocAccessible::AttributeWillChange(nsIDo
 
     accessible = this;
   }
 
   // Update dependent IDs cache. Take care of elements that are accessible
   // because dependent IDs cache doesn't contain IDs from non accessible
   // elements.
   if (aModType != nsIDOMMutationEvent::ADDITION)
-    RemoveDependentIDsFor(accessible, aAttribute);
+    RemoveDependentIDsFor(aElement, aAttribute);
 
   // Store the ARIA attribute old value so that it can be used after
   // attribute change. Note, we assume there's no nested ARIA attribute
   // changes. If this happens then we should end up with keeping a stack of
   // old values.
 
   // XXX TODO: bugs 472142, 472143.
   // Here we will want to cache whatever attribute values we are interested
@@ -923,17 +923,17 @@ DocAccessible::AttributeChanged(nsIDocum
 
   // Update dependent IDs cache. Take care of accessible elements because no
   // accessible element means either the element is not accessible at all or
   // its accessible will be created later. It doesn't make sense to keep
   // dependent IDs for non accessible elements. For the second case we'll update
   // dependent IDs cache when its accessible is created.
   if (aModType == nsIDOMMutationEvent::MODIFICATION ||
       aModType == nsIDOMMutationEvent::ADDITION) {
-    AddDependentIDsFor(accessible, aAttribute);
+    AddDependentIDsFor(aElement, aAttribute);
   }
 }
 
 // DocAccessible protected member
 void
 DocAccessible::AttributeChangedImpl(Accessible* aAccessible,
                                     int32_t aNameSpaceID, nsIAtom* aAttribute)
 {
@@ -1307,18 +1307,20 @@ DocAccessible::BindToDocument(Accessible
   // Put into DOM node cache.
   if (aAccessible->IsNodeMapEntry())
     mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible);
 
   // Put into unique ID cache.
   mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible);
 
   aAccessible->SetRoleMapEntry(aRoleMapEntry);
-  if (aAccessible->IsElement())
-    AddDependentIDsFor(aAccessible);
+
+  nsIContent* content = aAccessible->GetContent();
+  if (content && content->IsElement())
+    AddDependentIDsFor(content->AsElement());
 
   return true;
 }
 
 void
 DocAccessible::UnbindFromDocument(Accessible* aAccessible)
 {
   NS_ASSERTION(mAccessibleCache.GetWeak(aAccessible->UniqueID()),
@@ -1529,54 +1531,54 @@ DocAccessible::ProcessLoad()
 
   // Fire busy state change event.
   nsRefPtr<AccEvent> stateEvent =
     new AccStateChangeEvent(this, states::BUSY, false);
   nsEventShell::FireEvent(stateEvent);
 }
 
 void
-DocAccessible::AddDependentIDsFor(Accessible* aRelProvider,
+DocAccessible::AddDependentIDsFor(dom::Element* aRelProviderElm,
                                   nsIAtom* aRelAttr)
 {
   for (uint32_t idx = 0; idx < kRelationAttrsLen; idx++) {
     nsIAtom* relAttr = *kRelationAttrs[idx];
     if (aRelAttr && aRelAttr != relAttr)
       continue;
 
     if (relAttr == nsGkAtoms::_for) {
-      if (!aRelProvider->GetContent()->IsHTML() ||
-          (aRelProvider->GetContent()->Tag() != nsGkAtoms::label &&
-           aRelProvider->GetContent()->Tag() != nsGkAtoms::output))
+      if (!aRelProviderElm->IsHTML() ||
+          (aRelProviderElm->Tag() != nsGkAtoms::label &&
+           aRelProviderElm->Tag() != nsGkAtoms::output))
         continue;
 
     } else if (relAttr == nsGkAtoms::control) {
-      if (!aRelProvider->GetContent()->IsXUL() ||
-          (aRelProvider->GetContent()->Tag() != nsGkAtoms::label &&
-           aRelProvider->GetContent()->Tag() != nsGkAtoms::description))
+      if (!aRelProviderElm->IsXUL() ||
+          (aRelProviderElm->Tag() != nsGkAtoms::label &&
+           aRelProviderElm->Tag() != nsGkAtoms::description))
         continue;
     }
 
-    IDRefsIterator iter(this, aRelProvider->GetContent(), relAttr);
+    IDRefsIterator iter(this, aRelProviderElm, relAttr);
     while (true) {
       const nsDependentSubstring id = iter.NextID();
       if (id.IsEmpty())
         break;
 
       AttrRelProviderArray* providers = mDependentIDsHash.Get(id);
       if (!providers) {
         providers = new AttrRelProviderArray();
         if (providers) {
           mDependentIDsHash.Put(id, providers);
         }
       }
 
       if (providers) {
         AttrRelProvider* provider =
-          new AttrRelProvider(relAttr, aRelProvider->GetContent());
+          new AttrRelProvider(relAttr, aRelProviderElm);
         if (provider) {
           providers->AppendElement(provider);
 
           // We've got here during the children caching. If the referenced
           // content is not accessible then store it to pend its container
           // children invalidation (this happens immediately after the caching
           // is finished).
           nsIContent* dependentContent = iter.GetElem(id);
@@ -1590,36 +1592,36 @@ DocAccessible::AddDependentIDsFor(Access
     // If the relation attribute is given then we don't have anything else to
     // check.
     if (aRelAttr)
       break;
   }
 }
 
 void
-DocAccessible::RemoveDependentIDsFor(Accessible* aRelProvider,
+DocAccessible::RemoveDependentIDsFor(dom::Element* aRelProviderElm,
                                      nsIAtom* aRelAttr)
 {
   for (uint32_t idx = 0; idx < kRelationAttrsLen; idx++) {
     nsIAtom* relAttr = *kRelationAttrs[idx];
     if (aRelAttr && aRelAttr != *kRelationAttrs[idx])
       continue;
 
-    IDRefsIterator iter(this, aRelProvider->GetContent(), relAttr);
+    IDRefsIterator iter(this, aRelProviderElm, relAttr);
     while (true) {
       const nsDependentSubstring id = iter.NextID();
       if (id.IsEmpty())
         break;
 
       AttrRelProviderArray* providers = mDependentIDsHash.Get(id);
       if (providers) {
         for (uint32_t jdx = 0; jdx < providers->Length(); ) {
           AttrRelProvider* provider = (*providers)[jdx];
           if (provider->mRelAttr == relAttr &&
-              provider->mContent == aRelProvider->GetContent())
+              provider->mContent == aRelProviderElm)
             providers->RemoveElement(provider);
           else
             jdx++;
         }
         if (providers->Length() == 0)
           mDependentIDsHash.Remove(id);
       }
     }
@@ -1909,18 +1911,19 @@ DocAccessible::CacheChildrenInSubtree(Ac
   }
 }
 
 void
 DocAccessible::UncacheChildrenInSubtree(Accessible* aRoot)
 {
   aRoot->mStateFlags |= eIsNotInDocument;
 
-  if (aRoot->IsElement())
-    RemoveDependentIDsFor(aRoot);
+  nsIContent* rootContent = aRoot->GetContent();
+  if (rootContent && rootContent->IsElement())
+    RemoveDependentIDsFor(rootContent->AsElement());
 
   uint32_t count = aRoot->ContentChildCount();
   for (uint32_t idx = 0; idx < count; idx++)
     UncacheChildrenInSubtree(aRoot->ContentChildAt(idx));
 
   if (aRoot->IsNodeMapEntry() &&
       mNodeToAccessibleMap.Get(aRoot->GetNode()) == aRoot)
     mNodeToAccessibleMap.Remove(aRoot->GetNode());
--- a/accessible/src/generic/DocAccessible.h
+++ b/accessible/src/generic/DocAccessible.h
@@ -360,28 +360,28 @@ protected:
   /**
    * Add dependent IDs pointed by accessible element by relation attribute to
    * cache. If the relation attribute is missed then all relation attributes
    * are checked.
    *
    * @param aRelProvider [in] accessible that element has relation attribute
    * @param aRelAttr     [in, optional] relation attribute
    */
-  void AddDependentIDsFor(Accessible* aRelProvider,
+  void AddDependentIDsFor(dom::Element* aRelProviderElm,
                           nsIAtom* aRelAttr = nullptr);
 
   /**
    * Remove dependent IDs pointed by accessible element by relation attribute
    * from cache. If the relation attribute is absent then all relation
    * attributes are checked.
    *
    * @param aRelProvider [in] accessible that element has relation attribute
    * @param aRelAttr     [in, optional] relation attribute
    */
-  void RemoveDependentIDsFor(Accessible* aRelProvider,
+  void RemoveDependentIDsFor(dom::Element* aRelProviderElm,
                              nsIAtom* aRelAttr = nullptr);
 
   /**
    * Update or recreate an accessible depending on a changed attribute.
    *
    * @param aElement   [in] the element the attribute was changed on
    * @param aAttribute [in] the changed attribute
    * @return            true if an action was taken on the attribute change
--- a/accessible/src/mac/RootAccessibleWrap.mm
+++ b/accessible/src/mac/RootAccessibleWrap.mm
@@ -35,17 +35,17 @@ RootAccessibleWrap::GetNativeType()
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 void
 RootAccessibleWrap::GetNativeWidget(void** aOutView)
 {
   nsIFrame *frame = GetFrame();
   if (frame) {
-    nsIView *view = frame->GetViewExternal();
+    nsView *view = frame->GetViewExternal();
     if (view) {
       nsIWidget *widget = view->GetWidget();
       if (widget) {
         *aOutView = (void**)widget->GetNativeData (NS_NATIVE_WIDGET);
         NS_ASSERTION (*aOutView, 
                       "Couldn't get the native NSView parent we need to connect the accessibility hierarchy!");
       }
     }
--- a/accessible/src/msaa/AccessibleWrap.cpp
+++ b/accessible/src/msaa/AccessibleWrap.cpp
@@ -28,17 +28,17 @@
 
 #include "nsIMutableArray.h"
 #include "nsIFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsINameSpaceManager.h"
 #include "nsINodeInfo.h"
 #include "nsIServiceManager.h"
 #include "nsTextFormatter.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIViewManager.h"
 #include "nsEventMap.h"
 #include "nsArrayUtils.h"
 #include "mozilla/Preferences.h"
 
 #include "Accessible2_i.c"
 #include "AccessibleRole.h"
 #include "AccessibleStates.h"
--- a/accessible/tests/mochitest/name/test_svg.html
+++ b/accessible/tests/mochitest/name/test_svg.html
@@ -46,11 +46,10 @@
   <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg1">
     <title>A description</title>
     <desc>A name</desc>
   </svg>
 
   <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg2">
     <title>A tooltip</title>
   </svg>
-
 </body>
 </html>
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -14,16 +14,17 @@ const ROLE_CHECKBUTTON = nsIAccessibleRo
 const ROLE_CHECK_MENU_ITEM = nsIAccessibleRole.ROLE_CHECK_MENU_ITEM;
 const ROLE_CHROME_WINDOW = nsIAccessibleRole.ROLE_CHROME_WINDOW;
 const ROLE_COMBOBOX = nsIAccessibleRole.ROLE_COMBOBOX;
 const ROLE_COMBOBOX_LIST = nsIAccessibleRole.ROLE_COMBOBOX_LIST;
 const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
 const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER;
 const ROLE_DEFINITION = nsIAccessibleRole.ROLE_DEFINITION;
 const ROLE_DEFINITION_LIST = nsIAccessibleRole.ROLE_DEFINITION_LIST;
+const ROLE_DIAGRAM = nsIAccessibleRole.ROLE_DIAGRAM;
 const ROLE_DIALOG = nsIAccessibleRole.ROLE_DIALOG;
 const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
 const ROLE_EMBEDDED_OBJECT = nsIAccessibleRole.ROLE_EMBEDDED_OBJECT;
 const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
 const ROLE_FIGURE = nsIAccessibleRole.ROLE_FIGURE;
 const ROLE_FOOTER = nsIAccessibleRole.ROLE_FOOTER;
 const ROLE_FLAT_EQUATION = nsIAccessibleRole.ROLE_FLAT_EQUATION;
 const ROLE_FORM = nsIAccessibleRole.ROLE_FORM;
--- a/accessible/tests/mochitest/role/Makefile.in
+++ b/accessible/tests/mochitest/role/Makefile.in
@@ -9,11 +9,12 @@ VPATH		= @srcdir@
 relativesrcdir  = accessible/role
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_A11Y_FILES =\
 		test_aria.html \
 		test_aria.xul \
 		test_general.html \
+		test_svg.html \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/role/test_svg.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>SVG elements accessible roles</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../attributes.js"></script>
+
+  <script type="application/javascript">
+    function doTests()
+    {
+      testRole("svg", ROLE_DIAGRAM);
+      testRole("rect", ROLE_GRAPHIC);
+      testRole("circle", ROLE_GRAPHIC);
+      testRole("ellipse", ROLE_GRAPHIC);
+      testRole("line", ROLE_GRAPHIC);
+      testRole("polygon", ROLE_GRAPHIC);
+      testRole("polyline", ROLE_GRAPHIC);
+      testRole("path", ROLE_GRAPHIC);
+      testRole("image", ROLE_GRAPHIC);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=822983"
+     title="Map SVG graphic elements to accessibility API">
+    Bug 822983
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg"
+       xmlns:xlink="http://www.w3.org/1999/xlink">
+    <rect width="300" height="100" id="rect"
+          style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)"/>
+    <circle cx="100" cy="50" r="40" stroke="black" id="circle"
+            stroke-width="2" fill="red"/>
+    <ellipse cx="300" cy="80" rx="100" ry="50" id="ellipse"
+             style="fill:yellow;stroke:purple;stroke-width:2"/>
+    <line x1="0" y1="0" x2="200" y2="200" id="line"
+          style="stroke:rgb(255,0,0);stroke-width:2"/>
+    <polygon points="200,10 250,190 160,210" id="polygon"
+             style="fill:lime;stroke:purple;stroke-width:1"/>
+    <polyline points="20,20 40,25 60,40 80,120 120,140 200,180" id="polyline"
+              style="fill:none;stroke:black;stroke-width:3" />
+    <path d="M150 0 L75 200 L225 200 Z" id="path"/>
+    <image x1="25" y1="80" width="50" height="20" id="image"
+           xlink:href="../moz.png"/>
+  </svg>
+
+</body>
+</html>
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -490,17 +490,17 @@ pref("shutdown.watchdog.timeoutSecs", -1
 #endif
 
 // Extensions preferences
 pref("extensions.update.enabled", false);
 pref("extensions.getAddons.cache.enabled", false);
 
 // Context Menu
 pref("ui.click_hold_context_menus", true);
-pref("ui.click_hold_context_menus.delay", 1000);
+pref("ui.click_hold_context_menus.delay", 750);
 
 // Enable device storage
 pref("device.storage.enabled", true);
 
 pref("media.plugins.enabled", false);
 pref("media.omx.enabled", true);
 
 // Disable printing (particularly, window.print())
@@ -610,8 +610,12 @@ pref("font.size.inflation.disabledInMast
 pref("memory.free_dirty_pages", true);
 
 // UAProfile settings
 pref("wap.UAProf.url", "");
 pref("wap.UAProf.tagname", "x-wap-profile");
 
 // Wait up to this much milliseconds when orientation changed
 pref("layers.orientation.sync.timeout", 1000);
+
+// Don't discard WebGL contexts for foreground apps on memory
+// pressure.
+pref("webgl.can-lose-context-in-foreground", false);
--- a/b2g/config/panda/releng-pandaboard.tt
+++ b/b2g/config/panda/releng-pandaboard.tt
@@ -1,8 +1,8 @@
 [
 {
-"size": 676733720,
-"digest": "6ae117e64af1e8532004e9de44f172b5db88f42a91b8821503b3832de6e168f8c000229705a5110ce294065780a6371e7852dd76ddd8f3c6113892a093b6fc55",
+"size": 676664796,
+"digest": "d50e0a916bb54c12f55961b3155c1bb754e46fccd0cc965f6c37c2142a7080e58dc3980b7f7f1249b078a21553d6ae2edfefce18213cf8c8fc3f593db27bb0e6",
 "algorithm": "sha512",
 "filename": "gonk.tar.xz"
 }
 ]
--- a/b2g/config/panda/sources.xml
+++ b/b2g/config/panda/sources.xml
@@ -9,17 +9,17 @@
   <remote fetch="http://git.mozilla.org/" name="mozillaorg"/>
   <default remote="linaro" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
 
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="69380784721ae11af93ef4e1b5ce8a54e8570574">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="ffc42185726384eaa80ea685bd9c95b7dab467c3"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="22629c7597d0d658fb472f76f2bf35e7eaaf98fd"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="167b4c59a82b9130e385de786e8056d89a1cb8c3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="6ee1f8987ef36d688f97064c003ad57849dfadf2"/>
 
   <!-- Stock Android things -->
   <!-- Information: platform/abi/cpp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <!-- Information: platform/bionic is tagged with android-4.0.4_r2.1 --><project name="platform/bionic" path="bionic" revision="3d11bf0f3f3cf848f6f1e8449bf8736d8d1c78a3"/>
   <!-- Information: platform/bootable/recovery is tagged with android-4.0.4_r2.1 --><project name="platform/bootable/recovery" path="bootable/recovery" revision="fadc5ac81d6400ebdd041f7d4ea64021596d6b7d"/>
   <!-- Information: device/common is tagged with android-sdk-adt_r20 --><project name="device/common" path="device/common" revision="7d4526582f88808a3194e1a3b304abb369d2745c"/>
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -31,19 +31,19 @@ DEFINES += \
   -DNEWWINDOW_ICO=\"$(DIST)/branding/newwindow.ico\" \
   -DNEWTAB_ICO=\"$(DIST)/branding/newtab.ico\" \
   -DPBMODE_ICO=\"$(DIST)/branding/pbmode.ico\" \
 
   $(NULL)
 
 ifdef LIBXUL_SDK #{
 PREF_JS_EXPORTS += $(srcdir)/profile/channel-prefs.js
+DEFINES += -DLIBXUL_SDK
+endif #} LIBXUL_SDK
 
-include $(topsrcdir)/config/rules.mk
-else
 # Build a binary bootstrapping with XRE_main
 
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 
 CPPSRCS = nsBrowserApp.cpp
 
 LOCAL_INCLUDES += \
   -I$(topsrcdir)/toolkit/xre \
@@ -125,18 +125,16 @@ ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH
 
 libs:: 
 	cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
 
 GARBAGE += $(addprefix $(FINAL_TARGET)/defaults/pref/, firefox.js)
 
 endif
 
-endif #} LIBXUL_SDK
-
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 libs::
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(FINAL_TARGET)/icons
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default16.png  $(FINAL_TARGET)/chrome/icons/default
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default32.png  $(FINAL_TARGET)/chrome/icons/default
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png  $(FINAL_TARGET)/chrome/icons/default
 endif
 
@@ -183,31 +181,21 @@ libs-preqs = \
 
 .PHONY: repackage
 libs repackage:: $(PROGRAM) $(libs-preqs)
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/Contents/Resources/$(AB).lproj
 	sed -e "s/%APP_VERSION%/$(MOZ_APP_VERSION)/" -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" -e "s/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/" -e "s/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
 	sed -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(dist_dest)/Contents/$(APPFILES)
-ifdef LIBXUL_SDK
-	cp $(LIBXUL_DIST)/bin/$(XR_STUB_NAME) $(dist_dest)/Contents/MacOS/firefox
-else
 	$(RM) $(dist_dest)/Contents/MacOS/$(PROGRAM)
 	rsync -aL $(PROGRAM) $(dist_dest)/Contents/MacOS
-endif
 	cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
 	cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
 	printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
-
-else
-ifdef LIBXUL_SDK
-libs::
-	cp $(LIBXUL_DIST)/bin/$(XULRUNNER_STUB_NAME)$(BIN_SUFFIX) $(DIST)/bin/firefox$(BIN_SUFFIX)
-endif
 endif
 
 ifdef LIBXUL_SDK #{
 ifndef SKIP_COPY_XULRUNNER #{
 libs::
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) #{
 	rsync -a --copy-unsafe-links $(LIBXUL_DIST)/XUL.framework $(dist_dest)/Contents/Frameworks
 else
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -1,22 +1,24 @@
 /* -*- 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 "nsXULAppAPI.h"
+#include "mozilla/AppData.h"
 #include "application.ini.h"
 #include "nsXPCOMGlue.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
 #elif defined(XP_UNIX)
 #include <sys/time.h>
 #include <sys/resource.h>
+#include <unistd.h>
 #endif
 
 #ifdef XP_MACOSX
 #include "MacQuirks.h"
 #endif
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -33,16 +35,18 @@
 #define strcasecmp _stricmp
 #endif
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
 #include "mozilla/Telemetry.h"
 
+using namespace mozilla;
+
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
 #ifndef XP_WIN
   vfprintf(stderr, fmt, ap);
 #else
@@ -116,17 +120,17 @@ static const nsDynamicFunctionLoad kXULF
     { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
 #endif
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { nullptr, nullptr }
 };
 
-static int do_main(int argc, char* argv[])
+static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
 {
   nsCOMPtr<nsIFile> appini;
   nsresult rv;
 
   // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
   // Note that -app must be the *first* argument.
   const char *appDataFile = getenv("XUL_APP_FILE");
   if (appDataFile && *appDataFile) {
@@ -161,22 +165,37 @@ static int do_main(int argc, char* argv[
 
   if (appini) {
     nsXREAppData *appData;
     rv = XRE_CreateAppData(appini, &appData);
     if (NS_FAILED(rv)) {
       Output("Couldn't read application.ini");
       return 255;
     }
+    // xreDirectory already has a refcount from NS_NewLocalFile
+    appData->xreDirectory = xreDirectory;
     int result = XRE_main(argc, argv, appData, 0);
     XRE_FreeAppData(appData);
     return result;
   }
 
-  return XRE_main(argc, argv, &sAppData, 0);
+  ScopedAppData appData(&sAppData);
+  nsCOMPtr<nsIFile> exeFile;
+  rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile));
+  if (NS_FAILED(rv)) {
+    Output("Couldn't find the application directory.\n");
+    return 255;
+  }
+  nsCOMPtr<nsIFile> appDir;
+  exeFile->GetParent(getter_AddRefs(appDir));
+
+  SetStrongPtr(appData.directory, static_cast<nsIFile*>(appDir.get()));
+  // xreDirectory already has a refcount from NS_NewLocalFile
+  appData.xreDirectory = xreDirectory;
+  return XRE_main(argc, argv, &appData, 0);
 }
 
 /* Local implementation of PR_Now, since the executable can't depend on NSPR */
 static PRTime _PR_Now()
 {
 #ifdef XP_WIN
   MOZ_STATIC_ASSERT(sizeof(PRTime) == sizeof(FILETIME), "PRTime must have the same size as FILETIME");
   FILETIME ft;
@@ -191,60 +210,148 @@ static PRTime _PR_Now()
 
 #else
   struct timeval tm;
   gettimeofday(&tm, 0);
   return (((PRTime)tm.tv_sec * 1000000LL) + (PRTime)tm.tv_usec);
 #endif
 }
 
+static bool
+FileExists(const char *path)
+{
+#ifdef XP_WIN
+  wchar_t wideDir[MAX_PATH];
+  MultiByteToWideChar(CP_UTF8, 0, path, -1, wideDir, MAX_PATH);
+  DWORD fileAttrs = GetFileAttributesW(wideDir);
+  return fileAttrs != INVALID_FILE_ATTRIBUTES;
+#else
+  return access(path, R_OK) == 0;
+#endif
+}
+
+#ifdef LIBXUL_SDK
+#  define XPCOM_PATH "xulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL
+#else
+#  define XPCOM_PATH XPCOM_DLL
+#endif
+static nsresult
+InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory)
+{
+  char exePath[MAXPATHLEN];
+
+  nsresult rv = mozilla::BinaryPath::Get(argv0, exePath);
+  if (NS_FAILED(rv)) {
+    Output("Couldn't find the application directory.\n");
+    return rv;
+  }
+
+  char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
+  if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_PATH) - 1))
+    return NS_ERROR_FAILURE;
+
+  strcpy(lastSlash + 1, XPCOM_PATH);
+  lastSlash += sizeof(XPCOM_PATH) - sizeof(XPCOM_DLL);
+
+  if (!FileExists(exePath)) {
+#if defined(LIBXUL_SDK) && defined(XP_MACOSX)
+    // Check for <bundle>/Contents/Frameworks/XUL.framework/libxpcom.dylib
+    bool greFound = false;
+    CFBundleRef appBundle = CFBundleGetMainBundle();
+    if (!appBundle)
+      return NS_ERROR_FAILURE;
+    CFURLRef fwurl = CFBundleCopyPrivateFrameworksURL(appBundle);
+    CFURLRef absfwurl = nullptr;
+    if (fwurl) {
+      absfwurl = CFURLCopyAbsoluteURL(fwurl);
+      CFRelease(fwurl);
+    }
+    if (absfwurl) {
+      CFURLRef xulurl =
+        CFURLCreateCopyAppendingPathComponent(NULL, absfwurl,
+                                              CFSTR("XUL.framework"),
+                                              true);
+
+      if (xulurl) {
+        CFURLRef xpcomurl =
+          CFURLCreateCopyAppendingPathComponent(NULL, xulurl,
+                                                CFSTR("libxpcom.dylib"),
+                                                false);
+
+        if (xpcomurl) {
+          if (CFURLGetFileSystemRepresentation(xpcomurl, true,
+                                               (UInt8*) exePath,
+                                               sizeof(exePath)) &&
+              access(tbuffer, R_OK | X_OK) == 0) {
+            if (realpath(tbuffer, exePath)) {
+              greFound = true;
+            }
+          }
+          CFRelease(xpcomurl);
+        }
+        CFRelease(xulurl);
+      }
+      CFRelease(absfwurl);
+    }
+  }
+  if (!greFound) {
+#endif
+    Output("Could not find the Mozilla runtime.\n");
+    return NS_ERROR_FAILURE;
+  }
+
+  // We do this because of data in bug 771745
+  XPCOMGlueEnablePreload();
+
+  rv = XPCOMGlueStartup(exePath);
+  if (NS_FAILED(rv)) {
+    Output("Couldn't load XPCOM.\n");
+    return rv;
+  }
+
+  rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
+  if (NS_FAILED(rv)) {
+    Output("Couldn't load XRE functions.\n");
+    return rv;
+  }
+
+  // chop XPCOM_DLL off exePath
+  *lastSlash = '\0';
+#ifdef XP_WIN
+  NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
+                  xreDirectory);
+#else
+  NS_NewNativeLocalFile(nsDependentCString(exePath), false,
+                        xreDirectory);
+#endif
+
+  return rv;
+}
+
 int main(int argc, char* argv[])
 {
   PRTime start = _PR_Now();
-  char exePath[MAXPATHLEN];
 
 #ifdef XP_MACOSX
   TriggerQuirks();
 #endif
 
-  nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't calculate the application directory.\n");
-    return 255;
-  }
-
-  char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
-  if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
-    return 255;
-
-  strcpy(++lastSlash, XPCOM_DLL);
-
   int gotCounters;
 #if defined(XP_UNIX)
   struct rusage initialRUsage;
   gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
 #elif defined(XP_WIN)
   IO_COUNTERS ioCounters;
   gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
 #endif
 
-  // We do this because of data in bug 771745
-  XPCOMGlueEnablePreload();
+  nsIFile *xreDirectory;
 
-  rv = XPCOMGlueStartup(exePath);
+  nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory);
   if (NS_FAILED(rv)) {
-    Output("Couldn't load XPCOM.\n");
-    return 255;
-  }
-  // Reset exePath so that it is the directory name and not the xpcom dll name
-  *lastSlash = 0;
-
-  rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't load XRE functions.\n");
     return 255;
   }
 
   XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
 
 #ifdef XRE_HAS_DLL_BLOCKLIST
   XRE_SetupDllBlocklist();
 #endif
@@ -271,14 +378,14 @@ int main(int argc, char* argv[])
                               int(newRUsage.ru_majflt - initialRUsage.ru_majflt));
     }
 #endif
   }
 
   int result;
   {
     ScopedLogging log;
-    result = do_main(argc, argv);
+    result = do_main(argc, argv, xreDirectory);
   }
 
   XPCOMGlueShutdown();
   return result;
 }
--- a/browser/app/profile/extensions/Makefile.in
+++ b/browser/app/profile/extensions/Makefile.in
@@ -11,29 +11,42 @@ VPATH      = @srcdir@
 DISTROEXT = $(call core_abspath,$(FINAL_TARGET))/distribution/extensions
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = \
   {972ce4c6-7e08-4474-a285-3208198ce6fd} \
   $(NULL)
 
-include $(topsrcdir)/config/rules.mk
+include $(topsrcdir)/config/config.mk
 
 ifneq (,$(filter aurora beta,$(MOZ_UPDATE_CHANNEL)))
 EXTENSIONS = \
   testpilot@labs.mozilla.com \
   $(NULL)
 
-define _INSTALL_EXTENSION
-$(NSINSTALL) -D $(dir) && \
-  $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(srcdir)/$(dir)/install.rdf.in > $(dir)/install.rdf && \
-  cd $(dir) && \
-  $(ZIP) -r9XD $(DISTROEXT)/$(dir).xpi install.rdf && \
-  cd $(call core_abspath,$(srcdir)/$(dir)) && \
-  $(ZIP) -r9XD $(DISTROEXT)/$(dir).xpi * -x install.rdf.in
+all_xpis = $(foreach dir,$(EXTENSIONS),$(DISTROEXT)/$(dir).xpi)
+libs:: $(all_xpis)
+GARBAGE += $(all_xpis)
+
+$(all_xpis): $(DISTROEXT)/%.xpi: $(call mkdir_deps,$(DISTROEXT)) libs-%
+	cd $* && \
+	$(ZIP) -r9XD $@ * -x \*.in -x \*.mkdir.done
+	cd $(call core_abspath,$(srcdir)/$*) && \
+	$(ZIP) -r9XD $@ * -x \*.in -x \*.mkdir.done
+
+.PHONY: $(all_xpis:.xpi=)
 
-endef # do not remove the blank line!
+define pp_one
+$(2) := $(2)
+$(2)_PATH := $(dir $(2))
+$(2)_TARGET := libs-$(1)
+PP_TARGETS += $(2)
+endef
+$(foreach d,$(EXTENSIONS), \
+  $(foreach in,$(shell cd $(srcdir) ; find $(d) -name '*.in'), \
+    $(eval $(call pp_one,$(d),$(in))) \
+  ) \
+)
 
-libs::
-	$(NSINSTALL) -D $(DISTROEXT)
-	$(foreach dir,$(EXTENSIONS),$(_INSTALL_EXTENSION))
 endif
+
+include $(topsrcdir)/config/rules.mk
--- a/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in
+++ b/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in
@@ -4,19 +4,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
 
 FILES := \
-	install.rdf \
+	install.rdf.in \
 	$(NULL)
+FILES_PATH = $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
+PP_TARGETS := FILES
 
-libs::
-	$(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(srcdir)/install.rdf.in > install.rdf
-	$(INSTALL) $(FILES) $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
- 
-GARBAGE += $(FILES)
+include $(topsrcdir)/config/rules.mk
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -251,37 +251,40 @@ var gPluginHandler = {
   _notificationDisplayedOnce: false,
   handlePluginScripted: function PH_handlePluginScripted(aBrowser) {
     let contentWindow = aBrowser.contentWindow;
     if (!contentWindow)
       return;
 
     let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIDOMWindowUtils);
-    let haveVisibleCTPPlugin = cwu.plugins.some(function(plugin) {
+    let plugins = cwu.plugins.filter(function(plugin) {
       let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+      return gPluginHandler.canActivatePlugin(objLoadingContent);
+    });
+
+    let haveVisibleCTPPlugin = plugins.some(function(plugin) {
       let doc = plugin.ownerDocument;
       let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
       if (!overlay)
         return false;
 
       // if the plugin's style is 240x200, it's a good bet we set that in
       // toolkit/mozapps/plugins/content/pluginProblemContent.css
       // (meaning this plugin was never actually given a size, so it's really
       // not part of visible content)
       let computedStyle = contentWindow.getComputedStyle(plugin);
       let isInvisible = ((computedStyle.width == "240px" &&
                           computedStyle.height == "200px") ||
                          gPluginHandler.isTooSmall(plugin, overlay));
-      return (!isInvisible &&
-              gPluginHandler.canActivatePlugin(objLoadingContent));
+      return !isInvisible;
     });
 
     let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
-    if (notification && !haveVisibleCTPPlugin && !this._notificationDisplayedOnce) {
+    if (notification && plugins.length > 0 && !haveVisibleCTPPlugin && !this._notificationDisplayedOnce) {
       notification.dismissed = false;
       PopupNotifications._update(notification.anchorElement);
       this._notificationDisplayedOnce = true;
     }
 
     aBrowser._pluginScriptedState = this.PLUGIN_SCRIPTED_STATE_DONE;
   },
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -661,17 +661,19 @@
                    flex="100" persist="width" removable="true">
         <searchbar id="searchbar" flex="1"/>
       </toolbaritem>
 
       <toolbarbutton id="webrtc-status-button"
                      class="toolbarbutton-1 chromeclass-toolbar-additional"
                      type="menu"
                      hidden="true"
-                     orient="horizontal">
+                     orient="horizontal"
+                     label="&webrtcIndicatorButton.label;"
+                     tooltiptext="&webrtcIndicatorButton.tooltip;">
         <menupopup onpopupshowing="WebrtcIndicator.fillPopup(this);"
                    onpopuphiding="WebrtcIndicator.clearPopup(this);"
                    oncommand="WebrtcIndicator.menuCommand(event.target);"/>
       </toolbarbutton>
 
       <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      persist="class" removable="true"
                      label="&homeButton.label;"
--- a/browser/base/content/socialchat.xml
+++ b/browser/base/content/socialchat.xml
@@ -3,17 +3,17 @@
 <bindings id="socialChatBindings"
     xmlns="http://www.mozilla.org/xbl"
     xmlns:xbl="http://www.mozilla.org/xbl"
     xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="chatbox">
     <content orient="vertical" mousethrough="never">
       <xul:hbox class="chat-titlebar" xbl:inherits="minimized,selected,activity"
-                onclick="document.getBindingParent(this).toggle();" align="baseline">
+                onclick="document.getBindingParent(this).onTitlebarClick(event);" align="baseline">
         <xul:image class="chat-status-icon" xbl:inherits="src=image"/>
         <xul:label class="chat-title" flex="1" xbl:inherits="value=label" crop="center"/>
         <xul:toolbarbutton class="chat-close-button chat-toolbarbutton"
                            oncommand="document.getBindingParent(this).close();"/>
       </xul:hbox>
       <xul:iframe anonid="iframe" class="chat-frame" flex="1"
                   xbl:inherits="src,origin,collapsed=minimized" type="content"/>
     </content>
@@ -52,16 +52,26 @@
 
           // let the chat frame know if it is being shown or hidden
           let evt = this.iframe.contentDocument.createEvent("CustomEvent");
           evt.initCustomEvent(val ? "socialFrameShow" : "socialFrameHide", true, true, {});
           this.iframe.contentDocument.documentElement.dispatchEvent(evt);
         </setter>
       </property>
 
+      <method name="onTitlebarClick">
+        <parameter name="aEvent"/>
+        <body><![CDATA[
+          if (aEvent.button == 0) // left-click: toggle minimized.
+            this.toggle();
+          else if (aEvent.button == 1) // middle-click: close chat
+            this.close();
+        ]]></body>
+      </method>
+
       <method name="close">
         <body><![CDATA[
           this.parentNode.remove(this);
         ]]></body>
       </method>
 
       <method name="toggle">
         <body><![CDATA[
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1269,16 +1269,21 @@
               setTimeout(function (tabContainer) {
                 tabContainer._handleNewTab(t);
               }, 0, this.tabContainer);
             } else {
               setTimeout(function (tabContainer) {
                 if (t.pinned)
                   tabContainer._handleNewTab(t);
                 else {
+                  if (tabContainer._tabAnimationLoggingEnabled) {
+                    window.QueryInterface(Ci.nsIInterfaceRequestor)
+                          .getInterface(Ci.nsIDOMWindowUtils)
+                          .startFrameTimeRecording();
+                  }
                   t._animStartTime = Date.now();
                   t.setAttribute("fadein", "true");
 
                   // This call to adjustTabstrip is redundant but needed so that
                   // when opening a second tab, the first tab's close buttons
                   // appears immediately rather than when the transition ends.
                   if (tabContainer.childNodes.length == 2)
                     tabContainer.adjustTabstrip();
@@ -1569,16 +1574,21 @@
                 this._removingTabs.length > 3 /* don't want lots of concurrent animations */ ||
                 aTab.getAttribute("fadein") != "true" /* fade-in transition hasn't been triggered yet */ ||
                 window.getComputedStyle(aTab).maxWidth == "0.1px" /* fade-in transition hasn't moved yet */ ||
                 !Services.prefs.getBoolPref("browser.tabs.animate")) {
               this._endRemoveTab(aTab);
               return;
             }
 
+            if (this.tabContainer._tabAnimationLoggingEnabled) {
+              window.QueryInterface(Ci.nsIInterfaceRequestor)
+                    .getInterface(Ci.nsIDOMWindowUtils)
+                    .startFrameTimeRecording();
+            }
             aTab._animStartTime = Date.now();
 
             this._blurTab(aTab);
             aTab.style.maxWidth = ""; // ensure that fade-out transition happens
             aTab.removeAttribute("fadein");
 
             setTimeout(function (tab, tabbrowser) {
               if (tab.parentNode &&
@@ -2875,16 +2885,22 @@
           tab.setAttribute("crop", "end");
           tab.setAttribute("validate", "never");
           tab.setAttribute("onerror", "this.removeAttribute('image');");
           this.adjustTabstrip();
 
           Services.prefs.addObserver("browser.tabs.", this._prefObserver, false);
           window.addEventListener("resize", this, false);
           window.addEventListener("load", this, false);
+
+          try {
+            this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled");
+          } catch (ex) {
+            this._tabAnimationLoggingEnabled = false;
+          }
         ]]>
       </constructor>
 
       <destructor>
         <![CDATA[
           Services.prefs.removeObserver("browser.tabs.", this._prefObserver);
         ]]>
       </destructor>
@@ -3507,16 +3523,28 @@
         var tab = event.target;
 
         if (tab._animStartTime) {
           Services.telemetry.getHistogramById(tab.closing ?
                                               "FX_TAB_ANIM_CLOSE_MS" :
                                               "FX_TAB_ANIM_OPEN_MS")
                             .add(Date.now() - tab._animStartTime);
           tab._animStartTime = 0;
+
+          if (this._tabAnimationLoggingEnabled) {
+            let paints = {};
+            let intervals = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                                  .getInterface(Ci.nsIDOMWindowUtils)
+                                  .stopFrameTimeRecording(paints);
+            let msg = "Tab " + (tab.closing ? "close" : "open") + " (Frame-interval / paint-processing):\n";
+            for (let i = 0; i < intervals.length; i++) {
+              msg += Math.round(intervals[i]) + " / " + Math.round(paints.value[i]) + "\n";
+            }
+            Services.console.logStringMessage(msg);
+          }
         }
 
         if (tab.getAttribute("fadein") == "true") {
           if (tab._fullyOpen)
             this.adjustTabstrip();
           else
             this._handleNewTab(tab);
         } else if (tab.closing) {
--- a/browser/base/content/test/browser_clickToPlayPluginScriptAccessPopup.js
+++ b/browser/base/content/test/browser_clickToPlayPluginScriptAccessPopup.js
@@ -1,10 +1,10 @@
 const gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
-const EXPECTED_PLUGINSCRIPTED_EVENT_COUNT = 6;
+const EXPECTED_PLUGINSCRIPTED_EVENT_COUNT = 7;
 
 var gTestBrowser = null;
 var gNextTestList = [];
 var gNextTest = null;
 var gPluginScriptedFired = false;
 var gPluginScriptedFiredCount = 0;
 
 Components.utils.import("resource://gre/modules/Services.jsm");
@@ -85,16 +85,45 @@ function prepareTest(nextTest, url) {
 }
 
 function testNoEventFired() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "should have a click-to-play notification (" + getCurrentTestLocation() + ")");
   ok(notification.dismissed, "notification should not be showing (" + getCurrentTestLocation() + ")");
   ok(!gPluginScriptedFired, "PluginScripted should not have fired (" + getCurrentTestLocation() + ")");
 
+  prepareTest(testDenyPermissionPart1, gHttpTestRoot + "plugin_test_noScriptNoPopup.html");
+}
+
+function testDenyPermissionPart1() {
+  var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(notification, "test deny permission: should have a click-to-play notification");
+  // Simulate clicking the "Deny Always" button.
+  notification.secondaryActions[1].callback();
+  gPluginScriptedFired = false;
+  prepareTest(testDenyPermissionPart2, gHttpTestRoot + "plugin_test_scriptedPopup1.html");
+}
+
+function testDenyPermissionPart2() {
+  var condition = function() gPluginScriptedFired;
+  waitForCondition(condition, testDenyPermissionPart3, "test deny permission: waited too long for PluginScripted event");
+}
+
+function testDenyPermissionPart3() {
+  var condition = function() gTestBrowser._pluginScriptedState == gPluginHandler.PLUGIN_SCRIPTED_STATE_DONE;
+  waitForCondition(condition, testDenyPermissionPart4, "test deny permission: waited too long for PluginScripted event handling");
+}
+
+function testDenyPermissionPart4() {
+  var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(!notification, "test deny permission: should not have a click-to-play notification");
+
+  var pluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
+  Services.perms.remove("127.0.0.1:8888", pluginHost.getPermissionStringForType("application/x-test"));
+
   runNextTest();
 }
 
 function testExpectNoPopupPart1() {
   var condition = function() gPluginScriptedFired;
   waitForCondition(condition, testExpectNoPopupPart2, "waited too long for PluginScripted event (" + getCurrentTestLocation() + ")");
 }
 
--- a/browser/components/downloads/src/DownloadsUI.js
+++ b/browser/components/downloads/src/DownloadsUI.js
@@ -55,45 +55,45 @@ DownloadsUI.prototype = {
   //////////////////////////////////////////////////////////////////////////////
   //// nsISupports
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadManagerUI]),
 
   //////////////////////////////////////////////////////////////////////////////
   //// nsIDownloadManagerUI
 
-  show: function DUI_show(aWindowContext, aID, aReason)
+  show: function DUI_show(aWindowContext, aID, aReason, aUsePrivateUI)
   {
     if (DownloadsCommon.useToolkitUI) {
-      this._toolkitUI.show(aWindowContext, aID, aReason);
+      this._toolkitUI.show(aWindowContext, aID, aReason, aUsePrivateUI);
       return;
     }
 
     if (!aReason) {
       aReason = Ci.nsIDownloadManagerUI.REASON_USER_INTERACTED;
     }
 
     if (aReason == Ci.nsIDownloadManagerUI.REASON_NEW_DOWNLOAD) {
       const kMinimized = Ci.nsIDOMChromeWindow.STATE_MINIMIZED;
       let browserWin = gBrowserGlue.getMostRecentBrowserWindow();
 
       if (!browserWin || browserWin.windowState == kMinimized) {
-        this._showDownloadManagerUI(aWindowContext, aID, aReason);
+        this._showDownloadManagerUI(aWindowContext, aID, aReason, aUsePrivateUI);
       }
       else {
         // If the indicator is visible, then new download notifications are
         // already handled by the panel service.
         browserWin.DownloadsButton.checkIsVisible(function(isVisible) {
           if (!isVisible) {
-            this._showDownloadManagerUI(aWindowContext, aID, aReason);
+            this._showDownloadManagerUI(aWindowContext, aID, aReason, aUsePrivateUI);
           }
         }.bind(this));
       }
     } else {
-      this._showDownloadManagerUI(aWindowContext, aID, aReason);
+      this._showDownloadManagerUI(aWindowContext, aID, aReason, aUsePrivateUI);
     }
   },
 
   get visible()
   {
     // If we're still using the toolkit downloads manager, delegate the call
     // to it. Otherwise, return true for now, until we decide on how we want
     // to indicate that a new download has started if a browser window is
@@ -107,23 +107,23 @@ DownloadsUI.prototype = {
       this._toolkitUI.getAttention();
     }
   },
 
   /**
    * Helper function that opens the download manager UI.
    */
   _showDownloadManagerUI:
-  function DUI_showDownloadManagerUI(aWindowContext, aID, aReason)
+  function DUI_showDownloadManagerUI(aWindowContext, aID, aReason, aUsePrivateUI)
   {
     // If we weren't given a window context, try to find a browser window
     // to use as our parent - and if that doesn't work, error out and give up.
     let parentWindow = aWindowContext;
     if (!parentWindow) {
-      parentWindow = RecentWindow.getMostRecentBrowserWindow();
+      parentWindow = RecentWindow.getMostRecentBrowserWindow({ private: !!aUsePrivateUI });
       if (!parentWindow) {
         Components.utils.reportError(
           "Couldn't find a browser window to open the Places Downloads View " +
           "from.");
         return;
       }
     }
 
--- a/browser/components/preferences/in-content/jar.mn
+++ b/browser/components/preferences/in-content/jar.mn
@@ -5,17 +5,17 @@
 browser.jar:
 *  content/browser/preferences/in-content/preferences.js
    content/browser/preferences/in-content/landing.xul
 *  content/browser/preferences/in-content/preferences.xul
 *  content/browser/preferences/in-content/main.xul
    content/browser/preferences/in-content/main.js
 *  content/browser/preferences/in-content/tabs.xul
 *  content/browser/preferences/in-content/tabs.js
-   content/browser/preferences/in-content/privacy.xul
+*  content/browser/preferences/in-content/privacy.xul
 *  content/browser/preferences/in-content/privacy.js
 *  content/browser/preferences/in-content/advanced.xul
 *  content/browser/preferences/in-content/advanced.js
    content/browser/preferences/in-content/applications.xul
 *  content/browser/preferences/in-content/applications.js
    content/browser/preferences/in-content/content.xul
    content/browser/preferences/in-content/content.js
    content/browser/preferences/in-content/sync.xul
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -53,21 +53,26 @@
               type="bool"/>
   <preference id="privacy.sanitize.timeSpan"
               name="privacy.sanitize.timeSpan"
               type="int"/>
   <!-- Private Browsing -->
   <preference id="browser.privatebrowsing.autostart"
               name="browser.privatebrowsing.autostart"
               onchange="gPrivacyPane.updatePrivacyMicroControls();"
+#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
+              instantApply="true"
+#endif
               type="bool"/>
+#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
   <preference id="browser.privatebrowsing.keep_current_session"
               name="browser.privatebrowsing.keep_current_session"
               instantApply="true"
               type="bool"/>
+#endif
 
 </preferences>
 
 <hbox class="heading" data-category="panePrivacy" hidden="true">
   <image class="preference-icon" type="privacy"/>
   <html:h1>&panePrivacy.title;</html:h1>
 </hbox>
 
@@ -215,9 +220,9 @@
         <menuitem label="&locbar.both.label;" value="0"/>
         <menuitem label="&locbar.history.label;" value="1"/>
         <menuitem label="&locbar.bookmarks.label;" value="2"/>
         <menuitem label="&locbar.nothing.label;" value="-1"/>
       </menupopup>
     </menulist>
     <label>&locbar.post.label;</label>
   </hbox>
-</groupbox>
\ No newline at end of file
+</groupbox>
--- a/browser/components/preferences/jar.mn
+++ b/browser/components/preferences/jar.mn
@@ -27,17 +27,17 @@ browser.jar:
     content/browser/preferences/handlers.css
 *   content/browser/preferences/languages.xul
     content/browser/preferences/languages.js
 *   content/browser/preferences/main.xul
     content/browser/preferences/main.js
 *   content/browser/preferences/permissions.xul
     content/browser/preferences/permissions.js
 *   content/browser/preferences/preferences.xul
-    content/browser/preferences/privacy.xul
+*   content/browser/preferences/privacy.xul
 *   content/browser/preferences/privacy.js
     content/browser/preferences/sanitize.xul
     content/browser/preferences/security.xul
     content/browser/preferences/security.js
     content/browser/preferences/selectBookmark.xul
     content/browser/preferences/selectBookmark.js
 #ifdef MOZ_SERVICES_SYNC
     content/browser/preferences/sync.xul
--- a/browser/components/preferences/privacy.xul
+++ b/browser/components/preferences/privacy.xul
@@ -65,21 +65,26 @@
       <preference id="privacy.sanitize.timeSpan"
                   name="privacy.sanitize.timeSpan"
                   type="int"/>
 
       <!-- Private Browsing -->
       <preference id="browser.privatebrowsing.autostart"
                   name="browser.privatebrowsing.autostart"
                   onchange="gPrivacyPane.updatePrivacyMicroControls();"
+#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
+                  instantApply="true"
+#endif
                   type="bool"/>
+#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
       <preference id="browser.privatebrowsing.keep_current_session"
                   name="browser.privatebrowsing.keep_current_session"
                   instantApply="true"
                   type="bool"/>
+#endif
 
     </preferences>
     
     <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
     
     <script type="application/javascript" src="chrome://browser/content/preferences/privacy.js"/>
 
     <!-- Tracking -->
--- a/browser/components/privatebrowsing/Makefile.in
+++ b/browser/components/privatebrowsing/Makefile.in
@@ -6,15 +6,13 @@ DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = privatebrowsing
 
-ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
 DIRS = src
-endif
 
 TEST_DIRS += test
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/components/privatebrowsing/src/Makefile.in
+++ b/browser/components/privatebrowsing/src/Makefile.in
@@ -10,23 +10,34 @@ VPATH   = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = privatebrowsing
 LIBRARY_NAME = privatebrowsing_s
 
 FORCE_STATIC_LIB = 1
 USE_STATIC_LIBS = 1
 
+ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
+
+EXTRA_COMPONENTS = \
+  nsPrivateBrowsingServiceObsolete.manifest \
+  nsPrivateBrowsingServiceObsolete.js \
+  $(NULL)
+
+else
+
 CPPSRCS = \
 	nsPrivateBrowsingServiceWrapper.cpp \
 	$(NULL)
 
 LOCAL_INCLUDES = -I$(srcdir)/../../build
 
 EXTRA_COMPONENTS = \
   nsPrivateBrowsingService.manifest \
   $(NULL)
 
 EXTRA_PP_COMPONENTS = \
 	nsPrivateBrowsingService.js \
 	$(NULL)
 
+endif
+
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingServiceObsolete.js
@@ -0,0 +1,21 @@
+/* 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/. */
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const Ci = Components.interfaces;
+
+// This dummy object just emulates the old nsIPrivateBrowsingService, and is
+// non-functional in every aspect.  It is only used to make Jetpack work
+// again.
+
+function PrivateBrowsingService() {
+}
+
+PrivateBrowsingService.prototype = {
+  classID: Components.ID("{ba0e4d3d-7be2-41a0-b723-a7c16b22ebe9}"),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrivateBrowsingService])
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PrivateBrowsingService]);
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingServiceObsolete.manifest
@@ -0,0 +1,15 @@
+# WebappRT doesn't need these instructions, and they don't necessarily work
+# with it, but it does use a GRE directory that the GRE shares with Firefox,
+# so in order to prevent the instructions from being processed for WebappRT,
+# we need to restrict them to the applications that depend on them, i.e.:
+#
+#   b2g:            {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
+#   browser:        {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
+#   mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
+#   mobile/xul:     {a23983c0-fd0e-11dc-95ff-0800200c9a66}
+#
+# In theory we should do this for all these instructions, but in practice it is
+# sufficient to do it for the app-startup one, and the file is simpler that way.
+
+component {ba0e4d3d-7be2-41a0-b723-a7c16b22ebe9} nsPrivateBrowsingServiceObsolete.js
+contract @mozilla.org/privatebrowsing;1 {ba0e4d3d-7be2-41a0-b723-a7c16b22ebe9}
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -337,17 +337,20 @@
 @BINPATH@/components/nsBrowserGlue.js
 @BINPATH@/components/nsSetDefaultBrowser.manifest
 @BINPATH@/components/nsSetDefaultBrowser.js
 @BINPATH@/components/BrowserDownloads.manifest
 @BINPATH@/components/DownloadsStartup.js
 @BINPATH@/components/DownloadsUI.js
 @BINPATH@/components/BrowserPlaces.manifest
 @BINPATH@/components/BrowserPageThumbs.manifest
-#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
+@BINPATH@/components/nsPrivateBrowsingServiceObsolete.manifest
+@BINPATH@/components/nsPrivateBrowsingServiceObsolete.js
+#else
 @BINPATH@/components/nsPrivateBrowsingService.manifest
 @BINPATH@/components/nsPrivateBrowsingService.js
 #endif
 @BINPATH@/components/SiteSpecificUserAgent.js
 @BINPATH@/components/SiteSpecificUserAgent.manifest
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsSearchService.js
 @BINPATH@/components/nsSearchSuggestions.js
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -623,8 +623,11 @@ just addresses the organization to follo
 <!ENTITY social.chatBar.commandkey "c">
 <!ENTITY social.chatBar.label "Focus chats">
 <!ENTITY social.chatBar.accesskey "c">
 
 <!ENTITY getUserMedia.selectCamera.label "Camera to share:">
 <!ENTITY getUserMedia.selectCamera.accesskey "C">
 <!ENTITY getUserMedia.selectMicrophone.label "Microphone to share:">
 <!ENTITY getUserMedia.selectMicrophone.accesskey "M">
+
+<!ENTITY webrtcIndicatorButton.label "Camera / Microphone Access">
+<!ENTITY webrtcIndicatorButton.tooltip "Display sites you are currently sharing your camera or microphone with">
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -1,9 +1,10 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 et sw=4 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsScriptSecurityManager_h__
 #define nsScriptSecurityManager_h__
 
 #include "nsIScriptSecurityManager.h"
@@ -513,17 +514,16 @@ private:
 
     nsObjectHashtable* mOriginToPolicyMap;
     DomainPolicy* mDefaultPolicy;
     nsObjectHashtable* mCapabilities;
 
     nsCOMPtr<nsIPrincipal> mSystemPrincipal;
     bool mPrefInitialized;
     bool mIsJavaScriptEnabled;
-    bool mIsWritingPrefs;
     bool mPolicyPrefsChanged;
 
     static bool sStrictFileOriginPolicy;
 
     static nsIIOService    *sIOService;
     static nsIXPConnect    *sXPConnect;
     static nsIThreadJSContextStack* sJSContextStack;
     static nsIStringBundle *sStrBundle;
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -1,9 +1,10 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 et sw=4 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Util.h"
 
 #include "xpcprivate.h"
 #include "XPCWrapper.h"
@@ -2435,17 +2436,16 @@ nsScriptSecurityManager::Observe(nsISupp
 // Constructor, Destructor, Initialization //
 /////////////////////////////////////////////
 nsScriptSecurityManager::nsScriptSecurityManager(void)
     : mOriginToPolicyMap(nullptr),
       mDefaultPolicy(nullptr),
       mCapabilities(nullptr),
       mPrefInitialized(false),
       mIsJavaScriptEnabled(false),
-      mIsWritingPrefs(false),
       mPolicyPrefsChanged(true)
 {
     MOZ_STATIC_ASSERT(sizeof(intptr_t) == sizeof(void*),
                       "intptr_t and void* have different lengths on this platform. "
                       "This may cause a security failure with the SecurityLevel union.");
 }
 
 nsresult nsScriptSecurityManager::Init()
--- a/config/config.mk
+++ b/config/config.mk
@@ -200,19 +200,19 @@ endif
 
 #
 # Handle trace-malloc and DMD in optimized builds.
 # No opt to give sane callstacks.
 #
 ifneq (,$(NS_TRACE_MALLOC)$(MOZ_DMD))
 MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG
 ifdef HAVE_64BIT_OS
-OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF,ICF
+OS_LDFLAGS = -DEBUG -OPT:REF,ICF
 else
-OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF
+OS_LDFLAGS = -DEBUG -OPT:REF
 endif
 endif # NS_TRACE_MALLOC || MOZ_DMD
 
 endif # MOZ_DEBUG
 
 # We don't build a static CRT when building a custom CRT,
 # it appears to be broken. So don't link to jemalloc if
 # the Makefile wants static CRT linking.
--- a/config/msvc-stl-wrapper.template.h
+++ b/config/msvc-stl-wrapper.template.h
@@ -55,18 +55,20 @@
 //
 // FIXME/bug 551254: because we're not wrapping all the STL headers we
 // use, undefining this here can cause some headers to be built with
 // iterator checking and others not.  Turning this off until we have a
 // better plan.
 //#  undef _SECURE_SCL
 #endif
 
-// We know that code won't be able to catch exceptions, but that's OK
-// because we're not throwing them.
+// C4275: When _HAS_EXCEPTIONS is set to 0, system STL header
+//        will generate the warning which we can't modify.
+// C4530: We know that code won't be able to catch exceptions,
+//        but that's OK because we're not throwing them.
 #pragma warning( push )
-#pragma warning( disable : 4530 )
+#pragma warning( disable : 4275 4530 )
 
 #include <${HEADER_PATH}>
 
 #pragma warning( pop )
 
 #endif  // if mozilla_${HEADER}_h
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -103,16 +103,29 @@ ifdef CPP_UNIT_TESTS
 CPPSRCS += $(CPP_UNIT_TESTS)
 SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX))
 INCLUDES += -I$(DIST)/include/testing
 LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) $(if $(JS_SHARED_LIBRARY),,$(MOZ_ZLIB_LIBS))
 
 check::
 	@$(PYTHON) $(topsrcdir)/testing/runcppunittests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(subst .cpp,$(BIN_SUFFIX),$(CPP_UNIT_TESTS))
 
+cppunittests-remote: DM_TRANS?=adb
+cppunittests-remote:
+	@if [ "${TEST_DEVICE}" != "" -o "$(DM_TRANS)" = "adb" ]; then \
+		$(PYTHON) -u $(topsrcdir)/testing/remotecppunittests.py \
+			--xre-path=$(DEPTH)/dist/bin \
+			--localLib=$(DEPTH)/dist/$(MOZ_APP_NAME) \
+			--dm_trans=$(DM_TRANS) \
+			--deviceIP=${TEST_DEVICE} \
+ 			$(subst .cpp,$(BIN_SUFFIX),$(CPP_UNIT_TESTS)) $(EXTRA_TEST_ARGS); \
+	else \
+		echo "please prepare your host with environment variables for TEST_DEVICE"; \
+	fi
+
 endif # CPP_UNIT_TESTS
 
 .PHONY: check
 
 ifdef PYTHON_UNIT_TESTS
 
 RUN_PYTHON_UNIT_TESTS := $(addprefix run-,$(PYTHON_UNIT_TESTS))
 
--- a/configure.in
+++ b/configure.in
@@ -124,18 +124,26 @@ fi
 MOZ_BUILD_ROOT=`pwd`
 
 dnl Do not allow building if a clobber is required
 dnl ==============================================================
 dnl TODO Make this better, ideally this would clobber automaticially
 if test -e $_objdir/CLOBBER; then
   if test $_topsrcdir/CLOBBER -nt $_objdir/CLOBBER; then
     echo "	***"
-    echo "	*	CLOBBER has been modified indicating a clobber is required:"
+    echo "	*	The CLOBBER file has been updated, indicating that an incremental build"
+    echo "	*	since your last build will probably not work. A full build is required."
+    echo "	*	The change that caused this is:"
     cat $_topsrcdir/CLOBBER | sed '/^#/d' | sed 's/^/	*	/'
+    echo "	*	"
+    echo "	*	The easiest way to fix this is to manually delete your objdir:"
+    echo "	*	rm -rf $_objdir"
+    echo "	*	"
+    echo "	*	Or, if you know this clobber doesn't apply to you, it can be ignored with:"
+    echo "	*	cp '$_topsrcdir/CLOBBER' $_objdir"
     echo "	***"
     exit 1
     break;
   fi
 else
   touch $_objdir/CLOBBER
 fi
 
@@ -3721,17 +3729,17 @@ dnl creates some (http://code.google.com
 dnl We however want to avoid these text relocations, and this can be done
 dnl by making gcc not link crtbegin and crtend. In the broken NDKs, crtend
 dnl doesn't contain anything at all, beside placeholders for some sections,
 dnl and crtbegin only contains a finalizer function that calls
 dnl __cxa_finalize. The custom linker actually takes care of calling
 dnl __cxa_finalize when the library doesn't call it itself, which makes it
 dnl safe not to link crtbegin. Besides, previous versions of the NDK didn't
 dnl link crtbegin and crtend at all.
-if test -n "$MOZ_LINKER" -a -z "$MOZ_OLD_LINKER" -a "$OS_TARGET" = "Android"; then
+if test -n "$MOZ_LINKER" -a "$OS_TARGET" = "Android"; then
   AC_CACHE_CHECK([whether the CRT objects have text relocations],
     ac_cv_crt_has_text_relocations,
     [echo 'int foo() { return 0; }' > conftest.cpp
      if AC_TRY_COMMAND(${CXX-g++} -o conftest${DLL_SUFFIX} $CXXFLAGS $DSO_LDOPTS $LDFLAGS conftest.cpp $LIBS 1>&5) &&
         test -s conftest${DLL_SUFFIX}; then
        if ${TOOLCHAIN_PREFIX}readelf -d conftest${DLL_SUFFIX} | grep TEXTREL > /dev/null; then
          ac_cv_crt_has_text_relocations=yes
        else
@@ -4598,35 +4606,31 @@ cairo-uikit)
 cairo-android)
     AC_DEFINE(MOZ_WIDGET_ANDROID)
     MOZ_WIDGET_TOOLKIT=android
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS) $(MOZ_PIXMAN_LIBS)'
     MOZ_WEBGL=1
     MOZ_PDF_PRINTING=1
     MOZ_INSTRUMENT_EVENT_LOOP=1
-    if test "$MOZ_BUILD_APP" = "mobile/xul"; then
-        MOZ_OLD_LINKER=1
-    fi
     ;;
 
 cairo-gonk)
     AC_DEFINE(MOZ_WIDGET_GONK)
     AC_DEFINE(MOZ_TOUCH)
     MOZ_WIDGET_TOOLKIT=gonk
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS) $(MOZ_PIXMAN_LIBS)'
     MOZ_WEBGL=1
     MOZ_PDF_PRINTING=1
     MOZ_TOUCH=1
     ;;
 
 esac
 
-AC_SUBST(MOZ_OLD_LINKER)
 AC_SUBST(MOZ_PDF_PRINTING)
 if test "$MOZ_PDF_PRINTING"; then
    PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
    AC_DEFINE(MOZ_PDF_PRINTING)
 fi
 
 if test "$MOZ_ENABLE_XREMOTE"; then
     AC_DEFINE(MOZ_ENABLE_XREMOTE)
@@ -7080,17 +7084,17 @@ else
     MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS "'$(call EXPAND_LIBNAME_PATH,memory,$(LIBXUL_DIST)/lib)'
   fi
   MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS "'$(MKSHLIB_UNFORCE_ALL)'
   if test -n "$GNU_CC"; then
     dnl And we need mozglue symbols to be exported.
     MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS -rdynamic"
   fi
   if test "$MOZ_LINKER" = 1; then
-    MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS $ZLIB_LIBS"
+    MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS $MOZ_ZLIB_LIBS"
   fi
 fi
 
 dnl ========================================================
 dnl = Enable dynamic replacement of malloc implementation
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(replace-malloc,
 [  --enable-replace-malloc   Enable ability to dynamically replace the malloc implementation],
@@ -7275,19 +7279,16 @@ AC_SUBST(MOZ_GLUE_PROGRAM_LDFLAGS)
 AC_SUBST(WIN32_CRT_LIBS)
 dnl Need to set this for make because NSS doesn't have configure
 AC_SUBST(DLLFLAGS)
 
 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=PR_GetEnv,--wrap=PR_SetEnv"
     if test -z "$gonkdir"; then
         WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=fork,--wrap=pthread_atfork,--wrap=raise"
         WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=memccpy,--wrap=memchr,--wrap=memrchr,--wrap=memcmp,--wrap=memcpy,--wrap=memmove,--wrap=memset,--wrap=memmem,--wrap=memswap,--wrap=index,--wrap=strchr,--wrap=strrchr,--wrap=strlen,--wrap=strcmp,--wrap=strcpy,--wrap=strcat,--wrap=strcasecmp,--wrap=strncasecmp,--wrap=strstr,--wrap=strcasestr,--wrap=strtok,--wrap=strtok_r,--wrap=strerror,--wrap=strerror_r,--wrap=strnlen,--wrap=strncat,--wrap=strncmp,--wrap=strncpy,--wrap=strlcat,--wrap=strlcpy,--wrap=strcspn,--wrap=strpbrk,--wrap=strsep,--wrap=strspn,--wrap=strcoll,--wrap=strxfrm"
     fi
 fi
 
@@ -8683,21 +8684,16 @@ AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIRE
 AC_SUBST(FIREFOX_VERSION)
 AC_SUBST(MOZ_UA_OS_AGNOSTIC)
 if test -n "$MOZ_UA_OS_AGNOSTIC"; then
   AC_DEFINE(MOZ_UA_OS_AGNOSTIC)
 fi
 AC_DEFINE_UNQUOTED(MOZ_UA_BUILDID, "$MOZ_UA_BUILDID")
 AC_SUBST(MOZ_UA_BUILDID)
 
-# We can't use the static application.ini data when building against
-# a libxul SDK.
-if test -n "$LIBXUL_SDK"; then
-    MOZ_APP_STATIC_INI=
-fi
 AC_SUBST(MOZ_APP_STATIC_INI)
 
 AC_SUBST(MOZ_PKG_SPECIAL)
 
 AC_SUBST(MOZILLA_OFFICIAL)
 
 AC_DEFINE_UNQUOTED(MOZ_TELEMETRY_DISPLAY_REV, 2)
 AC_SUBST(MOZ_TELEMETRY_DISPLAY_REV)
@@ -9262,27 +9258,27 @@ if test -z "$MOZ_NATIVE_NSPR"; then
     fi
     if test -n "$HAVE_64BIT_OS"; then
         ac_configure_args="$ac_configure_args --enable-64bit"
     fi
     if test -n "$USE_ARM_KUSER"; then
         ac_configure_args="$ac_configure_args --with-arm-kuser"
     fi
     ac_configure_args="$ac_configure_args $NSPR_CONFIGURE_ARGS"
-    if test -n "$MOZ_LINKER" -a -z "$MOZ_OLD_LINKER" -a "$ac_cv_func_dladdr" = no ; then
+    if test -n "$MOZ_LINKER" -a "$ac_cv_func_dladdr" = no ; then
       # dladdr is supported by the new linker, even when the system linker doesn't
       # support it. Trick nspr into using dladdr when it's not supported.
       _SAVE_CPPFLAGS="$CPPFLAGS"
       export CPPFLAGS="-include $_topsrcdir/mozglue/linker/dladdr.h $CPPFLAGS"
     fi
     _SAVE_LDFLAGS="$LDFLAGS"
     export LDFLAGS="$LDFLAGS $NSPR_LDFLAGS"
     AC_OUTPUT_SUBDIRS(nsprpub)
     LDFLAGS="$_SAVE_LDFLAGS"
-    if test -n "$MOZ_LINKER" -a -z "$MOZ_OLD_LINKER" -a "$ac_cv_func_dladdr" = no; then
+    if test -n "$MOZ_LINKER" -a "$ac_cv_func_dladdr" = no; then
       unset CPPFLAGS
       CPPFLAGS="$_SAVE_CFLAGS"
     fi
     ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 fi
 
 dnl ========================================================
 dnl = Setup a nice relatively clean build environment for
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -490,16 +490,28 @@ public:
   virtual const nsTextFragment *GetText() = 0;
 
   /**
    * Get the length of the text content.
    * NOTE: This should not be called on elements.
    */
   virtual uint32_t TextLength() const = 0;
 
+   /**
+    * Determines if an event attribute name (such as onclick) is valid for
+    * a given element type.
+    * @note calls nsContentUtils::IsEventAttributeName with right flag
+    * @note overridden by subclasses as needed
+    * @param aName the event name to look up
+    */
+  virtual bool IsEventAttributeName(nsIAtom* aName)
+  {
+    return false;
+  }
+
   /**
    * Set the text to the given value. If aNotify is true then
    * the document is notified of the content change.
    * NOTE: For elements this always ASSERTS and returns NS_ERROR_FAILURE
    */
   virtual nsresult SetText(const PRUnichar* aBuffer, uint32_t aLength,
                            bool aNotify) = 0;
 
--- a/content/base/public/nsIImageLoadingContent.idl
+++ b/content/base/public/nsIImageLoadingContent.idl
@@ -27,16 +27,19 @@ interface nsIFrame;
  * the currently loaded image will start a "pending" request which will
  * become current only when the image is loaded.  It is the responsibility of
  * observers to check which request they are getting notifications for.
  *
  * Observers added in mid-load will not get any notifications they
  * missed.  We should NOT freeze this interface without considering
  * this issue.  (It could be that the image status on imgIRequest is
  * sufficient, when combined with the imageBlockingStatus information.)
+ *
+ * Please make sure to update the HTMLImageElement Web IDL interface to
+ * mirror this interface when changing it.
  */
 
 [scriptable, builtinclass, uuid(497bfb9b-d996-4d1e-a647-8137b0cfc876)]
 interface nsIImageLoadingContent : imgINotificationObserver
 {
   /**
    * Request types.  Image loading content nodes attempt to do atomic
    * image changes when the image url is changed.  This means that
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -88,17 +88,17 @@
 #include "nsIDOMUserDataHandler.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
 #include "nsIEditorDocShell.h"
 #include "nsEventDispatcher.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsIControllers.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsXBLInsertionPoint.h"
 #include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
 #include "nsCSSRuleProcessor.h"
 #include "nsRuleProcessorData.h"
 #include "nsAsyncDOMEvent.h"
 #include "nsTextNode.h"
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -87,17 +87,17 @@
 #include "nsIDOMUserDataHandler.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
 #include "nsIEditorDocShell.h"
 #include "nsEventDispatcher.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsIControllers.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsXBLInsertionPoint.h"
 #include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
 #include "nsRuleProcessorData.h"
 #include "nsAsyncDOMEvent.h"
 #include "nsTextNode.h"
 #include "mozilla/dom/NodeListBinding.h"
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -5,16 +5,17 @@
 
 #include "nsCCUncollectableMarker.h"
 #include "nsIObserverService.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
+#include "nsXULDocument.h"
 #include "nsIWindowMediator.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsISHistory.h"
 #include "nsISHEntry.h"
 #include "nsISHContainer.h"
 #include "nsIWindowWatcher.h"
 #include "mozilla/Services.h"
@@ -361,16 +362,25 @@ nsCCUncollectableMarker::Observe(nsISupp
     nsCOMPtr<nsIXULWindow> hw;
     appShell->GetHiddenWindow(getter_AddRefs(hw));
     if (hw) {
       nsCOMPtr<nsIDocShell> shell;
       hw->GetDocShell(getter_AddRefs(shell));
       nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
       MarkDocShell(shellTreeNode, cleanupJS, prepareForCC);
     }
+#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
+    appShell->GetHiddenPrivateWindow(getter_AddRefs(hw));
+    if (hw) {
+      nsCOMPtr<nsIDocShell> shell;
+      hw->GetDocShell(getter_AddRefs(shell));
+      nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
+      MarkDocShell(shellTreeNode, cleanupJS, prepareForCC);
+    }
+#endif
   }
 
 #ifdef MOZ_XUL
   nsXULPrototypeCache* xulCache = nsXULPrototypeCache::GetInstance();
   if (xulCache) {
     xulCache->MarkInCCGeneration(sGeneration);
   }
 #endif
@@ -389,37 +399,55 @@ nsCCUncollectableMarker::Observe(nsISupp
     if (!prepareForCC) {
       xpc_UnmarkSkippableJSHolders();
     }
   }
 
   return NS_OK;
 }
 
+struct TraceClosure
+{
+  TraceClosure(JSTracer* aTrc, uint32_t aGCNumber)
+    : mTrc(aTrc), mGCNumber(aGCNumber)
+  {}
+  JSTracer* mTrc;
+  uint32_t mGCNumber;
+};
+
 static PLDHashOperator
 TraceActiveWindowGlobal(const uint64_t& aId, nsGlobalWindow*& aWindow, void* aClosure)
 {
   if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) {
+    TraceClosure* closure = static_cast<TraceClosure*>(aClosure);
     if (JSObject* global = aWindow->FastGetGlobalJSObject()) {
-      JSTracer* trc = static_cast<JSTracer *>(aClosure);
-      JS_CALL_OBJECT_TRACER(trc, global, "active window global");
+      JS_CALL_OBJECT_TRACER(closure->mTrc, global, "active window global");
     }
+#ifdef MOZ_XUL
+    nsIDocument* doc = aWindow->GetExtantDoc();
+    if (doc && doc->IsXUL()) {
+      nsXULDocument* xulDoc = static_cast<nsXULDocument*>(doc);
+      xulDoc->TraceProtos(closure->mTrc, closure->mGCNumber);
+    }
+#endif
   }
   return PL_DHASH_NEXT;
 }
 
 void
-mozilla::dom::TraceBlackJS(JSTracer* aTrc)
+mozilla::dom::TraceBlackJS(JSTracer* aTrc, uint32_t aGCNumber)
 {
   if (!nsCCUncollectableMarker::sGeneration) {
     return;
   }
 
+  TraceClosure closure(aTrc, aGCNumber);
+
   // Mark globals of active windows black.
   nsGlobalWindow::WindowByIdTable* windowsById =
     nsGlobalWindow::GetWindowsTable();
   if (windowsById) {
-    windowsById->Enumerate(TraceActiveWindowGlobal, aTrc);
+    windowsById->Enumerate(TraceActiveWindowGlobal, &closure);
   }
 
   // Mark the safe context black
   nsContentUtils::TraceSafeJSContext(aTrc);
 }
--- a/content/base/src/nsCCUncollectableMarker.h
+++ b/content/base/src/nsCCUncollectableMarker.h
@@ -40,13 +40,13 @@ class nsCCUncollectableMarker MOZ_FINAL 
 
 private:
   nsCCUncollectableMarker() {}
 
 };
 
 namespace mozilla {
 namespace dom {
-void TraceBlackJS(JSTracer* aTrc);
+void TraceBlackJS(JSTracer* aTrc, uint32_t aGCNumber);
 }
 }
 
 #endif
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -242,16 +242,35 @@ bool nsContentUtils::sFragmentParsingAct
 
 namespace {
 
 static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
 static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
 
 static PLDHashTable sEventListenerManagersHash;
+static nsCOMPtr<nsIMemoryReporter> sEventListenerManagersHashReporter;
+
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(EventListenerManagersHashMallocSizeOf)
+
+static int64_t GetEventListenerManagersHash()
+{
+  // We don't measure the |nsEventListenerManager| objects pointed to by the
+  // entries because those references are non-owning.
+  return PL_DHashTableSizeOfExcludingThis(&sEventListenerManagersHash,
+                                          nullptr,
+                                          EventListenerManagersHashMallocSizeOf);
+}
+
+NS_MEMORY_REPORTER_IMPLEMENT(EventListenerManagersHash,
+  "explicit/dom/event-listener-managers-hash",
+  KIND_HEAP,
+  UNITS_BYTES,
+  GetEventListenerManagersHash,
+  "Memory used by the event listener manager's hash table.")
 
 class EventListenerManagerMapEntry : public PLDHashEntryHdr
 {
 public:
   EventListenerManagerMapEntry(const void *aKey)
     : mKey(aKey)
   {
   }
@@ -378,16 +397,20 @@ nsContentUtils::Init()
     };
 
     if (!PL_DHashTableInit(&sEventListenerManagersHash, &hash_table_ops,
                            nullptr, sizeof(EventListenerManagerMapEntry), 16)) {
       sEventListenerManagersHash.ops = nullptr;
 
       return NS_ERROR_OUT_OF_MEMORY;
     }
+
+    sEventListenerManagersHashReporter =
+      new NS_MEMORY_REPORTER_NAME(EventListenerManagersHash);
+    (void)::NS_RegisterMemoryReporter(sEventListenerManagersHashReporter);
   }
 
   sBlockedScriptRunners = new nsTArray< nsCOMPtr<nsIRunnable> >;
 
   Preferences::AddBoolVarCache(&sAllowXULXBL_for_file,
                                "dom.allow_XUL_XBL_for_file");
 
   Preferences::AddBoolVarCache(&sIsFullScreenApiEnabled,
@@ -775,30 +798,24 @@ nsContentUtils::GetPseudoAttributeValue(
 
 bool
 nsContentUtils::IsJavaScriptLanguage(const nsString& aName, uint32_t *aFlags)
 {
   JSVersion version = JSVERSION_UNKNOWN;
 
   if (aName.LowerCaseEqualsLiteral("javascript") ||
       aName.LowerCaseEqualsLiteral("livescript") ||
-      aName.LowerCaseEqualsLiteral("mocha")) {
+      aName.LowerCaseEqualsLiteral("mocha") ||
+      aName.LowerCaseEqualsLiteral("javascript1.0") ||
+      aName.LowerCaseEqualsLiteral("javascript1.1") ||
+      aName.LowerCaseEqualsLiteral("javascript1.2") ||
+      aName.LowerCaseEqualsLiteral("javascript1.3") ||
+      aName.LowerCaseEqualsLiteral("javascript1.4") ||
+      aName.LowerCaseEqualsLiteral("javascript1.5")) {
     version = JSVERSION_DEFAULT;
-  } else if (aName.LowerCaseEqualsLiteral("javascript1.0")) {
-    version = JSVERSION_1_0;
-  } else if (aName.LowerCaseEqualsLiteral("javascript1.1")) {
-    version = JSVERSION_1_1;
-  } else if (aName.LowerCaseEqualsLiteral("javascript1.2")) {
-    version = JSVERSION_1_2;
-  } else if (aName.LowerCaseEqualsLiteral("javascript1.3")) {
-    version = JSVERSION_1_3;
-  } else if (aName.LowerCaseEqualsLiteral("javascript1.4")) {
-    version = JSVERSION_1_4;
-  } else if (aName.LowerCaseEqualsLiteral("javascript1.5")) {
-    version = JSVERSION_1_5;
   } else if (aName.LowerCaseEqualsLiteral("javascript1.6")) {
     version = JSVERSION_1_6;
   } else if (aName.LowerCaseEqualsLiteral("javascript1.7")) {
     version = JSVERSION_1_7;
   } else if (aName.LowerCaseEqualsLiteral("javascript1.8")) {
     version = JSVERSION_1_8;
   }
 
@@ -813,22 +830,22 @@ JSVersion
 nsContentUtils::ParseJavascriptVersion(const nsAString& aVersionStr)
 {
   if (aVersionStr.Length() != 3 || aVersionStr[0] != '1' ||
       aVersionStr[1] != '.') {
     return JSVERSION_UNKNOWN;
   }
 
   switch (aVersionStr[2]) {
-  case '0': return JSVERSION_1_0;
-  case '1': return JSVERSION_1_1;
-  case '2': return JSVERSION_1_2;
-  case '3': return JSVERSION_1_3;
-  case '4': return JSVERSION_1_4;
-  case '5': return JSVERSION_1_5;
+  case '0': /* fall through */
+  case '1': /* fall through */
+  case '2': /* fall through */
+  case '3': /* fall through */
+  case '4': /* fall through */
+  case '5': return JSVERSION_DEFAULT;
   case '6': return JSVERSION_1_6;
   case '7': return JSVERSION_1_7;
   case '8': return JSVERSION_1_8;
   default:  return JSVERSION_UNKNOWN;
   }
 }
 
 void
@@ -1465,16 +1482,19 @@ nsContentUtils::Shutdown()
     // in case any elements are destroyed.  Because if they are, we need
     // their event listener managers to be destroyed too, or otherwise
     // it could leave dangling references in DOMClassInfo's preserved
     // wrapper table.
 
     if (sEventListenerManagersHash.entryCount == 0) {
       PL_DHashTableFinish(&sEventListenerManagersHash);
       sEventListenerManagersHash.ops = nullptr;
+
+      (void)::NS_UnregisterMemoryReporter(sEventListenerManagersHashReporter);
+      sEventListenerManagersHashReporter = nullptr;
     }
   }
 
   NS_ASSERTION(!sBlockedScriptRunners ||
                sBlockedScriptRunners->Length() == 0,
                "How'd this happen?");
   delete sBlockedScriptRunners;
   sBlockedScriptRunners = nullptr;
@@ -6393,18 +6413,17 @@ nsContentUtils::FindPresShellForDocument
   nsCOMPtr<nsISupports> container = doc->GetContainer();
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
   while (docShellTreeItem) {
     // We may be in a display:none subdocument, or we may not have a presshell
     // created yet.
     // Walk the docshell tree to find the nearest container that has a presshell,
     // and return that.
     nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
-    nsCOMPtr<nsIPresShell> presShell;
-    docShell->GetPresShell(getter_AddRefs(presShell));
+    nsIPresShell* presShell = docShell->GetPresShell();
     if (presShell) {
       return presShell;
     }
     nsCOMPtr<nsIDocShellTreeItem> parent;
     docShellTreeItem->GetParent(getter_AddRefs(parent));
     docShellTreeItem = parent;
   }
 
@@ -6413,19 +6432,19 @@ nsContentUtils::FindPresShellForDocument
 
 nsIWidget*
 nsContentUtils::WidgetForDocument(nsIDocument* aDoc)
 {
   nsIPresShell* shell = FindPresShellForDocument(aDoc);
   if (shell) {
     nsIViewManager* VM = shell->GetViewManager();
     if (VM) {
-      nsIView* rootView = VM->GetRootView();
+      nsView* rootView = VM->GetRootView();
       if (rootView) {
-        nsIView* displayRoot = nsIViewManager::GetDisplayRootFor(rootView);
+        nsView* displayRoot = nsIViewManager::GetDisplayRootFor(rootView);
         if (displayRoot) {
           return displayRoot->GetNearestWidget(nullptr);
         }
       }
     }
   }
 
   return nullptr;
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -54,17 +54,17 @@
 #include "nsIDocShellHistory.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIXULWindow.h"
 #include "nsIEditor.h"
 #include "nsIEditorDocShell.h"
 #include "nsIMozBrowserFrame.h"
 
 #include "nsLayoutUtils.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsAsyncDOMEvent.h"
 
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 
 #include "nsGkAtoms.h"
 #include "nsINameSpaceManager.h"
@@ -796,31 +796,30 @@ nsFrameLoader::Show(int32_t marginWidth,
     nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell);
     if (sc) {
       sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
                                          scrollbarPrefX);
       sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
                                          scrollbarPrefY);
     }
 
-    nsCOMPtr<nsIPresShell> presShell;
-    mDocShell->GetPresShell(getter_AddRefs(presShell));
+    nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
     if (presShell) {
       // Ensure root scroll frame is reflowed in case scroll preferences or
       // margins have changed
       nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
       if (rootScrollFrame) {
         presShell->FrameNeedsReflow(rootScrollFrame, nsIPresShell::eResize,
                                     NS_FRAME_IS_DIRTY);
       }
       return true;
     }
   }
 
-  nsIView* view = frame->EnsureInnerView();
+  nsView* view = frame->EnsureInnerView();
   if (!view)
     return false;
 
   if (mRemoteFrame) {
     return ShowRemoteFrame(GetSubDocumentSize(frame));
   }
 
   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mDocShell);
@@ -842,18 +841,17 @@ nsFrameLoader::Show(int32_t marginWidth,
   // "Create"...
   baseWindow->Create();
   baseWindow->SetVisibility(true);
 
   // Trigger editor re-initialization if midas is turned on in the
   // sub-document. This shouldn't be necessary, but given the way our
   // editor works, it is. See
   // https://bugzilla.mozilla.org/show_bug.cgi?id=284245
-  nsCOMPtr<nsIPresShell> presShell;
-  mDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   if (presShell) {
     nsCOMPtr<nsIDOMHTMLDocument> doc =
       do_QueryInterface(presShell->GetDocument());
 
     if (doc) {
       nsAutoString designMode;
       doc->GetDesignMode(designMode);
 
@@ -2449,24 +2447,24 @@ nsFrameLoader::SetRemoteBrowser(nsITabPa
   MOZ_ASSERT(!mCurrentRemoteFrame);
   mRemoteFrame = true;
   mRemoteBrowser = static_cast<TabParent*>(aTabParent);
 
   ShowRemoteFrame(nsIntSize(0, 0));
 }
 
 void
-nsFrameLoader::SetDetachedSubdocView(nsIView* aDetachedViews,
+nsFrameLoader::SetDetachedSubdocView(nsView* aDetachedViews,
                                      nsIDocument* aContainerDoc)
 {
   mDetachedSubdocViews = aDetachedViews;
   mContainerDocWhileDetached = aContainerDoc;
 }
 
-nsIView*
+nsView*
 nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const
 {
   NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached);
   return mDetachedSubdocViews;
 }
 
 /* virtual */ void
 nsFrameLoader::AttributeChanged(nsIDocument* aDocument,
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -21,17 +21,17 @@
 #include "nsFrameMessageManager.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Attributes.h"
 #include "FrameMetrics.h"
 #include "nsStubMutationObserver.h"
 
 class nsIURI;
 class nsSubDocumentFrame;
-class nsIView;
+class nsView;
 class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
 class nsITabParent;
 class nsIDocShellTreeItem;
 class nsIDocShellTreeOwner;
 class nsIDocShellTreeNode;
 class mozIApplication;
 
@@ -291,24 +291,24 @@ public:
    * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is
    * being reframed we'll restore the detached view when it's recreated,
    * otherwise we'll discard the old presentation and set the detached
    * subdoc view to null. aContainerDoc is the document containing the
    * the subdoc frame. This enables us to detect when the containing
    * document has changed during reframe, so we can discard the presentation 
    * in that case.
    */
-  void SetDetachedSubdocView(nsIView* aDetachedView,
+  void SetDetachedSubdocView(nsView* aDetachedView,
                              nsIDocument* aContainerDoc);
 
   /**
    * Retrieves the detached view and the document containing the view,
    * as set by SetDetachedSubdocView().
    */
-  nsIView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const;
+  nsView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const;
 
 private:
 
   void SetOwnerContent(mozilla::dom::Element* aContent);
 
   bool ShouldUseRemoteProcess();
 
   /**
@@ -387,17 +387,17 @@ private:
 
 public:
   // public because a callback needs these.
   nsRefPtr<nsFrameMessageManager> mMessageManager;
   nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
 private:
   // Stores the root view of the subdocument while the subdocument is being
   // reframed. Used to restore the presentation after reframing.
-  nsIView* mDetachedSubdocViews;
+  nsView* mDetachedSubdocViews;
   // Stores the containing document of the frame corresponding to this
   // frame loader. This is reference is kept valid while the subframe's
   // presentation is detached and stored in mDetachedSubdocViews. This
   // enables us to detect whether the frame has moved documents during
   // a reframe, so that we know not to restore the presentation.
   nsCOMPtr<nsIDocument> mContainerDocWhileDetached;
 
   bool mDepthTooGreat : 1;
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -68,17 +68,17 @@
 #include "nsINodeInfo.h"
 #include "nsIPresShell.h"
 #include "nsIScriptError.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsIServiceManager.h"
 #include "nsIURL.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIViewManager.h"
 #include "nsIWebNavigation.h"
 #include "nsIWidget.h"
 #include "nsLayoutStatics.h"
 #include "nsLayoutUtils.h"
 #include "nsMutationEvent.h"
 #include "nsNetUtil.h"
 #include "nsNodeInfoManager.h"
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -268,17 +268,17 @@ nsImageLoadingContent::SetLoadingEnabled
 }
 
 NS_IMETHODIMP
 nsImageLoadingContent::GetImageBlockingStatus(int16_t* aStatus)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
 
   NS_PRECONDITION(aStatus, "Null out param");
-  *aStatus = mImageBlockingStatus;
+  *aStatus = ImageBlockingStatus();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsImageLoadingContent::AddObserver(imgINotificationObserver* aObserver)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
 
@@ -336,35 +336,46 @@ nsImageLoadingContent::RemoveObserver(im
 #ifdef DEBUG
   else {
     NS_WARNING("Asked to remove nonexistent observer");
   }
 #endif
   return NS_OK;
 }
 
+already_AddRefed<imgIRequest>
+nsImageLoadingContent::GetRequest(int32_t aRequestType,
+                                  ErrorResult& aError)
+{
+  nsCOMPtr<imgIRequest> request;
+  switch(aRequestType) {
+  case CURRENT_REQUEST:
+    request = mCurrentRequest;
+    break;
+  case PENDING_REQUEST:
+    request = mPendingRequest;
+    break;
+  default:
+    NS_ERROR("Unknown request type");
+    aError.Throw(NS_ERROR_UNEXPECTED);
+  }
+
+  return request.forget();
+}
+
 NS_IMETHODIMP
 nsImageLoadingContent::GetRequest(int32_t aRequestType,
                                   imgIRequest** aRequest)
 {
-  switch(aRequestType) {
-  case CURRENT_REQUEST:
-    *aRequest = mCurrentRequest;
-    break;
-  case PENDING_REQUEST:
-    *aRequest = mPendingRequest;
-    break;
-  default:
-    NS_ERROR("Unknown request type");
-    *aRequest = nullptr;
-    return NS_ERROR_UNEXPECTED;
-  }
-  
-  NS_IF_ADDREF(*aRequest);
-  return NS_OK;
+  NS_ENSURE_ARG_POINTER(aRequest);
+
+  ErrorResult result;
+  *aRequest = GetRequest(aRequestType, result).get();
+
+  return result.ErrorCode();
 }
 
 NS_IMETHODIMP_(void)
 nsImageLoadingContent::FrameCreated(nsIFrame* aFrame)
 {
   NS_ASSERTION(aFrame, "aFrame is null");
 
   // We need to make sure that our image request is registered, if it should
@@ -396,107 +407,150 @@ nsImageLoadingContent::FrameDestroyed(ns
 
   if (mPendingRequest) {
     nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(),
                                           mPendingRequest,
                                           &mPendingRequestRegistered);
   }
 }
 
+int32_t
+nsImageLoadingContent::GetRequestType(imgIRequest* aRequest,
+                                      ErrorResult& aError)
+{
+  if (aRequest == mCurrentRequest) {
+    return CURRENT_REQUEST;
+  }
+
+  if (aRequest == mPendingRequest) {
+    return PENDING_REQUEST;
+  }
+
+  NS_ERROR("Unknown request");
+  aError.Throw(NS_ERROR_UNEXPECTED);
+  return UNKNOWN_REQUEST;
+}
+
 NS_IMETHODIMP
 nsImageLoadingContent::GetRequestType(imgIRequest* aRequest,
                                       int32_t* aRequestType)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
 
   NS_PRECONDITION(aRequestType, "Null out param");
-  
-  if (aRequest == mCurrentRequest) {
-    *aRequestType = CURRENT_REQUEST;
-    return NS_OK;
+
+  ErrorResult result;
+  *aRequestType = GetRequestType(aRequest, result);
+  return result.ErrorCode();
+}
+
+already_AddRefed<nsIURI>
+nsImageLoadingContent::GetCurrentURI(ErrorResult& aError)
+{
+  nsCOMPtr<nsIURI> uri;
+  if (mCurrentRequest) {
+    mCurrentRequest->GetURI(getter_AddRefs(uri));
+  } else if (mCurrentURI) {
+    nsresult rv = NS_EnsureSafeToReturn(mCurrentURI, getter_AddRefs(uri));
+    if (NS_FAILED(rv)) {
+      aError.Throw(rv);
+    }
   }
 
-  if (aRequest == mPendingRequest) {
-    *aRequestType = PENDING_REQUEST;
-    return NS_OK;
-  }
-
-  *aRequestType = UNKNOWN_REQUEST;
-  NS_ERROR("Unknown request");
-  return NS_ERROR_UNEXPECTED;
+  return uri.forget();
 }
 
 NS_IMETHODIMP
 nsImageLoadingContent::GetCurrentURI(nsIURI** aURI)
 {
-  if (mCurrentRequest) {
-    return mCurrentRequest->GetURI(aURI);
-  }
+  NS_ENSURE_ARG_POINTER(aURI);
 
-  if (!mCurrentURI) {
-    *aURI = nullptr;
-    return NS_OK;
-  }
-  
-  return NS_EnsureSafeToReturn(mCurrentURI, aURI);
+  ErrorResult result;
+  *aURI = GetCurrentURI(result).get();
+  return result.ErrorCode();
 }
 
-NS_IMETHODIMP
+already_AddRefed<nsIStreamListener>
 nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
-                                            nsIStreamListener** aListener)
+                                            ErrorResult& aError)
 {
-  NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
-
   if (!nsContentUtils::GetImgLoaderForChannel(aChannel)) {
-    return NS_ERROR_NULL_POINTER;
+    aError.Throw(NS_ERROR_NULL_POINTER);
+    return nullptr;
   }
 
   nsCOMPtr<nsIDocument> doc = GetOurOwnerDoc();
   if (!doc) {
     // Don't bother
-    return NS_OK;
+    return nullptr;
   }
 
   // XXX what should we do with content policies here, if anything?
   // Shouldn't that be done before the start of the load?
   // XXX what about shouldProcess?
 
   // Our state might change. Watch it.
   AutoStateChanger changer(this, true);
 
   // Do the load.
+  nsCOMPtr<nsIStreamListener> listener;
   nsRefPtr<imgRequestProxy>& req = PrepareNextRequest();
   nsresult rv = nsContentUtils::GetImgLoaderForChannel(aChannel)->
-    LoadImageWithChannel(aChannel, this, doc, aListener,
+    LoadImageWithChannel(aChannel, this, doc,
+                         getter_AddRefs(listener),
                          getter_AddRefs(req));
   if (NS_SUCCEEDED(rv)) {
     TrackImage(req);
     ResetAnimationIfNeeded();
   } else {
     // If we don't have a current URI, we might as well store this URI so people
     // know what we tried (and failed) to load.
     if (!mCurrentRequest)
       aChannel->GetURI(getter_AddRefs(mCurrentURI));
     FireEvent(NS_LITERAL_STRING("error"));
-    return rv;
+    aError.Throw(rv);
   }
-  return NS_OK;;
+  return listener.forget();
+}
+
+NS_IMETHODIMP
+nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
+                                            nsIStreamListener** aListener)
+{
+  NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
+  NS_ENSURE_ARG_POINTER(aListener);
+
+  ErrorResult result;
+  *aListener = LoadImageWithChannel(aChannel, result).get();
+  return result.ErrorCode();
+}
+
+void
+nsImageLoadingContent::ForceReload(ErrorResult& aError)
+{
+  nsCOMPtr<nsIURI> currentURI;
+  GetCurrentURI(getter_AddRefs(currentURI));
+  if (!currentURI) {
+    aError.Throw(NS_ERROR_NOT_AVAILABLE);
+    return;
+  }
+
+  nsresult rv = LoadImage(currentURI, true, true, nullptr, nsIRequest::VALIDATE_ALWAYS);
+  if (NS_FAILED(rv)) {
+    aError.Throw(rv);
+  }
 }
 
 NS_IMETHODIMP nsImageLoadingContent::ForceReload()
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
 
-  nsCOMPtr<nsIURI> currentURI;
-  GetCurrentURI(getter_AddRefs(currentURI));
-  if (!currentURI) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  return LoadImage(currentURI, true, true, nullptr, nsIRequest::VALIDATE_ALWAYS);
+  ErrorResult result;
+  ForceReload(result);
+  return result.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsImageLoadingContent::BlockOnload(imgIRequest* aRequest)
 {
   if (aRequest != mCurrentRequest) {
     return NS_OK;
   }
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -34,16 +34,37 @@ class nsImageLoadingContent : public nsI
 public:
   nsImageLoadingContent();
   virtual ~nsImageLoadingContent();
 
   NS_DECL_IMGINOTIFICATIONOBSERVER
   NS_DECL_NSIIMAGELOADINGCONTENT
   NS_DECL_IMGIONLOADBLOCKER
 
+  // Web IDL binding methods.
+  // Note that the XPCOM SetLoadingEnabled, AddObserver, RemoveObserver,
+  // ForceImageState methods are OK for Web IDL bindings to use as well,
+  // since none of them throw when called via the Web IDL bindings.
+
+  bool LoadingEnabled() const { return mLoadingEnabled; }
+  int16_t ImageBlockingStatus() const
+  {
+    return mImageBlockingStatus;
+  }
+  already_AddRefed<imgIRequest>
+    GetRequest(int32_t aRequestType, mozilla::ErrorResult& aError);
+  int32_t
+    GetRequestType(imgIRequest* aRequest, mozilla::ErrorResult& aError);
+  already_AddRefed<nsIURI> GetCurrentURI(mozilla::ErrorResult& aError);
+  already_AddRefed<nsIStreamListener>
+    LoadImageWithChannel(nsIChannel* aChannel, mozilla::ErrorResult& aError);
+  void ForceReload(mozilla::ErrorResult& aError);
+
+
+
 protected:
   /**
    * LoadImage is called by subclasses when the appropriate
    * attributes (eg 'src' for <img> tags) change.  The string passed
    * in is the new uri string; this consolidates the code for getting
    * the charset, constructing URI objects, and any other incidentals
    * into this superclass.   
    *
@@ -137,18 +158,16 @@ protected:
    * they rely on being able to QueryInterface to other derived classes,
    * which cannot happen once the derived class destructor has started
    * calling the base class destructors.
    */
   void DestroyImageLoadingContent();
 
   void ClearBrokenState() { mBroken = false; }
 
-  bool LoadingEnabled() { return mLoadingEnabled; }
-
   // Sets blocking state only if the desired state is different from the
   // current one. See the comment for mBlockingOnload for more information.
   void SetBlockingOnload(bool aBlocking);
 
   /**
    * Returns the CORS mode that will be used for all future image loads. The
    * default implementation returns CORS_NONE unconditionally.
    */
@@ -229,16 +248,17 @@ private:
                            int16_t aNewImageStatus);
 
   /**
    * Method to fire an event once we know what's going on with the image load.
    *
    * @param aEventType "load" or "error" depending on how things went
    */
   nsresult FireEvent(const nsAString& aEventType);
+
 protected:
   /**
    * Method to create an nsIURI object from the given string (will
    * handle getting the right charset, base, etc).  You MUST pass in a
    * non-null document to this function.
    *
    * @param aSpec the string spec (from an HTML attribute, eg)
    * @param aDocument the document we belong to
--- a/content/base/src/nsXMLContentSerializer.cpp
+++ b/content/base/src/nsXMLContentSerializer.cpp
@@ -780,33 +780,17 @@ nsXMLContentSerializer::IsJavaScript(nsI
     scheme.StripWhitespace();
     if ((scheme.Length() == (sizeof kJavaScript - 1)) &&
         scheme.EqualsIgnoreCase(kJavaScript))
       return true;
     else
       return false;
   }
 
-  // Wouldn't having an nsIContent::IsEventAttributeName work better? Bug 811753
-  // That way we would only have to put the flags in one place...
-  if (isHtml) {
-    return nsContentUtils::IsEventAttributeName(aAttrNameAtom,
-                                                EventNameType_HTML |
-                                                EventNameType_HTMLBodyOrFramesetOnly);
-  }
-  else if (isXul) {
-    return nsContentUtils::IsEventAttributeName(aAttrNameAtom, EventNameType_XUL);
-  }
-  else if (isSvg) {
-    return nsContentUtils::IsEventAttributeName(aAttrNameAtom,
-                                                EventNameType_SVGGraphic |
-                                                EventNameType_SVGSVG |
-                                                EventNameType_SMIL);
-  }
-  return false;
+  return aContent->IsEventAttributeName(aAttrNameAtom);
 }
 
 
 void 
 nsXMLContentSerializer::SerializeAttributes(nsIContent* aContent,
                                             nsIContent *aOriginalElement,
                                             nsAString& aTagPrefix,
                                             const nsAString& aTagNamespaceURI,
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -89,17 +89,17 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/unused.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsJSUtils.h"
 #include "XPCQuickStubs.h"
 #include "mozilla/dom/BindingUtils.h"
-#include "nsHTMLImageElement.h"
+#include "mozilla/dom/HTMLImageElement.h"
 #include "nsHTMLVideoElement.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include <cstdlib> // for std::abs(int/long)
 #include <cmath> // for std::abs(float/double)
 
 #ifdef XP_WIN
 #include "gfxWindowsPlatform.h"
 #endif
@@ -1416,17 +1416,17 @@ CanvasRenderingContext2D::CreatePattern(
       RefPtr<SourceSurface> srcSurf = srcCanvas->GetSurfaceSnapshot();
 
       nsRefPtr<CanvasPattern> pat =
         new CanvasPattern(srcSurf, repeatMode, htmlElement->NodePrincipal(), canvas->IsWriteOnly(), false);
 
       return pat.forget();
     }
   } else if (element.IsHTMLImageElement()) {
-    htmlElement = element.GetAsHTMLImageElement();
+    htmlElement = &element.GetAsHTMLImageElement();
   } else {
     htmlElement = element.GetAsHTMLVideoElement();
   }
 
   // The canvas spec says that createPattern should use the first frame
   // of animated images
   nsLayoutUtils::SurfaceFromElementResult res =
     nsLayoutUtils::SurfaceFromElement(htmlElement,
@@ -2939,17 +2939,17 @@ CanvasRenderingContext2D::DrawImage(cons
                                                 canvas->IsWriteOnly(),
                                                 false);
         }
         imgSize = gfxIntSize(srcSurf->GetSize().width, srcSurf->GetSize().height);
       }
     }
   } else {
     if (image.IsHTMLImageElement()) {
-      nsHTMLImageElement* img = image.GetAsHTMLImageElement();
+      HTMLImageElement* img = &image.GetAsHTMLImageElement();
       element = img;
     } else {
       nsHTMLVideoElement* video = image.GetAsHTMLVideoElement();
       element = video;
     }
 
     gfxASurface* imgsurf =
       CanvasImageCache::Lookup(element, mCanvasElement, &imgSize);
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -739,19 +739,17 @@ protected:
   /**
     * Gets the pres shell from either the canvas element or the doc shell
     */
   nsIPresShell *GetPresShell() {
     if (mCanvasElement) {
       return mCanvasElement->OwnerDoc()->GetShell();
     }
     if (mDocShell) {
-      nsCOMPtr<nsIPresShell> shell;
-      mDocShell->GetPresShell(getter_AddRefs(shell));
-      return shell.get();
+      return mDocShell->GetPresShell();
     }
     return nullptr;
   }
 
   // text
   enum TextAlign {
     TEXT_ALIGN_START,
     TEXT_ALIGN_END,
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -40,35 +40,40 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/ipc/ProcessPriorityManager.h"
 
 #include "Layers.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 using namespace mozilla::dom;
+using namespace mozilla::dom::ipc;
 using namespace mozilla::layers;
 
 NS_IMETHODIMP
 WebGLMemoryPressureObserver::Observe(nsISupports* aSubject,
                                      const char* aTopic,
                                      const PRUnichar* aSomeData)
 {
     if (strcmp(aTopic, "memory-pressure"))
         return NS_OK;
 
     bool wantToLoseContext = true;
 
-    if (!nsCRT::strcmp(aSomeData, NS_LITERAL_STRING("heap-minimize").get()))
+    if (!mContext->mCanLoseContextInForeground && CurrentProcessIsForeground())
+        wantToLoseContext = false;
+    else if (!nsCRT::strcmp(aSomeData,
+                            NS_LITERAL_STRING("heap-minimize").get()))
         wantToLoseContext = mContext->mLoseContextOnHeapMinimize;
 
     if (wantToLoseContext)
         mContext->ForceLoseContext();
 
     return NS_OK;
 }
 
@@ -174,16 +179,17 @@ WebGLContext::WebGLContext()
 
     mAllowRestore = true;
     mContextLossTimerRunning = false;
     mDrawSinceContextLossTimerSet = false;
     mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
     mContextStatus = ContextStable;
     mContextLostErrorSet = false;
     mLoseContextOnHeapMinimize = false;
+    mCanLoseContextInForeground = true;
 
     mAlreadyGeneratedWarnings = 0;
     mAlreadyWarnedAboutFakeVertexAttrib0 = false;
 
     mLastUseIndex = 0;
 
     mMinInUseAttribArrayLengthCached = false;
     mMinInUseAttribArrayLength = 0;
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -545,17 +545,17 @@ public:
     void TexImage2D(WebGLenum target, WebGLint level,
                     WebGLenum internalformat, WebGLenum format, WebGLenum type,
                     dom::ImageData* pixels, ErrorResult& rv);
     // Allow whatever element types the bindings are willing to pass
     // us in TexImage2D
     template<class ElementType>
     void TexImage2D(WebGLenum target, WebGLint level,
                     WebGLenum internalformat, WebGLenum format, WebGLenum type,
-                    ElementType* elt, ErrorResult& rv) {
+                    const ElementType& elt, ErrorResult& rv) {
         if (!IsContextStable())
             return;
         nsRefPtr<gfxImageSurface> isurf;
         WebGLTexelFormat srcFormat;
         nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
         rv = SurfaceFromElementResultToImageSurface(res, getter_AddRefs(isurf),
                                                     &srcFormat);
         if (rv.Failed())
@@ -582,17 +582,17 @@ public:
     void TexSubImage2D(WebGLenum target, WebGLint level,
                        WebGLint xoffset, WebGLint yoffset, WebGLenum format,
                        WebGLenum type, dom::ImageData* pixels, ErrorResult& rv);
     // Allow whatever element types the bindings are willing to pass
     // us in TexSubImage2D
     template<class ElementType>
     void TexSubImage2D(WebGLenum target, WebGLint level,
                        WebGLint xoffset, WebGLint yoffset, WebGLenum format,
-                       WebGLenum type, ElementType* elt, ErrorResult& rv) {
+                       WebGLenum type, const ElementType& elt, ErrorResult& rv) {
         if (!IsContextStable())
             return;
         nsRefPtr<gfxImageSurface> isurf;
         WebGLTexelFormat srcFormat;
         nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
         rv = SurfaceFromElementResultToImageSurface(res, getter_AddRefs(isurf),
                                                     &srcFormat);
         if (rv.Failed())
@@ -838,16 +838,17 @@ protected:
     bool mInvalidated;
     bool mResetLayer;
     bool mOptionsFrozen;
     bool mMinCapability;
     bool mDisableExtensions;
     bool mHasRobustness;
     bool mIsMesa;
     bool mLoseContextOnHeapMinimize;
+    bool mCanLoseContextInForeground;
 
     template<typename WebGLObjectType>
     void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array);
 
     WebGLuint mActiveTexture;
     WebGLenum mWebGLError;
 
     // whether shader validation is supported
@@ -981,16 +982,20 @@ protected:
             nsLayoutUtils::SFE_WANT_IMAGE_SURFACE;
 
         if (mPixelStoreColorspaceConversion == LOCAL_GL_NONE)
             flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
         if (!mPixelStorePremultiplyAlpha)
             flags |= nsLayoutUtils::SFE_NO_PREMULTIPLY_ALPHA;
         return nsLayoutUtils::SurfaceFromElement(aElement, flags);
     }
+    template<class ElementType>
+    nsLayoutUtils::SurfaceFromElementResult SurfaceFromElement(const dom::NonNull<ElementType>& aElement) {
+      return SurfaceFromElement(aElement.get());
+    }
 
     nsresult SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
                                                     gfxImageSurface **imageOut,
                                                     WebGLTexelFormat *format);
 
     void CopyTexSubImage2D_base(WebGLenum target,
                                 WebGLint level,
                                 WebGLenum internalformat,
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -853,16 +853,17 @@ WebGLContext::InitAndValidateGL()
     if (error != LOCAL_GL_NO_ERROR) {
         GenerateWarning("GL error 0x%x occurred during OpenGL context initialization, before WebGL initialization!", error);
         return false;
     }
 
     mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false);
     mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false);
     mLoseContextOnHeapMinimize = Preferences::GetBool("webgl.lose-context-on-heap-minimize", false);
+    mCanLoseContextInForeground = Preferences::GetBool("webgl.can-lose-context-in-foreground", true);
 
     mActiveTexture = 0;
     mWebGLError = LOCAL_GL_NO_ERROR;
 
     mAttribBuffers.Clear();
 
     mBound2DTextures.Clear();
     mBoundCubeMapTextures.Clear();
--- a/content/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsContentEventHandler.cpp
@@ -11,17 +11,17 @@
 #include "nsISelection.h"
 #include "nsIDOMRange.h"
 #include "nsRange.h"
 #include "nsGUIEvent.h"
 #include "nsCaret.h"
 #include "nsCopySupport.h"
 #include "nsFrameSelection.h"
 #include "nsIFrame.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIContentIterator.h"
 #include "nsTextFragment.h"
 #include "nsTextFrame.h"
 #include "nsISelectionController.h"
 #include "nsISelectionPrivate.h"
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsIMEStateManager.h"
@@ -789,17 +789,17 @@ nsContentEventHandler::OnQueryCharacterA
   NS_ENSURE_TRUE(rootFrame, NS_ERROR_FAILURE);
   nsIWidget* rootWidget = rootFrame->GetNearestWidget();
   NS_ENSURE_TRUE(rootWidget, NS_ERROR_FAILURE);
 
   // The root frame's widget might be different, e.g., the event was fired on
   // a popup but the rootFrame is the document root.
   if (rootWidget != aEvent->widget) {
     NS_PRECONDITION(aEvent->widget, "The event must have the widget");
-    nsIView* view = nsIView::GetViewFor(aEvent->widget);
+    nsView* view = nsView::GetViewFor(aEvent->widget);
     NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
     rootFrame = view->GetFrame();
     NS_ENSURE_TRUE(rootFrame, NS_ERROR_FAILURE);
     rootWidget = rootFrame->GetNearestWidget();
     NS_ENSURE_TRUE(rootWidget, NS_ERROR_FAILURE);
   }
 
   nsQueryContentEvent eventOnRoot(true, NS_QUERY_CHARACTER_AT_POINT,
@@ -977,17 +977,17 @@ nsContentEventHandler::GetStartFrameAndO
 }
 
 nsresult
 nsContentEventHandler::ConvertToRootViewRelativeOffset(nsIFrame* aFrame,
                                                        nsRect& aRect)
 {
   NS_ASSERTION(aFrame, "aFrame must not be null");
 
-  nsIView* view = nullptr;
+  nsView* view = nullptr;
   nsPoint posInView;
   aFrame->GetOffsetFromView(posInView, &view);
   if (!view)
     return NS_ERROR_FAILURE;
   aRect += posInView + view->GetOffsetTo(nullptr);
   return NS_OK;
 }
 
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -21,17 +21,17 @@
 #include "nsIJSEventListener.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptRuntime.h"
 #include "nsLayoutUtils.h"
 #include "nsINameSpaceManager.h"
 #include "nsIContent.h"
 #include "mozilla/dom/Element.h"
 #include "nsIFrame.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIViewManager.h"
 #include "nsCOMPtr.h"
 #include "nsIServiceManager.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsError.h"
 #include "nsIJSContextStack.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -170,18 +170,17 @@ PrintDocTree(nsIDocShellTreeItem* aParen
 {
   for (int32_t i=0;i<aLevel;i++) printf("  ");
 
   int32_t childWebshellCount;
   aParentItem->GetChildCount(&childWebshellCount);
   nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(aParentItem));
   int32_t type;
   aParentItem->GetItemType(&type);
-  nsCOMPtr<nsIPresShell> presShell;
-  parentAsDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = parentAsDocShell->GetPresShell();
   nsRefPtr<nsPresContext> presContext;
   parentAsDocShell->GetPresContext(getter_AddRefs(presContext));
   nsCOMPtr<nsIContentViewer> cv;
   parentAsDocShell->GetContentViewer(getter_AddRefs(cv));
   nsCOMPtr<nsIDOMDocument> domDoc;
   if (cv)
     cv->GetDOMDocument(getter_AddRefs(domDoc));
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
@@ -1462,18 +1461,17 @@ nsEventStateManager::HandleAccessKey(nsP
       nsCOMPtr<nsIDocShellTreeItem> subShellItem;
       docShell->GetChildAt(counter, getter_AddRefs(subShellItem));
       if (aAccessKeyState == eAccessKeyProcessingUp &&
           subShellItem == aBubbledFrom)
         continue;
 
       nsCOMPtr<nsIDocShell> subDS = do_QueryInterface(subShellItem);
       if (subDS && IsShellVisible(subDS)) {
-        nsCOMPtr<nsIPresShell> subPS;
-        subDS->GetPresShell(getter_AddRefs(subPS));
+        nsCOMPtr<nsIPresShell> subPS = subDS->GetPresShell();
 
         // Docshells need not have a presshell (eg. display:none
         // iframes, docshells in transition between documents, etc).
         if (!subPS) {
           // Oh, well.  Just move on to the next child
           continue;
         }
 
@@ -1499,19 +1497,17 @@ nsEventStateManager::HandleAccessKey(nsP
       NS_WARNING("no docShellTreeItem for presContext");
       return;
     }
 
     nsCOMPtr<nsIDocShellTreeItem> parentShellItem;
     docShell->GetParent(getter_AddRefs(parentShellItem));
     nsCOMPtr<nsIDocShell> parentDS = do_QueryInterface(parentShellItem);
     if (parentDS) {
-      nsCOMPtr<nsIPresShell> parentPS;
-
-      parentDS->GetPresShell(getter_AddRefs(parentPS));
+      nsCOMPtr<nsIPresShell> parentPS = parentDS->GetPresShell();
       NS_ASSERTION(parentPS, "Our PresShell exists but the parent's does not?");
 
       nsPresContext *parentPC = parentPS->GetPresContext();
       NS_ASSERTION(parentPC, "PresShell without PresContext");
 
       nsEventStateManager* esm =
         static_cast<nsEventStateManager *>(parentPC->EventStateManager());
 
--- a/content/html/content/src/HTMLBodyElement.cpp
+++ b/content/html/content/src/HTMLBodyElement.cpp
@@ -480,16 +480,24 @@ HTMLBodyElement::GetAssociatedEditor()
   if (!editorDocShell) {
     return nullptr;
   }
 
   editorDocShell->GetEditor(getter_AddRefs(editor));
   return editor.forget();
 }
 
+bool
+HTMLBodyElement::IsEventAttributeName(nsIAtom *aName)
+{
+  return nsContentUtils::IsEventAttributeName(aName,
+                                              EventNameType_HTML |
+                                              EventNameType_HTMLBodyOrFramesetOnly);
+}
+
 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by the superclass */
 // nsGenericHTMLElement::GetOnError returns
 // already_AddRefed<EventHandlerNonNull> while other getters return
 // EventHandlerNonNull*, so allow passing in the type to use here.
 #define FORWARDED_EVENT_HELPER(name_, forwardto_, type_, getter_type_)         \
   NS_IMETHODIMP                                                                \
   HTMLBodyElement::GetOn##name_(JSContext *cx, jsval *vp)                      \
   {                                                                            \
--- a/content/html/content/src/HTMLBodyElement.h
+++ b/content/html/content/src/HTMLBodyElement.h
@@ -138,16 +138,19 @@ public:
                               bool aNullParent = true);
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual already_AddRefed<nsIEditor> GetAssociatedEditor();
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   virtual nsXPCClassInfo* GetClassInfo();
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+  virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
+
 private:
   nsresult GetColorHelper(nsIAtom* aAtom, nsAString& aColor);
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
                              bool *aTriedToWrap) MOZ_OVERRIDE;
 
   nsRefPtr<BodyRule> mContentStyleRule;
--- a/content/html/content/src/HTMLFrameSetElement.cpp
+++ b/content/html/content/src/HTMLFrameSetElement.cpp
@@ -344,16 +344,25 @@ HTMLFrameSetElement::ParseRowCol(const n
 
   aNumSpecs = count;
   // Transfer ownership to caller here
   *aSpecs = specs;
   
   return NS_OK;
 }
 
+bool
+HTMLFrameSetElement::IsEventAttributeName(nsIAtom *aName)
+{
+  return nsContentUtils::IsEventAttributeName(aName,
+                                              EventNameType_HTML |
+                                              EventNameType_HTMLBodyOrFramesetOnly);
+}
+
+
 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by the shim */
 // nsGenericHTMLElement::GetOnError returns
 // already_AddRefed<EventHandlerNonNull> while other getters return
 // EventHandlerNonNull*, so allow passing in the type to use here.
 #define FORWARDED_EVENT_HELPER(name_, forwardto_, type_, getter_type_)         \
   NS_IMETHODIMP                                                                \
   HTMLFrameSetElement::GetOn##name_(JSContext *cx, jsval *vp)                  \
   {                                                                            \
--- a/content/html/content/src/HTMLFrameSetElement.h
+++ b/content/html/content/src/HTMLFrameSetElement.h
@@ -84,16 +84,18 @@ public:
   {
     GetHTMLAttr(nsGkAtoms::rows, aRows);
   }
   void SetRows(const nsAString& aRows, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::rows, aRows, aError);
   }
 
+  virtual bool IsEventAttributeName(nsIAtom *aName) MOZ_OVERRIDE;
+
   // Event listener stuff; we need to declare only the ones we need to
   // forward to window that don't come from nsIDOMHTMLFrameSetElement.
 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by the superclass */
 #define FORWARDED_EVENT(name_, id_, type_, struct_)                     \
   NS_IMETHOD GetOn##name_(JSContext *cx, jsval *vp);                    \
   NS_IMETHOD SetOn##name_(JSContext *cx, const jsval &v);
 #define WINDOW_EVENT_HELPER(name_, type_)                               \
   type_* GetOn##name_();                                                \
rename from content/html/content/src/nsHTMLImageElement.cpp
rename to content/html/content/src/HTMLImageElement.cpp
--- a/content/html/content/src/nsHTMLImageElement.cpp
+++ b/content/html/content/src/HTMLImageElement.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "mozilla/Util.h"
 
-#include "nsHTMLImageElement.h"
+#include "mozilla/dom/HTMLImageElement.h"
+#include "mozilla/dom/HTMLImageElementBinding.h"
 #include "nsIDOMEventTarget.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsMappedAttributes.h"
 #include "nsSize.h"
 #include "nsIDocument.h"
 #include "nsIScriptContext.h"
@@ -36,135 +37,141 @@
 #include "nsRuleData.h"
 
 #include "nsIJSContextStack.h"
 #include "nsIDOMHTMLMapElement.h"
 #include "nsEventDispatcher.h"
 
 #include "nsLayoutUtils.h"
 
-using namespace mozilla;
-using namespace mozilla::dom;
-
 nsGenericHTMLElement*
 NS_NewHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                       FromParser aFromParser)
+                       mozilla::dom::FromParser aFromParser)
 {
   /*
-   * nsHTMLImageElement's will be created without a nsINodeInfo passed in
+   * HTMLImageElement's will be created without a nsINodeInfo passed in
    * if someone says "var img = new Image();" in JavaScript, in a case like
    * that we request the nsINodeInfo from the document's nodeinfo list.
    */
   nsCOMPtr<nsINodeInfo> nodeInfo(aNodeInfo);
   if (!nodeInfo) {
     nsCOMPtr<nsIDocument> doc =
       do_QueryInterface(nsContentUtils::GetDocumentFromCaller());
     NS_ENSURE_TRUE(doc, nullptr);
 
     nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::img, nullptr,
                                                    kNameSpaceID_XHTML,
                                                    nsIDOMNode::ELEMENT_NODE);
     NS_ENSURE_TRUE(nodeInfo, nullptr);
   }
 
-  return new nsHTMLImageElement(nodeInfo.forget());
+  return new mozilla::dom::HTMLImageElement(nodeInfo.forget());
 }
 
-nsHTMLImageElement::nsHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+DOMCI_NODE_DATA(HTMLImageElement, mozilla::dom::HTMLImageElement)
+
+namespace mozilla {
+namespace dom {
+
+HTMLImageElement::HTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
   // We start out broken
   AddStatesSilently(NS_EVENT_STATE_BROKEN);
+  SetIsDOMBinding();
 }
 
-nsHTMLImageElement::~nsHTMLImageElement()
+HTMLImageElement::~HTMLImageElement()
 {
   DestroyImageLoadingContent();
 }
 
 
-NS_IMPL_ADDREF_INHERITED(nsHTMLImageElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLImageElement, Element)
+NS_IMPL_ADDREF_INHERITED(HTMLImageElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLImageElement, Element)
 
 
-DOMCI_NODE_DATA(HTMLImageElement, nsHTMLImageElement)
-
-// QueryInterface implementation for nsHTMLImageElement
-NS_INTERFACE_TABLE_HEAD(nsHTMLImageElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLImageElement,
+// QueryInterface implementation for HTMLImageElement
+NS_INTERFACE_TABLE_HEAD(HTMLImageElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE5(HTMLImageElement,
                                    nsIDOMHTMLImageElement,
                                    nsIJSNativeInitializer,
                                    nsIImageLoadingContent,
                                    imgIOnloadBlocker,
                                    imgINotificationObserver)
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLImageElement,
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLImageElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLImageElement)
 
 
-NS_IMPL_ELEMENT_CLONE(nsHTMLImageElement)
+NS_IMPL_ELEMENT_CLONE(HTMLImageElement)
 
 
-NS_IMPL_STRING_ATTR(nsHTMLImageElement, Name, name)
-NS_IMPL_STRING_ATTR(nsHTMLImageElement, Align, align)
-NS_IMPL_STRING_ATTR(nsHTMLImageElement, Alt, alt)
-NS_IMPL_STRING_ATTR(nsHTMLImageElement, Border, border)
-NS_IMPL_INT_ATTR(nsHTMLImageElement, Hspace, hspace)
-NS_IMPL_BOOL_ATTR(nsHTMLImageElement, IsMap, ismap)
-NS_IMPL_URI_ATTR(nsHTMLImageElement, LongDesc, longdesc)
-NS_IMPL_STRING_ATTR(nsHTMLImageElement, Lowsrc, lowsrc)
-NS_IMPL_URI_ATTR(nsHTMLImageElement, Src, src)
-NS_IMPL_STRING_ATTR(nsHTMLImageElement, UseMap, usemap)
-NS_IMPL_INT_ATTR(nsHTMLImageElement, Vspace, vspace)
+NS_IMPL_STRING_ATTR(HTMLImageElement, Name, name)
+NS_IMPL_STRING_ATTR(HTMLImageElement, Align, align)
+NS_IMPL_STRING_ATTR(HTMLImageElement, Alt, alt)
+NS_IMPL_STRING_ATTR(HTMLImageElement, Border, border)
+NS_IMPL_INT_ATTR(HTMLImageElement, Hspace, hspace)
+NS_IMPL_BOOL_ATTR(HTMLImageElement, IsMap, ismap)
+NS_IMPL_URI_ATTR(HTMLImageElement, LongDesc, longdesc)
+NS_IMPL_STRING_ATTR(HTMLImageElement, Lowsrc, lowsrc)
+NS_IMPL_URI_ATTR(HTMLImageElement, Src, src)
+NS_IMPL_STRING_ATTR(HTMLImageElement, UseMap, usemap)
+NS_IMPL_INT_ATTR(HTMLImageElement, Vspace, vspace)
 
 void
-nsHTMLImageElement::GetItemValueText(nsAString& aValue)
+HTMLImageElement::GetItemValueText(nsAString& aValue)
 {
   GetSrc(aValue);
 }
 
 void
-nsHTMLImageElement::SetItemValueText(const nsAString& aValue)
+HTMLImageElement::SetItemValueText(const nsAString& aValue)
 {
   SetSrc(aValue);
 }
 
 // crossorigin is not "limited to only known values" per spec, so it's
 // just a string attr purposes of the DOM crossOrigin property.
-NS_IMPL_STRING_ATTR(nsHTMLImageElement, CrossOrigin, crossorigin)
+NS_IMPL_STRING_ATTR(HTMLImageElement, CrossOrigin, crossorigin)
 
 bool
-nsHTMLImageElement::Draggable() const
+HTMLImageElement::Draggable() const
 {
   // images may be dragged unless the draggable attribute is false
   return !AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
                       nsGkAtoms::_false, eIgnoreCase);
 }
 
-NS_IMETHODIMP
-nsHTMLImageElement::GetComplete(bool* aComplete)
+bool
+HTMLImageElement::Complete()
 {
-  NS_PRECONDITION(aComplete, "Null out param!");
-  *aComplete = true;
-
   if (!mCurrentRequest) {
-    return NS_OK;
+    return true;
   }
 
   uint32_t status;
   mCurrentRequest->GetImageStatus(&status);
-  *aComplete =
+  return
     (status &
      (imgIRequest::STATUS_LOAD_COMPLETE | imgIRequest::STATUS_ERROR)) != 0;
+}
+
+NS_IMETHODIMP
+HTMLImageElement::GetComplete(bool* aComplete)
+{
+  NS_PRECONDITION(aComplete, "Null out param!");
+
+  *aComplete = Complete();
 
   return NS_OK;
 }
 
 nsIntPoint
-nsHTMLImageElement::GetXY()
+HTMLImageElement::GetXY()
 {
   nsIntPoint point(0, 0);
 
   nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
 
   if (!frame) {
     return point;
   }
@@ -174,64 +181,64 @@ nsHTMLImageElement::GetXY()
   // Convert to pixels using that scale
   point.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
   point.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
 
   return point;
 }
 
 NS_IMETHODIMP
-nsHTMLImageElement::GetX(int32_t* aX)
+HTMLImageElement::GetX(int32_t* aX)
 {
   *aX = GetXY().x;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLImageElement::GetY(int32_t* aY)
+HTMLImageElement::GetY(int32_t* aY)
 {
   *aY = GetXY().y;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLImageElement::GetHeight(uint32_t* aHeight)
+HTMLImageElement::GetHeight(uint32_t* aHeight)
 {
-  *aHeight = GetWidthHeightForImage(mCurrentRequest).height;
+  *aHeight = Height();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLImageElement::SetHeight(uint32_t aHeight)
+HTMLImageElement::SetHeight(uint32_t aHeight)
 {
   return nsGenericHTMLElement::SetUnsignedIntAttr(nsGkAtoms::height, aHeight);
 }
 
 NS_IMETHODIMP
-nsHTMLImageElement::GetWidth(uint32_t* aWidth)
+HTMLImageElement::GetWidth(uint32_t* aWidth)
 {
-  *aWidth = GetWidthHeightForImage(mCurrentRequest).width;
+  *aWidth = Width();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLImageElement::SetWidth(uint32_t aWidth)
+HTMLImageElement::SetWidth(uint32_t aWidth)
 {
   return nsGenericHTMLElement::SetUnsignedIntAttr(nsGkAtoms::width, aWidth);
 }
 
 bool
-nsHTMLImageElement::ParseAttribute(int32_t aNamespaceID,
-                                   nsIAtom* aAttribute,
-                                   const nsAString& aValue,
-                                   nsAttrValue& aResult)
+HTMLImageElement::ParseAttribute(int32_t aNamespaceID,
+                                 nsIAtom* aAttribute,
+                                 const nsAString& aValue,
+                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::align) {
       return ParseAlignValue(aValue, aResult);
     }
     if (aAttribute == nsGkAtoms::crossorigin) {
       ParseCORSValue(aValue, aResult);
       return true;
@@ -252,51 +259,51 @@ MapAttributesIntoRule(const nsMappedAttr
   nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 nsChangeHint
-nsHTMLImageElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
-                                           int32_t aModType) const
+HTMLImageElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
+                                         int32_t aModType) const
 {
   nsChangeHint retval =
     nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
   if (aAttribute == nsGkAtoms::usemap ||
       aAttribute == nsGkAtoms::ismap) {
     NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
   }
   return retval;
 }
 
 NS_IMETHODIMP_(bool)
-nsHTMLImageElement::IsAttributeMapped(const nsIAtom* aAttribute) const
+HTMLImageElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sCommonAttributeMap,
     sImageMarginSizeAttributeMap,
     sImageBorderAttributeMap,
     sImageAlignAttributeMap
   };
 
   return FindAttributeDependence(aAttribute, map);
 }
 
 
 nsMapRuleToAttributesFunc
-nsHTMLImageElement::GetAttributeMappingFunction() const
+HTMLImageElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
 
 nsresult
-nsHTMLImageElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
+HTMLImageElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   // If we are a map and get a mouse click, don't let it be handled by
   // the Generic Element as this could cause a click event to fire
   // twice, once by the image frame for the map and once by the Anchor
   // element. (bug 39723)
   if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
       aVisitor.mEvent->message == NS_MOUSE_CLICK &&
       static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
@@ -306,18 +313,18 @@ nsHTMLImageElement::PreHandleEvent(nsEve
     if (isMap) {
       aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
     }
   }
   return nsGenericHTMLElement::PreHandleEvent(aVisitor);
 }
 
 bool
-nsHTMLImageElement::IsHTMLFocusable(bool aWithMouse,
-                                    bool *aIsFocusable, int32_t *aTabIndex)
+HTMLImageElement::IsHTMLFocusable(bool aWithMouse,
+                                  bool *aIsFocusable, int32_t *aTabIndex)
 {
   int32_t tabIndex = TabIndex();
 
   if (IsInDoc()) {
     nsAutoString usemap;
     GetUseMap(usemap);
     // XXXbz which document should this be using?  sXBL/XBL2 issue!  I
     // think that OwnerDoc() is right, since we don't want to
@@ -345,19 +352,19 @@ nsHTMLImageElement::IsHTMLFocusable(bool
     (!aWithMouse || nsFocusManager::sMouseFocusesFormControl) &&
 #endif
     (tabIndex >= 0 || HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex));
 
   return false;
 }
 
 nsresult
-nsHTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
-                            nsIAtom* aPrefix, const nsAString& aValue,
-                            bool aNotify)
+HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                          nsIAtom* aPrefix, const nsAString& aValue,
+                          bool aNotify)
 {
   // If we plan to call LoadImage, we want to do it first so that the
   // image load kicks off _before_ the reflow triggered by the SetAttr.  But if
   // aNotify is false, we are coming from the parser or some such place; we'll
   // get bound after all the attributes have been set, so we'll do the
   // image load from BindToTree.  Skip the LoadImage call in that case.
   if (aNotify &&
       aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
@@ -380,30 +387,30 @@ nsHTMLImageElement::SetAttr(int32_t aNam
     mNewRequestsWillNeedAnimationReset = false;
   }
     
   return nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
                                        aNotify);
 }
 
 nsresult
-nsHTMLImageElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
-                              bool aNotify)
+HTMLImageElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
+                            bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::src) {
     CancelImageRequests(aNotify);
   }
 
   return nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
 }
 
 nsresult
-nsHTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                               nsIContent* aBindingParent,
-                               bool aCompileEventHandlers)
+HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                             nsIContent* aBindingParent,
+                             bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
                                     aCompileEventHandlers);
@@ -413,54 +420,54 @@ nsHTMLImageElement::BindToTree(nsIDocume
     // ClearBrokenState update our state and do it fast...
     ClearBrokenState();
     RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
     // If loading is temporarily disabled, don't even launch MaybeLoadImage.
     // Otherwise MaybeLoadImage may run later when someone has reenabled
     // loading.
     if (LoadingEnabled()) {
       nsContentUtils::AddScriptRunner(
-        NS_NewRunnableMethod(this, &nsHTMLImageElement::MaybeLoadImage));
+        NS_NewRunnableMethod(this, &HTMLImageElement::MaybeLoadImage));
     }
   }
 
   return rv;
 }
 
 void
-nsHTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
+HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 void
-nsHTMLImageElement::MaybeLoadImage()
+HTMLImageElement::MaybeLoadImage()
 {
   // Our base URI may have changed; claim that our URI changed, and the
   // nsImageLoadingContent will decide whether a new image load is warranted.
   // Note, check LoadingEnabled() after LoadImage call.
   nsAutoString uri;
   if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, uri) &&
       (NS_FAILED(LoadImage(uri, false, true)) ||
        !LoadingEnabled())) {
     CancelImageRequests(true);
   }
 }
 
 nsEventStates
-nsHTMLImageElement::IntrinsicState() const
+HTMLImageElement::IntrinsicState() const
 {
   return nsGenericHTMLElement::IntrinsicState() |
     nsImageLoadingContent::ImageState();
 }
 
 NS_IMETHODIMP
-nsHTMLImageElement::Initialize(nsISupports* aOwner, JSContext* aContext,
-                               JSObject *aObj, uint32_t argc, jsval *argv)
+HTMLImageElement::Initialize(nsISupports* aOwner, JSContext* aContext,
+                             JSObject *aObj, uint32_t argc, jsval *argv)
 {
   if (argc <= 0) {
     // Nothing to do here if we don't get any arguments.
 
     return NS_OK;
   }
 
   // The first (optional) argument is the width of the image
@@ -477,70 +484,92 @@ nsHTMLImageElement::Initialize(nsISuppor
     NS_ENSURE_TRUE(ret, NS_ERROR_INVALID_ARG);
 
     rv = SetIntAttr(nsGkAtoms::height, static_cast<int32_t>(height));
   }
 
   return rv;
 }
 
-NS_IMETHODIMP
-nsHTMLImageElement::GetNaturalHeight(uint32_t* aNaturalHeight)
+uint32_t
+HTMLImageElement::NaturalHeight()
 {
-  NS_ENSURE_ARG_POINTER(aNaturalHeight);
+  if (!mCurrentRequest) {
+    return 0;
+  }
 
-  *aNaturalHeight = 0;
-
-  if (!mCurrentRequest) {
-    return NS_OK;
-  }
-  
   nsCOMPtr<imgIContainer> image;
   mCurrentRequest->GetImage(getter_AddRefs(image));
   if (!image) {
-    return NS_OK;
+    return 0;
   }
 
   int32_t height;
   if (NS_SUCCEEDED(image->GetHeight(&height))) {
-    *aNaturalHeight = height;
+    return height;
   }
-  return NS_OK;
+  return 0;
 }
 
 NS_IMETHODIMP
-nsHTMLImageElement::GetNaturalWidth(uint32_t* aNaturalWidth)
+HTMLImageElement::GetNaturalHeight(uint32_t* aNaturalHeight)
 {
-  NS_ENSURE_ARG_POINTER(aNaturalWidth);
+  NS_ENSURE_ARG_POINTER(aNaturalHeight);
+
+  *aNaturalHeight = NaturalHeight();
 
-  *aNaturalWidth = 0;
+  return NS_OK;
+}
 
+uint32_t
+HTMLImageElement::NaturalWidth()
+{
   if (!mCurrentRequest) {
-    return NS_OK;
+    return 0;
   }
-  
+
   nsCOMPtr<imgIContainer> image;
   mCurrentRequest->GetImage(getter_AddRefs(image));
   if (!image) {
-    return NS_OK;
+    return 0;
   }
 
   int32_t width;
   if (NS_SUCCEEDED(image->GetWidth(&width))) {
-    *aNaturalWidth = width;
+    return width;
   }
+  return 0;
+}
+
+NS_IMETHODIMP
+HTMLImageElement::GetNaturalWidth(uint32_t* aNaturalWidth)
+{
+  NS_ENSURE_ARG_POINTER(aNaturalWidth);
+
+  *aNaturalWidth = NaturalWidth();
+
   return NS_OK;
 }
 
 nsresult
-nsHTMLImageElement::CopyInnerTo(Element* aDest)
+HTMLImageElement::CopyInnerTo(Element* aDest)
 {
   if (aDest->OwnerDoc()->IsStaticDocument()) {
-    CreateStaticImageClone(static_cast<nsHTMLImageElement*>(aDest));
+    CreateStaticImageClone(static_cast<HTMLImageElement*>(aDest));
   }
   return nsGenericHTMLElement::CopyInnerTo(aDest);
 }
 
 CORSMode
-nsHTMLImageElement::GetCORSMode()
+HTMLImageElement::GetCORSMode()
 {
   return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
 }
+
+JSObject*
+HTMLImageElement::WrapNode(JSContext* aCx, JSObject* aScope,
+                           bool* aTriedToWrap)
+{
+  return HTMLImageElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+} // namespace dom
+} // namespace mozilla
rename from content/html/content/src/nsHTMLImageElement.h
rename to content/html/content/src/HTMLImageElement.h
--- a/content/html/content/src/nsHTMLImageElement.h
+++ b/content/html/content/src/HTMLImageElement.h
@@ -1,29 +1,33 @@
 /* -*- 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 nsHTMLImageElement_h
-#define nsHTMLImageElement_h
+#ifndef mozilla_dom_HTMLImageElement_h
+#define mozilla_dom_HTMLImageElement_h
 
 #include "nsGenericHTMLElement.h"
 #include "nsImageLoadingContent.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIJSNativeInitializer.h"
+#include "imgRequestProxy.h"
 
-class nsHTMLImageElement : public nsGenericHTMLElement,
-                           public nsImageLoadingContent,
-                           public nsIDOMHTMLImageElement,
-                           public nsIJSNativeInitializer
+namespace mozilla {
+namespace dom {
+
+class HTMLImageElement MOZ_FINAL : public nsGenericHTMLElement,
+                                   public nsImageLoadingContent,
+                                   public nsIDOMHTMLImageElement,
+                                   public nsIJSNativeInitializer
 {
 public:
-  nsHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  virtual ~nsHTMLImageElement();
+  explicit HTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~HTMLImageElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
@@ -33,17 +37,17 @@ public:
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   virtual bool Draggable() const MOZ_OVERRIDE;
 
   // nsIDOMHTMLImageElement
   NS_DECL_NSIDOMHTMLIMAGEELEMENT
 
   // override from nsImageLoadingContent
-  mozilla::CORSMode GetCORSMode();
+  CORSMode GetCORSMode();
 
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
                         JSObject* aObj, uint32_t argc, jsval* argv);
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
@@ -74,20 +78,104 @@ public:
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep, bool aNullParent);
 
   virtual nsEventStates IntrinsicState() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
-  nsresult CopyInnerTo(mozilla::dom::Element* aDest);
+  nsresult CopyInnerTo(Element* aDest);
 
   void MaybeLoadImage();
   virtual nsXPCClassInfo* GetClassInfo();
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+  bool IsMap()
+  {
+    return GetBoolAttr(nsGkAtoms::ismap);
+  }
+  void SetIsMap(bool aIsMap, ErrorResult& aError)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::ismap, aIsMap, aError);
+  }
+  uint32_t Width()
+  {
+    return GetWidthHeightForImage(mCurrentRequest).width;
+  }
+  void SetWidth(uint32_t aWidth, ErrorResult& aError)
+  {
+    SetHTMLUnsignedIntAttr(nsGkAtoms::width, aWidth, aError);
+  }
+  uint32_t Height()
+  {
+    return GetWidthHeightForImage(mCurrentRequest).height;
+  }
+  void SetHeight(uint32_t aHeight, ErrorResult& aError)
+  {
+    SetHTMLUnsignedIntAttr(nsGkAtoms::height, aHeight, aError);
+  }
+  uint32_t NaturalWidth();
+  uint32_t NaturalHeight();
+  bool Complete();
+  int32_t Hspace()
+  {
+    return GetIntAttr(nsGkAtoms::hspace, 0);
+  }
+  void SetHspace(int32_t aHspace, ErrorResult& aError)
+  {
+    SetHTMLIntAttr(nsGkAtoms::hspace, aHspace, aError);
+  }
+  int32_t Vspace()
+  {
+    return GetIntAttr(nsGkAtoms::vspace, 0);
+  }
+  void SetVspace(int32_t aVspace, ErrorResult& aError)
+  {
+    SetHTMLIntAttr(nsGkAtoms::vspace, aVspace, aError);
+  }
+
+  // The XPCOM versions of the following getters work for Web IDL bindings as well
+  void SetAlt(const nsAString& aAlt, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::alt, aAlt, aError);
+  }
+  void SetSrc(const nsAString& aSrc, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::src, aSrc, aError);
+  }
+  void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError);
+  }
+  void SetUseMap(const nsAString& aUseMap, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::usemap, aUseMap, aError);
+  }
+  void SetName(const nsAString& aName, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::name, aName, aError);
+  }
+  void SetAlign(const nsAString& aAlign, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
+  }
+  void SetLongDesc(const nsAString& aLongDesc, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::longdesc, aLongDesc, aError);
+  }
+  void SetBorder(const nsAString& aBorder, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::border, aBorder, aError);
+  }
+
 protected:
   nsIntPoint GetXY();
   virtual void GetItemValueText(nsAString& text);
   virtual void SetItemValueText(const nsAString& text);
+  virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
+                             bool *aTriedToWrap) MOZ_OVERRIDE;
 };
 
-#endif /* nsHTMLImageElement_h */
+} // namespace dom
+} // namespace mozilla
+
+#endif /* mozilla_dom_HTMLImageElement_h */
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -31,16 +31,17 @@ EXPORTS_NAMESPACES = mozilla/dom
 
 EXPORTS_mozilla/dom = \
 		HTMLBodyElement.h \
 		HTMLDataListElement.h \
 		HTMLDivElement.h \
 		HTMLFontElement.h \
 		HTMLFrameSetElement.h \
 		HTMLHeadingElement.h \
+		HTMLImageElement.h \
 		HTMLLabelElement.h \
 		HTMLTitleElement.h \
 		HTMLUnknownElement.h
 
 CPPSRCS		= \
 		HTMLPropertiesCollection.cpp \
 		nsClientRect.cpp \
 		nsHTMLDNSPrefetch.cpp \
@@ -60,17 +61,17 @@ CPPSRCS		= \
 		nsHTMLFieldSetElement.cpp \
 		HTMLFontElement.cpp \
 		nsHTMLFormElement.cpp \
 		nsHTMLFrameElement.cpp \
 		HTMLFrameSetElement.cpp \
 		nsHTMLHRElement.cpp \
 		HTMLHeadingElement.cpp \
 		nsHTMLIFrameElement.cpp \
-		nsHTMLImageElement.cpp \
+		HTMLImageElement.cpp \
 		nsHTMLInputElement.cpp \
 		nsHTMLLIElement.cpp \
 		HTMLLabelElement.cpp \
 		nsHTMLLegendElement.cpp \
 		nsHTMLLinkElement.cpp \
 		nsHTMLMapElement.cpp \
 		nsHTMLMenuElement.cpp \
 		nsHTMLMenuItemElement.cpp \
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -32,17 +32,17 @@
 #include "nsILink.h"
 #include "nsPIDOMWindow.h"
 #include "nsIStyleRule.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsEscape.h"
 #include "nsIFrame.h"
 #include "nsIScrollableFrame.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIViewManager.h"
 #include "nsIWidget.h"
 #include "nsRange.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsINameSpaceManager.h"
@@ -792,23 +792,17 @@ nsGenericHTMLElement::BeforeSetAttr(int3
                                                  aValue, aNotify);
 }
 
 nsresult
 nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                    const nsAttrValue* aValue, bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
-    uint32_t eventType = EventNameType_HTML;
-    if (mNodeInfo->Equals(nsGkAtoms::body) ||
-        mNodeInfo->Equals(nsGkAtoms::frameset)) {
-      eventType |= EventNameType_HTMLBodyOrFramesetOnly;
-    }
-    if (nsContentUtils::IsEventAttributeName(aName, eventType) &&
-        aValue) {
+    if (IsEventAttributeName(aName) && aValue) {
       NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
         "Expected string value for script body");
       nsresult rv = SetEventHandler(aName, aValue->GetStringValue());
       NS_ENSURE_SUCCESS(rv, rv);
     }
     else if (aNotify && aName == nsGkAtoms::spellcheck) {
       SyncEditorsOnSubtree(this);
     }
@@ -1038,18 +1032,17 @@ nsGenericHTMLElement::UnsetAttr(int32_t 
       contentEditable = true;
       contentEditableChange = GetContentEditableValue() == eTrue ? -1 : 0;
     }
     else if (aAttribute == nsGkAtoms::accesskey) {
       // Have to unregister before clearing flag. See UnregAccessKey
       UnregAccessKey();
       UnsetFlags(NODE_HAS_ACCESSKEY);
     }
-    else if (nsContentUtils::IsEventAttributeName(aAttribute,
-                                                  EventNameType_HTML)) {
+    else if (IsEventAttributeName(aAttribute)) {
       nsEventListenerManager* manager = GetListenerManager(false);
       if (manager) {
         manager->RemoveEventHandler(aAttribute);
       }
     }
   }
 
   nsresult rv = nsGenericHTMLElementBase::UnsetAttr(aNameSpaceID, aAttribute,
@@ -3003,17 +2996,17 @@ nsGenericHTMLElement::RecompileScriptEve
         const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
 
         // Eventlistenener-attributes are always in the null namespace
         if (!name->IsAtom()) {
             continue;
         }
 
         nsIAtom *attr = name->Atom();
-        if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_HTML)) {
+        if (!IsEventAttributeName(attr)) {
             continue;
         }
 
         nsAutoString value;
         GetAttr(kNameSpaceID_None, attr, value);
         SetEventHandler(attr, value, true);
     }
 }
@@ -3290,8 +3283,14 @@ nsGenericHTMLElement::GetWidthHeightForI
       image->GetHeight(&size.height);
     }
   }
 
   NS_ASSERTION(size.width >= 0, "negative width");
   NS_ASSERTION(size.height >= 0, "negative height");
   return size;
 }
+
+bool
+nsGenericHTMLElement::IsEventAttributeName(nsIAtom *aName)
+{
+  return nsContentUtils::IsEventAttributeName(aName, EventNameType_HTML);
+}
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -234,16 +234,19 @@ public:
   {
     nsresult rv;
     nsICSSDeclaration* style = nsMappedAttributeElement::GetStyle(&rv);
     if (NS_FAILED(rv)) {
       aError.Throw(rv);
     }
     return style;
   }
+
+  virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
+
 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by nsINode */
 // The using nsINode::Get/SetOn* are to avoid warnings about shadowing the XPCOM
 // getter and setter on nsINode.
 #define FORWARDED_EVENT(name_, id_, type_, struct_)                           \
   using nsINode::GetOn##name_;                                                \
   using nsINode::SetOn##name_;                                                \
   mozilla::dom::EventHandlerNonNull* GetOn##name_();                          \
   void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler,               \
@@ -821,16 +824,23 @@ protected:
   }
   void SetHTMLIntAttr(nsIAtom* aName, int32_t aValue, mozilla::ErrorResult& aError)
   {
     nsAutoString value;
     value.AppendInt(aValue);
 
     SetHTMLAttr(aName, value, aError);
   }
+  void SetHTMLUnsignedIntAttr(nsIAtom* aName, uint32_t aValue, mozilla::ErrorResult& aError)
+  {
+    nsAutoString value;
+    value.AppendInt(aValue);
+
+    SetHTMLAttr(aName, value, aError);
+  }
 
   /**
    * Helper method for NS_IMPL_STRING_ATTR macro.
    * Sets the value of an attribute, returns specified default value if the
    * attribute isn't set. Only works for attributes in null namespace.
    *
    * @param aAttr    name of attribute.
    * @param aDefault default-value to return if attribute isn't set.
old mode 100755
new mode 100644
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -3,17 +3,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 "nsTextEditorState.h"
 
 #include "nsCOMPtr.h"
 #include "nsIPresShell.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsCaret.h"
 #include "nsEditorCID.h"
 #include "nsLayoutCID.h"
 #include "nsITextControlFrame.h" 
 #include "nsIPlaintextEditor.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMDocument.h"
 #include "nsContentCreatorFunctions.h"
--- a/content/html/content/test/reflect.js
+++ b/content/html/content/test/reflect.js
@@ -51,17 +51,35 @@ function reflectString(aParameters)
   is(element.getAttribute(contentAttr), "null",
      "null should have been stringified to 'null'");
   is(element[idlAttr], "null",
      "null should have been stringified to 'null'");
   element.removeAttribute(contentAttr);
 
   element[idlAttr] = null;
   // TODO: remove this ugly hack when null stringification will work as expected.
-  if (element.localName == "textarea" && idlAttr == "wrap") {
+  var todoAttrs = {
+    col: [ "align", "vAlign", "ch" ],
+    colgroup: [ "align", "vAlign", "ch" ],
+    form: [ "acceptCharset", "name", "target" ],
+    img: [ "align" ],
+    input: [ "accept", "alt", "formTarget", "max", "min", "name", "pattern", "placeholder", "step", "defaultValue" ],
+    link: [ "crossOrigin" ],
+    script: [ "crossOrigin" ],
+    source: [ "media" ],
+    table: [ "border", "width" ],
+    tbody: [ "align", "vAlign", "ch" ],
+    td: [ "align", "vAlign", "ch" ],
+    textarea: [ "name", "placeholder" ],
+    tfoot: [ "align", "vAlign", "ch" ],
+    th: [ "align", "vAlign", "ch" ],
+    thead: [ "align", "vAlign", "ch" ],
+    tr: [ "align", "vAlign", "ch" ],
+  };
+  if (!(element.localName in todoAttrs) || todoAttrs[element.localName].indexOf(idlAttr) == -1) {
     is(element.getAttribute(contentAttr), "null",
        "null should have been stringified to 'null'");
     is(element[idlAttr], "null", "null should have been stringified to 'null'");
     element.removeAttribute(contentAttr);
   } else {
     todo_is(element.getAttribute(contentAttr), "null",
        "null should have been stringified to 'null'");
     todo_is(element[idlAttr], "null",
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -154,18 +154,17 @@ HTML_TAG("head", "Head");
 HTML_TAG("header", "")
 HTML_TAG("hgroup", "")
 HTML_TAG("hr", "HR");
 HTML_TAG("html", "Html");
 HTML_TAG("i", "");
 HTML_TAG("iframe", "IFrame", [ "nsIDOMGetSVGDocument", "nsIDOMMozBrowserFrame" ],
                              [ "nsIFrameLoaderOwner" ]);
 HTML_TAG("image", "Span");
-HTML_TAG("img", "Image", [], [ "imgINotificationObserver",
-                               "nsIImageLoadingContent" ]);
+HTML_TAG("img", "Image", [ "nsIImageLoadingContent" ], []);
 HTML_TAG("input", "Input", [], [ "imgINotificationObserver",
                                  "nsIImageLoadingContent",
                                  "nsIDOMNSEditableElement" ]);
 HTML_TAG("ins", "Mod");
 HTML_TAG("kbd", "");
 HTML_TAG("keygen", "Span");
 HTML_TAG("label", "Label");
 HTML_TAG("legend", "Legend");
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2755,19 +2755,17 @@ nsHTMLDocument::TurnEditingOff()
   return NS_OK;
 }
 
 static bool HasPresShell(nsPIDOMWindow *aWindow)
 {
   nsIDocShell *docShell = aWindow->GetDocShell();
   if (!docShell)
     return false;
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
-  return presShell != nullptr;
+  return docShell->GetPresShell() != nullptr;
 }
 
 nsresult
 nsHTMLDocument::SetEditingState(EditingState aState)
 {
   mEditingState = aState;
   return NS_OK;
 }
--- a/content/html/document/test/test_non-ascii-cookie.html
+++ b/content/html/document/test/test_non-ascii-cookie.html
@@ -1,33 +1,58 @@
 <!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=784367
 -->
 <head>
   <meta charset="utf-8">
-  <title>Test for non-ASCII document.cookie</title>
+  <title>Test for non-ASCII cookie values</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=784367">Mozilla Bug 784367</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
-/** Test for non-ASCII document.cookie **/
+/** Test for non-ASCII cookie values **/
+
+var [Cc, Ci] = [SpecialPowers.Cc, SpecialPowers.Ci];
+
+var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
+function getCookieFromManager() {
+  var values = [];
+  var host = location.hostname;
+  var path = location.pathname;
+  path = path.substring(0, path.lastIndexOf("/") + 1);
+  var e = cm.enumerator;
+  while (e.hasMoreElements()) {
+    var cookie = e.getNext().QueryInterface(Ci.nsICookie);
+    if (!cookie) {
+      break;
+    }
+    if (host != cookie.host || path != cookie.path) {
+      continue;
+    }
+    values.push(cookie.name + "=" + cookie.value);
+  }
+  return values.join("; ");
+}
+
 var c = document.cookie;
 is(document.cookie, 'abc=012©ABC\ufffdDEF', "document.cookie should be decoded as UTF-8");
+is(getCookieFromManager(), document.cookie, "nsICookieManager should be consistent with document.cookie");
 var newCookie = 'def=∼≩≭≧∯≳≲≣∽≸≸∺≸∠≯≮≥≲≲≯≲∽≡≬≥≲≴∨∱∩∾';
 document.cookie = newCookie;
 is(document.cookie, c + '; ' + newCookie, "document.cookie should be encoded as UTF-8");
+is(getCookieFromManager(), document.cookie, "nsICookieManager should be consistent with document.cookie");
 var date1 = new Date();
 date1.setTime(0);
 document.cookie = newCookie + 'def=;expires=' + date1.toGMTString();
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/MediaResource.cpp
+++ b/content/media/MediaResource.cpp
@@ -310,25 +310,16 @@ ChannelMediaResource::OnStartRequest(nsI
 
     if (seekable) {
       mDecoder->SetInfinite(false);
     }
   }
   mDecoder->SetTransportSeekable(seekable);
   mCacheStream.SetTransportSeekable(seekable);
 
-  nsCOMPtr<nsICachingChannel> cc = do_QueryInterface(aRequest);
-  if (cc) {
-    bool fromCache = false;
-    rv = cc->IsFromCache(&fromCache);
-    if (NS_SUCCEEDED(rv) && !fromCache) {
-      cc->SetCacheAsFile(true);
-    }
-  }
-
   {
     MutexAutoLock lock(mLock);
     mChannelStatistics->Start();
   }
 
   mReopenOnError = false;
   // If we are seeking to get metadata, because we are playing an OGG file,
   // ignore if the channel gets closed without us suspending it explicitly. We
--- a/content/svg/content/src/nsSVGAltGlyphElement.cpp
+++ b/content/svg/content/src/nsSVGAltGlyphElement.cpp
@@ -43,22 +43,24 @@ public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+  virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
+
 protected:
 
   // nsSVGElement overrides
   virtual StringAttributesInfo GetStringInfo();
 
-  virtual bool IsEventName(nsIAtom* aName);
 
   enum { HREF };
   nsSVGString mStringAttributes[1];
   static StringInfo sStringInfo[1];
 
 };
 
 nsSVGElement::StringInfo nsSVGAltGlyphElement::sStringInfo[1] =
@@ -150,23 +152,24 @@ nsSVGAltGlyphElement::IsAttributeMapped(
     sGraphicsMap,
     sTextContentElementsMap
   };
   
   return FindAttributeDependence(name, map) ||
     nsSVGAltGlyphElementBase::IsAttributeMapped(name);
 }
 
-//----------------------------------------------------------------------
-// nsSVGElement overrides
 
 bool
-nsSVGAltGlyphElement::IsEventName(nsIAtom* aName)
+nsSVGAltGlyphElement::IsEventAttributeName(nsIAtom* aName)
 {
   return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
 }
 
+//----------------------------------------------------------------------
+// nsSVGElement overrides
+
 nsSVGElement::StringAttributesInfo
 nsSVGAltGlyphElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               ArrayLength(sStringInfo));
 }
--- a/content/svg/content/src/nsSVGAnimationElement.cpp
+++ b/content/svg/content/src/nsSVGAnimationElement.cpp
@@ -486,17 +486,17 @@ nsSVGAnimationElement::EndElementAt(floa
   AnimationNeedsResample();
   // Force synchronous sample
   FlushAnimations();
  
   return NS_OK;
 }
 
 bool
-nsSVGAnimationElement::IsEventName(nsIAtom* aName)
+nsSVGAnimationElement::IsEventAttributeName(nsIAtom* aName)
 {
   return nsContentUtils::IsEventAttributeName(aName, EventNameType_SMIL);
 }
 
 void
 nsSVGAnimationElement::UpdateHrefTarget(nsIContent* aNodeForContext,
                                         const nsAString& aHrefStr)
 {
--- a/content/svg/content/src/nsSVGAnimationElement.h
+++ b/content/svg/content/src/nsSVGAnimationElement.h
@@ -62,22 +62,23 @@ public:
   virtual bool HasAnimAttr(nsIAtom* aAttName) const;
   virtual Element* GetTargetElementContent();
   virtual bool GetTargetAttributeName(int32_t* aNamespaceID,
                                         nsIAtom** aLocalName) const;
   virtual nsSMILTargetAttrType GetTargetAttributeType() const;
   virtual nsSMILTimedElement& TimedElement();
   virtual nsSMILTimeContainer* GetTimeContainer();
 
+  virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
+
   // Utility methods for within SVG
   void ActivateByHyperlink();
 
 protected:
   // nsSVGElement overrides
-  bool IsEventName(nsIAtom* aName);
 
   void UpdateHrefTarget(nsIContent* aNodeForContext,
                         const nsAString& aHrefStr);
   void AnimationTargetChanged();
 
   class TargetReference : public nsReferencedElement {
   public:
     TargetReference(nsSVGAnimationElement* aAnimationElement) :
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -332,17 +332,17 @@ nsSVGElement::AfterSetAttr(int32_t aName
   // the content stylerule.
   // XXX For some reason incremental mapping doesn't work, so for now
   // just delete the style rule and lazily reconstruct it in
   // GetContentStyleRule()
   if (aNamespaceID == kNameSpaceID_None && IsAttributeMapped(aName)) {
     mContentStyleRule = nullptr;
   }
 
-  if (IsEventName(aName) && aValue) {
+  if (IsEventAttributeName(aName) && aValue) {
     NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
       "Expected string value for script body");
     nsresult rv = SetEventHandler(GetEventNameForAttr(aName),
                                   aValue->GetStringValue());
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify);
@@ -691,17 +691,17 @@ nsSVGElement::UnsetAttrInternal(int32_t 
   // XXXbz there's a bunch of redundancy here with AfterSetAttr.
   // Maybe consolidate?
 
   if (aNamespaceID == kNameSpaceID_None) {
     // If this is an svg presentation attribute, remove rule to force an update
     if (IsAttributeMapped(aName))
       mContentStyleRule = nullptr;
 
-    if (IsEventName(aName)) {
+    if (IsEventAttributeName(aName)) {
       nsEventListenerManager* manager = GetListenerManager(false);
       if (manager) {
         nsIAtom* eventName = GetEventNameForAttr(aName);
         manager->RemoveEventHandler(eventName);
       }
       return;
     }
     
@@ -1294,22 +1294,16 @@ MappedAttrParser::CreateStyleRule()
   return rule.forget();
 }
 
 } // anonymous namespace
 
 //----------------------------------------------------------------------
 // Implementation Helpers:
 
-bool
-nsSVGElement::IsEventName(nsIAtom* aName)
-{
-  return false;
-}
-
 void
 nsSVGElement::UpdateContentStyleRule()
 {
   NS_ASSERTION(!mContentStyleRule, "we already have a content style rule");
 
   uint32_t attrCount = mAttrsAndChildren.AttrCount();
   if (!attrCount) {
     // nothing to do
@@ -2558,17 +2552,17 @@ nsSVGElement::RecompileScriptEventListen
     const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
 
     // Eventlistenener-attributes are always in the null namespace
     if (!name->IsAtom()) {
         continue;
     }
 
     nsIAtom *attr = name->Atom();
-    if (!IsEventName(attr)) {
+    if (!IsEventAttributeName(attr)) {
       continue;
     }
 
     nsAutoString value;
     GetAttr(kNameSpaceID_None, attr, value);
     SetEventHandler(GetEventNameForAttr(attr), value, true);
   }
 }
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -320,19 +320,16 @@ protected:
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify);
   virtual bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                                 const nsAString& aValue, nsAttrValue& aResult);
   static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
                                               nsIAtom* aAttribute,
                                               const nsAString& aValue);
 
-  // Hooks for subclasses
-  virtual bool IsEventName(nsIAtom* aName);
-
   void UpdateContentStyleRule();
   void UpdateAnimatedContentStyleRule();
   mozilla::css::StyleRule* GetAnimatedContentStyleRule();
 
   nsAttrValue WillChangeValue(nsIAtom* aName);
   void DidChangeValue(nsIAtom* aName, const nsAttrValue& aEmptyOrOldValue,
                       nsAttrValue& aNewValue);
   void MaybeSerializeAttrBeforeRemoval(nsIAtom* aName, bool aNotify);
--- a/content/svg/content/src/nsSVGGraphicElement.cpp
+++ b/content/svg/content/src/nsSVGGraphicElement.cpp
@@ -171,25 +171,25 @@ nsSVGGraphicElement::GetAttributeChangeH
       // We just assume the old and new transforms are different.
       NS_UpdateHint(retval, NS_CombineHint(nsChangeHint_UpdateOverflow,
                                            nsChangeHint_UpdateTransformLayer));
     }
   }
   return retval;
 }
 
-//----------------------------------------------------------------------
-// nsSVGElement overrides
-
 bool
-nsSVGGraphicElement::IsEventName(nsIAtom* aName)
+nsSVGGraphicElement::IsEventAttributeName(nsIAtom* aName)
 {
   return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
 }
 
+//----------------------------------------------------------------------
+// nsSVGElement overrides
+
 gfxMatrix
 nsSVGGraphicElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
                                               TransformTypes aWhich) const
 {
   NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
                     "Skipping eUserSpaceToParent transforms makes no sense");
 
   gfxMatrix result(aMatrix);
--- a/content/svg/content/src/nsSVGGraphicElement.h
+++ b/content/svg/content/src/nsSVGGraphicElement.h
@@ -27,30 +27,33 @@ public:
   NS_DECL_NSIDOMSVGTRANSFORMABLE
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                       int32_t aModType) const;
 
+
+  virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
+
+
   virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
                       TransformTypes aWhich = eAllTransforms) const;
   virtual const gfxMatrix* GetAnimateMotionTransform() const;
   virtual void SetAnimateMotionTransform(const gfxMatrix* aMatrix);
 
   virtual mozilla::SVGAnimatedTransformList*
     GetAnimatedTransformList(uint32_t aFlags = 0);
   virtual nsIAtom* GetTransformListAttrName() const {
     return nsGkAtoms::transform;
   }
 
 protected:
   // nsSVGElement overrides
-  virtual bool IsEventName(nsIAtom* aName);
 
   nsAutoPtr<mozilla::SVGAnimatedTransformList> mTransforms;
 
   // XXX maybe move this to property table, to save space on un-animated elems?
   nsAutoPtr<gfxMatrix> mAnimateMotionTransform;
 };
 
 #endif // __NS_SVGGRAPHICELEMENT_H__
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -837,32 +837,32 @@ nsSVGSVGElement::PreHandleEvent(nsEventC
       // that requires up-to-date animations before our first sample callback,
       // we'll force a synchronous sample.
       AnimationNeedsResample();
     }
   }
   return nsSVGSVGElementBase::PreHandleEvent(aVisitor);
 }
 
-//----------------------------------------------------------------------
-// nsSVGElement overrides
-
 bool
-nsSVGSVGElement::IsEventName(nsIAtom* aName)
+nsSVGSVGElement::IsEventAttributeName(nsIAtom* aName)
 {
   /* The events in EventNameType_SVGSVG are for events that are only
      applicable to outermost 'svg' elements. We don't check if we're an outer
      'svg' element in case we're not inserted into the document yet, but since
      the target of the events in question will always be the outermost 'svg'
      element, this shouldn't cause any real problems.
   */
   return nsContentUtils::IsEventAttributeName(aName,
          (EventNameType_SVGGraphic | EventNameType_SVGSVG));
 }
 
+//----------------------------------------------------------------------
+// nsSVGElement overrides
+
 // Helper for GetViewBoxTransform on root <svg> node
 // * aLength: internal value for our <svg> width or height attribute.
 // * aViewportLength: length of the corresponding dimension of the viewport.
 // * aSelf: the outermost <svg> node itself.
 // NOTE: aSelf is not an ancestor viewport element, so it can't be used to
 // resolve percentage lengths. (It can only be used to resolve
 // 'em'/'ex'-valued units).
 inline float
--- a/content/svg/content/src/nsSVGSVGElement.h
+++ b/content/svg/content/src/nsSVGSVGElement.h
@@ -161,16 +161,18 @@ public:
   float GetPreviousScale() { return mPreviousScale; }
 
   nsSMILTimeContainer* GetTimedDocumentRoot();
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 
+  virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
+
   // nsSVGElement specializations:
   virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
                       TransformTypes aWhich = eAllTransforms) const;
   virtual bool HasValidDimensions() const;
  
   // nsSVGSVGElement methods:
   float GetLength(uint8_t mCtxType);
 
@@ -250,17 +252,16 @@ public:
   }
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
 
 private:
   // nsSVGElement overrides
-  bool IsEventName(nsIAtom* aName);
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep, bool aNullParent);
 
   // implementation helpers:
 
--- a/content/svg/content/src/nsSVGTSpanElement.cpp
+++ b/content/svg/content/src/nsSVGTSpanElement.cpp
@@ -40,20 +40,18 @@ public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
-protected:
 
-  // nsSVGElement overrides
-  virtual bool IsEventName(nsIAtom* aName);
+  virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
 };
 
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(TSpan)
 
 
 //----------------------------------------------------------------------
 // nsISupports methods
@@ -107,16 +105,19 @@ nsSVGTSpanElement::IsAttributeMapped(con
     sGraphicsMap,
     sTextContentElementsMap
   };
   
   return FindAttributeDependence(name, map) ||
     nsSVGTSpanElementBase::IsAttributeMapped(name);
 }
 
+
+bool
+nsSVGTSpanElement::IsEventAttributeName(nsIAtom* aName)
+{
+  return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
+}
+
 //----------------------------------------------------------------------
 // nsSVGElement overrides
 
-bool
-nsSVGTSpanElement::IsEventName(nsIAtom* aName)
-{
-  return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
-}
+// - no methods -
--- a/content/svg/content/src/nsSVGTextPathElement.cpp
+++ b/content/svg/content/src/nsSVGTextPathElement.cpp
@@ -123,25 +123,25 @@ nsSVGTextPathElement::IsAttributeMapped(
     sGraphicsMap,
     sTextContentElementsMap
   };
   
   return FindAttributeDependence(name, map) ||
     nsSVGTextPathElementBase::IsAttributeMapped(name);
 }
 
-//----------------------------------------------------------------------
-// nsSVGElement overrides
-
 bool
-nsSVGTextPathElement::IsEventName(nsIAtom* aName)
+nsSVGTextPathElement::IsEventAttributeName(nsIAtom* aName)
 {
   return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
 }
 
+//----------------------------------------------------------------------
+// nsSVGElement overrides
+
 nsSVGElement::LengthAttributesInfo
 nsSVGTextPathElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 nsSVGElement::EnumAttributesInfo
--- a/content/svg/content/src/nsSVGTextPathElement.h
+++ b/content/svg/content/src/nsSVGTextPathElement.h
@@ -53,23 +53,26 @@ public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+  virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
+
+
 protected:
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   virtual StringAttributesInfo GetStringInfo();
 
-  virtual bool IsEventName(nsIAtom* aName);
 
   enum { STARTOFFSET };
   nsSVGLength2 mLengthAttributes[1];
   static LengthInfo sLengthInfo[1];
 
   enum { METHOD, SPACING };
   nsSVGEnum mEnumAttributes[2];
   static nsSVGEnumMapping sMethodMap[];
--- a/content/xbl/src/nsXBLWindowKeyHandler.cpp
+++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp
@@ -421,17 +421,17 @@ nsXBLWindowKeyHandler::IsEditor()
   fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
   if (!focusedWindow)
     return false;
 
   nsCOMPtr<nsPIDOMWindow> piwin(do_QueryInterface(focusedWindow));
   nsIDocShell *docShell = piwin->GetDocShell();
   nsCOMPtr<nsIPresShell> presShell;
   if (docShell)
-    docShell->GetPresShell(getter_AddRefs(presShell));
+    presShell = docShell->GetPresShell();
 
   if (presShell) {
     return presShell->GetSelectionFlags() == nsISelectionDisplay::DISPLAY_ALL;
   }
 
   return false;
 }
 
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -1660,17 +1660,17 @@ nsXULElement::HideWindowChrome(bool aSho
     nsIPresShell *shell = doc->GetShell();
 
     if (shell) {
         nsIFrame* frame = GetPrimaryFrame();
 
         nsPresContext *presContext = shell->GetPresContext();
 
         if (frame && presContext && presContext->IsChrome()) {
-            nsIView* view = frame->GetClosestView();
+            nsView* view = frame->GetClosestView();
 
             if (view) {
                 nsIWidget* w = view->GetWidget();
                 NS_ENSURE_STATE(w);
                 w->HideWindowChrome(aShouldHide);
             }
         }
     }
@@ -1821,16 +1821,22 @@ nsXULElement::RecompileScriptEventListen
         }
 
         nsAutoString value;
         GetAttr(kNameSpaceID_None, attr, value);
         SetEventHandler(attr, value, true);
     }
 }
 
+bool
+nsXULElement::IsEventAttributeName(nsIAtom *aName)
+{
+  return nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL);
+}
+
 NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_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) {
         static_cast<nsXULPrototypeScript*>(tmp)->UnlinkJSObjects();
@@ -2221,16 +2227,32 @@ nsXULPrototypeElement::SetAttrAt(uint32_
 void
 nsXULPrototypeElement::Unlink()
 {
     mNumAttributes = 0;
     delete[] mAttributes;
     mAttributes = nullptr;
 }
 
+void
+nsXULPrototypeElement::TraceAllScripts(JSTracer* aTrc)
+{
+    for (uint32_t i = 0; i < mChildren.Length(); ++i) {
+        nsXULPrototypeNode* child = mChildren[i];
+        if (child->mType == nsXULPrototypeNode::eType_Element) {
+            static_cast<nsXULPrototypeElement*>(child)->TraceAllScripts(aTrc);
+        } else if (child->mType == nsXULPrototypeNode::eType_Script) {
+            JSScript* script = static_cast<nsXULPrototypeScript*>(child)->GetScriptObject();
+            if (script) {
+                JS_CALL_SCRIPT_TRACER(aTrc, script, "active window XUL prototype script");
+            }
+        }
+    }
+}
+
 //----------------------------------------------------------------------
 //
 // nsXULPrototypeScript
 //
 
 nsXULPrototypeScript::nsXULPrototypeScript(uint32_t aLineNo, uint32_t aVersion)
     : nsXULPrototypeNode(eType_Script),
       mLineNo(aLineNo),
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -181,16 +181,19 @@ public:
                                  nsIScriptGlobalObject* aGlobal,
                                  nsIURI* aDocumentURI,
                                  const nsCOMArray<nsINodeInfo> *aNodeInfos);
 
     nsresult SetAttrAt(uint32_t aPos, const nsAString& aValue, nsIURI* aDocumentURI);
 
     void Unlink();
 
+    // Trace all scripts held by this element and its children.
+    void TraceAllScripts(JSTracer* aTrc);
+
     nsPrototypeArray         mChildren;
 
     nsCOMPtr<nsINodeInfo>    mNodeInfo;           // [OWNER]
 
     uint32_t                 mNumAttributes:29;
     uint32_t                 mHasIdAttribute:1;
     uint32_t                 mHasClassAttribute:1;
     uint32_t                 mHasStyleAttribute:1;
@@ -412,16 +415,19 @@ public:
     void SetXULBindingParent(nsIContent* aBindingParent)
     {
       mBindingParent = aBindingParent;
     }
 
     virtual nsXPCClassInfo* GetClassInfo();
 
     virtual nsIDOMNode* AsDOMNode() { return this; }
+
+    virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
+
 protected:
 
     // This can be removed if EnsureContentsGenerated dies.
     friend class nsNSElementTearoff;
 
     // Implementation methods
     nsresult EnsureContentsGenerated(void) const;
 
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -24,17 +24,17 @@
 #include "mozilla/Util.h"
 
 // Note the ALPHABETICAL ORDERING
 #include "nsXULDocument.h"
 
 #include "nsError.h"
 #include "nsIBoxObject.h"
 #include "nsIChromeRegistry.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIViewManager.h"
 #include "nsIContentViewer.h"
 #include "nsGUIEvent.h"
 #include "nsIDOMXULElement.h"
 #include "nsIRDFNode.h"
 #include "nsIRDFRemoteDataSource.h"
 #include "nsIRDFService.h"
 #include "nsIStreamListener.h"
@@ -244,22 +244,16 @@ nsXULDocument::~nsXULDocument()
                                     "intl.uidirection.", this);
 
     if (--gRefCnt == 0) {
         NS_IF_RELEASE(gRDFService);
 
         NS_IF_RELEASE(kNC_persist);
         NS_IF_RELEASE(kNC_attribute);
         NS_IF_RELEASE(kNC_value);
-
-        // Remove the current document here from the table in
-        // case the document did not make it past StartLayout in
-        // ResumeWalk. 
-        if (mDocumentURI)
-            nsXULPrototypeCache::GetInstance()->RemoveFromCacheSet(mDocumentURI);
     }
 }
 
 nsresult
 NS_NewXULDocument(nsIXULDocument** result)
 {
     NS_PRECONDITION(result != nullptr, "null ptr");
     if (! result)
@@ -2216,16 +2210,25 @@ nsXULDocument::ApplyPersistentAttributes
                                   wrapper,
                                   true);
         }
     }
 
     return NS_OK;
 }
 
+void
+nsXULDocument::TraceProtos(JSTracer* aTrc, uint32_t aGCNumber)
+{
+    uint32_t i, count = mPrototypes.Length();
+    for (i = 0; i < count; ++i) {
+        mPrototypes[i]->TraceProtos(aTrc, aGCNumber);
+    }
+}
+
 //----------------------------------------------------------------------
 //
 // nsXULDocument::ContextStack
 //
 
 nsXULDocument::ContextStack::ContextStack()
     : mTop(nullptr), mDepth(0)
 {
--- a/content/xul/document/src/nsXULDocument.h
+++ b/content/xul/document/src/nsXULDocument.h
@@ -35,18 +35,19 @@ class nsIObjectOutputStream;
 class nsIXULPrototypeScript;
 #else
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsXULElement.h"
 #endif
 #include "nsURIHashKey.h"
 #include "nsInterfaceHashtable.h"
- 
+
 struct JSObject;
+struct JSTracer;
 struct PRLogModuleInfo;
 
 class nsRefMapEntry : public nsStringHashKey
 {
 public:
   nsRefMapEntry(const nsAString& aKey) :
     nsStringHashKey(&aKey)
   {
@@ -173,16 +174,19 @@ public:
     MatchAttribute(nsIContent* aContent,
                    int32_t aNameSpaceID,
                    nsIAtom* aAttrName,
                    void* aData);
 
     NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULDocument, nsXMLDocument)
 
     virtual nsXPCClassInfo* GetClassInfo();
+
+    void TraceProtos(JSTracer* aTrc, uint32_t aGCNumber);
+
 protected:
     // Implementation methods
     friend nsresult
     NS_NewXULDocument(nsIXULDocument** aResult);
 
     nsresult Init(void);
     nsresult StartLayout(void);
 
--- a/content/xul/document/src/nsXULPrototypeCache.cpp
+++ b/content/xul/document/src/nsXULPrototypeCache.cpp
@@ -50,17 +50,16 @@ DisableXULCacheChangedCallback(const cha
     if (cache)
         cache->Flush();
 
     return 0;
 }
 
 //----------------------------------------------------------------------
 
-StartupCache*   nsXULPrototypeCache::gStartupCache = nullptr;
 nsXULPrototypeCache*  nsXULPrototypeCache::sInstance = nullptr;
 
 
 nsXULPrototypeCache::nsXULPrototypeCache()
 {
 }
 
 
@@ -100,22 +99,16 @@ nsXULPrototypeCache::GetInstance()
             obsSvc->AddObserver(p, "chrome-flush-caches", false);
             obsSvc->AddObserver(p, "startupcache-invalidate", false);
         }
 		
     }
     return sInstance;
 }
 
-/* static */ StartupCache*
-nsXULPrototypeCache::GetStartupCache()
-{
-    return gStartupCache;
-}
-
 //----------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsXULPrototypeCache::Observe(nsISupports* aSubject,
                              const char *aTopic,
                              const PRUnichar *aData)
 {
     if (!strcmp(aTopic, "chrome-flush-skin-caches")) {
@@ -158,17 +151,16 @@ nsXULPrototypeCache::GetPrototype(nsIURI
     rv = newProto->Read(ois);
     if (NS_SUCCEEDED(rv)) {
         rv = PutPrototype(newProto);
     } else {
         newProto = nullptr;
     }
     
     mInputStreamTable.Remove(aURI);
-    RemoveFromCacheSet(aURI);
     return newProto;
 }
 
 nsresult
 nsXULPrototypeCache::PutPrototype(nsXULPrototypeDocument* aDocument)
 {
     nsCOMPtr<nsIURI> uri = aDocument->GetURI();
     // Put() releases any old value and addrefs the new one
@@ -350,39 +342,23 @@ nsXULPrototypeCache::AbortCaching()
 
     // Clear the cache set
     mCacheURITable.Clear();
 }
 
 
 static const char kDisableXULDiskCachePref[] = "nglayout.debug.disable_xul_fastload";
 
-void
-nsXULPrototypeCache::RemoveFromCacheSet(nsIURI* aURI)
-{
-    mCacheURITable.Remove(aURI);
-}
-
 nsresult
 nsXULPrototypeCache::WritePrototype(nsXULPrototypeDocument* aPrototypeDocument)
 {
     nsresult rv = NS_OK, rv2 = NS_OK;
 
-    // We're here before the startupcache service has been initialized, probably because
-    // of the profile manager. Bail quietly, don't worry, we'll be back later.
-    if (!gStartupCache)
-        return NS_OK;
-
     nsCOMPtr<nsIURI> protoURI = aPrototypeDocument->GetURI();
 
-    // Remove this document from the cache table. We use the table's
-    // emptiness instead of a counter to decide when the caching process 
-    // has completed.
-    RemoveFromCacheSet(protoURI);
-
     nsCOMPtr<nsIObjectOutputStream> oos;
     rv = GetOutputStream(protoURI, getter_AddRefs(oos));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = aPrototypeDocument->Write(oos);
     NS_ENSURE_SUCCESS(rv, rv);
     FinishOutputStream(protoURI);
     return NS_FAILED(rv) ? rv : rv2;
@@ -394,21 +370,22 @@ nsXULPrototypeCache::GetInputStream(nsIU
     nsAutoCString spec(kXULCachePrefix);
     nsresult rv = PathifyURI(uri, spec);
     if (NS_FAILED(rv)) 
         return NS_ERROR_NOT_AVAILABLE;
     
     nsAutoArrayPtr<char> buf;
     uint32_t len;
     nsCOMPtr<nsIObjectInputStream> ois;
-    if (!gStartupCache)
+    StartupCache* sc = StartupCache::GetSingleton();
+    if (!sc)
         return NS_ERROR_NOT_AVAILABLE;
-    
-    rv = gStartupCache->GetBuffer(spec.get(), getter_Transfers(buf), &len);
-    if (NS_FAILED(rv)) 
+
+    rv = sc->GetBuffer(spec.get(), getter_Transfers(buf), &len);
+    if (NS_FAILED(rv))
         return NS_ERROR_NOT_AVAILABLE;
 
     rv = NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(ois));
     NS_ENSURE_SUCCESS(rv, rv);
     buf.forget();
 
     mInputStreamTable.Put(uri, ois);
     
@@ -445,41 +422,46 @@ nsXULPrototypeCache::GetOutputStream(nsI
     NS_ADDREF(*stream = objectOutput);
     return NS_OK;
 }
 
 nsresult
 nsXULPrototypeCache::FinishOutputStream(nsIURI* uri) 
 {
     nsresult rv;
-    if (!gStartupCache)
+    StartupCache* sc = StartupCache::GetSingleton();
+    if (!sc)
         return NS_ERROR_NOT_AVAILABLE;
-    
+
     nsCOMPtr<nsIStorageStream> storageStream;
     bool found = mOutputStreamTable.Get(uri, getter_AddRefs(storageStream));
     if (!found)
         return NS_ERROR_UNEXPECTED;
     nsCOMPtr<nsIOutputStream> outputStream
         = do_QueryInterface(storageStream);
     outputStream->Close();
     
     nsAutoArrayPtr<char> buf;
     uint32_t len;
     rv = NewBufferFromStorageStream(storageStream, getter_Transfers(buf), 
                                     &len);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsAutoCString spec(kXULCachePrefix);
-    rv = PathifyURI(uri, spec);
-    if (NS_FAILED(rv))
-        return NS_ERROR_NOT_AVAILABLE;
-    rv = gStartupCache->PutBuffer(spec.get(), buf, len);
-    if (NS_SUCCEEDED(rv))
-        mOutputStreamTable.Remove(uri);
-    
+    if (!mCacheURITable.GetEntry(uri)) {
+        nsAutoCString spec(kXULCachePrefix);
+        rv = PathifyURI(uri, spec);
+        if (NS_FAILED(rv))
+            return NS_ERROR_NOT_AVAILABLE;
+        rv = sc->PutBuffer(spec.get(), buf, len);
+        if (NS_SUCCEEDED(rv)) {
+            mOutputStreamTable.Remove(uri);
+            mCacheURITable.RemoveEntry(uri);
+        }
+    }
+
     return rv;
 }
 
 // We have data if we're in the middle of writing it or we already
 // have it in the cache.
 nsresult
 nsXULPrototypeCache::HasData(nsIURI* uri, bool* exists)
 {
@@ -490,29 +472,22 @@ nsXULPrototypeCache::HasData(nsIURI* uri
     nsAutoCString spec(kXULCachePrefix);
     nsresult rv = PathifyURI(uri, spec);
     if (NS_FAILED(rv)) {
         *exists = false;
         return NS_OK;
     }
     nsAutoArrayPtr<char> buf;
     uint32_t len;
-    if (gStartupCache)
-        rv = gStartupCache->GetBuffer(spec.get(), getter_Transfers(buf), 
-                                      &len);
+    StartupCache* sc = StartupCache::GetSingleton();
+    if (sc)
+        rv = sc->GetBuffer(spec.get(), getter_Transfers(buf), &len);
     else {
-        // We don't have everything we need to call BeginCaching and set up
-        // gStartupCache right now, but we just need to check the cache for 
-        // this URI.
-        StartupCache* sc = StartupCache::GetSingleton();
-        if (!sc) {
-            *exists = false;
-            return NS_OK;
-        }
-        rv = sc->GetBuffer(spec.get(), getter_Transfers(buf), &len);
+        *exists = false;
+        return NS_OK;
     }
     *exists = NS_SUCCEEDED(rv);
     return NS_OK;
 }
 
 static int
 CachePrefChangedCallback(const char* aPref, void* aClosure)
 {
@@ -535,31 +510,16 @@ nsXULPrototypeCache::BeginCaching(nsIURI
 {
     nsresult rv, tmp;
 
     nsAutoCString path;
     aURI->GetPath(path);
     if (!StringEndsWith(path, NS_LITERAL_CSTRING(".xul")))
         return NS_ERROR_NOT_AVAILABLE;
 
-    // Test gStartupCache to decide whether this is the first nsXULDocument
-    // participating in the serialization.  If gStartupCache is non-null, this document
-    // must not be first, but it can join the process.  Examples of
-    // multiple master documents participating include hiddenWindow.xul and
-    // navigator.xul on the Mac, and multiple-app-component (e.g., mailnews
-    // and browser) startup due to command-line arguments.
-    //
-    if (gStartupCache) {
-        mCacheURITable.Put(aURI, 1);
-
-        return NS_OK;
-    }
-
-    // Use a local to refer to the service till we're sure we succeeded, then
-    // commit to gStartupCache.
     StartupCache* startupCache = StartupCache::GetSingleton();
     if (!startupCache)
         return NS_ERROR_FAILURE;
 
     gDisableXULDiskCache =
         Preferences::GetBool(kDisableXULCachePref, gDisableXULDiskCache);
 
     Preferences::RegisterCallback(CachePrefChangedCallback,
@@ -672,19 +632,18 @@ nsXULPrototypeCache::BeginCaching(nsIURI
         if (NS_FAILED(rv)) {
             startupCache->InvalidateCache();
             return NS_ERROR_FAILURE;
         }
     }
 
     // Success!  Insert this URI into the mCacheURITable
     // and commit locals to globals.
-    mCacheURITable.Put(aURI, 1);
+    mCacheURITable.PutEntry(aURI);
 
-    gStartupCache = startupCache;
     return NS_OK;
 }
 
 static PLDHashOperator
 MarkXBLInCCGeneration(nsIURI* aKey, nsRefPtr<nsXBLDocumentInfo> &aDocInfo,
                       void* aClosure)
 {
     uint32_t* gen = static_cast<uint32_t*>(aClosure);
--- a/content/xul/document/src/nsXULPrototypeCache.h
+++ b/content/xul/document/src/nsXULPrototypeCache.h
@@ -86,38 +86,31 @@ public:
 
     /**
      * Store a style sheet in the cache. The key, style sheet's URI is obtained
      * from the style sheet itself.
      */
     nsresult PutStyleSheet(nsCSSStyleSheet* aStyleSheet);
 
     /**
-     * Remove a XUL document from the set of loading documents.
-     */
-    void RemoveFromCacheSet(nsIURI* aDocumentURI);
-
-    /**
      * Write the XUL prototype document to a cache file. The proto must be
      * fully loaded.
      */
     nsresult WritePrototype(nsXULPrototypeDocument* aPrototypeDocument);
 
     /**
      * This interface allows partial reads and writes from the buffers in the
      * startupCache.
      */
     nsresult GetInputStream(nsIURI* aURI, nsIObjectInputStream** objectInput);
     nsresult FinishInputStream(nsIURI* aURI);
     nsresult GetOutputStream(nsIURI* aURI, nsIObjectOutputStream** objectOutput);
     nsresult FinishOutputStream(nsIURI* aURI);
     nsresult HasData(nsIURI* aURI, bool* exists);
 
-    static mozilla::scache::StartupCache* GetStartupCache();
-
     static nsXULPrototypeCache* GetInstance();
 
     static void ReleaseGlobals()
     {
         NS_IF_RELEASE(sInstance);
     }
 
     void MarkInCCGeneration(uint32_t aGeneration);
@@ -133,22 +126,18 @@ protected:
     void FlushScripts();
     void FlushSkinFiles();
 
     nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument>  mPrototypeTable; // owns the prototypes
     nsRefPtrHashtable<nsURIHashKey,nsCSSStyleSheet>        mStyleSheetTable;
     nsDataHashtable<nsURIHashKey,CacheScriptEntry>         mScriptTable;
     nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo>  mXBLDocTable;
 
-    ///////////////////////////////////////////////////////////////////////////
-    // StartupCache
-    // this is really a hash set, with a dummy data parameter
-    nsDataHashtable<nsURIHashKey,uint32_t> mCacheURITable;
+    nsTHashtable<nsURIHashKey> mCacheURITable;
 
-    static mozilla::scache::StartupCache* gStartupCache;
     nsInterfaceHashtable<nsURIHashKey, nsIStorageStream> mOutputStreamTable;
     nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable;
  
     // Bootstrap caching service
     nsresult BeginCaching(nsIURI* aDocumentURI);
 };
 
 #endif // nsXULPrototypeCache_h__
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -122,17 +122,18 @@ JSClass nsXULPDGlobalObject::gSharedGlob
 //----------------------------------------------------------------------
 //
 // ctors, dtors, n' stuff
 //
 
 nsXULPrototypeDocument::nsXULPrototypeDocument()
     : mRoot(nullptr),
       mLoaded(false),
-      mCCGeneration(0)
+      mCCGeneration(0),
+      mGCNumber(0)
 {
     ++gRefCnt;
 }
 
 
 nsresult
 nsXULPrototypeDocument::Init()
 {
@@ -673,16 +674,28 @@ nsXULPrototypeDocument::NotifyLoadDone()
         rv = mPrototypeWaiters[i]->OnPrototypeLoadDone(true);
         if (NS_FAILED(rv)) break;
     }
     mPrototypeWaiters.Clear();
 
     return rv;
 }
 
+void
+nsXULPrototypeDocument::TraceProtos(JSTracer* aTrc, uint32_t aGCNumber)
+{
+  // Only trace the protos once per GC.
+  if (mGCNumber == aGCNumber) {
+    return;
+  }
+
+  mGCNumber = aGCNumber;
+  mRoot->TraceAllScripts(aTrc);
+}
+
 //----------------------------------------------------------------------
 //
 // nsIScriptGlobalObjectOwner methods
 //
 
 nsIScriptGlobalObject*
 nsXULPrototypeDocument::GetScriptGlobalObject()
 {
--- a/content/xul/document/src/nsXULPrototypeDocument.h
+++ b/content/xul/document/src/nsXULPrototypeDocument.h
@@ -17,16 +17,17 @@
 class nsIAtom;
 class nsIPrincipal;
 class nsIURI;
 class nsNodeInfoManager;
 class nsXULDocument;
 class nsXULPrototypeElement;
 class nsXULPrototypePI;
 class nsXULPDGlobalObject;
+struct JSTracer;
 
 /**
  * A "prototype" document that stores shared document information
  * for the XUL cache.
  * Among other things, stores the tree of nsXULPrototype*
  * objects, from which the real DOM tree is built later in
  * nsXULDocument::ResumeWalk.
  */
@@ -113,30 +114,33 @@ public:
     void MarkInCCGeneration(uint32_t aCCGeneration)
     {
         mCCGeneration = aCCGeneration;
     }
 
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULPrototypeDocument,
                                              nsIScriptGlobalObjectOwner)
 
+    void TraceProtos(JSTracer* aTrc, uint32_t aGCNumber);
+
 protected:
     nsCOMPtr<nsIURI> mURI;
     nsRefPtr<nsXULPrototypeElement> mRoot;
     nsTArray<nsRefPtr<nsXULPrototypePI> > mProcessingInstructions;
     nsCOMArray<nsIURI> mStyleSheetReferences;
 
     nsRefPtr<nsXULPDGlobalObject> mGlobalObject;
 
     bool mLoaded;
     nsTArray< nsRefPtr<nsXULDocument> > mPrototypeWaiters;
 
     nsRefPtr<nsNodeInfoManager> mNodeInfoManager;
 
     uint32_t mCCGeneration;
+    uint32_t mGCNumber;
 
     nsXULPrototypeDocument();
     virtual ~nsXULPrototypeDocument();
     nsresult Init();
 
     friend NS_IMETHODIMP
     NS_NewXULPrototypeDocument(nsXULPrototypeDocument** aResult);
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -60,17 +60,17 @@
 #include "nsXPCOMCID.h"
 #include "nsISeekableStream.h"
 #include "nsAutoPtr.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsIAppShell.h"
 #include "nsWidgetsCID.h"
 #include "nsDOMJSUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIViewManager.h"
 #include "nsIScriptChannel.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsITimedChannel.h"
 #include "nsIPrivacyTransitionObserver.h"
 #include "nsCPrefetchService.h"
 #include "nsJSON.h"
 #include "IHistory.h"
@@ -213,16 +213,23 @@ using namespace mozilla::dom;
 static int32_t gNumberOfDocumentsLoading = 0;
 
 // Global count of existing docshells.
 static int32_t gDocShellCount = 0;
 
 // Global count of docshells with the private attribute set
 static uint32_t gNumberOfPrivateDocShells = 0;
 
+// Global count of private docshells which will always remain open
+#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
+static const uint32_t kNumberOfAlwaysOpenPrivateDocShells = 1; // the private hidden window
+#else
+static const uint32_t kNumberOfAlwaysOpenPrivateDocShells = 0;
+#endif
+
 // Global reference to the URI fixup service.
 nsIURIFixup *nsDocShell::sURIFixup = 0;
 
 // True means we validate window targets to prevent frameset
 // spoofing. Initialize this to a non-bolean value so we know to check
 // the pref on the creation of the first docshell.
 static uint32_t gValidateOrigin = 0xffffffff;
 
@@ -680,31 +687,31 @@ ConvertLoadTypeToNavigationType(uint32_t
 }
 
 static nsISHEntry* GetRootSHEntry(nsISHEntry *entry);
 
 static void
 IncreasePrivateDocShellCount()
 {
     gNumberOfPrivateDocShells++;
-    if (gNumberOfPrivateDocShells > 1 ||
+    if (gNumberOfPrivateDocShells > kNumberOfAlwaysOpenPrivateDocShells + 1 ||
         XRE_GetProcessType() != GeckoProcessType_Content) {
         return;
     }
 
     mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
     cc->SendPrivateDocShellsExist(true);
 }
 
 static void
 DecreasePrivateDocShellCount()
 {
     MOZ_ASSERT(gNumberOfPrivateDocShells > 0);
     gNumberOfPrivateDocShells--;
-    if (!gNumberOfPrivateDocShells)
+    if (gNumberOfPrivateDocShells == kNumberOfAlwaysOpenPrivateDocShells)
     {
         if (XRE_GetProcessType() == GeckoProcessType_Content) {
             mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
             cc->SendPrivateDocShellsExist(false);
             return;
         }
 
         nsCOMPtr<nsIObserverService> obsvc = mozilla::services::GetObserverService();
@@ -1032,19 +1039,18 @@ NS_IMETHODIMP nsDocShell::GetInterface(c
     }
     else if (aIID.Equals(NS_GET_IID(nsIClipboardDragDropHookList)) 
             && NS_SUCCEEDED(EnsureTransferableHookData())) {
         *aSink = mTransferableHookData;
         NS_ADDREF((nsISupports *)*aSink);
         return NS_OK;
     }
     else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay))) {
-      nsCOMPtr<nsIPresShell> shell;
-      nsresult rv = GetPresShell(getter_AddRefs(shell));
-      if (NS_SUCCEEDED(rv) && shell)
+      nsIPresShell* shell = GetPresShell();
+      if (shell)
         return shell->QueryInterface(aIID,aSink);    
     }
     else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner))) {
       nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
       nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
       if (NS_SUCCEEDED(rv) && treeOwner)
         return treeOwner->QueryInterface(aIID, aSink);
     }
@@ -1728,32 +1734,22 @@ nsDocShell::GetPresContext(nsPresContext
     *aPresContext = nullptr;
 
     if (!mContentViewer)
       return NS_OK;
 
     return mContentViewer->GetPresContext(aPresContext);
 }
 
-NS_IMETHODIMP
-nsDocShell::GetPresShell(nsIPresShell ** aPresShell)
-{
-    nsresult rv = NS_OK;
-
-    NS_ENSURE_ARG_POINTER(aPresShell);
-    *aPresShell = nullptr;
-
+NS_IMETHODIMP_(nsIPresShell*)
+nsDocShell::GetPresShell()
+{
     nsRefPtr<nsPresContext> presContext;
     (void) GetPresContext(getter_AddRefs(presContext));
-
-    if (presContext) {
-        NS_IF_ADDREF(*aPresShell = presContext->GetPresShell());
-    }
-
-    return rv;
+    return presContext ? presContext->GetPresShell() : nullptr;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetEldestPresShell(nsIPresShell** aPresShell)
 {
     nsresult rv = NS_OK;
 
     NS_ENSURE_ARG_POINTER(aPresShell);
@@ -1864,18 +1860,17 @@ nsDocShell::SetCurrentURI(nsIURI *aURI, 
 }
 
 NS_IMETHODIMP
 nsDocShell::GetCharset(char** aCharset)
 {
     NS_ENSURE_ARG_POINTER(aCharset);
     *aCharset = nullptr; 
 
-    nsCOMPtr<nsIPresShell> presShell;
-    GetPresShell(getter_AddRefs(presShell));
+    nsIPresShell* presShell = GetPresShell();
     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
     nsIDocument *doc = presShell->GetDocument();
     NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
     *aCharset = ToNewCString(doc->GetDocumentCharacterSet());
     if (!*aCharset) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
@@ -3241,18 +3236,17 @@ PrintDocTree(nsIDocShellTreeItem * aPare
 {
   for (int32_t i=0;i<aLevel;i++) printf("  ");
 
   int32_t childWebshellCount;
   aParentNode->GetChildCount(&childWebshellCount);
   nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(aParentNode));
   int32_t type;
   aParentNode->GetItemType(&type);
-  nsCOMPtr<nsIPresShell> presShell;
-  parentAsDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = parentAsDocShell->GetPresShell();
   nsRefPtr<nsPresContext> presContext;
   parentAsDocShell->GetPresContext(getter_AddRefs(presContext));
   nsIDocument *doc = presShell->GetDocument();
 
   nsCOMPtr<nsIDOMWindow> domwin(doc->GetWindow());
 
   nsCOMPtr<nsIWidget> widget;
   nsIViewManager* vm = presShell->GetViewManager();
@@ -5046,18 +5040,17 @@ nsDocShell::DoGetPositionAndSize(int32_t
         *cx = mBounds.width;
     if (cy)
         *cy = mBounds.height;
 }
 
 NS_IMETHODIMP
 nsDocShell::Repaint(bool aForce)
 {
-    nsCOMPtr<nsIPresShell> presShell;
-    GetPresShell(getter_AddRefs(presShell));
+    nsCOMPtr<nsIPresShell> presShell =GetPresShell();
     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
     nsIViewManager* viewManager = presShell->GetViewManager();
     NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE);
 
     NS_ENSURE_SUCCESS(viewManager->InvalidateAllViews(), NS_ERROR_FAILURE);
     return NS_OK;
 }
@@ -5112,47 +5105,45 @@ nsDocShell::GetVisibility(bool * aVisibi
 {
     NS_ENSURE_ARG_POINTER(aVisibility);
 
     *aVisibility = false;
 
     if (!mContentViewer)
         return NS_OK;
 
-    nsCOMPtr<nsIPresShell> presShell;
-    GetPresShell(getter_AddRefs(presShell));
+    nsCOMPtr<nsIPresShell> presShell = GetPresShell();
     if (!presShell)
         return NS_OK;
 
     // get the view manager
     nsIViewManager* vm = presShell->GetViewManager();
     NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
 
     // get the root view
-    nsIView *view = vm->GetRootView(); // views are not ref counted
+    nsView *view = vm->GetRootView(); // views are not ref counted
     NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
 
     // if our root view is hidden, we are not visible
     if (view->GetVisibility() == nsViewVisibility_kHide)
         return NS_OK;
 
     // otherwise, we must walk up the document and view trees checking
     // for a hidden view, unless we're an off screen browser, which 
     // would make this test meaningless.
 
     nsCOMPtr<nsIDocShellTreeItem> treeItem = this;
     nsCOMPtr<nsIDocShellTreeItem> parentItem;
     treeItem->GetParent(getter_AddRefs(parentItem));
     while (parentItem) {
         nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(treeItem));
-        docShell->GetPresShell(getter_AddRefs(presShell));
+        presShell = docShell->GetPresShell();
 
         nsCOMPtr<nsIDocShell> parentDS = do_QueryInterface(parentItem);
-        nsCOMPtr<nsIPresShell> pPresShell;
-        parentDS->GetPresShell(getter_AddRefs(pPresShell));
+        nsCOMPtr<nsIPresShell> pPresShell = parentDS->GetPresShell();
 
         // Null-check for crash in bug 267804
         if (!pPresShell) {
             NS_NOTREACHED("parent docshell has null pres shell");
             return NS_OK;
         }
 
         nsIContent *shellContent =
@@ -5203,18 +5194,17 @@ nsDocShell::SetIsActive(bool aIsActive)
   // We disallow setting active on chrome docshells.
   if (mItemType == nsIDocShellTreeItem::typeChrome)
     return NS_ERROR_INVALID_ARG;
 
   // Keep track ourselves.
   mIsActive = aIsActive;
 
   // Tell the PresShell about it.
-  nsCOMPtr<nsIPresShell> pshell;
-  GetPresShell(getter_AddRefs(pshell));
+  nsCOMPtr<nsIPresShell> pshell = GetPresShell();
   if (pshell)
     pshell->SetIsActive(aIsActive);
 
   // Tell the window about it
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mScriptGlobal);
   if (win) {
       win->SetIsBackground(!aIsActive);
       nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
@@ -7388,25 +7378,24 @@ nsDocShell::RestoreFromHistory()
             previousViewer->Destroy();
         }
     }
 
     // Save off the root view's parent and sibling so that we can insert the
     // new content viewer's root view at the same position.  Also save the
     // bounds of the root view's widget.
 
-    nsIView *rootViewSibling = nullptr, *rootViewParent = nullptr;
+    nsView *rootViewSibling = nullptr, *rootViewParent = nullptr;
     nsIntRect newBounds(0, 0, 0, 0);
 
-    nsCOMPtr<nsIPresShell> oldPresShell;
-    nsDocShell::GetPresShell(getter_AddRefs(oldPresShell));
+    nsCOMPtr<nsIPresShell> oldPresShell = GetPresShell();
     if (oldPresShell) {
         nsIViewManager *vm = oldPresShell->GetViewManager();
         if (vm) {
-            nsIView *oldRootView = vm->GetRootView();
+            nsView *oldRootView = vm->GetRootView();
 
             if (oldRootView) {
                 rootViewSibling = oldRootView->GetNextSibling();
                 rootViewParent = oldRootView->GetParent();
 
                 mContentViewer->GetBounds(newBounds);
             }
         }
@@ -7613,21 +7602,20 @@ nsDocShell::RestoreFromHistory()
         childShell->SetAllowSubframes(allowSubframes);
         childShell->SetAllowImages(allowImages);
         childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
 
         rv = childShell->BeginRestore(nullptr, false);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
-    nsCOMPtr<nsIPresShell> shell;
-    nsDocShell::GetPresShell(getter_AddRefs(shell));
+    nsCOMPtr<nsIPresShell> shell = GetPresShell();
 
     nsIViewManager *newVM = shell ? shell->GetViewManager() : nullptr;
-    nsIView *newRootView = newVM ? newVM->GetRootView() : nullptr;
+    nsView *newRootView = newVM ? newVM->GetRootView() : nullptr;
 
     // Insert the new root view at the correct location in the view tree.
     if (container) {
         nsSubDocumentFrame* subDocFrame = do_QueryFrame(container->GetPrimaryFrame());
         rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
     }
     if (sibling &&
         sibling->GetShell() &&
@@ -7894,18 +7882,17 @@ nsDocShell::CreateContentViewer(const ch
     mSavedRefreshURIList = nullptr;
     mSavingOldViewer = false;
     mEODForCurrentDocument = false;
 
     // if this document is part of a multipart document,
     // the ID can be used to distinguish it from the other parts.
     nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(request));
     if (multiPartChannel) {
-      nsCOMPtr<nsIPresShell> shell;
-      rv = GetPresShell(getter_AddRefs(shell));
+      nsCOMPtr<nsIPresShell> shell = GetPresShell();
       if (NS_SUCCEEDED(rv) && shell) {
         nsIDocument *doc = shell->GetDocument();
         if (doc) {
           uint32_t partID;
           multiPartChannel->GetPartID(&partID);
           doc->SetPartID(partID);
         }
       }
@@ -9600,22 +9587,21 @@ nsresult nsDocShell::DoChannelLoad(nsICh
 nsresult
 nsDocShell::ScrollToAnchor(nsACString & aCurHash, nsACString & aNewHash,
                            uint32_t aLoadType)
 {
     if (!mCurrentURI) {
         return NS_OK;
     }
 
-    nsCOMPtr<nsIPresShell> shell;
-    nsresult rv = GetPresShell(getter_AddRefs(shell));
-    if (NS_FAILED(rv) || !shell) {
+    nsCOMPtr<nsIPresShell> shell = GetPresShell();
+    if (!shell) {
         // If we failed to get the shell, or if there is no shell,
         // nothing left to do here.
-        return rv;
+        return NS_OK;
     }
 
     // If we have no new anchor, we do not want to scroll, unless there is a
     // current anchor and we are doing a history load.  So return if we have no
     // new anchor, and there is no current anchor or the load is not a history
     // load.
     if ((aCurHash.IsEmpty() || aLoadType != LOAD_HISTORY) &&
         aNewHash.IsEmpty()) {
@@ -9647,17 +9633,17 @@ nsDocShell::ScrollToAnchor(nsACString & 
         // spec:
         // http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.1
 
         // We try the UTF-8 string first, and then try the document's
         // charset (see below).  If the string is not UTF-8,
         // conversion will fail and give us an empty Unicode string.
         // In that case, we should just fall through to using the
         // page's charset.
-        rv = NS_ERROR_FAILURE;
+        nsresult rv = NS_ERROR_FAILURE;
         NS_ConvertUTF8toUTF16 uStr(str);
         if (!uStr.IsEmpty()) {
             rv = shell->GoToAnchor(NS_ConvertUTF8toUTF16(str), scroll);
         }
         nsMemory::Free(str);
 
         // Above will fail if the anchor name is not UTF-8.  Need to
         // convert from document charset to unicode.
@@ -10630,19 +10616,18 @@ NS_IMETHODIMP nsDocShell::GetShouldSaveL
     return NS_OK;
 }
 
 NS_IMETHODIMP nsDocShell::PersistLayoutHistoryState()
 {
     nsresult  rv = NS_OK;
     
     if (mOSHE) {
-        nsCOMPtr<nsIPresShell> shell;
-        rv = GetPresShell(getter_AddRefs(shell));
-        if (NS_SUCCEEDED(rv) && shell) {
+        nsCOMPtr<nsIPresShell> shell = GetPresShell();
+        if (shell) {
             nsCOMPtr<nsILayoutHistoryState> layoutState;
             rv = shell->CaptureHistoryState(getter_AddRefs(layoutState));
         }
     }
 
     return rv;
 }
 
@@ -11278,18 +11263,17 @@ nsDocShell::GetChildOffset(nsIDOMNode * 
     }
 
     return NS_ERROR_FAILURE;
 }
 
 nsIScrollableFrame *
 nsDocShell::GetRootScrollFrame()
 {
-    nsCOMPtr<nsIPresShell> shell;
-    NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(shell)), nullptr);
+    nsCOMPtr<nsIPresShell> shell = GetPresShell();
     NS_ENSURE_TRUE(shell, nullptr);
 
     return shell->GetRootScrollFrameAsScrollableExternal();
 }
 
 NS_IMETHODIMP
 nsDocShell::EnsureScriptEnvironment()
 {
--- a/docshell/base/nsIContentViewer.idl
+++ b/docshell/base/nsIContentViewer.idl
@@ -10,26 +10,26 @@ interface nsIPrintSettings;
 
 
 %{ C++
 class nsIWidget;
 class nsIDocument;
 struct nsIntRect;
 class nsIPresShell;
 class nsPresContext;
-class nsIView;
+class nsView;
 class nsDOMNavigationTiming;
 %}
 
 [ptr] native nsIWidgetPtr(nsIWidget);
 [ptr] native nsIDocumentPtr(nsIDocument);
 [ref] native nsIntRectRef(nsIntRect);
 [ptr] native nsIPresShellPtr(nsIPresShell);
 [ptr] native nsPresContextPtr(nsPresContext);
-[ptr] native nsIViewPtr(nsIView);
+[ptr] native nsViewPtr(nsView);
 [ptr] native nsDOMNavigationTimingPtr(nsDOMNavigationTiming);
 
 [scriptable, builtinclass, uuid(b9d92b8b-5623-4079-ae11-36bb341f322e)]
 interface nsIContentViewer : nsISupports
 {
 
   [noscript] void init(in nsIWidgetPtr aParentWidget,
                        [const] in nsIntRectRef aBounds);
@@ -166,14 +166,14 @@ interface nsIContentViewer : nsISupports
   [noscript] void setDocumentInternal(in nsIDocumentPtr aDocument,
                                       in boolean aForceReuseInnerWindow);
   /**
    * Find the view to use as the container view for MakeWindow. Returns
    * null if this will be the root of a view manager hierarchy. In that
    * case, if mParentWidget is null then this document should not even
    * be displayed.
    */
-  [noscript,notxpcom,nostdcall] nsIViewPtr findContainerView();
+  [noscript,notxpcom,nostdcall] nsViewPtr findContainerView();
   /**
    * Set collector for navigation timing data (load, unload events).
    */
   [noscript,notxpcom,nostdcall] void setNavigationTiming(in nsDOMNavigationTimingPtr aTiming);
 };
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -34,17 +34,17 @@ interface nsISHEntry;
 interface nsILayoutHistoryState;
 interface nsISecureBrowserUI;
 interface nsIDOMStorage;
 interface nsIPrincipal;
 interface nsIWebBrowserPrint;
 interface nsIVariant;
 interface nsIPrivacyTransitionObserver;
 
-[scriptable, builtinclass, uuid(ed04b29f-ae9a-460a-858e-960b523bb3a5)]
+[scriptable, builtinclass, uuid(008f5c86-b915-458c-aaf1-78de3b484e68)]
 interface nsIDocShell : nsISupports
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -181,17 +181,17 @@ interface nsIDocShell : nsISupports
   /**
    * Presentation context for the currently loaded document.  This may be null.
    */
   [noscript] readonly attribute nsPresContext presContext;
 
   /**
    * Presentation shell for the currently loaded document.  This may be null.
    */
-  [noscript] readonly attribute nsIPresShell presShell;
+  [noscript,notxpcom] nsIPresShell GetPresShell();
 
   /**
    * Presentation shell for the oldest document, if this docshell is
    * currently transitioning between documents.
    */
   [noscript] readonly attribute nsIPresShell eldestPresShell;
 
   /**
--- a/dom/apps/src/OfflineCacheInstaller.jsm
+++ b/dom/apps/src/OfflineCacheInstaller.jsm
@@ -16,16 +16,18 @@ Cu.import("resource://gre/modules/AppsUt
 Cu.import("resource://gre/modules/NetUtil.jsm");
 
 let Namespace = CC('@mozilla.org/network/application-cache-namespace;1',
                    'nsIApplicationCacheNamespace',
                    'init');
 let makeFile = CC('@mozilla.org/file/local;1',
                 'nsIFile',
                 'initWithPath');
+let MutableArray = CC('@mozilla.org/array;1', 'nsIMutableArray');
+
 const nsICache = Ci.nsICache;
 const nsIApplicationCache = Ci.nsIApplicationCache;
 const applicationCacheService =
   Cc['@mozilla.org/network/application-cache-service;1']
     .getService(Ci.nsIApplicationCacheService);
 
 
 function debug(aMsg) {
@@ -93,82 +95,167 @@ function readFile(aFile, aCallback) {
     converter.charset = "UTF-8";
 
     let data = NetUtil.readInputStreamToString(aStream,
                                                aStream.available());
     aCallback(converter.ConvertToUnicode(data));
   });
 }
 
-this.OfflineCacheInstaller = {
-  installCache: function installCache(app) {
-    let cacheDir = makeFile(app.basePath)
-    cacheDir.append(app.appId);
-    cacheDir.append("cache");
-    if (!cacheDir.exists())
-      return;
+function parseCacheLine(app, urls, line) {
+  // Prepend webapp origin in case of absolute path
+  if (line[0] == '/') {
+    urls.push(app.origin + line.substring(1));
+  // Just pass along the url, if we have one
+  } else if (line.substr(0, 4) == 'http') {
+    urls.push(line);
+  } else {
+    throw new Error('Only accept absolute path and http/https URLs');
+  }
+}
+
+function parseFallbackLine(app, namespaces, fallbacks, line) {
+  let split = line.split(/[ \t]+/);
+  if (split.length != 2) {
+    throw new Error('Should be made of two URLs seperated with spaces')
+  }
+  let type = Ci.nsIApplicationCacheNamespace.NAMESPACE_FALLBACK;
+  let [ namespace, fallback ] = split;
+
+  // Prepend webapp origin in case of absolute path
+  if (namespace[0] == '/')
+    namespace = app.origin + namespace.substring(1);
+  if (fallback[0] == '/')
+    fallback = app.origin + fallback.substring(1);
+
+  namespaces.push([type, namespace, fallback]);
+  fallbacks.push(fallback);
+}
 
-    let cacheManifest = cacheDir.clone();
-    cacheManifest.append("manifest.appcache");
-    if (!cacheManifest.exists())
-      return;
+function parseNetworkLine(namespaces, line) {
+  let type = Ci.nsIApplicationCacheNamespace.NAMESPACE_BYPASS;
+  if (line[0] == '*' && (line.length == 1 || line[1] == ' '
+                                          || line[1] == '\t')) {
+    namespaces.push([type, '', '']);
+  } else {
+    namespaces.push([type, namespace, '']);
+  }
+}
 
-    enableOfflineCacheForApp(app.origin, app.localId);
+function parseAppCache(app, path, content) {
+  let lines = content.split(/\r?\n/);
+
+  let urls = [];
+  let namespaces = [];
+  let fallbacks = [];
 
-    // Get the url for the manifest.
-    let appcacheURL = app.origin + "cache/manifest.appcache";
+  let currentSection = 'CACHE';
+  for (let i = 0; i < lines.length; i++) {
+    let line = lines[i];
+
+    // Ignore comments
+    if (/^#/.test(line) || !line.length)
+      continue;
 
-    // The group ID contains application id and 'f' for not being hosted in
-    // a browser element, but a mozbrowser iframe.
-    // See netwerk/cache/nsDiskCacheDeviceSQL.cpp: AppendJARIdentifier
-    let groupID = appcacheURL + '#' + app.localId+ '+f';
-    let applicationCache = applicationCacheService.createApplicationCache(groupID);
-    applicationCache.activate();
+    // Process section headers
+    if (line == 'CACHE MANIFEST')
+      continue;
+    if (line == 'CACHE:') {
+      currentSection = 'CACHE';
+      continue;
+    } else if (line == 'NETWORK:') {
+      currentSection = 'NETWORK';
+      continue;
+    } else if (line == 'FALLBACK:') {
+      currentSection = 'FALLBACK';
+      continue;
+    }
 
-    readFile(cacheManifest, function (content) {
-      let lines = content.split(/\r?\n/);
-      // Process each manifest line, read only CACHE entries
-      // (ignore NETWORK entries) and compute absolute URL for each entry
-      let urls = [];
-      for(let i = 0; i < lines.length; i++) {
-        let line = lines[i];
-        // Ignore comments
-        if (/^#/.test(line) || !line.length)
-          continue;
-        if (line == 'CACHE MANIFEST')
-          continue;
-        if (line == 'CACHE:')
-          continue;
-        // Ignore network entries and everything that comes after
-        if (line == 'NETWORK:')
-          break;
+    // Process cache, network and fallback rules
+    try {
+      if (currentSection == 'CACHE') {
+        parseCacheLine(app, urls, line);
+      } else if (currentSection == 'NETWORK') {
+        parseNetworkLine(namespaces, line);
+      } else if (currentSection == 'FALLBACK') {
+        parseFallbackLine(app, namespaces, fallbacks, line);
+      }
+    } catch(e) {
+      throw new Error('Invalid ' + currentSection + ' line in appcache ' +
+                      'manifest:\n' + e.message +
+                      '\nFrom: ' + path +
+                      '\nLine ' + i + ': ' + line);
+    }
+  }
+
+  return {
+    urls: urls,
+    namespaces: namespaces,
+    fallbacks: fallbacks
+  };
+}
+
+function installCache(app) {
+  let cacheDir = makeFile(app.basePath)
+  cacheDir.append(app.appId);
+  cacheDir.append('cache');
+  if (!cacheDir.exists())
+    return;
+
+  let cacheManifest = cacheDir.clone();
+  cacheManifest.append('manifest.appcache');
+  if (!cacheManifest.exists())
+    return;
+
+  enableOfflineCacheForApp(app.origin, app.localId);
+
+  // Get the url for the manifest.
+  let appcacheURL = app.origin + 'cache/manifest.appcache';
 
-        // Prepend webapp origin in case of absolute path
-        if (line[0] == '/') {
-          urls.push(app.origin + line.substring(1));
-        // Just pass along the url, if we have one
-        } else if (line.substr(0, 4) == 'http') {
-          urls.push(line);
-        } else {
-          throw new Error('Invalid line in appcache manifest:\n' + line +
-                          '\nFrom: ' + cacheManifest.path);
-        }
+  // The group ID contains application id and 'f' for not being hosted in
+  // a browser element, but a mozbrowser iframe.
+  // See netwerk/cache/nsDiskCacheDeviceSQL.cpp: AppendJARIdentifier
+  let groupID = appcacheURL + '#' + app.localId+ '+f';
+  let applicationCache = applicationCacheService.createApplicationCache(groupID);
+  applicationCache.activate();
+
+  readFile(cacheManifest, function readAppCache(content) {
+    let entries = parseAppCache(app, cacheManifest.path, content);
+
+    entries.urls.forEach(function processCachedFile(url) {
+      // Get this nsIFile from cache folder for this URL
+      let path = url.replace(/https?:\/\//, '');
+      let file = cacheDir.clone();
+      let paths = path.split('/');
+      paths.forEach(file.append);
+
+      if (!file.exists()) {
+        let msg = 'File ' + file.path + ' exists in the manifest but does ' +
+                  'not points to a real file.';
+        throw new Error(msg);
       }
-      urls.forEach(function processCachedFile(url) {
-        // Get this nsIFile from cache folder for this URL
-        let path = url.replace(/https?:\/\//, '');
-        let file = cacheDir.clone();
-        let paths = path.split('/');
-        paths.forEach(file.append);
+
+      let itemType = nsIApplicationCache.ITEM_EXPLICIT;
+      storeCache(applicationCache, url, file, itemType);
+    });
+
+    let array = new MutableArray();
+    entries.namespaces.forEach(function processNamespace([type, spec, data]) {
+      debug('add namespace: ' + type + ' - ' + spec + ' - ' + data + '\n');
+      array.appendElement(new Namespace(type, spec, data), false);
+    });
+    applicationCache.addNamespaces(array);
 
-        if (!file.exists()) {
-          let msg = 'File ' + file.path + ' exists in the manifest but does ' +
-                    'not points to a real file.';
-          throw new Error(msg);
-        }
+    entries.fallbacks.forEach(function processFallback(url) {
+      debug('add fallback: ' + url + '\n');
+      let type = nsIApplicationCache.ITEM_FALLBACK;
+      applicationCache.markEntry(url, type);
+    });
+  });
+}
 
-        let itemType = nsIApplicationCache.ITEM_EXPLICIT;
-        storeCache(applicationCache, url, file, itemType);
-      });
-    });
-  }
+
+// Public API
+
+this.OfflineCacheInstaller = {
+  installCache: installCache
 };
 
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -128,16 +128,17 @@ AudioChannelService::UnregisterType(Audi
       isNoChannelUsed = false;
       break;
     }
   }
 
   if (isNoChannelUsed) {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     obs->NotifyObservers(nullptr, "audio-channel-changed", NS_LITERAL_STRING("default").get());
+    mCurrentHigherChannel = AUDIO_CHANNEL_NORMAL;
     return;
   }
 
   // In order to avoid race conditions, it's safer to notify any existing
   // agent any time a new one is registered.
   Notify();
 }
 
@@ -146,20 +147,33 @@ AudioChannelService::GetMuted(AudioChann
 {
   // We are not visible, maybe we have to mute:
   if (aElementHidden) {
     switch (aType) {
       case AUDIO_CHANNEL_NORMAL:
         return true;
 
       case AUDIO_CHANNEL_CONTENT:
-        // TODO: this should work per apps
-        if (mChannelCounters[AUDIO_CHANNEL_CONTENT].Length() > 1)
-          return true;
+      {
+        // If we have more than 1 using the content channel,
+        // this must be muted.
+        uint32_t childId = CONTENT_PARENT_UNKNOWN_CHILD_ID;
+        bool empty = true;
+        for (uint32_t i = 0;
+             i < mChannelCounters[AUDIO_CHANNEL_CONTENT].Length();
+             ++i) {
+          if (empty) {
+            childId = mChannelCounters[AUDIO_CHANNEL_CONTENT][i];
+            empty = false;
+          }
+          else if (childId != mChannelCounters[AUDIO_CHANNEL_CONTENT][i])
+            return true;
+        }
         break;
+      }
 
       case AUDIO_CHANNEL_NOTIFICATION:
       case AUDIO_CHANNEL_ALARM:
       case AUDIO_CHANNEL_TELEPHONY:
       case AUDIO_CHANNEL_RINGER:
       case AUDIO_CHANNEL_PUBLICNOTIFICATION:
         // Nothing to do
         break;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -435,16 +435,17 @@
 #include "mozilla/dom/indexedDB/IDBEvents.h"
 #include "mozilla/dom/indexedDB/IDBObjectStore.h"
 #include "mozilla/dom/indexedDB/IDBTransaction.h"
 #include "mozilla/dom/indexedDB/IDBCursor.h"
 #include "mozilla/dom/indexedDB/IDBKeyRange.h"
 #include "mozilla/dom/indexedDB/IDBIndex.h"
 
 using mozilla::dom::indexedDB::IDBWrapperCache;
+using mozilla::dom::workers::ResolveWorkerClasses;
 
 #include "nsIDOMMediaQueryList.h"
 
 #include "nsDOMTouchEvent.h"
 
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 
@@ -453,16 +454,17 @@ using mozilla::dom::indexedDB::IDBWrappe
 #include "nsIDOMPowerManager.h"
 #include "nsIDOMWakeLock.h"
 #include "nsIDOMSmsManager.h"
 #include "nsIDOMSmsMessage.h"
 #include "nsIDOMSmsEvent.h"
 #include "nsIDOMSmsRequest.h"
 #include "nsIDOMSmsFilter.h"
 #include "nsIDOMSmsCursor.h"
+#include "nsIDOMSmsSegmentInfo.h"
 #include "nsIDOMConnection.h"
 #ifdef MOZ_B2G_RIL
 #include "nsIDOMMobileConnection.h"
 #endif
 #include "USSDReceivedEvent.h"
 #include "DataErrorEvent.h"
 #include "mozilla/dom/network/Utils.h"
 
@@ -1367,16 +1369,19 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozSmsFilter, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozSmsCursor, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
+  NS_DEFINE_CLASSINFO_DATA(MozSmsSegmentInfo, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
   NS_DEFINE_CLASSINFO_DATA(MozConnection, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
 #ifdef MOZ_B2G_RIL
   NS_DEFINE_CLASSINFO_DATA(MozMobileConnection, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozCellBroadcast, nsDOMGenericSH,
@@ -2628,16 +2633,17 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLIFrameElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMGetSVGDocument)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozBrowserFrame)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLImageElement, nsIDOMHTMLImageElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLImageElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIImageLoadingContent)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLInputElement, nsIDOMHTMLInputElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLInputElement)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
@@ -3673,16 +3679,20 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(MozSmsFilter, nsIDOMMozSmsFilter)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsFilter)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozSmsCursor, nsIDOMMozSmsCursor)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsCursor)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(MozSmsSegmentInfo, nsIDOMMozSmsSegmentInfo)
+     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsSegmentInfo)
+  DOM_CLASSINFO_MAP_END
+
   DOM_CLASSINFO_MAP_BEGIN(MozConnection, nsIDOMMozConnection)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozConnection)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
 #ifdef MOZ_B2G_RIL
   DOM_CLASSINFO_MAP_BEGIN(MozMobileConnection, nsIDOMMozMobileConnection)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileConnection)
@@ -5164,23 +5174,16 @@ nsWindowSH::GetProperty(nsIXPConnectWrap
         // Yup, *vp is a window object, return early (*vp is already
         // the window, so no need to wrap it again).
 
         return NS_SUCCESS_I_DID_SOMETHING;
       }
     }
   }
 
-  if (id == sWrappedJSObject_id &&
-      xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
-    obj = JS_ObjectToOuterObject(cx, obj);
-    *vp = OBJECT_TO_JSVAL(obj);
-    return NS_SUCCESS_I_DID_SOMETHING;
-  }
-
   return NS_OK;
 }
 
 struct ResolveGlobalNameClosure
 {
   JSContext* cx;
   JSObject* obj;
   bool* retval;
@@ -6553,20 +6556,16 @@ ContentWindowGetter(JSContext *cx, unsig
 {
   JSObject *obj = JS_THIS_OBJECT(cx, vp);
   if (!obj)
     return JS_FALSE;
 
   return ::JS_GetProperty(cx, obj, "content", vp);
 }
 
-static JSNewResolveOp sOtherResolveFuncs[] = {
-  mozilla::dom::workers::ResolveWorkerClasses
-};
-
 template<class Interface>
 static nsresult
 LocationSetterGuts(JSContext *cx, JSObject *obj, jsval *vp)
 {
   // This function duplicates some of the logic in XPC_WN_HelperSetProperty
   XPCWrappedNative *wrapper =
     XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
 
@@ -6741,25 +6740,24 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
 
   if (!my_context || !my_context->IsContextInitialized()) {
     // The context is not yet initialized so there's nothing we can do
     // here yet.
 
     return NS_OK;
   }
 
-  nsresult rv = NS_OK;
   if (sLocation_id == id) {
     // This must be done even if we're just getting the value of
     // window.location (i.e. no checking flags & JSRESOLVE_ASSIGNING
     // here) since we must define window.location to prevent the
     // getter from being overriden (for security reasons).
 
     nsCOMPtr<nsIDOMLocation> location;
-    rv = win->GetLocation(getter_AddRefs(location));
+    nsresult rv = win->GetLocation(getter_AddRefs(location));
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Make sure we wrap the location object in the window's scope.
     JSObject *scope = nullptr;
     wrapper->GetJSObject(&scope);
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     jsval v;
@@ -6778,17 +6776,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
 
     *objp = obj;
 
     return NS_OK;
   }
 
   if (sTop_id == id) {
     nsCOMPtr<nsIDOMWindow> top;
-    rv = win->GetScriptableTop(getter_AddRefs(top));
+    nsresult rv = win->GetScriptableTop(getter_AddRefs(top));
     NS_ENSURE_SUCCESS(rv, rv);
 
     jsval v;
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     rv = WrapNative(cx, obj, top, &NS_GET_IID(nsIDOMWindow), true,
                     &v, getter_AddRefs(holder));
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -6828,19 +6826,19 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
         // on the wrapper so that ::NewResolve() doesn't get called
         // again for this property name.
 
         JSObject *wrapperObj;
         wrapper->GetJSObject(&wrapperObj);
 
         jsval v;
         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-        rv = WrapNative(cx, wrapperObj, child_win,
-                        &NS_GET_IID(nsIDOMWindow), true, &v,
-                        getter_AddRefs(holder));
+        nsresult rv = WrapNative(cx, wrapperObj, child_win,
+                                 &NS_GET_IID(nsIDOMWindow), true, &v,
+                                 getter_AddRefs(holder));
         NS_ENSURE_SUCCESS(rv, rv);
 
         JSAutoRequest ar(cx);
 
         bool ok = JS_WrapValue(cx, &v) &&
                     JS_DefinePropertyById(cx, obj, id, v, nullptr, nullptr, 0);
         if (!ok) {
           return NS_ERROR_FAILURE;
@@ -6848,48 +6846,38 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
 
         *objp = obj;
 
         return NS_OK;
       }
     }
   }
 
-  // It is not worth calling GlobalResolve() if we are resolving
-  // for assignment, since only read-write properties get dealt
-  // with there.
-  if (!(flags & JSRESOLVE_ASSIGNING)) {
-    JSAutoRequest ar(cx);
-
-    // Resolve special classes.
-    for (uint32_t i = 0; i < ArrayLength(sOtherResolveFuncs); i++) {
-      js::RootedObject tmp(cx, *objp);
-      if (!sOtherResolveFuncs[i](cx, obj, id, flags, &tmp)) {
-        return NS_ERROR_FAILURE;
-      }
-      *objp = tmp;
-      if (*objp) {
-        return NS_OK;
-      }
-    }
-
-    // Call GlobalResolve() after we call FindChildWithName() so
-    // that named child frames will override external properties
-    // which have been registered with the script namespace manager.
-
-    bool did_resolve = false;
-    rv = GlobalResolve(win, cx, obj, id, &did_resolve);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (did_resolve) {
-      // GlobalResolve() resolved something, so we're done here.
-      *objp = obj;
-
-      return NS_OK;
-    }
+  // Handle resolving if id refers to a name resolved by DOM worker code.
+  js::RootedObject tmp(cx, NULL);
+  if (!ResolveWorkerClasses(cx, obj, id, flags, &tmp)) {
+    return NS_ERROR_FAILURE;
+  }
+  if (tmp) {
+    *objp = tmp;
+    return NS_OK;
+  }
+
+  // Check for names managed by the script namespace manager.  Call
+  // GlobalResolve() after we call FindChildWithName() so that named child
+  // frames will override external properties which have been registered with
+  // the script namespace manager -- pages must be able to depend on frame
+  // names working no matter how Gecko's been configured.
+  bool did_resolve = false;
+  nsresult rv = GlobalResolve(win, cx, obj, id, &did_resolve);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (did_resolve) {
+    *objp = obj;
+    return NS_OK;
   }
 
   if (s_content_id == id) {
     // Map window._content to window.content for backwards
     // compatibility, this should spit out an message on the JS
     // console.
 
     JSObject *windowObj = win->GetGlobalJSObject();
@@ -6999,21 +6987,20 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
 
         *objp = obj;
       }
 
       return NS_OK;
     }
   }
 
-  JSObject *oldobj = *objp;
   rv = nsDOMGenericSH::NewResolve(wrapper, cx, obj, id, flags, objp,
                                   _retval);
 
-  if (NS_FAILED(rv) || *objp != oldobj) {
+  if (NS_FAILED(rv) || *objp) {
     // Something went wrong, or the property got resolved. Return.
     return rv;
   }
 
   // Make a fast expando if we're assigning to (not declaring or
   // binding a name) a new undefined property that's not already
   // defined on our prototype chain. This way we can access this
   // expando w/o ever getting back into XPConnect.
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -339,16 +339,17 @@ DOMCI_CLASS(MozPowerManager)
 DOMCI_CLASS(MozWakeLock)
 
 DOMCI_CLASS(MozSmsManager)
 DOMCI_CLASS(MozSmsMessage)
 DOMCI_CLASS(MozSmsEvent)
 DOMCI_CLASS(MozSmsRequest)
 DOMCI_CLASS(MozSmsFilter)
 DOMCI_CLASS(MozSmsCursor)
+DOMCI_CLASS(MozSmsSegmentInfo)
 
 DOMCI_CLASS(MozConnection)
 #ifdef MOZ_B2G_RIL
 DOMCI_CLASS(MozMobileConnection)
 DOMCI_CLASS(MozCellBroadcast)
 #endif
 
 DOMCI_CLASS(USSDReceivedEvent)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -103,19 +103,17 @@ nsDOMWindowUtils::GetPresShell()
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   if (!window)
     return nullptr;
 
   nsIDocShell *docShell = window->GetDocShell();
   if (!docShell)
     return nullptr;
 
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
-  return presShell;
+  return docShell->GetPresShell();
 }
 
 nsPresContext*
 nsDOMWindowUtils::GetPresContext()
 {
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   if (!window)
     return nullptr;
@@ -661,17 +659,17 @@ nsDOMWindowUtils::SendMouseEventCommon(c
   nsEventStatus status;
   if (aToWindow) {
     nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
     if (!presShell)
       return NS_ERROR_FAILURE;
     nsIViewManager* viewManager = presShell->GetViewManager();
     if (!viewManager)
       return NS_ERROR_FAILURE;
-    nsIView* view = viewManager->GetRootView();
+    nsView* view = viewManager->GetRootView();
     if (!view)
       return NS_ERROR_FAILURE;
 
     status = nsEventStatus_eIgnore;
     return presShell->HandleEvent(view->GetFrame(), &event, false, &status);
   }
   return widget->DispatchEvent(&event, status);
 }
@@ -1050,18 +1048,17 @@ nsDOMWindowUtils::ForceUpdateNativeMenuA
 
 nsIWidget*
 nsDOMWindowUtils::GetWidget(nsPoint* aOffset)
 {
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   if (window) {
     nsIDocShell *docShell = window->GetDocShell();
     if (docShell) {
-      nsCOMPtr<nsIPresShell> presShell;
-      docShell->GetPresShell(getter_AddRefs(presShell));
+      nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
       if (presShell) {
         nsIFrame* frame = presShell->GetRootFrame();
         if (frame)
           return frame->GetView()->GetNearestWidget(aOffset);
       }
     }
   }
 
@@ -1369,18 +1366,17 @@ nsDOMWindowUtils::DisableNonTestMouseEve
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
   nsIDocShell *docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
   presShell->DisableNonTestMouseEvents(aDisable);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SuppressEventHandling(bool aSuppress)
 {
@@ -1760,18 +1756,17 @@ nsDOMWindowUtils::SendQueryContentEvent(
   }
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
   nsIDocShell *docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
   nsPresContext* presContext = presShell->GetPresContext();
   NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
 
   // get the widget to send the event to
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
@@ -2156,47 +2151,60 @@ nsDOMWindowUtils::StartFrameTimeRecordin
     return NS_ERROR_FAILURE;
 
   mgr->StartFrameTimeRecording();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMWindowUtils::StopFrameTimeRecording(uint32_t *frameCount, float **frames)
+nsDOMWindowUtils::StopFrameTimeRecording(float** paintTimes, uint32_t *frameCount, float **frameIntervals)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   NS_ENSURE_ARG_POINTER(frameCount);
-  NS_ENSURE_ARG_POINTER(frames);
+  NS_ENSURE_ARG_POINTER(frameIntervals);
+  NS_ENSURE_ARG_POINTER(paintTimes);
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   LayerManager *mgr = widget->GetLayerManager();
   if (!mgr)
     return NS_ERROR_FAILURE;
 
-  nsTArray<float> frameTimes;
-  mgr->StopFrameTimeRecording(frameTimes);
-
-  *frames = nullptr;
-  *frameCount = frameTimes.Length();
+  nsTArray<float> tmpFrameIntervals;
+  nsTArray<float> tmpPaintTimes;
+  mgr->StopFrameTimeRecording(tmpFrameIntervals, tmpPaintTimes);
+
+  *frameIntervals = nullptr;
+  *paintTimes = nullptr;
+  *frameCount = tmpFrameIntervals.Length();
 
   if (*frameCount != 0) {
-    *frames = (float*)nsMemory::Alloc(*frameCount * sizeof(float*));
-    if (!*frames)
+    *frameIntervals = (float*)nsMemory::Alloc(*frameCount * sizeof(float*));
+    if (!*frameIntervals)
+      return NS_ERROR_OUT_OF_MEMORY;
+
+    *paintTimes = (float*)nsMemory::Alloc(*frameCount * sizeof(float*));
+    if (!*paintTimes)
       return NS_ERROR_OUT_OF_MEMORY;
 
-    /* copy over the frame times into the array we just allocated */
+    /* copy over the frame intervals and paint times into the arrays we just allocated */
     for (uint32_t i = 0; i < *frameCount; i++) {
-      (*frames)[i] = frameTimes[i];
+      (*frameIntervals)[i] = tmpFrameIntervals[i];
+#ifndef ANDROID
+      (*paintTimes)[i] = tmpPaintTimes[i];
+#else
+      // Waiting for bug 785597 to work on android.
+      (*paintTimes)[i] = 0;
+#endif
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::BeginTabSwitch()
@@ -2809,18 +2817,17 @@ nsDOMWindowUtils::GetPaintingSuppressed(
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
   nsIDocShell *docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
   *aPaintingSuppressed = presShell->IsPaintingSuppressed();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetPlugins(JSContext* cx, jsval* aPlugins)
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -613,18 +613,17 @@ nsFocusManager::MoveCaretToFocus(nsIDOMW
         editorDocShell->GetEditable(&isEditable);
         if (isEditable)
           return NS_OK;
       }
 
       nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(dsti);
       NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
-      nsCOMPtr<nsIPresShell> presShell;
-      docShell->GetPresShell(getter_AddRefs(presShell));
+      nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
       NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
       nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
       nsCOMPtr<nsIContent> content = window->GetFocusedNode();
       if (content)
         MoveCaretToFocus(presShell, content);
     }
   }
@@ -711,18 +710,17 @@ nsFocusManager::WindowRaised(nsIDOMWindo
     GetFocusedDescendant(window, true, getter_AddRefs(currentWindow));
 
   NS_ASSERTION(currentWindow, "window raised with no window current");
   if (!currentWindow)
     return NS_OK;
 
   nsCOMPtr<nsIDocShell> currentDocShell = currentWindow->GetDocShell();
 
-  nsCOMPtr<nsIPresShell> presShell;
-  currentDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = currentDocShell->GetPresShell();
   if (presShell) {
     // disable selection mousedown state on activation
     // XXXndeakin P3 not sure if this is necessary, but it doesn't hurt
     nsRefPtr<nsFrameSelection> frameSelection = presShell->FrameSelection();
     frameSelection->SetMouseDownState(false);
   }
 
   Focus(currentWindow, currentFocus, 0, true, false, true, true);
@@ -922,18 +920,17 @@ nsFocusManager::WindowHidden(nsIDOMWindo
 
   // at this point, we know that the window being hidden is either the focused
   // window, or an ancestor of the focused window. Either way, the focus is no
   // longer valid, so it needs to be updated.
 
   nsCOMPtr<nsIContent> oldFocusedContent = mFocusedContent.forget();
 
   nsCOMPtr<nsIDocShell> focusedDocShell = mFocusedWindow->GetDocShell();
-  nsCOMPtr<nsIPresShell> presShell;
-  focusedDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = focusedDocShell->GetPresShell();
 
   if (oldFocusedContent && oldFocusedContent->IsInDoc()) {
     NotifyFocusStateChange(oldFocusedContent,
                            mFocusedWindow->ShouldShowFocusRing(),
                            false);
     window->UpdateCommands(NS_LITERAL_STRING("focus"));
 
     if (presShell) {
@@ -1051,18 +1048,17 @@ nsFocusManager::EnsureCurrentWidgetFocus
 {
   if (!mFocusedWindow || sTestMode)
     return;
 
   // get the main child widget for the focused window and ensure that the
   // platform knows that this widget is focused.
   nsCOMPtr<nsIDocShell> docShell = mFocusedWindow->GetDocShell();
   if (docShell) {
-    nsCOMPtr<nsIPresShell> presShell;
-    docShell->GetPresShell(getter_AddRefs(presShell));
+    nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
     if (presShell) {
       nsIViewManager* vm = presShell->GetViewManager();
       if (vm) {
         nsCOMPtr<nsIWidget> widget;
         vm->GetRootWidget(getter_AddRefs(widget));
         if (widget)
           widget->SetFocus(false);
       }
@@ -1257,18 +1253,17 @@ nsFocusManager::SetFocusInner(nsIContent
 
     // set the focus node and method as needed
     uint32_t focusMethod = aFocusChanged ? aFlags & FOCUSMETHODANDRING_MASK :
                            newWindow->GetFocusMethod() | (aFlags & FLAG_SHOWRING);
     newWindow->SetFocusedNode(contentToFocus, focusMethod);
     if (aFocusChanged) {
       nsCOMPtr<nsIDocShell> docShell = newWindow->GetDocShell();
 
-      nsCOMPtr<nsIPresShell> presShell;
-      docShell->GetPresShell(getter_AddRefs(presShell));
+      nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
       if (presShell)
         ScrollIntoView(presShell, contentToFocus, aFlags);
     }
 
     // update the commands even when inactive so that the attributes for that
     // window are up to date.
     if (allowFrameSwitch)
       newWindow->UpdateCommands(NS_LITERAL_STRING("focus"));
@@ -1508,18 +1503,17 @@ nsFocusManager::Blur(nsPIDOMWindow* aWin
   nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
   if (!docShell) {
     mFocusedContent = nullptr;
     return true;
   }
 
   // Keep a ref to presShell since dispatching the DOM event may cause
   // the document to be destroyed.
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   if (!presShell) {
     mFocusedContent = nullptr;
     return true;
   }
 
   bool clearFirstBlurEvent = false;
   if (!mFirstBlurEvent) {
     mFirstBlurEvent = content;
@@ -1659,18 +1653,17 @@ nsFocusManager::Focus(nsPIDOMWindow* aWi
     return;
 
   // Keep a reference to the presShell since dispatching the DOM event may
   // cause the document to be destroyed.
   nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
   if (!docShell)
     return;
 
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   if (!presShell)
     return;
 
   // If the focus actually changed, set the focus method (mouse, keyboard, etc).
   // Otherwise, just get the current focus method and use that. This ensures
   // that the method is set during the document and window focus events.
   uint32_t focusMethod = aFocusChanged ? aFlags & FOCUSMETHODANDRING_MASK :
                          aWindow->GetFocusMethod() | (aFlags & FLAG_SHOWRING);
@@ -1972,18 +1965,17 @@ nsFocusManager::RaiseWindow(nsPIDOMWindo
   GetFocusedDescendant(aWindow, true, getter_AddRefs(childWindow));
   if (!childWindow)
     childWindow = aWindow;
 
   nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
   if (!docShell)
     return;
 
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   if (!presShell)
     return;
 
   nsIViewManager* vm = presShell->GetViewManager();
   if (vm) {
     nsCOMPtr<nsIWidget> widget;
     vm->GetRootWidget(getter_AddRefs(widget));
     if (widget)
@@ -2021,18 +2013,17 @@ nsFocusManager::UpdateCaret(bool aMoveCa
   int32_t itemType;
   dsti->GetItemType(&itemType);
   if (itemType == nsIDocShellTreeItem::typeChrome)
     return;  // Never browse with caret in chrome
 
   bool browseWithCaret =
     Preferences::GetBool("accessibility.browsewithcaret");
 
-  nsCOMPtr<nsIPresShell> presShell;
-  focusedDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = focusedDocShell->GetPresShell();
   if (!presShell)
     return;
 
   // If this is an editable document which isn't contentEditable, or a
   // contentEditable document and the node to focus is contentEditable,
   // return, so that we don't mess with caret visibility.
   bool isEditable = false;
   nsCOMPtr<nsIEditorDocShell> editorDocShell(do_QueryInterface(dsti));
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -112,17 +112,17 @@
 #include "nsILoadContext.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIPresShell.h"
 #include "nsIProgrammingLanguage.h"
 #include "nsIServiceManager.h"
 #include "nsIScriptGlobalObjectOwner.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollableFrame.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIViewManager.h"
 #include "nsISelectionController.h"
 #include "nsISelection.h"
 #include "nsIPrompt.h"
 #include "nsIPromptService.h"
 #include "nsIPromptFactory.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsIWebNavigation.h"
@@ -221,16 +221,23 @@
 #include "nsWrapperCacheInlines.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIAppsService.h"
 #include "prrng.h"
 #include "nsSandboxFlags.h"
 #include "TimeChangeObserver.h"
 #include "nsPISocketTransportService.h"
 #include "mozilla/dom/AudioContext.h"
+#include "mozilla/dom/FunctionBinding.h"
+
+// Apple system headers seem to have a check() macro.  <sigh>
+#ifdef check
+#undef check
+#endif // check
+#include "AccessCheck.h"
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDOMLeakPRLog;
 #endif
@@ -520,18 +527,20 @@ nsPIDOMWindow::~nsPIDOMWindow() {}
 class nsOuterWindowProxy : public js::Wrapper
 {
 public:
   nsOuterWindowProxy() : js::Wrapper(0) { setSafeToUnwrap(false); }
 
   virtual bool isOuterWindow() {
     return true;
   }
-  JSString *obj_toString(JSContext *cx, JSObject *wrapper);
-  void finalize(JSFreeOp *fop, JSObject *proxy);
+  virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
+  virtual void finalize(JSFreeOp *fop, JSObject *proxy) MOZ_OVERRIDE;
+  virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver,
+                   jsid id, js::Value *vp) MOZ_OVERRIDE;
 
   static nsOuterWindowProxy singleton;
 };
 
 
 JSString *
 nsOuterWindowProxy::obj_toString(JSContext *cx, JSObject *proxy)
 {
@@ -547,16 +556,29 @@ nsOuterWindowProxy::finalize(JSFreeOp *f
     static_cast<nsISupports*>(js::GetProxyExtra(proxy, 0).toPrivate());
   if (global) {
     nsWrapperCache *cache;
     CallQueryInterface(global, &cache);
     cache->ClearWrapper();
   }
 }
 
+bool
+nsOuterWindowProxy::get(JSContext *cx, JSObject *wrapper, JSObject *receiver,
+                        jsid id, js::Value *vp)
+{
+  if (id == nsDOMClassInfo::sWrappedJSObject_id &&
+      xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
+    *vp = JS::ObjectValue(*wrapper);
+    return true;
+  }
+
+  return js::Wrapper::get(cx, wrapper, receiver, id, vp);
+}
+
 nsOuterWindowProxy
 nsOuterWindowProxy::singleton;
 
 class nsChromeOuterWindowProxy : public nsOuterWindowProxy
 {
 public:
   nsChromeOuterWindowProxy() : nsOuterWindowProxy() {}
 
@@ -1360,18 +1382,22 @@ nsGlobalWindow::IsBlackForCC()
 
 void
 nsGlobalWindow::UnmarkGrayTimers()
 {
   for (nsTimeout* timeout = mTimeouts.getFirst();
        timeout;
        timeout = timeout->getNext()) {
     if (timeout->mScriptHandler) {
-      JSObject* o = timeout->mScriptHandler->GetScriptObject();
-      xpc_UnmarkGrayObject(o);
+      Function* f = timeout->mScriptHandler->GetCallback();
+      if (f) {
+        // Callable() already does xpc_UnmarkGrayObject.
+        DebugOnly<JSObject*> o = f->Callable();
+        MOZ_ASSERT(!xpc_IsGrayGCThing(o), "Should have been unmarked");
+      }
     }
   }
 }
 
 //*****************************************************************************
 // nsGlobalWindow::nsIScriptGlobalObject
 //*****************************************************************************
 
@@ -1515,18 +1541,17 @@ nsGlobalWindow::SetInitialPrincipalToSub
                  NS_IsAboutBlank(mDoc->GetDocumentURI()),
                  "Unexpected original document");
 #endif
   }
 
   GetDocShell()->CreateAboutBlankContentViewer(newWindowPrincipal);
   mDoc->SetIsInitialDocument(true);
 
-  nsCOMPtr<nsIPresShell> shell;
-  GetDocShell()->GetPresShell(getter_AddRefs(shell));
+  nsCOMPtr<nsIPresShell> shell = GetDocShell()->GetPresShell();
 
   if (shell && !shell->DidInitialize()) {
     // Ensure that if someone plays with this document they will get
     // layout happening.
     nsRect r = shell->GetPresContext()->GetVisibleArea();
     shell->Initialize(r.width, r.height);
   }
 }
@@ -3639,18 +3664,17 @@ nsGlobalWindow::SetInnerWidth(int32_t aI
   if (!CanMoveResizeWindows() || IsFrame()) {
     return NS_OK;
   }
 
   NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aInnerWidth, nullptr),
                     NS_ERROR_FAILURE);
 
 
-  nsRefPtr<nsIPresShell> presShell;
-  mDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsRefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
   if (presShell && presShell->GetIsViewportOverridden())
   {
     nscoord height = 0;
     nscoord width  = 0;
 
     nsRefPtr<nsPresContext> presContext;
     presContext = presShell->GetPresContext();
@@ -3706,18 +3730,17 @@ nsGlobalWindow::SetInnerHeight(int32_t a
    */
   if (!CanMoveResizeWindows() || IsFrame()) {
     return NS_OK;
   }
 
   NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(nullptr, &aInnerHeight),
                     NS_ERROR_FAILURE);
 
-  nsRefPtr<nsIPresShell> presShell;
-  mDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsRefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
   if (presShell && presShell->GetIsViewportOverridden())
   {
     nscoord height = 0;
     nscoord width  = 0;
 
     nsRefPtr<nsPresContext> presContext;
     presContext = presShell->GetPresContext();
@@ -3861,18 +3884,17 @@ nsGlobalWindow::GetInnerScreenRect()
     return nsRect();
 
   nsGlobalWindow* rootWindow =
     static_cast<nsGlobalWindow*>(GetPrivateRoot());
   if (rootWindow) {
     rootWindow->FlushPendingNotifications(Flush_Layout);
   }
 
-  nsCOMPtr<nsIPresShell> presShell;
-  mDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   if (!presShell)
     return nsRect();
   nsIFrame* rootFrame = presShell->GetRootFrame();
   if (!rootFrame)
     return nsRect();
 
   return rootFrame->GetScreenRectInAppUnits();
 }
@@ -3922,18 +3944,17 @@ nsGlobalWindow::GetMozPaintCount(uint64_
 {
   FORWARD_TO_OUTER(GetMozPaintCount, (aResult), NS_ERROR_NOT_INITIALIZED);
 
   *aResult = 0;
 
   if (!mDocShell)
     return NS_OK;
 
-  nsCOMPtr<nsIPresShell> presShell;
-  mDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   if (!presShell)
     return NS_OK;
 
   *aResult = presShell->GetPaintCount();
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -4462,18 +4483,17 @@ nsGlobalWindow::GetMainWidget()
   return widget;
 }
 
 nsIWidget*
 nsGlobalWindow::GetNearestWidget()
 {
   nsIDocShell* docShell = GetDocShell();
   NS_ENSURE_TRUE(docShell, nullptr);
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   NS_ENSURE_TRUE(presShell, nullptr);
   nsIFrame* rootFrame = presShell->GetRootFrame();
   NS_ENSURE_TRUE(rootFrame, nullptr);
   return rootFrame->GetView()->GetNearestWidget(nullptr);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::SetFullScreen(bool aFullScreen)
@@ -4650,18 +4670,17 @@ nsGlobalWindow::EnsureReflowFlushAndPain
   NS_ASSERTION(IsOuterWindow(), "EnsureReflowFlushAndPaint() must be called on"
                "the outer window");
   NS_ASSERTION(mDocShell, "EnsureReflowFlushAndPaint() called with no "
                "docshell!");
 
   if (!mDocShell)
     return;
 
-  nsCOMPtr<nsIPresShell> presShell;
-  mDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
   if (!presShell)
     return;
 
   // Flush pending reflows.
   if (mDoc) {
     mDoc->FlushPendingNotifications(Flush_Layout);
   }
@@ -7396,18 +7415,17 @@ nsGlobalWindow::GetSelection(nsISelectio
   FORWARD_TO_OUTER(GetSelection, (aSelection), NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_ARG_POINTER(aSelection);
   *aSelection = nullptr;
 
   if (!mDocShell)
     return NS_OK;
 
-  nsCOMPtr<nsIPresShell> presShell;
-  mDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
   if (!presShell)
     return NS_OK;
     
   *aSelection = presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
   
   NS_IF_ADDREF(*aSelection);
 
@@ -8226,18 +8244,17 @@ nsGlobalWindow::UpdateCanvasFocus(bool a
   nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell);
   if (editorDocShell) {
     bool editable;
     editorDocShell->GetEditable(&editable);
     if (editable)
       return;
   }
 
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   if (!presShell || !mDocument)
     return;
 
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
   Element *rootElement = doc->GetRootElement();
   if (rootElement) {
       if ((mHasFocus || aFocusChanged) &&
           (mFocusedNode == rootElement || aNewContent == rootElement)) {
@@ -8294,18 +8311,17 @@ nsGlobalWindow::GetComputedStyleHelper(n
   if (!aElt) {
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 
   if (!mDocShell) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIPresShell> presShell;
-  mDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
   if (!presShell) {
     // Try flushing frames on our parent in case there's a pending
     // style change that will create the presshell.
     nsGlobalWindow *parent =
       static_cast<nsGlobalWindow *>(GetPrivateParent());
     if (!parent) {
       return NS_OK;
@@ -8313,18 +8329,17 @@ nsGlobalWindow::GetComputedStyleHelper(n
 
     parent->FlushPendingNotifications(Flush_Frames);
 
     // Might have killed mDocShell
     if (!mDocShell) {
       return NS_OK;
     }
 
-    mDocShell->GetPresShell(getter_AddRefs(presShell));
-
+    presShell = mDocShell->GetPresShell();
     if (!presShell) {
       return NS_OK;
     }
   }
 
   nsCOMPtr<dom::Element> element = do_QueryInterface(aElt);
   NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
   nsRefPtr<nsComputedDOMStyle> compStyle =
@@ -9540,21 +9555,21 @@ nsGlobalWindow::SetTimeoutOrInterval(nsI
 
   nsRefPtr<nsTimeout> timeout = new nsTimeout();
   timeout->mIsInterval = aIsInterval;
   timeout->mInterval = interval;
   timeout->mScriptHandler = aHandler;
 
   // Now clamp the actual interval we will use for the timer based on
   uint32_t nestingLevel = sNestingLevel + 1;
-  int32_t realInterval = interval;
+  uint32_t realInterval = interval;
   if (aIsInterval || nestingLevel >= DOM_CLAMP_TIMEOUT_NESTING_LEVEL) {
     // Don't allow timeouts less than DOMMinTimeoutValue() from
     // now...
-    realInterval = NS_MAX(realInterval, DOMMinTimeoutValue());
+    realInterval = NS_MAX(realInterval, uint32_t(DOMMinTimeoutValue()));
   }
 
   // Get principal of currently executing code, save for execution of timeout.
   // If our principals subsume the subject principal then use the subject
   // principal. Otherwise, use our principal to avoid running script in
   // elevated principals.
 
   nsCOMPtr<nsIPrincipal> subjectPrincipal;
@@ -9720,44 +9735,43 @@ nsGlobalWindow::RunTimeoutHandler(nsTime
   bool trackNestingLevel = !timeout->mIsInterval;
   uint32_t nestingLevel;
   if (trackNestingLevel) {
     nestingLevel = sNestingLevel;
     sNestingLevel = timeout->mNestingLevel;
   }
 
   nsCOMPtr<nsIScriptTimeoutHandler> handler(timeout->mScriptHandler);
-  JSObject* scriptObject = handler->GetScriptObject();
-  if (!scriptObject) {
+  nsRefPtr<Function> callback = handler->GetCallback();
+  if (!callback) {
     // Evaluate the timeout expression.
     const PRUnichar* script = handler->GetHandlerText();
     NS_ASSERTION(script, "timeout has no script nor handler text!");
 
     const char* filename = nullptr;
     uint32_t lineNo = 0;
     handler->GetLocation(&filename, &lineNo);
 
     bool is_undefined;
     aScx->EvaluateString(nsDependentString(script), FastGetGlobalJSObject(),
                          timeout->mPrincipal, timeout->mPrincipal,
                          filename, lineNo, JSVERSION_DEFAULT, nullptr,
                          &is_undefined);
   } else {
-    nsCOMPtr<nsIVariant> dummy;
+    // Hold strong ref to ourselves while we call the callback.
     nsCOMPtr<nsISupports> me(static_cast<nsIDOMWindow *>(this));
-    aScx->CallEventHandler(me, FastGetGlobalJSObject(),
-                           scriptObject, handler->GetArgv(),
-                           // XXXmarkh - consider allowing CallEventHandler to
-                           // accept nullptr?
-                           getter_AddRefs(dummy));
-
-  }
-
-  // We ignore any failures from calling EvaluateString() or
-  // CallEventHandler() on the context here since we're in a loop
+    ErrorResult ignored;
+    // Need the .get() because the first argument is a template, and C++ can't
+    // decide between it being a ParentObject& and a void* if we pass in the
+    // nsCOMPtr.
+    callback->Call(me.get(), handler->GetArgs(), ignored);
+  }
+
+  // We ignore any failures from calling EvaluateString() on the context or
+  // Call() on a Function here since we're in a loop
   // where we're likely to be running timeouts whose OS timers
   // didn't fire in time and we don't want to not fire those timers
   // now just because execution of one timer failed. We can't
   // propagate the error to anyone who cares about it from this
   // point anyway, and the script context should have already reported
   // the script error in the usual way - so we just drop it.
 
   if (trackNestingLevel) {
@@ -10324,18 +10338,17 @@ nsIScrollableFrame *
 nsGlobalWindow::GetScrollFrame()
 {
   FORWARD_TO_OUTER(GetScrollFrame, (), nullptr);
 
   if (!mDocShell) {
     return nullptr;
   }
 
-  nsCOMPtr<nsIPresShell> presShell;
-  mDocShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   if (presShell) {
     return presShell->GetRootScrollFrameAsScrollable();
   }
   return nullptr;
 }
 
 nsresult
 nsGlobalWindow::BuildURIfromBase(const char *aURL, nsIURI **aBuiltURI,
@@ -11003,24 +11016,23 @@ nsGlobalChromeWindow::SetCursor(const ns
 
   nsRefPtr<nsPresContext> presContext;
   if (mDocShell) {
     mDocShell->GetPresContext(getter_AddRefs(presContext));
   }
 
   if (presContext) {
     // Need root widget.
-    nsCOMPtr<nsIPresShell> presShell;
-    mDocShell->GetPresShell(getter_AddRefs(presShell));
+    nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
     nsIViewManager* vm = presShell->GetViewManager();
     NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
 
-    nsIView* rootView = vm->GetRootView();
+    nsView* rootView = vm->GetRootView();
     NS_ENSURE_TRUE(rootView, NS_ERROR_FAILURE);
 
     nsIWidget* widget = rootView->GetNearestWidget(nullptr);
     NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
 
     // Call esm and set cursor.
     rv = presContext->EventStateManager()->SetCursor(cursor, nullptr,
                                                      false, 0.0f, 0.0f,
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -142,19 +142,19 @@ struct nsTimeout : mozilla::LinkedListEl
   nsTimeout();
   ~nsTimeout();
 
   NS_DECL_CYCLE_COLLECTION_LEGACY_NATIVE_CLASS(nsTimeout)
 
   nsrefcnt Release();
   nsrefcnt AddRef();
 
-  nsresult InitTimer(nsTimerCallbackFunc aFunc, uint64_t delay) {
-    return mTimer->InitWithFuncCallback(aFunc, this,
-                                        static_cast<uint32_t>(delay),
+  nsresult InitTimer(nsTimerCallbackFunc aFunc, uint32_t aDelay)
+  {
+    return mTimer->InitWithFuncCallback(aFunc, this, aDelay,
                                         nsITimer::TYPE_ONE_SHOT);
   }
 
   // Window for which this timeout fires
   nsRefPtr<nsGlobalWindow> mWindow;
 
   // The actual timer object
   nsCOMPtr<nsITimer> mTimer;
--- a/dom/base/nsGlobalWindowCommands.cpp
+++ b/dom/base/nsGlobalWindowCommands.cpp
@@ -168,17 +168,18 @@ nsresult
 nsSelectionCommandsBase::GetPresShellFromWindow(nsPIDOMWindow *aWindow, nsIPresShell **aPresShell)
 {
   *aPresShell = nullptr;
   NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE);
 
   nsIDocShell *docShell = aWindow->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
-  return docShell->GetPresShell(aPresShell);
+  NS_IF_ADDREF(*aPresShell = docShell->GetPresShell());
+  return NS_OK;
 }
 
 nsresult
 nsSelectionCommandsBase::GetSelectionControllerFromWindow(nsPIDOMWindow *aWindow, nsISelectionController **aSelCon)
 {
   *aSelCon = nullptr;
 
   nsCOMPtr<nsIPresShell> presShell;
@@ -357,18 +358,17 @@ nsClipboardCommand::DoCommand(const char
     return NS_OK;
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContext);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
   nsIDocShell *docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
   nsCopySupport::FireClipboardEvent(NS_COPY, presShell, nullptr);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsClipboardCommand::GetCommandStateParams(const char *aCommandName,
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -40,18 +40,18 @@ public:
 
   virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
                               NS_ISCRIPTCONTEXTPRINCIPAL_IID)
 
 #define NS_ISCRIPTCONTEXT_IID \
-{ 0x95870c91, 0xe21d, 0x4499, \
-  { 0x9b, 0x61, 0x45, 0x79, 0x5f, 0x12, 0x0c, 0x98 } }
+{ 0xa786f089, 0xafda, 0x4442, \
+ { 0xb9, 0xe3, 0x06, 0xc3, 0xb3, 0xf0, 0xda, 0x22 } }
 
 /* This MUST match JSVERSION_DEFAULT.  This version stuff if we don't
    know what language we have is a little silly... */
 #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
 
 /**
  * It is used by the application to initialize a runtime and run scripts.
  * A script runtime would implement this interface.
@@ -179,32 +179,16 @@ public:
                                        const nsAString& aBody,
                                        const char* aURL,
                                        uint32_t aLineNo,
                                        uint32_t aVersion,
                                        bool aIsXBL,
                                        nsScriptObjectHolder<JSObject>& aHandler) = 0;
 
   /**
-   * Call the function object with given args and return its boolean result,
-   * or true if the result isn't boolean.
-   *
-   * @param aTarget the event target
-   * @param aScript an object telling the scope in which to call the compiled
-   *        event handler function.
-   * @param aHandler function object (function and static scope) to invoke.
-   * @param argv array of arguments.  Note each element is assumed to
-   *        be an nsIVariant.
-   * @param rval out parameter returning result
-   **/
-  virtual nsresult CallEventHandler(nsISupports* aTarget,
-                                    JSObject* aScope, JSObject* aHandler,
-                                    nsIArray *argv, nsIVariant **rval) = 0;
-
-  /**
    * Bind an already-compiled event handler function to the given
    * target.  Scripting languages with static scoping must re-bind the
    * scope chain for aHandler to begin (after the activation scope for
    * aHandler itself, typically) with aTarget's scope.
    *
    * The result of the bind operation is a new handler object, with
    * principals now set and scope set as above.  This is returned in
    * aBoundHandler.  When this function is called, aBoundHandler is
--- a/dom/base/nsIScriptTimeoutHandler.h
+++ b/dom/base/nsIScriptTimeoutHandler.h
@@ -1,46 +1,53 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsIScriptTimeoutHandler_h___
 #define nsIScriptTimeoutHandler_h___
 
-class nsIArray;
+#include "nsTArray.h"
+
+namespace JS {
+class Value;
+} // namespace JS
+namespace mozilla {
+namespace dom {
+class Function;
+} // namespace dom
+} // namespace mozilla
 
 #define NS_ISCRIPTTIMEOUTHANDLER_IID \
-{ 0xcaf520a5, 0x8078, 0x4cba, \
-  { 0x8a, 0xb9, 0xb6, 0x8a, 0x12, 0x43, 0x4f, 0x05 } }
+{ 0x53c8e80e, 0xcc78, 0x48bc, \
+ { 0xba, 0x63, 0x0c, 0xb9, 0xdb, 0xf7, 0x06, 0x34 } }
 
 /**
  * Abstraction of the script objects etc required to do timeouts in a
  * language agnostic way.
  */
 
 class nsIScriptTimeoutHandler : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTTIMEOUTHANDLER_IID)
 
-  // Get a script object for the language suitable for passing back to
-  // the language's context as an event handler.  If this returns nullptr,
-  // GetHandlerText() will be called to get the string.
-  virtual JSObject *GetScriptObject() = 0;
+  // Get the Function to call.  If this returns nullptr, GetHandlerText() will
+  // be called to get the string.
+  virtual mozilla::dom::Function *GetCallback() = 0;
 
   // Get the handler text of not a compiled object.
   virtual const PRUnichar *GetHandlerText() = 0;
 
   // Get the location of the script.
   // Note: The memory pointed to by aFileName is owned by the
   // nsIScriptTimeoutHandler and should not be freed by the caller.
   virtual void GetLocation(const char **aFileName, uint32_t *aLineNo) = 0;
 
-  // If a script object, get the argv suitable for passing back to the
-  // script context.
-  virtual nsIArray *GetArgv() = 0;
+  // If we have a Function, get the arguments for passing to it.
+  virtual const nsTArray<JS::Value>& GetArgs() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptTimeoutHandler,
                               NS_ISCRIPTTIMEOUTHANDLER_IID)
 
 #endif // nsIScriptTimeoutHandler_h___
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1856,117 +1856,16 @@ nsJSContext::CompileFunction(JSObject* a
   if (!fun)
     return NS_ERROR_FAILURE;
 
   *aFunctionObject = JS_GetFunctionObject(fun);
   return NS_OK;
 }
 
 nsresult
-nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
-                              JSObject* aHandler, nsIArray* aargv,
-                              nsIVariant** arv)
-{
-  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
-
-  if (!mScriptsEnabled) {
-    return NS_OK;
-  }
-
-  SAMPLE_LABEL("JS", "CallEventHandler");
-
-  nsAutoMicroTask mt;
-  xpc_UnmarkGrayObject(aScope);
-  xpc_UnmarkGrayObject(aHandler);
-
-  XPCAutoRequest ar(mContext);
-  JSObject* target = nullptr;
-  nsresult rv = JSObjectFromInterface(aTarget, aScope, &target);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  JS::AutoObjectRooter targetVal(mContext, target);
-  jsval rval = JSVAL_VOID;
-
-  // This one's a lot easier than EvaluateString because we don't have to
-  // hassle with principals: they're already compiled into the JS function.
-  // xxxmarkh - this comment is no longer true - principals are not used at
-  // all now, and never were in some cases.
-
-  nsCxPusher pusher;
-  if (!pusher.Push(mContext, true))
-    return NS_ERROR_FAILURE;
-
-  // check if the event handler can be run on the object in question
-  rv = sSecurityManager->CheckFunctionAccess(mContext, aHandler, target);
-
-  nsJSContext::TerminationFuncHolder holder(this);
-
-  if (NS_SUCCEEDED(rv)) {
-    // Convert args to jsvals.
-    uint32_t argc = 0;
-    jsval *argv = nullptr;
-
-    JSObject *funobj = aHandler;
-    jsval funval = OBJECT_TO_JSVAL(funobj);
-    JSAutoCompartment ac(mContext, funobj);
-    if (!JS_WrapObject(mContext, &target)) {
-      ReportPendingException();
-      return NS_ERROR_FAILURE;
-    }
-
-    Maybe<nsRootedJSValueArray> tempStorage;
-
-    // Use |target| as the scope for wrapping the arguments, since aScope is
-    // the safe scope in many cases, which isn't very useful.  Wrapping aTarget
-    // was OK because those typically have PreCreate methods that give them the
-    // right scope anyway, and we want to make sure that the arguments end up
-    // in the same scope as aTarget.
-    rv = ConvertSupportsTojsvals(aargv, target, &argc, &argv, tempStorage);
-    NS_ENSURE_SUCCESS(rv, rv);
-    for (uint32_t i = 0; i < argc; i++) {
-      if (!JSVAL_IS_PRIMITIVE(argv[i])) {
-        xpc_UnmarkGrayObject(JSVAL_TO_OBJECT(argv[i]));
-      }
-    }
-
-    ++mExecuteDepth;
-    bool ok = ::JS_CallFunctionValue(mContext, target,
-                                       funval, argc, argv, &rval);
-    --mExecuteDepth;
-
-    if (!ok) {
-      // Don't pass back results from failed calls.
-      rval = JSVAL_VOID;
-
-      // Tell the caller that the handler threw an error.
-      rv = NS_ERROR_FAILURE;
-    } else if (rval == JSVAL_NULL) {
-      *arv = nullptr;
-    } else if (!JS_WrapValue(mContext, &rval)) {
-      rv = NS_ERROR_FAILURE;
-    } else {
-      rv = nsContentUtils::XPConnect()->JSToVariant(mContext, rval, arv);
-    }
-
-    // Tell XPConnect about any pending exceptions. This is needed
-    // to avoid dropping JS exceptions in case we got here through
-    // nested calls through XPConnect.
-    if (NS_FAILED(rv))
-      ReportPendingException();
-  }
-
-  pusher.Pop();
-
-  // ScriptEvaluated needs to come after we pop the stack
-  ScriptEvaluated(true);
-
-  return rv;
-}
-
-nsresult
 nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, JSObject* aScope,
                                       JSObject* aHandler,
                                       nsScriptObjectHolder<JSObject>& aBoundHandler)
 {
   NS_ENSURE_ARG(aHandler);
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
   NS_PRECONDITION(!aBoundHandler, "Shouldn't already have a bound handler!");
 
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -79,19 +79,16 @@ public:
   virtual nsresult CompileEventHandler(nsIAtom *aName,
                                        uint32_t aArgCount,
                                        const char** aArgNames,
                                        const nsAString& aBody,
                                        const char *aURL, uint32_t aLineNo,
                                        uint32_t aVersion,
                                        bool aIsXBL,
                                        nsScriptObjectHolder<JSObject>& aHandler);
-  virtual nsresult CallEventHandler(nsISupports* aTarget, JSObject* aScope,
-                                    JSObject* aHandler,
-                                    nsIArray *argv, nsIVariant **rv);
   virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
                                             JSObject *aScope,
                                             JSObject* aHandler,
                                             nsScriptObjectHolder<JSObject>& aBoundHandler);
   virtual nsresult CompileFunction(JSObject* aTarget,
                                    const nsACString& aName,
                                    uint32_t aArgCount,
                                    const char** aArgArray,
--- a/dom/base/nsJSTimeoutHandler.cpp
+++ b/dom/base/nsJSTimeoutHandler.cpp
@@ -16,62 +16,65 @@
 #include "nsJSEnvironment.h"
 #include "nsServiceManagerUtils.h"
 #include "nsError.h"
 #include "nsGlobalWindow.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsAlgorithm.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Likely.h"
+#include "mozilla/dom/FunctionBinding.h"
 
 static const char kSetIntervalStr[] = "setInterval";
 static const char kSetTimeoutStr[] = "setTimeout";
 
+using namespace mozilla::dom;
+
 // Our JS nsIScriptTimeoutHandler implementation.
 class nsJSScriptTimeoutHandler MOZ_FINAL : public nsIScriptTimeoutHandler
 {
 public:
   // nsISupports
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsJSScriptTimeoutHandler)
 
   nsJSScriptTimeoutHandler();
   ~nsJSScriptTimeoutHandler();
 
   virtual const PRUnichar *GetHandlerText();
-  virtual JSObject *GetScriptObject() {
-    return mFunObj;
+  virtual Function* GetCallback()
+  {
+    return mFunction;
   }
-  virtual void GetLocation(const char **aFileName, uint32_t *aLineNo) {
+  virtual void GetLocation(const char **aFileName, uint32_t *aLineNo)
+  {
     *aFileName = mFileName.get();
     *aLineNo = mLineNo;
   }
 
-  virtual nsIArray *GetArgv() {
-    return mArgv;
+  virtual const nsTArray<JS::Value>& GetArgs()
+  {
+    return mArgs;
   }
 
   nsresult Init(nsGlobalWindow *aWindow, bool *aIsInterval,
                 int32_t *aInterval);
 
   void ReleaseJSObjects();
 
 private:
-
-  nsCOMPtr<nsIScriptContext> mContext;
-
   // filename, line number and JS language version string of the
   // caller of setTimeout()
   nsCString mFileName;
   uint32_t mLineNo;
-  nsCOMPtr<nsIJSArgArray> mArgv;
+  nsTArray<JS::Value> mArgs;
 
   // The JS expression to evaluate or function to call, if !mExpr
   JSFlatString *mExpr;
-  JSObject *mFunObj;
+  nsRefPtr<Function> mFunction;
 };
 
 
 // nsJSScriptTimeoutHandler
 // QueryInterface implementation for nsJSScriptTimeoutHandler
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSScriptTimeoutHandler)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSScriptTimeoutHandler)
   tmp->ReleaseJSObjects();
@@ -81,18 +84,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     nsAutoCString name("nsJSScriptTimeoutHandler");
     if (tmp->mExpr) {
       name.AppendLiteral(" [");
       name.Append(tmp->mFileName);
       name.AppendLiteral(":");
       name.AppendInt(tmp->mLineNo);
       name.AppendLiteral("]");
     }
-    else if (tmp->mFunObj) {
-      JSFunction* fun = JS_GetObjectFunction(tmp->mFunObj);
+    else if (tmp->mFunction) {
+      JSFunction* fun =
+        JS_GetObjectFunction(js::UnwrapObject(tmp->mFunction->Callable()));
       if (fun && JS_GetFunctionId(fun)) {
         JSFlatString *funId = JS_ASSERT_STRING_IS_FLAT(JS_GetFunctionId(fun));
         size_t size = 1 + JS_PutEscapedFlatString(NULL, 0, funId, 0);
         char *funIdName = new char[size];
         if (funIdName) {
           JS_PutEscapedFlatString(funIdName, size, funId, 0);
           name.AppendLiteral(" [");
           name.Append(funIdName);
@@ -103,63 +107,63 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     }
     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name.get());
   }
   else {
     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsJSScriptTimeoutHandler,
                                       tmp->mRefCnt.get())
   }
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArgv)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFunction)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSScriptTimeoutHandler)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mExpr)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mFunObj)
+  for (uint32_t i = 0; i < tmp->mArgs.Length(); ++i) {
+    NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mArgs[i])
+  }
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSScriptTimeoutHandler)
   NS_INTERFACE_MAP_ENTRY(nsIScriptTimeoutHandler)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsJSScriptTimeoutHandler)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSScriptTimeoutHandler)
 
 nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler() :
   mLineNo(0),
-  mExpr(nullptr),
-  mFunObj(nullptr)
+  mExpr(nullptr)
 {
 }
 
 nsJSScriptTimeoutHandler::~nsJSScriptTimeoutHandler()
 {
   ReleaseJSObjects();
 }
 
 void
 nsJSScriptTimeoutHandler::ReleaseJSObjects()
 {
   if (mExpr) {
     mExpr = nullptr;
   } else {
-    mFunObj = nullptr;
+    mFunction = nullptr;
+    mArgs.Clear();
   }
   NS_DROP_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
 }
 
 nsresult
 nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
                                int32_t *aInterval)
 {
-  mContext = aWindow->GetContextInternal();
-  if (!mContext) {
+  if (!aWindow->GetContextInternal() || !aWindow->FastGetGlobalJSObject()) {
     // This window was already closed, or never properly initialized,
     // don't let a timer be scheduled on such a window.
 
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   nsAXPCNativeCallContext *ncc = nullptr;
   nsresult rv = nsContentUtils::XPConnect()->
@@ -267,43 +271,38 @@ nsJSScriptTimeoutHandler::Init(nsGlobalW
     // Get the calling location.
     const char *filename;
     if (nsJSUtils::GetCallingLocation(cx, &filename, &mLineNo)) {
       mFileName.Assign(filename);
     }
   } else if (funobj) {
     NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
 
-    mFunObj = funobj;
+    bool ok;
+    mFunction = new Function(cx, aWindow->FastGetGlobalJSObject(), funobj, &ok);
+    if (!ok) {
+      NS_DROP_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
 
     // Create our arg array.  argc is the number of arguments passed
     // to setTimeout or setInterval; the first two are our callback
     // and the delay, so only arguments after that need to go in our
     // array.
-    nsCOMPtr<nsIJSArgArray> array;
     // NS_MAX(argc - 2, 0) wouldn't work right because argc is unsigned.
-    rv = NS_CreateJSArgv(cx, NS_MAX(argc, 2u) - 2, nullptr,
-                         getter_AddRefs(array));
-    if (NS_FAILED(rv)) {
+    uint32_t argCount = NS_MAX(argc, 2u) - 2;
+    FallibleTArray<JS::Value> args;
+    if (!args.SetCapacity(argCount)) {
+      // No need to drop here, since we already have a non-null mFunction
       return NS_ERROR_OUT_OF_MEMORY;
     }
-
-    uint32_t dummy;
-    jsval *jsargv = nullptr;
-    array->GetArgs(&dummy, reinterpret_cast<void **>(&jsargv));
-
-    // jsargv might be null if we have argc <= 2
-    if (jsargv) {
-      for (int32_t i = 2; (uint32_t)i < argc; ++i) {
-        jsargv[i - 2] = argv[i];
-      }
-    } else {
-      NS_ASSERTION(argc <= 2, "Why do we have no jsargv when we have arguments?");
+    for (uint32_t idx = 0; idx < argCount; ++idx) {
+      *args.AppendElement() = argv[idx + 2];
     }
-    mArgv = array;
+    args.SwapElements(mArgs);
   } else {
     NS_WARNING("No func and no expr - why are we here?");
   }
   *aInterval = interval;
   return NS_OK;
 }
 
 const PRUnichar *
@@ -314,22 +313,18 @@ nsJSScriptTimeoutHandler::GetHandlerText
 }
 
 nsresult NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
                                    bool *aIsInterval,
                                    int32_t *aInterval,
                                    nsIScriptTimeoutHandler **aRet)
 {
   *aRet = nullptr;
-  nsJSScriptTimeoutHandler *handler = new nsJSScriptTimeoutHandler();
-  if (!handler)
-    return NS_ERROR_OUT_OF_MEMORY;
-
+  nsRefPtr<nsJSScriptTimeoutHandler> handler = new nsJSScriptTimeoutHandler();
   nsresult rv = handler->Init(aWindow, aIsInterval, aInterval);
   if (NS_FAILED(rv)) {
-    delete handler;
     return rv;
   }
 
-  NS_ADDREF(*aRet = handler);
+  handler.forget(aRet);
 
   return NS_OK;
 }
--- a/dom/base/test/Makefile.in
+++ b/dom/base/test/Makefile.in
@@ -6,16 +6,18 @@ DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 relativesrcdir = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_FILES = \
+  test_constructor.html \
+  test_constructor-assignment.html \
   test_document.all_unqualified.html \
   test_domrequest.html \
   test_e4x_for_each.html \
   test_gsp-standards.html \
   test_gsp-quirks.html \
   test_gsp-qualified.html \
   test_nondomexception.html \
   test_screen_orientation.html \
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_constructor-assignment.html
@@ -0,0 +1,61 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script type="application/javascript">
+function testConstructor(name)
+{
+  window[name] = 17; // resolve through assignment
+
+
+  var desc = Object.getOwnPropertyDescriptor(window, name);
+  ok(typeof desc === "object" && desc !== null, name + ": property must exist");
+
+  is(desc.value, 17, name + ": overwrite didn't work correctly");
+  is(desc.enumerable, false,
+     name + ": initial descriptor was non-enumerable, and [[Put]] changes " +
+     "the property value but not its enumerability");
+  is(desc.configurable, true,
+     name + ": initial descriptor was configurable, and [[Put]] changes the " +
+     "property value but not its configurability");
+  is(desc.writable, true,
+     name + ": initial descriptor was writable, and [[Put]] changes the " +
+     "property value but not its writability");
+}
+
+var ctors =
+  [
+   "HTMLElement",
+   "HTMLDivElement",
+   "HTMLSpanElement",
+   "HTMLParagraphElement",
+   "HTMLOptionElement",
+   "HTMLHtmlElement",
+   "Element",
+   "Node",
+   "Document",
+   "Image",
+   "Audio",
+   "HTMLAudioElement",
+   "HTMLVideoElement",
+   "Window",
+   "XMLHttpRequest",
+   "Navigator",
+   "WebSocket",
+   "Event",
+   "IDBKeyRange",
+   "CSSPageRule",
+   "SVGPatternElement",
+  ];
+
+ctors.forEach(testConstructor);
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_constructor.html
@@ -0,0 +1,61 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script type="application/javascript">
+function testConstructor(name)
+{
+  window[name]; // resolve not through assignment
+  window[name] = 17;
+
+  var desc = Object.getOwnPropertyDescriptor(window, name);
+  ok(typeof desc === "object" && desc !== null, name + ": property must exist");
+
+  is(desc.value, 17, name + ": overwrite didn't work correctly");
+  is(desc.enumerable, false,
+     name + ": initial descriptor was non-enumerable, and [[Put]] changes " +
+     "the property value but not its enumerability");
+  is(desc.configurable, true,
+     name + ": initial descriptor was configurable, and [[Put]] changes the " +
+     "property value but not its configurability");
+  is(desc.writable, true,
+     name + ": initial descriptor was writable, and [[Put]] changes the " +
+     "property value but not its writability");
+}
+
+var ctors =
+  [
+   "HTMLElement",
+   "HTMLDivElement",
+   "HTMLSpanElement",
+   "HTMLParagraphElement",
+   "HTMLOptionElement",
+   "HTMLHtmlElement",
+   "Element",
+   "Node",
+   "Document",
+   "Image",
+   "Audio",
+   "HTMLAudioElement",
+   "HTMLVideoElement",
+   "Window",
+   "XMLHttpRequest",
+   "Navigator",
+   "WebSocket",
+   "Event",
+   "IDBKeyRange",
+   "CSSPageRule",
+   "SVGPatternElement",
+  ];
+
+ctors.forEach(testConstructor);
+</script>
+</body>
+</html>
--- a/dom/battery/test/marionette/manifest.ini
+++ b/dom/battery/test/marionette/manifest.ini
@@ -1,10 +1,11 @@
 [DEFAULT]
 b2g = true
 browser = false
 qemu = true
 
+[test_battery_level.js]
 [test_battery_status_charging.js]
 [test_battery_status_discharging.js]
 [test_battery_status_full.js]
 [test_battery_status_not_charging.js]
 [test_battery_status_unknown.js]
new file mode 100644
--- /dev/null
+++ b/dom/battery/test/marionette/test_battery_level.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 10000;
+
+let battery = window.navigator.battery;
+
+function verifyInitialState() {
+  ok(battery, "battery");
+  is(battery.level, 0.5, "battery.level");
+  runEmulatorCmd("power display", function (result) {
+    is(result.pop(), "OK", "power display successful");
+    ok(result.indexOf("capacity: 50") !== -1, "power capacity");
+    setUp();
+  });
+}
+
+function unexpectedEvent(event) {
+  ok(false, "Unexpected " + event.type + " event");
+}
+
+function setUp() {
+  battery.onchargingchange = unexpectedEvent;
+  battery.onlevelchange = unexpectedEvent;
+  levelUp();
+}
+
+function changeCapacity(capacity, changeExpected, nextFunction) {
+  log("Changing power capacity to " + capacity);
+  if (changeExpected) {
+    battery.onlevelchange = function (event) {
+     battery.onlevelchange = unexpectedEvent;
+     is(event.type, "levelchange", "event.type");
+     is(battery.level, capacity / 100, "battery.level");
+     nextFunction();
+    };
+    runEmulatorCmd("power capacity " + capacity);
+  }
+  else {
+    runEmulatorCmd("power capacity " + capacity, function () {
+      is(battery.level, capacity / 100, "battery.level");
+      nextFunction();
+    });
+  }
+}
+
+function levelUp() {
+  changeCapacity("90", true, levelDown);
+}
+
+function levelDown() {
+  changeCapacity("10", true, levelSame);
+}
+
+function levelSame() {
+  changeCapacity("10", false, cleanUp);
+}
+
+function cleanUp() {
+  battery.onchargingchange = null;
+  battery.onlevelchange = function () {
+    battery.onlevelchange = null;
+    finish();
+  };
+  runEmulatorCmd("power capacity 50");
+}
+
+verifyInitialState();
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -188,63 +188,60 @@ UnwrapObject(JSContext* cx, JSObject* ob
     return NS_OK;
   }
 
   /* It's the wrong sort of DOM object */
   return NS_ERROR_XPC_BAD_CONVERT_JS;
 }
 
 inline bool
-IsArrayLike(JSContext* cx, JSObject* obj)
+IsNotDateOrRegExp(JSContext* cx, JSObject* obj)
 {
   MOZ_ASSERT(obj);
   // For simplicity, check for security wrappers up front.  In case we
   // have a security wrapper, don't forget to enter the compartment of
   // the underlying object after unwrapping.
   Maybe<JSAutoCompartment> ac;
   if (js::IsWrapper(obj)) {
     obj = xpc::Unwrap(cx, obj, false);
     if (!obj) {
       // Let's say it's not
       return false;
     }
 
     ac.construct(cx, obj);
   }
 
-  // XXXbz need to detect platform objects (including listbinding
-  // ones) with indexGetters here!
-  return JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj);
+  // Everything except dates and regexps is arraylike
+  return !JS_ObjectIsDate(cx, obj) && !JS_ObjectIsRegExp(cx, obj);
+}
+
+MOZ_ALWAYS_INLINE bool
+IsArrayLike(JSContext* cx, JSObject* obj)
+{
+  return IsNotDateOrRegExp(cx, obj);
 }
 
-inline bool
-IsPlatformObject(JSContext* cx, JSObject* obj)
+MOZ_ALWAYS_INLINE bool
+IsConvertibleToDictionary(JSContext* cx, JSObject* obj)
+{
+  return IsNotDateOrRegExp(cx, obj);
+}
+
+MOZ_ALWAYS_INLINE bool
+IsConvertibleToDictionary(JSContext* cx, JS::Value val)
 {
-  // XXXbz Should be treating list-binding objects as platform objects
-  // too?  The one consumer so far wants non-array-like platform
-  // objects, so listbindings that have an indexGetter should test
-  // false from here.  Maybe this function should have a different
-  // name?
-  MOZ_ASSERT(obj);
-  // Fast-path the common case
-  JSClass* clasp = js::GetObjectJSClass(obj);
-  if (IsDOMClass(clasp)) {
-    return true;
-  }
-  // Now for simplicity check for security wrappers before anything else
-  if (js::IsWrapper(obj)) {
-    obj = xpc::Unwrap(cx, obj, false);
-    if (!obj) {
-      // Let's say it's not
-      return false;
-    }
-    clasp = js::GetObjectJSClass(obj);
-  }
-  return IS_WRAPPER_CLASS(js::Valueify(clasp)) || IsDOMClass(clasp) ||
-    JS_IsArrayBufferObject(obj);
+  return val.isNullOrUndefined() ||
+    (val.isObject() && IsConvertibleToDictionary(cx, &val.toObject()));
+}
+
+MOZ_ALWAYS_INLINE bool
+IsConvertibleToCallbackInterface(JSContext* cx, JSObject* obj)
+{
+  return IsNotDateOrRegExp(cx, obj);
 }
 
 // U must be something that a T* can be assigned to (e.g. T* or an nsRefPtr<T>).
 template <class T, typename U>
 inline nsresult
 UnwrapObject(JSContext* cx, JSObject* obj, U& value)
 {
   return UnwrapObject<static_cast<prototypes::ID>(
@@ -363,34 +360,16 @@ CreateInterfaceObjects(JSContext* cx, JS
  */
 bool
 DefineUnforgeableAttributes(JSContext* cx, JSObject* obj,
                             Prefable<JSPropertySpec>* props);
 
 bool
 DefineWebIDLBindingPropertiesOnXPCProto(JSContext* cx, JSObject* proto, const NativeProperties* properties);
 
-// If *vp is a gcthing and is not in the compartment of cx, wrap *vp
-// into the compartment of cx (typically by replacing it with an Xray or
-// cross-compartment wrapper around the original object).
-inline bool
-MaybeWrapValue(JSContext* cx, JS::Value* vp)
-{
-  if (vp->isGCThing()) {
-    void* gcthing = vp->toGCThing();
-    // Might be null if vp.isNull() :(
-    if (gcthing &&
-        js::GetGCThingCompartment(gcthing) != js::GetContextCompartment(cx)) {
-      return JS_WrapValue(cx, vp);
-    }
-  }
-
-  return true;
-}
-
 #ifdef _MSC_VER
 #define HAS_MEMBER_CHECK(_name)                                           \
   template<typename V> static yes& Check(char (*)[(&V::_name == 0) + 1])
 #else
 #define HAS_MEMBER_CHECK(_name)                                           \
   template<typename V> static yes& Check(char (*)[sizeof(&V::_name) + 1])
 #endif
 
@@ -516,16 +495,52 @@ GetSameCompartmentWrapperForDOMBinding(J
 
 inline void
 SetSystemOnlyWrapper(JSObject* obj, nsWrapperCache* cache, JSObject& wrapper)
 {
   SetSystemOnlyWrapperSlot(obj, JS::ObjectValue(wrapper));
   cache->SetHasSystemOnlyWrapper();
 }
 
+// If *vp is a gcthing and is not in the compartment of cx, wrap *vp
+// into the compartment of cx (typically by replacing it with an Xray or
+// cross-compartment wrapper around the original object).
+MOZ_ALWAYS_INLINE bool
+MaybeWrapValue(JSContext* cx, JS::Value* vp)
+{
+  if (vp->isGCThing()) {
+    void* gcthing = vp->toGCThing();
+    // Might be null if vp.isNull() :(
+    if (gcthing &&
+        js::GetGCThingCompartment(gcthing) != js::GetContextCompartment(cx)) {
+      return JS_WrapValue(cx, vp);
+    }
+
+    // We're same-compartment, but even then we might need to wrap
+    // objects specially.  Check for that.
+    if (vp->isObject()) {
+      JSObject* obj = &vp->toObject();
+      if (GetSameCompartmentWrapperForDOMBinding(obj)) {
+        // We're a new-binding object, and "obj" now points to the right thing
+        *vp = JS::ObjectValue(*obj);
+        return true;
+      }
+
+      if (!IS_SLIM_WRAPPER(obj)) {
+        // We might need a SOW
+        return JS_WrapValue(cx, vp);
+      }
+
+      // Fall through to returning true
+    }
+  }
+
+  return true;
+}
+
 static inline void
 WrapNewBindingForSameCompartment(JSContext* cx, JSObject* obj, void* value,
                                  JS::Value* vp)
 {
   *vp = JS::ObjectValue(*obj);
 }
 
 static inline void
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -339,16 +339,20 @@ DOMInterfaces = {
 'HTMLFrameSetElement': {
   'hasInstanceInterface': 'nsIDOMHTMLFrameSetElement',
 },
 
 'HTMLHeadingElement': {
   'hasInstanceInterface': 'nsIDOMHTMLHeadingElement',
 },
 
+'HTMLImageElement': {
+  'hasInstanceInterface': 'nsIDOMHTMLImageElement',
+},
+
 'HTMLLabelElement': {
     'resultNotAddRefed': [
         'form', 'control'
     ],
     'hasInstanceInterface': 'nsIDOMHTMLLabelElement',
 },
 
 'HTMLOptionsCollection': {
@@ -1018,17 +1022,16 @@ def addExternalIface(iface, nativeType=N
 # macros added for it
 def addExternalHTMLElement(element):
    nativeElement = 'ns' + element
    addExternalIface(element, nativeType=nativeElement,
                     headerFile=nativeElement + '.h')
 
 addExternalHTMLElement('HTMLCanvasElement')
 addExternalHTMLElement('HTMLFormElement')
-addExternalHTMLElement('HTMLImageElement')
 addExternalHTMLElement('HTMLMenuElement')
 addExternalHTMLElement('HTMLOptionElement')
 addExternalHTMLElement('HTMLOptGroupElement')
 addExternalHTMLElement('HTMLVideoElement')
 addExternalIface('Attr')
 addExternalIface('CanvasGradient', headerFile='nsIDOMCanvasRenderingContext2D.h')
 addExternalIface('CanvasPattern', headerFile='nsIDOMCanvasRenderingContext2D.h')
 addExternalIface('CDATASection')
@@ -1036,20 +1039,23 @@ addExternalIface('ClientRect')
 addExternalIface('Comment', nativeType='mozilla::dom::Comment')
 addExternalIface("Counter")
 addExternalIface('CSSRule')
 addExternalIface('DOMRequest')
 addExternalIface('DOMStringList')
 addExternalIface('File')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('HTMLHeadElement', nativeType='mozilla::dom::Element')
+addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
+addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
 addExternalIface('LockedFile')
 addExternalIface('MediaStream')
 addExternalIface('NamedNodeMap')
 addExternalIface('NodeIterator')
+addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
 addExternalIface('nsISupports', nativeType='nsISupports')
 addExternalIface('OutputStream', nativeType='nsIOutputStream',
                  notflattened=True)
 addExternalIface('Principal', nativeType='nsIPrincipal',
                  headerFile='nsIPrincipal.h', notflattened=True)
 addExternalIface('ProcessingInstruction', nativeType='nsXMLProcessingInstruction')
 addExternalIface('Range', nativeType='nsRange')
 addExternalIface('Selection', nativeType='nsISelection')
--- a/dom/bindings/CallbackFunction.cpp
+++ b/dom/bindings/CallbackFunction.cpp
@@ -88,17 +88,17 @@ CallbackFunction::CallSetup::CallSetup(J
   // Make sure our JSContext is pushed on the stack.
   if (!mCxPusher.Push(cx, false)) {
     return;
   }
 
   // After this point we guarantee calling ScriptEvaluated() if we
   // have an nsIScriptContext.
   // XXXbz Why, if, say CheckFunctionAccess fails?  I know that's how
-  // nsJSContext::CallEventHandler works, but is it required?
+  // nsJSContext::CallEventHandler used to work, but is it required?
   // FIXME: Bug 807369.
   mCtx = ctx;
 
   // Check that it's ok to run this callback at all.
   // FIXME: Bug 807371: we want a less silly check here.
   // Make sure to unwrap aCallable before passing it in, because
   // getting principals from wrappers is silly.
   nsresult rv = nsContentUtils::GetSecurityManager()->
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1931,22 +1931,26 @@ class CallbackObjectUnwrapper:
                 '%s' % (descriptor.name, exceptionCode))
         self.descriptor = descriptor
         self.substitution = { "nativeType" : descriptor.nativeType,
                               "source" : source,
                               "target" : target,
                               "codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure)).define() }
 
     def __str__(self):
+        checkObjectType = CGIfWrapper(
+            CGGeneric(self.substitution["codeOnFailure"]),
+            "!IsConvertibleToCallbackInterface(cx, %(source)s)" %
+            self.substitution).define() + "\n\n"
         if self.descriptor.workers:
-            return string.Template(
+            return checkObjectType + string.Template(
                 "${target} = ${source};"
                 ).substitute(self.substitution)
 
-        return string.Template(
+        return checkObjectType + string.Template(
             """nsresult rv;
 XPCCallContext ccx(JS_CALLER, cx);
 if (!ccx.IsValid()) {
   rv = NS_ERROR_XPC_BAD_CONVERT_JS;
 ${codeOnFailure}
 }
 
 const nsIID& iid = NS_GET_IID(${nativeType});
@@ -1996,17 +2000,18 @@ def getJSToNativeConversionTemplate(type
                                     invalidEnumValueFatal=True,
                                     defaultValue=None,
                                     treatNullAs="Default",
                                     treatUndefinedAs="Default",
                                     isEnforceRange=False,
                                     isClamp=False,
                                     isNullOrUndefined=False,
                                     exceptionCode=None,
-                                    lenientFloatCode=None):
+                                    lenientFloatCode=None,
+                                    allowTreatNonCallableAsNull=False):
     """
     Get a template for converting a JS value to a native object based on the
     given type and descriptor.  If failureCode is given, then we're actually
     testing whether we can convert the argument to the desired type.  That
     means that failures to convert due to the JS value being the wrong type of
     value need to use failureCode instead of throwing exceptions.  Failures to
     convert that are due to JS exceptions (from toString or valueOf methods) or
     out of memory conditions need to throw exceptions no matter what
@@ -2037,16 +2042,19 @@ def getJSToNativeConversionTemplate(type
     value is out of range.
 
     If isClamp is true, we're converting an integer and clamping if the
     value is out of range.
 
     If lenientFloatCode is not None, it should be used in cases when
     we're a non-finite float that's not unrestricted.
 
+    If allowTreatNonCallableAsNull is true, then [TreatNonCallableAsNull]
+    extended attributes on nullable callback functions will be honored.
+
     The return value from this function is a tuple consisting of four things:
 
     1)  A string representing the conversion code.  This will have template
         substitution performed on it as follows:
 
           ${val} replaced by an expression for the JS::Value in question
           ${valPtr} is a pointer to the JS::Value in question
           ${holderName} replaced by the holder's name, if any
@@ -2308,19 +2316,16 @@ for (uint32_t i = 0; i < length; ++i) {
             interfaceObject = None
 
         arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes)
         if len(arrayObjectMemberTypes) > 0:
             assert len(arrayObjectMemberTypes) == 1
             memberType = arrayObjectMemberTypes[0]
             name = memberType.name
             arrayObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${obj}, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
-            # XXX Now we're supposed to check for an array or a platform object
-            # that supports indexed properties... skip that last for now. It's a
-            # bit of a pain.
             arrayObject = CGWrapper(CGIndenter(arrayObject),
                                     pre="if (IsArrayLike(cx, &argObj)) {\n",
                                     post="}")
             names.append(name)
         else:
             arrayObject = None
 
         dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes)
@@ -2349,57 +2354,49 @@ for (uint32_t i = 0; i < length; ++i) {
 
         dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
         if len(dictionaryMemberTypes) > 0:
             raise TypeError("No support for unwrapping dictionaries as member "
                             "of a union")
         else:
             dictionaryObject = None
 
-        if callbackObject or dictionaryObject:
-            nonPlatformObject = CGList([callbackObject, dictionaryObject], "\n")
-            nonPlatformObject = CGWrapper(CGIndenter(nonPlatformObject),
-                                          pre="if (!IsPlatformObject(cx, &argObj)) {\n",
-                                          post="\n}")
-        else:
-            nonPlatformObject = None
-
         objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
         if len(objectMemberTypes) > 0:
             object = CGGeneric("%s.SetToObject(&argObj);\n"
                                "done = true;" % unionArgumentObj)
         else:
             object = None
 
-        hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object
+        hasObjectTypes = interfaceObject or arrayObject or dateObject or callbackObject or dictionaryObject or object
         if hasObjectTypes:
-            # If we try more specific object types first then we need to check
-            # whether that succeeded before converting to object.
-            if object and (interfaceObject or arrayObject or dateObject or nonPlatformObject):
-                object = CGWrapper(CGIndenter(object), pre="if (!done) {\n",
-                                   post=("\n}"))
-
-            if arrayObject or dateObject or nonPlatformObject:
-                # An object can be both an array object and not a platform
-                # object, but we shouldn't have both in the union's members
+            # "object" is not distinguishable from other types
+            assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or dictionaryObject)
+            if arrayObject or dateObject or callbackObject or dictionaryObject:
+                # An object can be both an array object and a callback or
+                # dictionary, but we shouldn't have both in the union's members
                 # because they are not distinguishable.
-                assert not (arrayObject and nonPlatformObject)
-                templateBody = CGList([arrayObject, dateObject, nonPlatformObject], " else ")
+                assert not (arrayObject and callbackObject)
+                assert not (arrayObject and dictionaryObject)
+                assert not (dictionaryObject and callbackObject)
+                templateBody = CGList([arrayObject, dateObject, callbackObject,
+                                       dictionaryObject], " else ")
             else:
                 templateBody = None
             if interfaceObject:
+                assert not object
                 if templateBody:
-                    templateBody = CGList([templateBody, object], "\n")
                     templateBody = CGWrapper(CGIndenter(templateBody),
                                              pre="if (!done) {\n", post=("\n}"))
                 templateBody = CGList([interfaceObject, templateBody], "\n")
             else:
                 templateBody = CGList([templateBody, object], "\n")
 
-            if any([arrayObject, dateObject, nonPlatformObject, object]):
+            if any([arrayObject, dateObject, callbackObject, dictionaryObject,
+                    object]):
                 templateBody.prepend(CGGeneric("JSObject& argObj = ${val}.toObject();"))
             templateBody = CGWrapper(CGIndenter(templateBody),
                                      pre="if (${val}.isObject()) {\n",
                                      post="\n}")
         else:
             templateBody = CGGeneric()
 
         otherMemberTypes = filter(lambda t: t.isString() or t.isEnum(),
@@ -2790,17 +2787,17 @@ for (uint32_t i = 0; i < length; ++i) {
                 declType = CGGeneric("OwningNonNull<%s>" % name)
             conversion = (
                 "  bool inited;\n"
                 "  ${declName} = new %s(cx, ${obj}, &${val}.toObject(), &inited);\n"
                 "  if (!inited) {\n"
                 "%s\n"
                 "  }\n" % (name, CGIndenter(exceptionCodeIndented).define()))
 
-        if type.treatNonCallableAsNull():
+        if allowTreatNonCallableAsNull and type.treatNonCallableAsNull():
             haveCallable = "JS_ObjectIsCallable(cx, &${val}.toObject())"
             if not isDefinitelyObject:
                 haveCallable = "${val}.isObject() && " + haveCallable
             if defaultValue is not None:
                 assert(isinstance(defaultValue, IDLNullValue))
                 haveCallable = "${haveValue} && " + haveCallable
             template = (
                 ("if (%s) {\n" % haveCallable) +
@@ -2864,18 +2861,20 @@ for (uint32_t i = 0; i < length; ++i) {
             setToNullCode = "${declName} = NULL"
 
         template = wrapObjectTemplate(templateBody, type, setToNullCode,
                                       failureCode)
 
         return (template, declType, None, isOptional)
 
     if type.isDictionary():
-        if failureCode is not None:
-            raise TypeError("Can't handle dictionaries when failureCode is not None")
+        if failureCode is not None and not isDefinitelyObject:
+            raise TypeError("Can't handle dictionaries when failureCode is "
+                            "not None and we don't know we're an object")
+
         # There are no nullable dictionaries
         assert not type.nullable()
         # All optional dictionaries always have default values, so we
         # should be able to assume not isOptional here.
         assert not isOptional
 
         typeName = CGDictionary.makeDictionaryName(type.inner,
                                                    descriptorProvider.workers)
@@ -2887,25 +2886,39 @@ for (uint32_t i = 0; i < length; ++i) {
         # If we're a member of something else, the const
         # will come from the Optional or our container.
         if not isMember:
             declType = CGWrapper(declType, pre="const ")
             selfRef = "const_cast<%s&>(%s)" % (typeName, selfRef)
 
         # We do manual default value handling here, because we
         # actually do want a jsval, and we only handle null anyway
-        if defaultValue is not None:
+        # NOTE: if isNullOrUndefined or isDefinitelyObject are true,
+        # we know we have a value, so we don't have to worry about the
+        # default value.
+        if (not isNullOrUndefined and not isDefinitelyObject and
+            defaultValue is not None):
             assert(isinstance(defaultValue, IDLNullValue))
             val = "(${haveValue}) ? ${val} : JSVAL_NULL"
         else:
             val = "${val}"
 
-        template = ("if (!%s.Init(cx, ${obj}, %s)) {\n"
-                    "%s\n"
-                    "}" % (selfRef, val, exceptionCodeIndented.define()))
+        if failureCode is not None:
+            assert isDefinitelyObject
+            # Check that the value we have can in fact be converted to
+            # a dictionary, and return failureCode if not.
+            template = CGIfWrapper(
+                CGGeneric(failureCode),
+                "!IsConvertibleToDictionary(cx, &${val}.toObject())").define() + "\n\n"
+        else:
+            template = ""
+
+        template += ("if (!%s.Init(cx, ${obj}, %s)) {\n"
+                     "%s\n"
+                     "}" % (selfRef, val, exceptionCodeIndented.define()))
 
         return (template, declType, None, False)
 
     if type.isVoid():
         assert not isOptional
         # This one only happens for return values, and its easy: Just
         # ignore the jsval.
         return ("", None, None, False)
@@ -3085,17 +3098,18 @@ def convertConstIDLValueToJSVal(value):
 
 class CGArgumentConverter(CGThing):
     """
     A class that takes an IDL argument object, its index in the
     argument list, and the argv and argc strings and generates code to
     unwrap the argument to the right native type.
     """
     def __init__(self, argument, index, argv, argc, descriptorProvider,
-                 invalidEnumValueFatal=True, lenientFloatCode=None):
+                 invalidEnumValueFatal=True, lenientFloatCode=None,
+                 allowTreatNonCallableAsNull=False):
         CGThing.__init__(self)
         self.argument = argument
         assert(not argument.defaultValue or argument.optional)
 
         replacer = {
             "index" : index,
             "argc" : argc,
             "argv" : argv
@@ -3115,31 +3129,33 @@ class CGArgumentConverter(CGThing):
                 "${index} < ${argc}").substitute(replacer)
         self.descriptorProvider = descriptorProvider
         if self.argument.optional and not self.argument.defaultValue:
             self.argcAndIndex = replacer
         else:
             self.argcAndIndex = None
         self.invalidEnumValueFatal = invalidEnumValueFatal
         self.lenientFloatCode = lenientFloatCode
+        self.allowTreatNonCallableAsNull = allowTreatNonCallableAsNull
 
     def define(self):
         typeConversion = getJSToNativeConversionTemplate(
             self.argument.type,
             self.descriptorProvider,
             isOptional=(self.argcAndIndex is not None and
                         not self.argument.variadic),
             invalidEnumValueFatal=self.invalidEnumValueFatal,
             defaultValue=self.argument.defaultValue,
             treatNullAs=self.argument.treatNullAs,
             treatUndefinedAs=self.argument.treatUndefinedAs,
             isEnforceRange=self.argument.enforceRange,
             isClamp=self.argument.clamp,
             lenientFloatCode=self.lenientFloatCode,
-            isMember=self.argument.variadic)
+            isMember=self.argument.variadic,
+            allowTreatNonCallableAsNull=self.allowTreatNonCallableAsNull)
 
         if not self.argument.variadic:
             return instantiateJSToNativeConversionTemplate(
                 typeConversion,
                 self.replacementVariables,
                 self.argcAndIndex).define()
 
         # Variadic arguments get turned into a sequence.
@@ -3704,16 +3720,17 @@ class CGPerSignatureCall(CGThing):
             if setter:
                 lenientFloatCode = "return true;"
             elif idlNode.isMethod():
                 lenientFloatCode = ("*vp = JSVAL_VOID;\n"
                                     "return true;")
         cgThings.extend([CGArgumentConverter(arguments[i], i, self.getArgv(),
                                              self.getArgc(), self.descriptor,
                                              invalidEnumValueFatal=not setter,
+                                             allowTreatNonCallableAsNull=setter,
                                              lenientFloatCode=lenientFloatCode) for
                          i in range(argConversionStartsAt, self.argCount)])
 
         cgThings.append(CGCallGenerator(
                     self.getErrorReport() if self.isFallible() else None,
                     self.getArguments(), self.argsPre, returnType,
                     self.extendedAttributes, descriptor, nativeMethodName,
                     static))
@@ -4005,49 +4022,54 @@ class CGMethodCall(CGThing):
                                           distinguishingArg))
                 tryCall(nullOrUndefSigs[0], 2, isNullOrUndefined=True)
                 caseBody.append(CGGeneric("}"))
 
             # Now check for distinguishingArg being various kinds of objects.
             # The spec says to check for the following things in order:
             # 1)  A platform object that's not a platform array object, being
             #     passed to an interface or "object" arg.
-            # 2)  A platform array object or Array or platform object with
-            #     indexed properties being passed to an array or sequence or
+            # 2)  A Date object being passed to a Date or "object" arg.
+            # 3)  A RegExp object being passed to a RegExp or "object" arg.
+            # 4)  A callable object being passed to a callback or "object" arg.
+            # 5)  Any non-Date and non-RegExp object being passed to a
+            #     array or sequence or callback interface dictionary or
             #     "object" arg.
-            # 3)  A Date object being passed to a Date or "object" arg
-            # 4)  Some other kind of object being passed to a callback
-            #     interface, callback function, dictionary, or "object" arg.
             #
-            # Unfortunately, we cannot push the "some other kind of object"
-            # check down into case 4, because dictionaries _can_ normally be
-            # initialized from platform objects. But we can coalesce the other
-            # three cases together, as long as we make sure to check whether our
-            # object works as an interface argument before checking whether it
-            # works as an arraylike.
+            # We can can coalesce these five cases together, as long as we make
+            # sure to check whether our object works as an interface argument
+            # before checking whether it works as an arraylike or dictionary or
+            # callback function or callback interface.
 
             # First grab all the overloads that have a non-callback interface
             # (which includes typed arrays and arraybuffers) at the
             # distinguishing index.  We can also include the ones that have an
             # "object" here, since if those are present no other object-typed
             # argument will be.
             objectSigs = [
                 s for s in possibleSignatures
                 if (distinguishingType(s).isObject() or
                     distinguishingType(s).isNonCallbackInterface()) ]
 
-            # Now append all the overloads that take an array or sequence:
-            objectSigs.extend(s for s in possibleSignatures
-                              if (distinguishingType(s).isArray() or
-                                  distinguishingType(s).isSequence()))
-
             # And all the overloads that take Date
             objectSigs.extend(s for s in possibleSignatures
                               if distinguishingType(s).isDate())
 
+            # And all the overloads that take callbacks
+            objectSigs.extend(s for s in possibleSignatures
+                              if distinguishingType(s).isCallback())
+
+            # Now append all the overloads that take an array or sequence or
+            # dictionary or callback interface:
+            objectSigs.extend(s for s in possibleSignatures
+                              if (distinguishingType(s).isArray() or
+                                  distinguishingType(s).isSequence() or
+                                  distinguishingType(s).isDictionary() or
+                                  distinguishingType(s).isCallbackInterface()))
+
             # There might be more than one thing in objectSigs; we need to check
             # which ones we unwrap to.
             if len(objectSigs) > 0:
                 # Here it's enough to guard on our argument being an object. The
                 # code for unwrapping non-callback interfaces, typed arrays,
                 # sequences, arrays, and Dates will just bail out and move on to
                 # the next overload if the object fails to unwrap correctly,
                 # while "object" accepts any object anyway.  We could even not
@@ -4062,24 +4084,16 @@ class CGMethodCall(CGThing):
                     caseBody.append(CGIndenter(CGGeneric("do {")));
                     # Indent by 4, since we need to indent further
                     # than our "do" statement
                     tryCall(sig, 4, isDefinitelyObject=True)
                     caseBody.append(CGIndenter(CGGeneric("} while (0);")))
 
                 caseBody.append(CGGeneric("}"))
 
-            # Check for vanilla JS objects
-            # XXXbz Do we need to worry about security wrappers?
-            pickFirstSignature("%s.isObject() && !IsPlatformObject(cx, &%s.toObject())" %
-                               (distinguishingArg, distinguishingArg),
-                               lambda s: (distinguishingType(s).isCallback() or
-                                          distinguishingType(s).isCallbackInterface() or
-                                          distinguishingType(s).isDictionary()))
-
             # The remaining cases are mutually exclusive.  The
             # pickFirstSignature calls are what change caseBody
             # Check for strings or enums
             if pickFirstSignature(None,
                                   lambda s: (distinguishingType(s).isString() or
                                              distinguishingType(s).isEnum())):
                 pass
             # Check for primitives
@@ -4536,47 +4550,53 @@ class CGMemberJITInfo(CGThing):
     """
     def __init__(self, descriptor, member):
         self.member = member
         self.descriptor = descriptor
 
     def declare(self):
         return ""
 
-    def defineJitInfo(self, infoName, opName, opType, infallible, constant):
+    def defineJitInfo(self, infoName, opName, opType, infallible, constant,
+                      returnTypes):
         protoID = "prototypes::id::%s" % self.descriptor.name
         depth = "PrototypeTraits<%s>::Depth" % protoID
         failstr = toStringBool(infallible)
         conststr = toStringBool(constant)
+        returnType = reduce(CGMemberJITInfo.getSingleReturnType, returnTypes,
+                            "")
         return ("\n"
                 "const JSJitInfo %s = {\n"
                 "  %s,\n"
                 "  %s,\n"
                 "  %s,\n"
                 "  JSJitInfo::%s,\n"
                 "  %s,  /* isInfallible. False in setters. */\n"
-                "  %s  /* isConstant. Only relevant for getters. */\n"
+                "  %s,  /* isConstant. Only relevant for getters. */\n"
+                "  %s   /* returnType.  Only relevant for getters/methods. */\n"
                 "};\n" % (infoName, opName, protoID, depth, opType, failstr,
-                          conststr))
+                          conststr, returnType))
 
     def define(self):
         if self.member.isAttr():
             getterinfo = ("%s_getterinfo" % self.member.identifier.name)
             getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name)
             getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
             getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
             getterconst = self.member.getExtendedAttribute("Constant")
             result = self.defineJitInfo(getterinfo, getter, "Getter",
-                                        getterinfal, getterconst)
+                                        getterinfal, getterconst,
+                                        [self.member.type])
             if not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None:
                 setterinfo = ("%s_setterinfo" % self.member.identifier.name)
                 setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name)
                 # Setters are always fallible, since they have to do a typed unwrap.
                 result += self.defineJitInfo(setterinfo, setter, "Setter",
-                                             False, False)
+                                             False, False,
+                                             [BuiltinTypes[IDLBuiltinType.Types.void]])
             return result
         if self.member.isMethod():
             methodinfo = ("%s_methodinfo" % self.member.identifier.name)
             name = CppKeywords.checkMethodName(self.member.identifier.name)
             # Actually a JSJitMethodOp, but JSJitPropertyOp by struct definition.
             method = ("(JSJitPropertyOp)%s" % name)
 
             # Methods are infallible if they are infallible, have no arguments
@@ -4588,20 +4608,95 @@ class CGMemberJITInfo(CGThing):
                 # Don't handle overloading. If there's more than one signature,
                 # one of them must take arguments.
                 sig = sigs[0]
                 if len(sig[1]) == 0 and infallibleForMember(self.member, sig[0], self.descriptor):
                     # No arguments and infallible return boxing
                     methodInfal = True
 
             result = self.defineJitInfo(methodinfo, method, "Method",
-                                        methodInfal, False)
+                                        methodInfal, False,
+                                        [s[0] for s in sigs])
             return result
         raise TypeError("Illegal member type to CGPropertyJITInfo")
 
+    @staticmethod
+    def getJSReturnTypeTag(t):
+        if t.nullable():
+            # Sometimes it might return null, sometimes not
+            return "JSVAL_TYPE_UNKNOWN"
+        if t.isVoid():
+            # No return, every time
+            return "JSVAL_TYPE_UNDEFINED"
+        if t.isArray():
+            # No idea yet
+            assert False
+        if t.isSequence():
+            return "JSVAL_TYPE_OBJECT"
+        if t.isGeckoInterface():
+            return "JSVAL_TYPE_OBJECT"
+        if t.isString():
+            return "JSVAL_TYPE_STRING"
+        if t.isEnum():
+            return "JSVAL_TYPE_STRING"
+        if t.isCallback():
+            return "JSVAL_TYPE_OBJECT"
+        if t.isAny():
+            # The whole point is to return various stuff
+            return "JSVAL_TYPE_UNKNOWN"
+        if t.isObject():
+            return "JSVAL_TYPE_OBJECT"
+        if t.isSpiderMonkeyInterface():
+            return "JSVAL_TYPE_OBJECT"
+        if t.isUnion():
+            u = t.unroll();
+            if u.hasNullableType:
+                # Might be null or not
+                return "JSVAL_TYPE_UNKNOWN"
+            return reduce(CGMemberJITInfo.getSingleReturnType,
+                          u.flatMemberTypes, "")
+        if t.isDictionary():
+            return "JSVAL_TYPE_OBJECT"
+        if not t.isPrimitive():
+            raise TypeError("No idea what type " + str(t) + " is.")
+        tag = t.tag()
+        if tag in [IDLType.Tags.int8, IDLType.Tags.uint8,
+                   IDLType.Tags.int16, IDLType.Tags.uint16,
+                   IDLType.Tags.int32, IDLType.Tags.bool]:
+            return "JSVAL_TYPE_INT32"
+        if tag in [IDLType.Tags.int64, IDLType.Tags.uint64,
+                   IDLType.Tags.unrestricted_float, IDLType.Tags.float,
+                   IDLType.Tags.unrestricted_double, IDLType.Tags.double]:
+            # These all use JS_NumberValue, which can return int or double.
+            # But TI treats "double" as meaning "int or double", so we're
+            # good to return JSVAL_TYPE_DOUBLE here.
+            return "JSVAL_TYPE_DOUBLE"
+        if tag != IDLType.Tags.uint32:
+            raise TypeError("No idea what type " + str(t) + " is.")
+        # uint32 is sometimes int and sometimes double.
+        return "JSVAL_TYPE_DOUBLE"
+
+    @staticmethod
+    def getSingleReturnType(existingType, t):
+        type = CGMemberJITInfo.getJSReturnTypeTag(t)
+        if existingType == "":
+            # First element of the list; just return its type
+            return type
+
+        if type == existingType:
+            return existingType
+        if ((type == "JSVAL_TYPE_DOUBLE" and
+             existingType == "JSVAL_TYPE_INT32") or
+            (existingType == "JSVAL_TYPE_DOUBLE" and
+             type == "JSVAL_TYPE_INT32")):
+            # Promote INT32 to DOUBLE as needed
+            return "JSVAL_TYPE_DOUBLE"
+        # Different types
+        return "JSVAL_TYPE_UNKNOWN"
+
 def getEnumValueName(value):
     # Some enum values can be empty strings.  Others might have weird
     # characters in them.  Deal with the former by returning "_empty",
     # deal with possible name collisions from that by throwing if the
     # enum value is actually "_empty", and throw on any value
     # containing non-ASCII chars for now. Replace all chars other than
     # [0-9A-Za-z_] with '_'.
     if re.match("[^\x20-\x7E]", value):
@@ -6546,18 +6641,18 @@ class CGDictionary(CGThing):
             # NOTE: jsids are per-runtime, so don't use them in workers
             ("  if (cx && !initedIds && !InitIds(cx)) {\n"
              "    return false;\n"
              "  }\n" if self.needToInitIds else "") +
             "${initParent}" +
             ("  JSBool found;\n"
              "  JS::Value temp;\n" if len(memberInits) > 0 else "") +
             "  bool isNull = val.isNullOrUndefined();\n"
-            "  if (!isNull && !val.isObject()) {\n"
-            "    return ThrowErrorMessage(cx, MSG_NOT_OBJECT);\n"
+            "  if (!IsConvertibleToDictionary(cx, val)) {\n"
+            "    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY);\n"
             "  }\n"
             "\n"
             "${initMembers}\n"
             "  return true;\n"
             "}\n"
             "\n"
             "bool\n"
             "${selfName}::ToObject(JSContext* cx, JSObject* parentObject, JS::Value *vp)\n"
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -25,13 +25,14 @@ MSG_DEF(MSG_NOT_OBJECT, 0, "Value not an
 MSG_DEF(MSG_NOT_CALLABLE, 0, "Value is not callable.")
 MSG_DEF(MSG_DOES_NOT_IMPLEMENT_INTERFACE, 1, "Value does not implement interface {0}.")
 MSG_DEF(MSG_NOT_IN_UNION, 1, "Value could not be converted to any of: {0}.")
 MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, "Illegal constructor.")
 MSG_DEF(MSG_NO_PROPERTY_SETTER, 1, "{0} doesn't have an indexed property setter.")
 MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, "Non-finite value is out of range for {0}.")
 MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, "Value is out of range for {0}.")
 MSG_DEF(MSG_NOT_SEQUENCE, 0, "object can not be converted to a sequence")
+MSG_DEF(MSG_NOT_DICTIONARY, 0, "value can not be converted to a dictionary")
 MSG_DEF(MSG_INVALID_ARG, 2, "argument {0} is not valid for any of the {1}-argument overloads")
 MSG_DEF(MSG_GLOBAL_NOT_NATIVE, 0, "global is not a native object")
 MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, "The given encoding '{0}' is not supported.")
 MSG_DEF(MSG_DOM_ENCODING_NOT_UTF, 0, "The encoding must be utf-8, utf-16, or utf-16be.")
 MSG_DEF(MSG_NOT_FINITE, 0, "Floating-point value is not finite.")
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -1282,24 +1282,24 @@ class IDLSequenceType(IDLType):
     def unroll(self):
         return self.inner.unroll()
 
     def isDistinguishableFrom(self, other):
         if other.isUnion():
             # Just forward to the union; it'll deal
             return other.isDistinguishableFrom(self)
         return (other.isPrimitive() or other.isString() or other.isEnum() or
-                other.isDictionary() or other.isDate() or
-                other.isNonCallbackInterface())
+                other.isDate() or other.isNonCallbackInterface())
 
 class IDLUnionType(IDLType):
     def __init__(self, location, memberTypes):
         IDLType.__init__(self, location, "")
         self.memberTypes = memberTypes
         self.hasNullableType = False
+        self.hasDictionaryType = False
         self.flatMemberTypes = None
         self.builtin = False
 
     def __eq__(self, other):
         return isinstance(other, IDLUnionType) and self.memberTypes == other.memberTypes
 
     def isVoid(self):
         return False
@@ -1340,21 +1340,34 @@ class IDLUnionType(IDLType):
         self.name = "Or".join(typeName(type) for type in self.memberTypes)
         self.flatMemberTypes = list(self.memberTypes)
         i = 0
         while i < len(self.flatMemberTypes):
             if self.flatMemberTypes[i].nullable():
                 if self.hasNullableType:
                     raise WebIDLError("Can't have more than one nullable types in a union",
                                       [nullableType.location, self.flatMemberTypes[i].location])
+                if self.hasDictionaryType:
+                    raise WebIDLError("Can't have a nullable type and a "
+                                      "dictionary type in a union",
+                                      [dictionaryType.location,
+                                       self.flatMemberTypes[i].location])
                 self.hasNullableType = True
                 nullableType = self.flatMemberTypes[i]
                 self.flatMemberTypes[i] = self.flatMemberTypes[i].inner
                 continue
-            if self.flatMemberTypes[i].isUnion():
+            if self.flatMemberTypes[i].isDictionary():
+                if self.hasNullableType:
+                    raise WebIDLError("Can't have a nullable type and a "
+                                      "dictionary type in a union",
+                                      [nullableType.location,
+                                       self.flatMemberTypes[i].location])
+                self.hasDictionaryType = True
+                dictionaryType = self.flatMemberTypes[i]
+            elif self.flatMemberTypes[i].isUnion():
                 self.flatMemberTypes[i:i + 1] = self.flatMemberTypes[i].memberTypes
                 continue
             i += 1
 
         for (i, t) in enumerate(self.flatMemberTypes[:-1]):
             for u in self.flatMemberTypes[i + 1:]:
                 if not t.isDistinguishableFrom(u):
                     raise WebIDLError("Flat member types of a union should be "
@@ -1447,18 +1460,17 @@ class IDLArrayType(IDLType):
     def unroll(self):
         return self.inner.unroll()
 
     def isDistinguishableFrom(self, other):
         if other.isUnion():
             # Just forward to the union; it'll deal
             return other.isDistinguishableFrom(self)
         return (other.isPrimitive() or other.isString() or other.isEnum() or
-                other.isDictionary() or other.isDate() or
-                other.isNonCallbackInterface())
+                other.isDate() or other.isNonCallbackInterface())
 
 class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
     def __init__(self, location, innerType, name):
         IDLType.__init__(self, location, innerType.name)
 
         identifier = IDLUnresolvedIdentifier(location, name)
 
         IDLObjectWithIdentifier.__init__(self, location, None, identifier)
@@ -1613,26 +1625,24 @@ class IDLWrapperType(IDLType):
             # Just forward to the union; it'll deal
             return other.isDistinguishableFrom(self)
         assert self.isInterface() or self.isEnum() or self.isDictionary()
         if self.isEnum():
             return (other.isInterface() or other.isObject() or
                     other.isCallback() or other.isDictionary() or
                     other.isSequence() or other.isArray() or
                     other.isDate())
+        if self.isDictionary() and other.nullable():
+            return False
         if other.isPrimitive() or other.isString() or other.isEnum() or other.isDate():
             return True
         if self.isDictionary():
-            return (not other.nullable() and
-                    (other.isNonCallbackInterface() or other.isSequence() or
-                     other.isArray()))
+            return other.isNonCallbackInterface()
 
         assert self.isInterface()
-        # XXXbz need to check that the interfaces can't be implemented
-        # by the same object
         if other.isInterface():
             if other.isSpiderMonkeyInterface():
                 # Just let |other| handle things
                 return other.isDistinguishableFrom(self)
             assert self.isGeckoInterface() and other.isGeckoInterface()
             if self.inner.isExternal() or other.unroll().inner.isExternal():
                 return self != other
             return (len(self.inner.interfacesBasedOnSelf &
@@ -2141,16 +2151,19 @@ class IDLAttribute(IDLInterfaceMember):
             if self.isStatic():
                 raise WebIDLError("[LenientThis] is only allowed on non-static "
                                   "attributes", [attr.location, self.location])
             self.lenientThis = True
         elif identifier == "Unforgeable":
             if not self.readonly:
                 raise WebIDLError("[Unforgeable] is only allowed on readonly "
                                   "attributes", [attr.location, self.location])
+            if self.isStatic():
+                raise WebIDLError("[Unforgeable] is only allowed on non-static "
+                                  "attributes", [attr.location, self.location])
             self._unforgeable = True
         elif identifier == "Constant" and not self.readonly:
             raise WebIDLError("[Constant] only allowed on readonly attributes",
                               [attr.location, self.location])
         elif identifier == "PutForwards":
             if not self.readonly:
                 raise WebIDLError("[PutForwards] is only allowed on readonly "
                                   "attributes", [attr.location, self.location])
@@ -2531,38 +2544,37 @@ class IDLMethod(IDLInterfaceMember, IDLS
             arguments = overload.arguments
             for (idx, argument) in enumerate(arguments):
                 if argument.isComplete():
                     continue
 
                 argument.complete(scope)
                 assert argument.type.isComplete()
 
-                if argument.type.isDictionary():
-                    # Dictionaries at the end of the list or followed by
-                    # optional arguments must be optional.
+                if (argument.type.isDictionary() or
+                    (argument.type.isUnion() and
+                     argument.type.unroll().hasDictionaryType)):
+                    # Dictionaries and unions containing dictionaries at the
+                    # end of the list or followed by optional arguments must be
+                    # optional.
                     if (not argument.optional and
                         (idx == len(arguments) - 1 or arguments[idx+1].optional)):
-                        raise WebIDLError("Dictionary argument not followed by "
-                                          "a required argument must be "
-                                          "optional", [argument.location])
+                        raise WebIDLError("Dictionary argument or union "
+                                          "argument containing a dictionary "
+                                          "not followed by a required argument "
+                                          "must be optional",
+                                          [argument.location])
 
                     # An argument cannot be a Nullable Dictionary
                     if argument.type.nullable():
-                        raise WebIDLError("An argument cannot be a nullable dictionary",
+                        raise WebIDLError("An argument cannot be a nullable "
+                                          "dictionary or nullable union "
+                                          "containing a dictionary",
                                           [argument.location])
 
-                # An argument cannot be a nullable union containing a dictionary
-                if argument.type.isUnion() and argument.type.nullable():
-                    for memberType in argument.type.inner.flatMemberTypes:
-                        if memberType.isDictionary():
-                            raise WebIDLError("An argument cannot be a nullable union "
-                                              "containing a dictionary",
-                                              [argument.location, memberType.location])
-
                 # Only the last argument can be variadic
                 if variadicArgument:
                     raise WebIDLError("Variadic argument is not last argument",
                                       [variadicArgument.location])
                 # Once we see an optional argument, there can't be any non-optional
                 # arguments.
                 if inOptionalArguments and not argument.optional:
                     raise WebIDLError("Non-optional argument after optional "
--- a/dom/bindings/parser/tests/test_dictionary.py
+++ b/dom/bindings/parser/tests/test_dictionary.py
@@ -140,26 +140,61 @@ def WebIDLTest(parser, harness):
 
     parser = parser.reset()
     threw = False
     try:
         parser.parse("""
             dictionary A {
             };
             interface X {
+              void doFoo((A or DOMString) arg);
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw,
+               "Trailing union arg containing a dictionary must be optional")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            dictionary A {
+            };
+            interface X {
               void doFoo(A arg1, optional long arg2);
             };
         """)
         results = parser.finish()
     except:
         threw = True
 
     harness.ok(threw, "Dictionary arg followed by optional arg must be optional")
 
     parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            dictionary A {
+            };
+            interface X {
+              void doFoo((A or DOMString) arg1, optional long arg2);
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw,
+               "Union arg containing dictionary followed by optional arg must "
+               "be optional")
+
+    parser = parser.reset()
     parser.parse("""
             dictionary A {
             };
             interface X {
               void doFoo(A arg1, long arg2);
             };
         """)
     results = parser.finish()
@@ -183,29 +218,81 @@ def WebIDLTest(parser, harness):
 
     parser = parser.reset()
     threw = False
     try:
         parser.parse("""
             dictionary A {
             };
             interface X {
-              void doFoo((A or long)? arg1);
+              void doFoo(optional (A or long)? arg1);
             };
         """)
         results = parser.finish()
     except:
         threw = True
 
     harness.ok(threw, "Dictionary arg must not be in a nullable union")
 
     parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            dictionary A {
+            };
+            interface X {
+              void doFoo(optional (A or long?) arg1);
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+    harness.ok(threw,
+               "Dictionary must not be in a union with a nullable type")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            dictionary A {
+            };
+            interface X {
+              void doFoo(optional (long? or A) arg1);
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+    harness.ok(threw,
+               "A nullable type must not be in a union with a dictionary")
+
+    parser = parser.reset()
     parser.parse("""
         dictionary A {
         };
         interface X {
           A? doFoo();
         };
     """)
     results = parser.finish()
-
     harness.ok(True, "Dictionary return value can be nullable")
 
+    parser = parser.reset()
+    parser.parse("""
+        dictionary A {
+        };
+        interface X {
+          void doFoo(optional A arg);
+        };
+    """)
+    results = parser.finish()
+    harness.ok(True, "Dictionary arg should actually parse")
+
+    parser = parser.reset()
+    parser.parse("""
+        dictionary A {
+        };
+        interface X {
+          void doFoo(optional (A or DOMString) arg);
+        };
+    """)
+    results = parser.finish()
+    harness.ok(True, "Union arg containing a dictionary should actually parse")
--- a/dom/bindings/parser/tests/test_distinguishability.py
+++ b/dom/bindings/parser/tests/test_distinguishability.py
@@ -143,8 +143,114 @@ def WebIDLTest(parser, harness):
             void method(DOMString arg1, DOMString arg2, DOMString arg3);
           };
         """)
         results = parser.finish()
     except:
         threw = True
 
     harness.ok(threw, "Should throw when there is no distinguishing index")
+
+    # Now let's test our whole distinguishability table
+    argTypes = [ "long", "short", "long?", "short?", "DOMString", "Enum",
+                 "Enum2", "Interface", "Interface?",
+                 "AncestorInterface", "UnrelatedInterface",
+                 "ImplementedInterface", "CallbackInterface",
+                 "CallbackInterface?", "CallbackInterface2",
+                 "object", "Callback", "Callback2", "optional Dict",
+                 "optional Dict2", "sequence<long>", "sequence<short>",
+                 "long[]", "short[]" ]
+    # When we can parse Date and RegExp, we need to add them here.
+
+    # Try to categorize things a bit to keep list lengths down
+    def allBut(list1, list2):
+        return [a for a in list1 if a not in list2]
+    primitives = [ "long", "short", "long?", "short?", "DOMString",
+                   "Enum", "Enum2" ]
+    nonPrimitives = allBut(argTypes, primitives)
+    interfaces = [ "Interface", "Interface?", "AncestorInterface",
+                   "UnrelatedInterface", "ImplementedInterface" ]
+    nullables = ["long?", "short?", "Interface?", "CallbackInterface?",
+                 "optional Dict", "optional Dict2"]
+    nonUserObjects = primitives + interfaces
+    otherObjects = allBut(argTypes, nonUserObjects + ["object"])
+    notRelatedInterfaces = primitives + ["UnrelatedInterface"] + otherObjects
+
+    # Build a representation of the distinguishability table as a dict
+    # of dicts, holding True values where needed, holes elsewhere.
+    data = dict();
+    for type in argTypes:
+        data[type] = dict()
+    def setDistinguishable(type, types):
+        for other in types:
+            data[type][other] = True
+
+    setDistinguishable("long", nonPrimitives)
+    setDistinguishable("short", nonPrimitives)
+    setDistinguishable("long?", allBut(nonPrimitives, nullables))
+    setDistinguishable("short?", allBut(nonPrimitives, nullables))
+    setDistinguishable("DOMString", nonPrimitives)
+    setDistinguishable("Enum", nonPrimitives)
+    setDistinguishable("Enum2", nonPrimitives)
+    setDistinguishable("Interface", notRelatedInterfaces)
+    setDistinguishable("Interface?", allBut(notRelatedInterfaces, nullables))
+    setDistinguishable("AncestorInterface", notRelatedInterfaces)
+    setDistinguishable("UnrelatedInterface",
+                       allBut(argTypes, ["object", "UnrelatedInterface"]))
+    setDistinguishable("ImplementedInterface", notRelatedInterfaces)
+    setDistinguishable("CallbackInterface", nonUserObjects)
+    setDistinguishable("CallbackInterface?", allBut(nonUserObjects, nullables))
+    setDistinguishable("CallbackInterface2", nonUserObjects)
+    setDistinguishable("object", primitives)
+    setDistinguishable("Callback", nonUserObjects)
+    setDistinguishable("Callback2", nonUserObjects)
+    setDistinguishable("optional Dict", allBut(nonUserObjects, nullables))
+    setDistinguishable("optional Dict2", allBut(nonUserObjects, nullables))
+    setDistinguishable("sequence<long>", nonUserObjects)
+    setDistinguishable("sequence<short>", nonUserObjects)
+    setDistinguishable("long[]", nonUserObjects)
+    setDistinguishable("short[]", nonUserObjects)
+
+    def areDistinguishable(type1, type2):
+        return data[type1].get(type2, False)
+
+    def checkDistinguishability(parser, type1, type2):
+        idlTemplate = """
+          enum Enum { "a", "b" };
+          enum Enum2 { "c", "d" };
+          interface Interface : AncestorInterface {};
+          interface AncestorInterface {};
+          interface UnrelatedInterface {};
+          interface ImplementedInterface {};
+          Interface implements ImplementedInterface;
+          callback interface CallbackInterface {};
+          callback interface CallbackInterface2 {};
+          callback Callback = any();
+          callback Callback2 = long(short arg);
+          dictionary Dict {};
+          dictionary Dict2 {};
+          interface TestInterface {%s
+          };
+        """
+        methodTemplate = """
+            void myMethod(%s arg);"""
+        methods = (methodTemplate % type1) + (methodTemplate % type2)
+        idl = idlTemplate % methods
+        parser = parser.reset()
+        threw = False
+        try:
+            parser.parse(idl)
+            results = parser.finish()
+        except:
+            threw = True
+
+        if areDistinguishable(type1, type2):
+            harness.ok(not threw,
+                       "Should not throw for '%s' and '%s' because they are distinguishable" % (type1, type2))
+        else:
+            harness.ok(threw,
+                       "Should throw for '%s' and '%s' because they are not distinguishable" % (type1, type2))
+
+    # Enumerate over everything in both orders, since order matters in
+    # terms of our implementation of distinguishability checks
+    for type1 in argTypes:
+        for type2 in argTypes:
+            checkDistinguishability(parser, type1, type2)
--- a/dom/bindings/parser/tests/test_unforgeable.py
+++ b/dom/bindings/parser/tests/test_unforgeable.py
@@ -171,8 +171,23 @@ def WebIDLTest(parser, harness):
             };
         """)
 
         results = parser.finish()
     except:
         threw = True
 
     harness.ok(threw, "Should have thrown for writable [Unforgeable] attribute.")
+
+    parser = parser.reset();
+    threw = False
+    try:
+        parser.parse("""
+            interface iface {
+              [Unforgeable] static readonly attribute long foo;
+            };
+        """)
+
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw, "Should have thrown for static [Unforgeable] attribute.")
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -399,16 +399,20 @@ public:
   void PassOptionalCallback(const Optional<OwningNonNull<TestCallback> >&);
   void PassOptionalNullableCallback(const Optional<nsRefPtr<TestCallback> >&);
   void PassOptionalNullableCallbackWithDefaultValue(TestCallback*);
   already_AddRefed<TestCallback> ReceiveCallback();
   already_AddRefed<TestCallback> ReceiveNullableCallback();
   void PassNullableTreatAsNullCallback(TestTreatAsNullCallback*);
   void PassOptionalNullableTreatAsNullCallback(const Optional<nsRefPtr<TestTreatAsNullCallback> >&);
   void PassOptionalNullableTreatAsNullCallbackWithDefaultValue(TestTreatAsNullCallback*);
+  void SetTreatAsNullCallback(TestTreatAsNullCallback&);
+  already_AddRefed<TestTreatAsNullCallback> TreatAsNullCallback();
+  void SetNullableTreatAsNullCallback(TestTreatAsNullCallback*);
+  already_AddRefed<TestTreatAsNullCallback> GetNullableTreatAsNullCallback();
 
   // Any types
   void PassAny(JSContext*, JS::Value);
   void PassOptionalAny(JSContext*, const Optional<JS::Value>&);
   void PassAnyDefaultNull(JSContext*, JS::Value);
   JS::Value ReceiveAny(JSContext*);
 
   // object types
@@ -473,16 +477,25 @@ public:
   // Static methods and attributes
   static void StaticMethod(nsISupports*, bool);
   static bool StaticAttribute(nsISupports*);
   static void SetStaticAttribute(nsISupports*, bool);
 
   // Overload resolution tests
   bool Overload1(TestInterface&);
   TestInterface* Overload1(const nsAString&, TestInterface&);
+  void Overload2(TestInterface&);
+  void Overload2(const Dict&);
+  void Overload2(const nsAString&);
+  void Overload3(TestInterface&);
+  void Overload3(const TestCallback&);
+  void Overload3(const nsAString&);
+  void Overload4(TestInterface&);
+  void Overload4(TestCallbackInterface&);
+  void Overload4(const nsAString&);
 
   // Variadic handling
   void PassVariadicThirdArg(const nsAString&, int32_t,
                             const Sequence<OwningNonNull<TestInterface> >&);
 
   // Miscellania
   int32_t AttrWithLenientThis();
   void SetAttrWithLenientThis(int32_t);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -354,16 +354,18 @@ interface TestInterface {
   void passOptionalCallback(optional TestCallback arg);
   void passOptionalNullableCallback(optional TestCallback? arg);
   void passOptionalNullableCallbackWithDefaultValue(optional TestCallback? arg = null);
   TestCallback receiveCallback();
   TestCallback? receiveNullableCallback();
   void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
+  attribute TestTreatAsNullCallback treatAsNullCallback;
+  attribute TestTreatAsNullCallback? nullableTreatAsNullCallback;
 
   // Any types
   void passAny(any arg);
   void passOptionalAny(optional any arg);
   void passAnyDefaultNull(optional any arg = null);
   any receiveAny();
 
   // object types
@@ -425,16 +427,25 @@ interface TestInterface {
   // Static methods and attributes
   static attribute boolean staticAttribute;
   static void staticMethod(boolean arg);
 
   // Overload resolution tests
   //void overload1(DOMString... strs);
   boolean overload1(TestInterface arg);
   TestInterface overload1(DOMString strs, TestInterface arg);
+  void overload2(TestInterface arg);
+  void overload2(optional Dict arg);
+  void overload2(DOMString arg);
+  void overload3(TestInterface arg);
+  void overload3(TestCallback arg);
+  void overload3(DOMString arg);
+  void overload4(TestInterface arg);
+  void overload4(TestCallbackInterface arg);
+  void overload4(DOMString arg);
 
   // Variadic handling
   void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
 
   // Miscellania
   [LenientThis] attribute long attrWithLenientThis;
   [Unforgeable] readonly attribute long unforgeableAttr;
   [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2;
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -346,16 +346,25 @@ interface TestExampleInterface {
   // Static methods and attributes
   static attribute boolean staticAttribute;
   static void staticMethod(boolean arg);
 
   // Overload resolution tests
   //void overload1(DOMString... strs);
   boolean overload1(TestInterface arg);
   TestInterface overload1(DOMString strs, TestInterface arg);
+  void overload2(TestInterface arg);
+  void overload2(optional Dict arg);
+  void overload2(DOMString arg);
+  void overload3(TestInterface arg);
+  void overload3(TestCallback arg);
+  void overload3(DOMString arg);
+  void overload4(TestInterface arg);
+  void overload4(TestCallbackInterface arg);
+  void overload4(DOMString arg);
 
   // Variadic handling
   void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
 
   // Miscellania
   [LenientThis] attribute long attrWithLenientThis;
   [Unforgeable] readonly attribute long unforgeableAttr;
   [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2;
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -35,17 +35,17 @@ interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMTouch;
 interface nsIDOMClientRect;
 interface nsIURI;
 
-[scriptable, uuid(2196a216-ed3c-46dd-aa24-9f5b3ac17539)]
+[scriptable, uuid(c98249a5-d38a-4ec6-b6e0-6866ea87d6bb)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1039,18 +1039,19 @@ interface nsIDOMWindowUtils : nsISupport
   /**
    * What type of layer manager the widget associated with this window is
    * using. "Basic" is unaccelerated; other types are accelerated. Throws an
    * error if there is no widget associated with this window.
    */
   readonly attribute AString layerManagerType;
 
   void startFrameTimeRecording();
-  void stopFrameTimeRecording([optional] out unsigned long frameCount,
-                              [retval, array, size_is(frameCount)] out float frameTime);
+  void stopFrameTimeRecording([optional, array, size_is(frameCount)] out float paintTimes,
+                              [optional] out unsigned long frameCount,
+                              [retval, array, size_is(frameCount)] out float frameIntervals);
   /**
    * Signals that we're begining to tab switch. This is used by painting code to
    * determine total tab switch time.
    */
   void beginTabSwitch();
 
   /**
    * The DPI of the display
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -700,26 +700,30 @@ ContentParent::ActorDestroy(ActorDestroy
         props->Init();
 
         props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), mChildID);
 
         if (AbnormalShutdown == why) {
             props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), true);
 
 #ifdef MOZ_CRASHREPORTER
-            MOZ_ASSERT(ManagedPCrashReporterParent().Length() > 0);
-            CrashReporterParent* crashReporter =
+            // There's a window in which child processes can crash
+            // after IPC is established, but before a crash reporter
+            // is created.
+            if (ManagedPCrashReporterParent().Length() > 0) {
+                CrashReporterParent* crashReporter =
                     static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
 
-            crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("URL"),
-                                               NS_ConvertUTF16toUTF8(mAppManifestURL));
-            crashReporter->GenerateCrashReport(this, NULL);
+                crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("URL"),
+                                                   NS_ConvertUTF16toUTF8(mAppManifestURL));
+                crashReporter->GenerateCrashReport(this, NULL);
 
-            nsAutoString dumpID(crashReporter->ChildDumpID());
-            props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
+                nsAutoString dumpID(crashReporter->ChildDumpID());
+                props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
+            }
 #endif
         }
         obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nullptr);
     }
 
     MessageLoop::current()->
         PostTask(FROM_HERE,
                  NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et ft=cpp : */
 /* 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 "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/ipc/ProcessPriorityManager.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/Hal.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/HalTypes.h"
 #include "mozilla/TimeStamp.h"
@@ -21,32 +22,35 @@
 #include "nsIObserverService.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMDocument.h"
 #include "nsPIDOMWindow.h"
+#include "StaticPtr.h"
 
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #else
 #include <unistd.h>
 #endif
 
 using namespace mozilla::hal;
 
 namespace mozilla {
 namespace dom {
 namespace ipc {
 
 namespace {
 static bool sInitialized = false;
+class ProcessPriorityManager;
+static StaticRefPtr<ProcessPriorityManager> sManager;
 
 // Some header defines a LOG macro, but we don't want it here.
 #ifdef LOG
 #undef LOG
 #endif
 
 // Enable logging by setting
 //
@@ -122,16 +126,18 @@ class ProcessPriorityManager MOZ_FINAL
 public:
   ProcessPriorityManager();
   void Init();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIDOMEVENTLISTENER
 
+  ProcessPriority GetPriority() const { return mProcessPriority; }
+
 private:
   void SetPriority(ProcessPriority aPriority);
   void OnContentDocumentGlobalCreated(nsISupports* aOuterWindow);
   void OnInnerWindowDestroyed();
   void OnGracePeriodTimerFired();
   void RecomputeNumVisibleWindows();
 
   // mProcessPriority tracks the priority we've given this process in hal,
@@ -384,16 +390,22 @@ InitProcessPriorityManager()
   // ProcessPriorityManager (we never want to mark the master process as
   // backgrounded).
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     LOG("This is the master process.");
     hal::SetProcessPriority(getpid(), PROCESS_PRIORITY_MASTER);
     return;
   }
 
-  // This object is held alive by the observer service.
-  nsRefPtr<ProcessPriorityManager> mgr = new ProcessPriorityManager();
-  mgr->Init();
+  sManager = new ProcessPriorityManager();
+  sManager->Init();
+  ClearOnShutdown(&sManager);
+}
+
+bool
+CurrentProcessIsForeground()
+{
+  return sManager->GetPriority() >= PROCESS_PRIORITY_FOREGROUND;
 }
 
 } // namespace ipc
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ProcessPriorityManager.h
+++ b/dom/ipc/ProcessPriorityManager.h
@@ -21,13 +21,20 @@ namespace ipc {
  *
  * Hal may adjust this process's operating system priority (e.g. niceness, on
  * *nix) according to these notificaitons.
  *
  * This function call does nothing if the pref for OOP tabs is not set.
  */
 void InitProcessPriorityManager();
 
+/**
+ * True iff the current process has foreground or higher priority as
+ * computed by DOM visibility.  The returned answer may not match the
+ * actual OS process priority, for short intervals.
+ */
+bool CurrentProcessIsForeground();
+
 } // namespace ipc
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -50,17 +50,17 @@
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISecureBrowserUI.h"
 #include "nsIServiceManager.h"
 #include "nsISupportsImpl.h"
 #include "nsIURI.h"
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
-#include "nsIView.h"
+#include "nsView.h"
 #include "nsIWebBrowser.h"
 #include "nsIWebBrowserFocus.h"
 #include "nsIWebBrowserSetup.h"
 #include "nsIWebProgress.h"
 #include "nsIXPCSecurityManager.h"
 #include "nsInterfaceHashtable.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
--- a/dom/media/tests/mochitest/Makefile.in
+++ b/dom/media/tests/mochitest/Makefile.in
@@ -5,31 +5,29 @@
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 relativesrcdir = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-# Bug 814718 prevents us from running the following test:
-#  test_getUserMedia_basicVideo.html
-
 MOCHITEST_FILES = \
   test_getUserMedia_exceptions.html \
+  test_getUserMedia_basicAudio.html \
+  test_getUserMedia_basicVideo.html \
+  test_getUserMedia_basicVideoAudio.html \
   head.js \
   mediaStreamPlayback.js \
   pc.js \
   $(NULL)
 
 # The following tests are leaking and cannot be run by default yet
 ifdef MOZ_WEBRTC_LEAKING_TESTS
 MOCHITEST_FILES += \
-  test_getUserMedia_basicAudio.html \
-  test_getUserMedia_basicVideoAudio.html \
   test_peerConnection_basicAudio.html \
   test_peerConnection_basicAudioVideo.html \
   test_peerConnection_basicAudioVideoCombined.html \
   test_peerConnection_basicVideo.html \
   $(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/media/tests/mochitest/mediaStreamPlayback.js
+++ b/dom/media/tests/mochitest/mediaStreamPlayback.js
@@ -76,35 +76,35 @@ function MediaStreamPlayback(mediaElemen
       is(self.mediaElement.preload, "", "Preload should not exist");
       is(self.mediaElement.src, "", "No src should be defined");
       is(self.mediaElement.currentSrc, "",
          "Current src should still be an empty string");
 
       var timeUpdateFired = false;
 
       var timeUpdateCallback = function() {
-        timeUpdateFired = true;
-        self.mediaElement.removeEventListener('timeupdate', timeUpdateCallback,
-          false);
-
-        ok(self.mediaStream.currentTime > 0,
-           "Stream's time should be greater than zero");
-        ok(self.mediaElement.currentTime > 0,
-           "MediaElement time shall be greater than zero");
-        onSuccess();
+        if(self.mediaStream.currentTime > 0 &&
+           self.mediaElement.currentTime > 0) {
+          timeUpdateFired = true;
+          self.mediaElement.removeEventListener('timeupdate', timeUpdateCallback,
+            false);
+          onSuccess();
+        }
       };
 
       // When timeupdate fires, we validate time has passed and move
       // onto the success condition
       self.mediaElement.addEventListener('timeupdate', timeUpdateCallback,
         false);
 
       // If timeupdate doesn't fire in enough time, we fail the test
       setTimeout(function() {
         if(!timeUpdateFired) {
+          self.mediaElement.removeEventListener('timeupdate',
+            timeUpdateCallback, false);
           ok(false, "timeUpdate event never fired");
           onError();
         }
       }, timeoutLength);
     };
 
     // Adds a listener intended to be fired when playback is available
     // without further buffering.
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -722,17 +722,17 @@ NS_IMETHODIMP nsPluginInstanceOwner::Get
     // would otherwise cause coordinates to be offset incorrectly. (i.e.
     // if the enclosing window if offset from the document window)
     //
     // fixing both the caret and ability to interact issues for a windowless control in a non document aligned windw
     // does not seem to be possible without a change to the flash plugin
     
     nsIWidget* win = mObjectFrame->GetNearestWidget();
     if (win) {
-      nsIView *view = nsIView::GetViewFor(win);
+      nsView *view = nsView::GetViewFor(win);
       NS_ASSERTION(view, "No view for widget");
       nsPoint offset = view->GetOffsetTo(nullptr);
       
       if (offset.x || offset.y) {
         // in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window
         // so that mouse co-ordinates are not messed up.
         *pvalue = (void*)win->GetNativeData(NS_NATIVE_WINDOW);
         if (*pvalue)
--- a/dom/plugins/base/nsPluginNativeWindowGtk2.cpp
+++ b/dom/plugins/base/nsPluginNativeWindowGtk2.cpp
@@ -129,25 +129,24 @@ nsresult nsPluginNativeWindowGtk2::CallS
         }
       }
 
       if (!mSocketWidget) {
         return NS_ERROR_FAILURE;
       }
 
       // Make sure to resize and re-place the window if required.
+      SetAllocation();
       // Need to reset "window" each time as nsObjectFrame::DidReflow sets it
       // to the ancestor window.
       if (GTK_IS_XTBIN(mSocketWidget)) {
-        gtk_xtbin_resize(mSocketWidget, width, height);
         // Point the NPWindow structures window to the actual X window
         SetWindow(GTK_XTBIN(mSocketWidget)->xtwindow);
       }
       else { // XEmbed or OOP&Xt
-        SetAllocation();
         SetWindow(gtk_socket_get_id(GTK_SOCKET(mSocketWidget)));
       }
 #ifdef DEBUG
       printf("nsPluginNativeWindowGtk2: call SetWindow with xid=%p\n", (void *)window);
 #endif
     } // NPWindowTypeWindow
     aPluginInstance->SetWindow(this);
   }
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -3,17 +3,16 @@
  * 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 "nsPluginStreamListenerPeer.h"
 #include "nsIStreamConverterService.h"
 #include "nsIHttpChannel.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsIFileChannel.h"
-#include "nsICachingChannel.h"
 #include "nsMimeTypes.h"
 #include "nsISupportsPrimitives.h"
 #include "nsNetCID.h"
 #include "nsPluginLogging.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsPluginHost.h"
 #include "nsIByteRangeRequest.h"
@@ -354,18 +353,16 @@ nsresult nsPluginStreamListenerPeer::Ini
   mDataForwardToRequest = new nsHashtable(16, false);
   if (!mDataForwardToRequest)
     return NS_ERROR_FAILURE;
 
   return NS_OK;
 }
 
 // SetupPluginCacheFile is called if we have to save the stream to disk.
-// the most likely cause for this is either there is no disk cache available
-// or the stream is coming from a https server.
 //
 // These files will be deleted when the host is destroyed.
 //
 // TODO? What if we fill up the the dest dir?
 nsresult
 nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
 {
   nsresult rv = NS_OK;
@@ -754,23 +751,19 @@ nsresult nsPluginStreamListenerPeer::Ser
   
   mSeekable = false;
   mPStreamListener->OnStartBinding(this);
   mStreamOffset = 0;
   
   // force the plugin to use stream as file
   mStreamType = NP_ASFILE;
   
-  // then check it out if browser cache is not available
-  nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request);
-  if (!(cacheChannel && (NS_SUCCEEDED(cacheChannel->SetCacheAsFile(true))))) {
-    nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
-    if (channel) {
-      SetupPluginCacheFile(channel);
-    }
+  nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
+  if (channel) {
+    SetupPluginCacheFile(channel);
   }
   
   // unset mPendingRequests
   mPendingRequests = 0;
   
   return NS_OK;
 }
 
@@ -979,25 +972,20 @@ NS_IMETHODIMP nsPluginStreamListenerPeer
   }
   
   // call OnFileAvailable if plugin requests stream type StreamType_AsFile or StreamType_AsFileOnly
   if (mStreamType >= NP_ASFILE) {
     nsCOMPtr<nsIFile> localFile;
     if (mLocalCachedFileHolder)
       localFile = mLocalCachedFileHolder->file();
     else {
-      nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request);
-      if (cacheChannel) {
-        cacheChannel->GetCacheFile(getter_AddRefs(localFile));
-      } else {
-        // see if it is a file channel.
-        nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(request);
-        if (fileChannel) {
-          fileChannel->GetFile(getter_AddRefs(localFile));
-        }
+      // see if it is a file channel.
+      nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(request);
+      if (fileChannel) {
+        fileChannel->GetFile(getter_AddRefs(localFile));
       }
     }
     
     if (localFile) {
       OnFileAvailable(localFile);
     }
   }
   
@@ -1138,21 +1126,17 @@ nsresult nsPluginStreamListenerPeer::Set
     return rv;
   
   mPStreamListener->GetStreamType(&mStreamType);
   
   if (!useLocalCache && mStreamType >= NP_ASFILE) {
     // check it out if this is not a file channel.
     nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(request);
     if (!fileChannel) {
-      // and browser cache is not available
-      nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request);
-      if (!(cacheChannel && (NS_SUCCEEDED(cacheChannel->SetCacheAsFile(true))))) {
         useLocalCache = true;
-      }
     }
   }
   
   if (useLocalCache) {
     SetupPluginCacheFile(channel);
   }
   
   return NS_OK;
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -176,20 +176,16 @@ PluginModuleChild::Init(const std::strin
 
 #if defined(MOZ_X11) && !defined(MOZ_PLATFORM_MAEMO)
     NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
     if (StringBeginsWith(nsDependentCString(info.fDescription), flash10Head)) {
         AddQuirk(QUIRK_FLASH_EXPOSE_COORD_TRANSLATION);
     }
 #else // defined(OS_MACOSX)
     mozilla::plugins::PluginUtilsOSX::SetProcessName(info.fName);
-    NS_NAMED_LITERAL_CSTRING(flashHead, "Shockwave Flash");
-    if (StringBeginsWith(nsDependentCString(info.fDescription), flashHead)) {
-        AddQuirk(QUIRK_FLASH_AVOID_CGMODE_CRASHES);
-    }
 #endif
 
     if (!mLibrary)
 #endif
     {
         nsresult rv = pluginFile.LoadPlugin(&mLibrary);
         if (NS_FAILED(rv))
             return false;
@@ -1992,16 +1988,19 @@ PluginModuleChild::InitQuirksModes(const
       mQuirks |= QUIRK_QUICKTIME_AVOID_SETWINDOW;
     }
 #endif
 
 #ifdef XP_MACOSX
     // Whitelist Flash and Quicktime to support offline renderer
     NS_NAMED_LITERAL_CSTRING(flash, "application/x-shockwave-flash");
     NS_NAMED_LITERAL_CSTRING(quicktime, "QuickTime Plugin.plugin");
+    if (FindInReadable(flash, aMimeType)) {
+      mQuirks |= QUIRK_FLASH_AVOID_CGMODE_CRASHES;
+    }
     if (FindInReadable(flash, aMimeType) ||
         FindInReadable(quicktime, mPluginFilename)) {
         mQuirks |= QUIRK_ALLOW_OFFLINE_RENDERER;
     }
 #endif
 }
 
 bool
--- a/dom/sms/interfaces/Makefile.in
+++ b/dom/sms/interfaces/Makefile.in
@@ -16,16 +16,17 @@ include $(topsrcdir)/dom/dom-config.mk
 XPIDLSRCS = \
   nsIDOMNavigatorSms.idl \
   nsIDOMSmsManager.idl \
   nsIDOMSmsMessage.idl \
   nsIDOMSmsEvent.idl \
   nsIDOMSmsRequest.idl \
   nsIDOMSmsFilter.idl \
   nsIDOMSmsCursor.idl \
+  nsIDOMSmsSegmentInfo.idl \
   nsISmsDatabaseService.idl \
   nsISmsRequest.idl \
   nsISmsService.idl \
   $(NULL)
 
 ifdef MOZ_B2G_RIL
 XPIDLSRCS += \
   nsIRilSmsDatabaseService.idl \
--- a/dom/sms/interfaces/nsIDOMSmsManager.idl
+++ b/dom/sms/interfaces/nsIDOMSmsManager.idl
@@ -2,21 +2,22 @@
  * 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 nsIDOMEventListener;
 interface nsIDOMMozSmsRequest;
 interface nsIDOMMozSmsFilter;
+interface nsIDOMMozSmsSegmentInfo;
 
-[scriptable, builtinclass, uuid(1b3b8a3e-7ee6-4192-ae8f-a627b2ece95b)]
+[scriptable, builtinclass, uuid(2bdb02e7-ec3a-47a9-885c-0ab514566801)]
 interface nsIDOMMozSmsManager : nsIDOMEventTarget
 {
-  unsigned short getNumberOfMessagesForText(in DOMString text);
+  nsIDOMMozSmsSegmentInfo getSegmentInfoForText(in DOMString text);
 
   // The first parameter can be either a DOMString (only one number) or an array
   // of DOMStrings.
   // The method returns a SmsRequest object if one number has been passed.
   // An array of SmsRequest objects otherwise.
   jsval send(in jsval number, in DOMString message);
 
   [binaryname(GetMessageMoz)]
new file mode 100644
--- /dev/null
+++ b/dom/sms/interfaces/nsIDOMSmsSegmentInfo.idl
@@ -0,0 +1,16 @@
+/* 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, builtinclass, uuid(57ac3989-531e-4928-998b-53fde81a05a6)]
+interface nsIDOMMozSmsSegmentInfo : nsISupports
+{
+  /* The number of total segments for the input string. */
+  readonly attribute long segments;
+  /* The number of characters available per segment. */
+  readonly attribute long charsPerSegment;
+  /* The maximum number of available characters in the last segment. */
+  readonly attribute long charsAvailableInLastSegment;
+};
--- a/dom/sms/interfaces/nsISmsService.idl
+++ b/dom/sms/interfaces/nsISmsService.idl