Merge m-c to b-s.
authorMs2ger <ms2ger@gmail.com>
Tue, 26 Feb 2013 19:09:25 +0100
changeset 133663 1ef658c8d6462e0c54ae57f713a2a3320e75253c
parent 133662 f5edb9df59386952a904d6b0251ec83479b3cffb (current diff)
parent 133387 a4f834dd884f8c081915f53097671622c220bf37 (diff)
child 133664 eb634979fdd7ab2ddf37135cacee51d51cdfdd33
push id2452
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 16:59:38 +0000
treeherdermozilla-beta@d4b152d29d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone22.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 m-c to b-s.
browser/components/privatebrowsing/Makefile.in
browser/components/privatebrowsing/moz.build
browser/components/privatebrowsing/src/Makefile.in
browser/components/privatebrowsing/src/moz.build
browser/components/privatebrowsing/src/nsPrivateBrowsingServiceObsolete.js
browser/components/privatebrowsing/src/nsPrivateBrowsingServiceObsolete.manifest
configure.in
content/html/content/test/Makefile.in
netwerk/base/public/nsIPrivateBrowsingServiceObsolete.idl
--- a/CLOBBER
+++ b/CLOBBER
@@ -10,9 +10,9 @@
 #                  O   <-- Users coming from both parents need to Clobber
 #               /     \
 #          O               O
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
-Bug 829832 - BackgroundFileSaver xpcshell failures without clobber
+Bug 845063 needs clobber
--- a/accessible/public/nsIAccessibleRelation.idl
+++ b/accessible/public/nsIAccessibleRelation.idl
@@ -5,119 +5,114 @@
 
 #include "nsISupports.idl"
 #include "nsIArray.idl"
 
 interface nsIAccessible;
 
 /**
  * This interface gives access to an accessible's set of relations.
- * Be carefull, do not change constants until ATK has a structure to map gecko
- * constants into ATK constants.
  */
-[scriptable, uuid(f42a1589-70ab-4704-877f-4a9162bbe188)]
+[scriptable, uuid(9f85fc0d-2969-48e6-b822-68140f7e5770)]
 interface nsIAccessibleRelation : nsISupports
 {
+  /**
+   * This object is labelled by a target object.
+   */
+  const unsigned long RELATION_LABELLED_BY = 0x00;
 
-  const unsigned long RELATION_NUL = 0x00;
+  /**
+   * This object is label for a target object.
+   */
+  const unsigned long RELATION_LABEL_FOR = 0x01;
+
+  /**
+   * This object is described by the target object.
+   */
+  const unsigned long RELATION_DESCRIBED_BY = 0x02;
+
+  /**
+   * This object is describes the target object.
+   */
+  const unsigned long RELATION_DESCRIPTION_FOR = 0x3;
+
+  /**
+   * This object is a child of a target object.
+   */
+  const unsigned long RELATION_NODE_CHILD_OF = 0x4;
+
+  /**
+   * This object is a parent of a target object. A dual relation to
+   * RELATION_NODE_CHILD_OF
+   */
+  const unsigned long RELATION_NODE_PARENT_OF = 0x5;
 
   /**
    * Some attribute of this object is affected by a target object.
    */
-  const unsigned long RELATION_CONTROLLED_BY = 0x01;
-
-  // First relation
-  const unsigned long RELATION_FIRST = RELATION_CONTROLLED_BY;
+  const unsigned long RELATION_CONTROLLED_BY = 0x06;
 
   /**
    * This object is interactive and controls some attribute of a target object.
    */
-  const unsigned long RELATION_CONTROLLER_FOR = 0x02;
+  const unsigned long RELATION_CONTROLLER_FOR = 0x07;
 
   /**
-   * This object is label for a target object.
+   * Content flows from this object to a target object, i.e. has content that
+   * flows logically to another object in a sequential way, e.g. text flow.
    */
-  const unsigned long RELATION_LABEL_FOR = 0x03;
+  const unsigned long RELATION_FLOWS_TO = 0x08;
 
   /**
-   * This object is labelled by a target object.
+   * Content flows to this object from a target object, i.e. has content that
+   * flows logically from another object in a sequential way, e.g. text flow.
    */
-  const unsigned long RELATION_LABELLED_BY = 0x04;
+  const unsigned long RELATION_FLOWS_FROM = 0x09;
 
   /**
    * This object is a member of a group of one or more objects. When there is
    * more than one object in the group each member may have one and the same
    * target, e.g. a grouping object.  It is also possible that each member has
    * multiple additional targets, e.g. one for every other member in the group.
    */
-  const unsigned long RELATION_MEMBER_OF = 0x05;
-
-  /**
-   * This object is a child of a target object.
-   */
-  const unsigned long RELATION_NODE_CHILD_OF = 0x06;
-
-  /**
-   * Content flows from this object to a target object, i.e. has content that
-   * flows logically to another object in a sequential way, e.g. text flow.
-   */
-  const unsigned long RELATION_FLOWS_TO = 0x07;
-
-  /**
-   * Content flows to this object from a target object, i.e. has content that
-   * flows logically from another object in a sequential way, e.g. text flow.
-   */
-  const unsigned long RELATION_FLOWS_FROM = 0x08;
+  const unsigned long RELATION_MEMBER_OF = 0x0a;
 
   /**
    * This object is a sub window of a target object.
    */
-  const unsigned long RELATION_SUBWINDOW_OF = 0x09;
+  const unsigned long RELATION_SUBWINDOW_OF = 0x0b;
 
   /**
    * This object embeds a target object. This relation can be used on the
    * OBJID_CLIENT accessible for a top level window to show where the content
    * areas are.
    */
-  const unsigned long RELATION_EMBEDS = 0x0a;
+  const unsigned long RELATION_EMBEDS = 0x0c;
 
   /**
    * This object is embedded by a target object.
    */
-  const unsigned long RELATION_EMBEDDED_BY = 0x0b;
+  const unsigned long RELATION_EMBEDDED_BY = 0x0d;
 
   /**
    * This object is a transient component related to the target object. When
    * this object is activated the target object doesn't lose focus.
    */
-  const unsigned long RELATION_POPUP_FOR = 0x0c;
+  const unsigned long RELATION_POPUP_FOR = 0x0e;
 
   /**
    * This object is a parent window of the target object.
    */
-  const unsigned long RELATION_PARENT_WINDOW_OF = 0x0d;
-
-  /**
-   * This object is described by the target object.
-   */
-  const unsigned long RELATION_DESCRIBED_BY = 0x0e;
-
-  /**
-   * This object is describes the target object.
-   */
-  const unsigned long RELATION_DESCRIPTION_FOR = 0x0f;
-
-  // Last relation that is standard to desktop accessibility APIs
-  const unsigned long RELATION_LAST = RELATION_DESCRIPTION_FOR;
+  const unsigned long RELATION_PARENT_WINDOW_OF = 0x0f;
 
   /**
    * Part of a form/dialog with a related default button. It is used for
-   * MSAA only, no for IA2 nor ATK.
+   * MSAA/XPCOM, it isn't for IA2 or ATK.
    */
-  const unsigned long RELATION_DEFAULT_BUTTON = 0x4000;
+  const unsigned long RELATION_DEFAULT_BUTTON = 0x10;
 
   /**
    * Returns the type of the relation.
    */
   readonly attribute unsigned long relationType;
 
   /**
    * Returns the number of targets for this relation.
--- a/accessible/src/atk/AccessibleWrap.cpp
+++ b/accessible/src/atk/AccessibleWrap.cpp
@@ -848,31 +848,39 @@ refRelationSetCB(AtkObject *aAtkObj)
 {
   AtkRelationSet* relation_set =
     ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
 
   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   if (!accWrap)
     return relation_set;
 
-  uint32_t relationTypes[] = {
-    nsIAccessibleRelation::RELATION_LABELLED_BY,
-    nsIAccessibleRelation::RELATION_LABEL_FOR,
-    nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
+  // Keep in sync with AtkRelationType enum.
+  static const uint32_t relationTypes[] = {
     nsIAccessibleRelation::RELATION_CONTROLLED_BY,
     nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
-    nsIAccessibleRelation::RELATION_EMBEDS,
+    nsIAccessibleRelation::RELATION_LABEL_FOR,
+    nsIAccessibleRelation::RELATION_LABELLED_BY,
+    nsIAccessibleRelation::RELATION_MEMBER_OF,
+    nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
     nsIAccessibleRelation::RELATION_FLOWS_TO,
     nsIAccessibleRelation::RELATION_FLOWS_FROM,
+    nsIAccessibleRelation::RELATION_SUBWINDOW_OF,
+    nsIAccessibleRelation::RELATION_EMBEDS,
+    nsIAccessibleRelation::RELATION_EMBEDDED_BY,
+    nsIAccessibleRelation::RELATION_POPUP_FOR,
+    nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF,
     nsIAccessibleRelation::RELATION_DESCRIBED_BY,
     nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
+    nsIAccessibleRelation::RELATION_NODE_PARENT_OF
   };
 
   for (uint32_t i = 0; i < ArrayLength(relationTypes); i++) {
-    AtkRelationType atkType = static_cast<AtkRelationType>(relationTypes[i]);
+    // Shift to 1 to skip ATK_RELATION_NULL.
+    AtkRelationType atkType = static_cast<AtkRelationType>(i + 1);
     AtkRelation* atkRelation =
       atk_relation_set_get_relation_by_type(relation_set, atkType);
     if (atkRelation)
       atk_relation_set_remove(relation_set, atkRelation);
 
     Relation rel(accWrap->RelationByType(relationTypes[i]));
     nsTArray<AtkObject*> targets;
     Accessible* tempAcc = nullptr;
--- a/accessible/src/base/AccGroupInfo.cpp
+++ b/accessible/src/base/AccGroupInfo.cpp
@@ -133,16 +133,65 @@ AccGroupInfo::AccGroupInfo(Accessible* a
   }
 
   // Previous sibling of parent group is a tree item, this is the
   // conceptual tree item parent.
   if (parentPrevSiblingRole == roles::OUTLINEITEM)
     mParent = parentPrevSibling;
 }
 
+Accessible*
+AccGroupInfo::FirstItemOf(Accessible* aContainer)
+{
+  // ARIA trees can be arranged by ARIA groups, otherwise aria-level works.
+  a11y::role containerRole = aContainer->Role();
+  Accessible* item = aContainer->NextSibling();
+  if (item) {
+    if (containerRole == roles::OUTLINEITEM && item->Role() == roles::GROUPING)
+      item = item->FirstChild();
+
+    AccGroupInfo* itemGroupInfo = item->GetGroupInfo();
+    if (itemGroupInfo && itemGroupInfo->ConceptualParent() == aContainer)
+      return item;
+  }
+
+  // Otherwise it can be a direct child.
+  item = aContainer->FirstChild();
+  if (item && IsConceptualParent(BaseRole(item->Role()), containerRole))
+    return item;
+
+  return nullptr;
+}
+
+Accessible*
+AccGroupInfo::NextItemTo(Accessible* aItem)
+{
+  AccGroupInfo* groupInfo = aItem->GetGroupInfo();
+  if (!groupInfo)
+    return nullptr;
+
+  // If the item in middle of the group then search next item in siblings.
+  if (groupInfo->PosInSet() >= groupInfo->SetSize())
+    return nullptr;
+
+  Accessible* parent = aItem->Parent();
+  uint32_t childCount = parent->ChildCount();
+  for (int32_t idx = aItem->IndexInParent() + 1; idx < childCount; idx++) {
+    Accessible* nextItem = parent->GetChildAt(idx);
+    AccGroupInfo* nextGroupInfo = nextItem->GetGroupInfo();
+    if (nextGroupInfo &&
+        nextGroupInfo->ConceptualParent() == groupInfo->ConceptualParent()) {
+      return nextItem;
+    }
+  }
+
+  NS_NOTREACHED("Item in the midle of the group but there's no next item!");
+  return nullptr;
+}
+
 bool
 AccGroupInfo::IsConceptualParent(role aRole, role aParentRole)
 {
   if (aParentRole == roles::OUTLINE && aRole == roles::OUTLINEITEM)
     return true;
   if ((aParentRole == roles::TABLE || aParentRole == roles::TREE_TABLE) &&
       aRole == roles::ROW)
     return true;
--- a/accessible/src/base/AccGroupInfo.h
+++ b/accessible/src/base/AccGroupInfo.h
@@ -12,21 +12,32 @@ namespace mozilla {
 namespace a11y {
 
 /**
  * Calculate and store group information.
  */
 class AccGroupInfo
 {
 public:
-  AccGroupInfo(Accessible* aItem, mozilla::a11y::role aRole);
   ~AccGroupInfo() { MOZ_COUNT_DTOR(AccGroupInfo); }
 
-  int32_t PosInSet() const { return mPosInSet; }
+  /**
+   * Return 1-based position in the group.
+   */
+  uint32_t PosInSet() const { return mPosInSet; }
+
+  /**
+   * Return a number of items in the group.
+   */
   uint32_t SetSize() const { return mSetSize; }
+
+  /**
+   * Return a direct or logical parent of the accessible that this group info is
+   * created for.
+   */
   Accessible* ConceptualParent() const { return mParent; }
 
   /**
    * Create group info.
    */
   static AccGroupInfo* CreateGroupInfo(Accessible* aAccessible)
   {
     mozilla::a11y::role role = aAccessible->Role();
@@ -45,19 +56,33 @@ public:
         role != mozilla::a11y::roles::RADIOBUTTON &&
         role != mozilla::a11y::roles::PAGETAB)
       return nullptr;
 
     AccGroupInfo* info = new AccGroupInfo(aAccessible, BaseRole(role));
     return info;
   }
 
+  /**
+   * Return a first item for the given container.
+   */
+  static Accessible* FirstItemOf(Accessible* aContainer);
+
+  /**
+   * Return next item of the same group to the given item.
+   */
+  static Accessible* NextItemTo(Accessible* aItem);
+
+protected:
+  AccGroupInfo(Accessible* aItem, a11y::role aRole);
+
 private:
-  AccGroupInfo(const AccGroupInfo&);
-  AccGroupInfo& operator =(const AccGroupInfo&);
+  AccGroupInfo() MOZ_DELETE;
+  AccGroupInfo(const AccGroupInfo&) MOZ_DELETE;
+  AccGroupInfo& operator =(const AccGroupInfo&) MOZ_DELETE;
 
   static mozilla::a11y::role BaseRole(mozilla::a11y::role aRole)
   {
     if (aRole == mozilla::a11y::roles::CHECK_MENU_ITEM ||
         aRole == mozilla::a11y::roles::PARENT_MENUITEM ||
         aRole == mozilla::a11y::roles::RADIO_MENU_ITEM)
       return mozilla::a11y::roles::MENUITEM;
 
@@ -66,18 +91,17 @@ private:
 
     return aRole;
   }
 
   /**
    * Return true if the given parent role is conceptual parent of the given
    * role.
    */
-  static bool IsConceptualParent(mozilla::a11y::role aRole,
-				 mozilla::a11y::role aParentRole);
+  static bool IsConceptualParent(a11y::role aRole, a11y::role aParentRole);
 
   uint32_t mPosInSet;
   uint32_t mSetSize;
   Accessible* mParent;
 };
 
 } // namespace mozilla
 } // namespace a11y
--- a/accessible/src/base/AccIterator.cpp
+++ b/accessible/src/base/AccIterator.cpp
@@ -1,16 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AccIterator.h"
 
 #include "nsAccessibilityService.h"
+#include "AccGroupInfo.h"
 #include "Accessible-inl.h"
+#ifdef MOZ_XUL
+#include "XULTreeAccessible.h"
+#endif
 
 #include "mozilla/dom/Element.h"
 #include "nsBindingManager.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -324,16 +328,74 @@ IDRefsIterator::GetElem(const nsDependen
 
 Accessible*
 IDRefsIterator::Next()
 {
   nsIContent* nextElm = NextElem();
   return nextElm ? mDoc->GetAccessible(nextElm) : nullptr;
 }
 
+
+////////////////////////////////////////////////////////////////////////////////
+// SingleAccIterator
+////////////////////////////////////////////////////////////////////////////////
+
 Accessible*
 SingleAccIterator::Next()
 {
   nsRefPtr<Accessible> nextAcc;
   mAcc.swap(nextAcc);
   return (nextAcc && !nextAcc->IsDefunct()) ? nextAcc : nullptr;
 }
 
+
+////////////////////////////////////////////////////////////////////////////////
+// ItemIterator
+////////////////////////////////////////////////////////////////////////////////
+
+Accessible*
+ItemIterator::Next()
+{
+  if (mContainer) {
+    mAnchor = AccGroupInfo::FirstItemOf(mContainer);
+    mContainer = nullptr;
+    return mAnchor;
+  }
+
+  return mAnchor ? (mAnchor = AccGroupInfo::NextItemTo(mAnchor)) : nullptr;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// XULTreeItemIterator
+////////////////////////////////////////////////////////////////////////////////
+
+XULTreeItemIterator::XULTreeItemIterator(XULTreeAccessible* aXULTree,
+                                         nsITreeView* aTreeView,
+                                         int32_t aRowIdx) :
+  mXULTree(aXULTree), mTreeView(aTreeView), mRowCount(-1),
+  mContainerLevel(-1), mCurrRowIdx(aRowIdx + 1)
+{
+  mTreeView->GetRowCount(&mRowCount);
+  if (aRowIdx != -1)
+    mTreeView->GetLevel(aRowIdx, &mContainerLevel);
+}
+
+Accessible*
+XULTreeItemIterator::Next()
+{
+  while (mCurrRowIdx < mRowCount) {
+    int32_t level = 0;
+    mTreeView->GetLevel(mCurrRowIdx, &level);
+
+    if (level == mContainerLevel + 1)
+      return mXULTree->GetTreeItemAccessible(mCurrRowIdx++);
+
+    if (level <= mContainerLevel) { // got level up
+      mCurrRowIdx = mRowCount;
+      break;
+    }
+
+    mCurrRowIdx++;
+  }
+
+  return nullptr;
+}
--- a/accessible/src/base/AccIterator.h
+++ b/accessible/src/base/AccIterator.h
@@ -261,12 +261,59 @@ public:
 private:
   SingleAccIterator();
   SingleAccIterator(const SingleAccIterator&);
   SingleAccIterator& operator = (const SingleAccIterator&);
 
   nsRefPtr<Accessible> mAcc;
 };
 
+
+/**
+ * Used to iterate items of the given item container.
+ */
+class ItemIterator : public AccIterable
+{
+public:
+  ItemIterator(Accessible* aItemContainer) :
+    mContainer(aItemContainer), mAnchor(nullptr) { }
+  virtual ~ItemIterator() { }
+
+  virtual Accessible* Next();
+
+private:
+  ItemIterator() MOZ_DELETE;
+  ItemIterator(const ItemIterator&) MOZ_DELETE;
+  ItemIterator& operator = (const ItemIterator&) MOZ_DELETE;
+
+  Accessible* mContainer;
+  Accessible* mAnchor;
+};
+
+
+/**
+ * Used to iterate through XUL tree items of the same level.
+ */
+class XULTreeItemIterator : public AccIterable
+{
+public:
+  XULTreeItemIterator(XULTreeAccessible* aXULTree, nsITreeView* aTreeView,
+                      int32_t aRowIdx);
+  virtual ~XULTreeItemIterator() { }
+
+  virtual Accessible* Next();
+
+private:
+  XULTreeItemIterator() MOZ_DELETE;
+  XULTreeItemIterator(const XULTreeItemIterator&) MOZ_DELETE;
+  XULTreeItemIterator& operator = (const XULTreeItemIterator&) MOZ_DELETE;
+
+  XULTreeAccessible* mXULTree;
+  nsITreeView* mTreeView;
+  int32_t mRowCount;
+  int32_t mContainerLevel;
+  int32_t mCurrRowIdx;
+};
+
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/src/base/Relation.h
+++ b/accessible/src/base/Relation.h
@@ -14,37 +14,36 @@ namespace a11y {
 
 /**
  * This class is used to return Relation objects from functions.  A copy
  * constructor doesn't work here because we need to mutate the old relation to
  * have its nsAutoPtr forget what it points to.
  */
 struct RelationCopyHelper
 {
-  RelationCopyHelper(mozilla::a11y::AccIterable* aFirstIter,
-                     mozilla::a11y::AccIterable* aLastIter) :
+  RelationCopyHelper(AccIterable* aFirstIter, AccIterable* aLastIter) :
     mFirstIter(aFirstIter), mLastIter(aLastIter) { }
 
-  mozilla::a11y::AccIterable* mFirstIter;
-  mozilla::a11y::AccIterable* mLastIter;
+  AccIterable* mFirstIter;
+  AccIterable* mLastIter;
 };
 
 /**
  * A collection of relation targets of a certain type.  Targets are computed
  * lazily while enumerating.
  */
 class Relation
 {
 public:
   Relation() : mFirstIter(nullptr), mLastIter(nullptr) { }
 
   Relation(const RelationCopyHelper aRelation) :
     mFirstIter(aRelation.mFirstIter), mLastIter(aRelation.mLastIter) { }
 
-  Relation(mozilla::a11y::AccIterable* aIter) :
+  Relation(AccIterable* aIter) :
     mFirstIter(aIter), mLastIter(aIter) { }
 
   Relation(Accessible* aAcc) :
     mFirstIter(nullptr), mLastIter(nullptr)
     { AppendTarget(aAcc); }
 
   Relation(DocAccessible* aDocument, nsIContent* aContent) :
     mFirstIter(nullptr), mLastIter(nullptr)
@@ -64,33 +63,33 @@ public:
     return *this;
   }
 
   operator RelationCopyHelper()
   {
     return RelationCopyHelper(mFirstIter.forget(), mLastIter);
   }
 
-  inline void AppendIter(mozilla::a11y::AccIterable* aIter)
+  inline void AppendIter(AccIterable* aIter)
   {
     if (mLastIter)
       mLastIter->mNextIter = aIter;
     else
       mFirstIter = aIter;
 
     mLastIter = aIter;
   }
 
   /**
    * Append the given accessible to the set of related accessibles.
    */
   inline void AppendTarget(Accessible* aAcc)
   {
     if (aAcc)
-      AppendIter(new mozilla::a11y::SingleAccIterator(aAcc));
+      AppendIter(new SingleAccIterator(aAcc));
   }
 
   /**
    * Append the one accessible for this content node to the set of related
    * accessibles.
    */
   void AppendTarget(DocAccessible* aDocument, nsIContent* aContent)
   {
@@ -113,17 +112,17 @@ public:
       mLastIter = nullptr;
 
     return target;
   }
 
 private:
   Relation& operator = (const Relation&);
 
-  nsAutoPtr<mozilla::a11y::AccIterable> mFirstIter;
-  mozilla::a11y::AccIterable* mLastIter;
+  nsAutoPtr<AccIterable> mFirstIter;
+  AccIterable* mLastIter;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
 
--- a/accessible/src/base/Role.h
+++ b/accessible/src/base/Role.h
@@ -582,19 +582,18 @@ enum Role {
 
   /**
    * A toggle button. A specialized push button that can be checked or
    * unchecked, but does not provide a separate indicator for the current state.
    */
   TOGGLE_BUTTON = 93,
 
   /**
-   * Representas a control that is capable of expanding and collapsing rows as
+   * Represent a control that is capable of expanding and collapsing rows as
    * well as showing multiple columns of data.
-   * XXX: it looks like this role is dupe of OUTLINE.
    */
   TREE_TABLE = 94,
 
   /**
    * A viewport. An object usually used in a scroll pane. It represents the
    * portion of the entire data that the user can see. As the user manipulates
    * the scroll bars, the contents of the viewport can change. Also refer to
    * SCROLL_PANE.
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -313,29 +313,29 @@ static const char kEventTypeNames[][40] 
   "virtual cursor changed"                   // EVENT_VIRTUALCURSOR_CHANGED
 };
 
 /**
  * Map nsIAccessibleRelation constants to strings. Used by
  * nsIAccessibleRetrieval::getStringRelationType() method.
  */
 static const char kRelationTypeNames[][20] = {
-  "unknown",             // RELATION_NUL
+  "labelled by",         // RELATION_LABELLED_BY
+  "label for",           // RELATION_LABEL_FOR
+  "described by",        // RELATION_DESCRIBED_BY
+  "description for",     // RELATION_DESCRIPTION_FOR
+  "node child of",       // RELATION_NODE_CHILD_OF
+  "node parent of",      // RELATION_NODE_PARENT_OF
   "controlled by",       // RELATION_CONTROLLED_BY
   "controller for",      // RELATION_CONTROLLER_FOR
-  "label for",           // RELATION_LABEL_FOR
-  "labelled by",         // RELATION_LABELLED_BY
-  "member of",           // RELATION_MEMBER_OF
-  "node child of",       // RELATION_NODE_CHILD_OF
   "flows to",            // RELATION_FLOWS_TO
   "flows from",          // RELATION_FLOWS_FROM
+  "member of",           // RELATION_MEMBER_OF
   "subwindow of",        // RELATION_SUBWINDOW_OF
   "embeds",              // RELATION_EMBEDS
   "embedded by",         // RELATION_EMBEDDED_BY
   "popup for",           // RELATION_POPUP_FOR
   "parent window of",    // RELATION_PARENT_WINDOW_OF
-  "described by",        // RELATION_DESCRIBED_BY
-  "description for",     // RELATION_DESCRIPTION_FOR
   "default button"       // RELATION_DEFAULT_BUTTON
 };
 
 #endif /* __nsIAccessibilityService_h__ */
 
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -1962,72 +1962,72 @@ Relation
 Accessible::RelationByType(uint32_t aType)
 {
   if (!HasOwnContent())
     return Relation();
 
   // Relationships are defined on the same content node that the role would be
   // defined on.
   switch (aType) {
-    case nsIAccessibleRelation::RELATION_LABEL_FOR: {
-      Relation rel(new RelatedAccIterator(Document(), mContent,
-                                          nsGkAtoms::aria_labelledby));
-      if (mContent->Tag() == nsGkAtoms::label)
-        rel.AppendIter(new IDRefsIterator(mDoc, mContent, mContent->IsHTML() ?
-                                          nsGkAtoms::_for :
-                                          nsGkAtoms::control));
-
-      return rel;
-    }
     case nsIAccessibleRelation::RELATION_LABELLED_BY: {
       Relation rel(new IDRefsIterator(mDoc, mContent,
                                       nsGkAtoms::aria_labelledby));
       if (mContent->IsHTML()) {
         rel.AppendIter(new HTMLLabelIterator(Document(), this));
       } else if (mContent->IsXUL()) {
         rel.AppendIter(new XULLabelIterator(Document(), mContent));
       }
 
       return rel;
     }
+
+    case nsIAccessibleRelation::RELATION_LABEL_FOR: {
+      Relation rel(new RelatedAccIterator(Document(), mContent,
+                                          nsGkAtoms::aria_labelledby));
+      if (mContent->Tag() == nsGkAtoms::label)
+        rel.AppendIter(new IDRefsIterator(mDoc, mContent, mContent->IsHTML() ?
+          nsGkAtoms::_for :
+          nsGkAtoms::control));
+
+      return rel;
+    }
+
     case nsIAccessibleRelation::RELATION_DESCRIBED_BY: {
       Relation rel(new IDRefsIterator(mDoc, mContent,
                                       nsGkAtoms::aria_describedby));
       if (mContent->IsXUL())
         rel.AppendIter(new XULDescriptionIterator(Document(), mContent));
 
       return rel;
     }
+
     case nsIAccessibleRelation::RELATION_DESCRIPTION_FOR: {
       Relation rel(new RelatedAccIterator(Document(), mContent,
                                           nsGkAtoms::aria_describedby));
 
       // This affectively adds an optional control attribute to xul:description,
       // which only affects accessibility, by allowing the description to be
       // tied to a control.
       if (mContent->Tag() == nsGkAtoms::description &&
           mContent->IsXUL())
         rel.AppendIter(new IDRefsIterator(mDoc, mContent,
                                           nsGkAtoms::control));
 
       return rel;
     }
+
     case nsIAccessibleRelation::RELATION_NODE_CHILD_OF: {
       Relation rel(new RelatedAccIterator(Document(), mContent,
                                           nsGkAtoms::aria_owns));
-      
+
       // This is an ARIA tree or treegrid that doesn't use owns, so we need to
       // get the parent the hard way.
       if (mRoleMapEntry && (mRoleMapEntry->role == roles::OUTLINEITEM || 
                             mRoleMapEntry->role == roles::ROW)) {
-        AccGroupInfo* groupInfo = GetGroupInfo();
-        if (!groupInfo)
-          return rel;
-
-        rel.AppendTarget(groupInfo->ConceptualParent());
+        rel.AppendTarget(GetGroupInfo()->ConceptualParent());
       }
 
       // 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).
@@ -2038,31 +2038,62 @@ Accessible::RelationByType(uint32_t aTyp
           nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
           if (scrollFrame || view->GetWidget() || !frame->GetParent())
             rel.AppendTarget(Parent());
         }
       }
 
       return rel;
     }
+
+    case nsIAccessibleRelation::RELATION_NODE_PARENT_OF: {
+      Relation rel(new IDRefsIterator(mDoc, mContent, nsGkAtoms::aria_owns));
+
+      // ARIA tree or treegrid can do the hierarchy by @aria-level, ARIA trees
+      // also can be organized by groups.
+      if (mRoleMapEntry &&
+          (mRoleMapEntry->role == roles::OUTLINEITEM ||
+           mRoleMapEntry->role == roles::ROW ||
+           mRoleMapEntry->role == roles::OUTLINE ||
+           mRoleMapEntry->role == roles::TREE_TABLE)) {
+        rel.AppendIter(new ItemIterator(this));
+      }
+
+      return rel;
+    }
+
     case nsIAccessibleRelation::RELATION_CONTROLLED_BY:
       return Relation(new RelatedAccIterator(Document(), mContent,
                                              nsGkAtoms::aria_controls));
+
     case nsIAccessibleRelation::RELATION_CONTROLLER_FOR: {
       Relation rel(new IDRefsIterator(mDoc, mContent,
                                       nsGkAtoms::aria_controls));
       rel.AppendIter(new HTMLOutputIterator(Document(), mContent));
       return rel;
     }
+
     case nsIAccessibleRelation::RELATION_FLOWS_TO:
       return Relation(new IDRefsIterator(mDoc, mContent,
                                          nsGkAtoms::aria_flowto));
+
     case nsIAccessibleRelation::RELATION_FLOWS_FROM:
       return Relation(new RelatedAccIterator(Document(), mContent,
                                              nsGkAtoms::aria_flowto));
+
+    case nsIAccessibleRelation::RELATION_MEMBER_OF:
+          return Relation(mDoc, GetAtomicRegion());
+
+    case nsIAccessibleRelation::RELATION_SUBWINDOW_OF:
+    case nsIAccessibleRelation::RELATION_EMBEDS:
+    case nsIAccessibleRelation::RELATION_EMBEDDED_BY:
+    case nsIAccessibleRelation::RELATION_POPUP_FOR:
+    case nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF:
+      return Relation();
+
     case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON: {
       if (mContent->IsHTML()) {
         // HTML form controls implements nsIFormControl interface.
         nsCOMPtr<nsIFormControl> control(do_QueryInterface(mContent));
         if (control) {
           nsCOMPtr<nsIForm> form(do_QueryInterface(control->GetFormElement()));
           if (form) {
             nsCOMPtr<nsIContent> formContent =
@@ -2100,46 +2131,57 @@ Accessible::RelationByType(uint32_t aTyp
             }
           }
           nsCOMPtr<nsIContent> relatedContent(do_QueryInterface(buttonEl));
           return Relation(mDoc, relatedContent);
         }
       }
       return Relation();
     }
-    case nsIAccessibleRelation::RELATION_MEMBER_OF:
-      return Relation(mDoc, GetAtomicRegion());
-    case nsIAccessibleRelation::RELATION_SUBWINDOW_OF:
-    case nsIAccessibleRelation::RELATION_EMBEDS:
-    case nsIAccessibleRelation::RELATION_EMBEDDED_BY:
-    case nsIAccessibleRelation::RELATION_POPUP_FOR:
-    case nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF:
+
     default:
-    return Relation();
+      return Relation();
   }
 }
 
 NS_IMETHODIMP
 Accessible::GetRelations(nsIArray **aRelations)
 {
   NS_ENSURE_ARG_POINTER(aRelations);
   *aRelations = nullptr;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIMutableArray> relations = do_CreateInstance(NS_ARRAY_CONTRACTID);
   NS_ENSURE_TRUE(relations, NS_ERROR_OUT_OF_MEMORY);
 
-  for (uint32_t relType = nsIAccessibleRelation::RELATION_FIRST;
-       relType < nsIAccessibleRelation::RELATION_LAST;
-       ++relType) {
-
+  static const uint32_t relationTypes[] = {
+    nsIAccessibleRelation::RELATION_LABELLED_BY,
+    nsIAccessibleRelation::RELATION_LABEL_FOR,
+    nsIAccessibleRelation::RELATION_DESCRIBED_BY,
+    nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
+    nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
+    nsIAccessibleRelation::RELATION_NODE_PARENT_OF,
+    nsIAccessibleRelation::RELATION_CONTROLLED_BY,
+    nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
+    nsIAccessibleRelation::RELATION_FLOWS_TO,
+    nsIAccessibleRelation::RELATION_FLOWS_FROM,
+    nsIAccessibleRelation::RELATION_MEMBER_OF,
+    nsIAccessibleRelation::RELATION_SUBWINDOW_OF,
+    nsIAccessibleRelation::RELATION_EMBEDS,
+    nsIAccessibleRelation::RELATION_EMBEDDED_BY,
+    nsIAccessibleRelation::RELATION_POPUP_FOR,
+    nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF,
+    nsIAccessibleRelation::RELATION_DEFAULT_BUTTON
+  };
+
+  for (uint32_t idx = 0; idx < ArrayLength(relationTypes); idx++) {
     nsCOMPtr<nsIAccessibleRelation> relation;
-    nsresult rv = GetRelationByType(relType, getter_AddRefs(relation));
+    nsresult rv = GetRelationByType(relationTypes[idx], getter_AddRefs(relation));
 
     if (NS_SUCCEEDED(rv) && relation) {
       uint32_t targets = 0;
       relation->GetTargetsCount(&targets);
       if (targets)
         relations->AppendElement(relation, false);
     }
   }
--- a/accessible/src/msaa/AccessibleWrap.cpp
+++ b/accessible/src/msaa/AccessibleWrap.cpp
@@ -8,17 +8,16 @@
 
 #include "Compatibility.h"
 #include "DocAccessible-inl.h"
 #include "EnumVariant.h"
 #include "ia2AccessibleRelation.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsIAccessibleEvent.h"
-#include "nsIAccessibleRelation.h"
 #include "nsWinUtils.h"
 #include "ServiceProvider.h"
 #include "Relation.h"
 #include "Role.h"
 #include "RootAccessible.h"
 #include "sdnAccessible.h"
 #include "States.h"
 
@@ -1043,19 +1042,18 @@ AccessibleWrap::get_nRelations(long *aNR
   if (!aNRelations)
     return E_INVALIDARG;
 
   *aNRelations = 0;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  for (uint32_t relType = nsIAccessibleRelation::RELATION_FIRST;
-       relType <= nsIAccessibleRelation::RELATION_LAST; relType++) {
-    Relation rel = RelationByType(relType);
+  for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
+    Relation rel = RelationByType(sRelationTypesForIA2[idx]);
     if (rel.Next())
       (*aNRelations)++;
   }
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
@@ -1069,18 +1067,18 @@ AccessibleWrap::get_relation(long aRelat
     return E_INVALIDARG;
 
   *aRelation = NULL;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   long relIdx = 0;
-  for (uint32_t relType = nsIAccessibleRelation::RELATION_FIRST;
-       relType <= nsIAccessibleRelation::RELATION_LAST; relType++) {
+  for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
+    uint32_t relType = sRelationTypesForIA2[idx];
     Relation rel = RelationByType(relType);
     nsRefPtr<ia2AccessibleRelation> ia2Relation =
       new ia2AccessibleRelation(relType, &rel);
     if (ia2Relation->HasTargets()) {
       if (relIdx == aRelationIndex) {
         ia2Relation.forget(aRelation);
         return S_OK;
       }
@@ -1104,19 +1102,19 @@ AccessibleWrap::get_relations(long aMaxR
   if (!aRelation || !aNRelations)
     return E_INVALIDARG;
 
   *aNRelations = 0;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  for (uint32_t relType = nsIAccessibleRelation::RELATION_FIRST;
-       relType <= nsIAccessibleRelation::RELATION_LAST &&
-       *aNRelations < aMaxRelations; relType++) {
+  for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2) &&
+       *aNRelations < aMaxRelations; idx++) {
+    uint32_t relType = sRelationTypesForIA2[idx];
     Relation rel = RelationByType(relType);
     nsRefPtr<ia2AccessibleRelation> ia2Rel =
       new ia2AccessibleRelation(relType, &rel);
     if (ia2Rel->HasTargets()) {
       ia2Rel.forget(aRelation + (*aNRelations));
       (*aNRelations)++;
     }
   }
--- a/accessible/src/windows/ia2/ia2AccessibleRelation.h
+++ b/accessible/src/windows/ia2/ia2AccessibleRelation.h
@@ -4,16 +4,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/. */
 
 #ifndef _NS_ACCESSIBLE_RELATION_WRAP_H
 #define _NS_ACCESSIBLE_RELATION_WRAP_H
 
 #include "Accessible.h"
+#include "nsIAccessibleRelation.h"
 
 #include "nsTArray.h"
 
 #include "AccessibleRelation.h"
 
 namespace mozilla {
 namespace a11y {
 
@@ -55,13 +56,35 @@ private:
   ia2AccessibleRelation(const ia2AccessibleRelation&);
   ia2AccessibleRelation& operator = (const ia2AccessibleRelation&);
 
   uint32_t mType;
   nsTArray<nsRefPtr<Accessible> > mTargets;
   ULONG mReferences;
 };
 
+
+/**
+ * Relations exposed to IAccessible2.
+ */
+static const uint32_t sRelationTypesForIA2[] = {
+  nsIAccessibleRelation::RELATION_LABELLED_BY,
+  nsIAccessibleRelation::RELATION_LABEL_FOR,
+  nsIAccessibleRelation::RELATION_DESCRIBED_BY,
+  nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
+  nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
+  nsIAccessibleRelation::RELATION_CONTROLLED_BY,
+  nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
+  nsIAccessibleRelation::RELATION_FLOWS_TO,
+  nsIAccessibleRelation::RELATION_FLOWS_FROM,
+  nsIAccessibleRelation::RELATION_MEMBER_OF,
+  nsIAccessibleRelation::RELATION_SUBWINDOW_OF,
+  nsIAccessibleRelation::RELATION_EMBEDS,
+  nsIAccessibleRelation::RELATION_EMBEDDED_BY,
+  nsIAccessibleRelation::RELATION_POPUP_FOR,
+  nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF
+};
+
 } // namespace a11y
 } // namespace mozilla
 
 #endif
 
--- a/accessible/src/xul/XULTreeAccessible.cpp
+++ b/accessible/src/xul/XULTreeAccessible.cpp
@@ -432,16 +432,29 @@ XULTreeAccessible::ChildCount() const
 
   int32_t rowCount = 0;
   mTreeView->GetRowCount(&rowCount);
   childCount += rowCount;
 
   return childCount;
 }
 
+Relation
+XULTreeAccessible::RelationByType(uint32_t aType)
+{
+  if (aType == nsIAccessibleRelation::RELATION_NODE_PARENT_OF) {
+    if (mTreeView)
+      return Relation(new XULTreeItemIterator(this, mTreeView, -1));
+
+    return Relation();
+  }
+
+  return Accessible::RelationByType(aType);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeAccessible: Widgets
 
 bool
 XULTreeAccessible::IsWidget() const
 {
   return true;
 }
@@ -793,28 +806,44 @@ XULTreeItemAccessibleBase::TakeFocus()
 }
 
 Relation
 XULTreeItemAccessibleBase::RelationByType(uint32_t aType)
 {
   if (!mTreeView)
     return Relation();
 
-  if (aType != nsIAccessibleRelation::RELATION_NODE_CHILD_OF)
-    return Relation();
+  switch (aType) {
+    case nsIAccessibleRelation::RELATION_NODE_CHILD_OF: {
+      int32_t parentIndex = -1;
+      if (!NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex)))
+        return Relation();
+
+      if (parentIndex == -1)
+        return Relation(mParent);
+
+      XULTreeAccessible* treeAcc = mParent->AsXULTree();
+      return Relation(treeAcc->GetTreeItemAccessible(parentIndex));
+    }
 
-  int32_t parentIndex = -1;
-  if (!NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex)))
-    return Relation();
+    case nsIAccessibleRelation::RELATION_NODE_PARENT_OF: {
+      bool isTrue = false;
+      if (NS_FAILED(mTreeView->IsContainerEmpty(mRow, &isTrue)) || isTrue)
+        return Relation();
+
+      if (NS_FAILED(mTreeView->IsContainerOpen(mRow, &isTrue)) || !isTrue)
+        return Relation();
 
-  if (parentIndex == -1)
-    return Relation(mParent);
+      XULTreeAccessible* tree = mParent->AsXULTree();
+      return Relation(new XULTreeItemIterator(tree, mTreeView, mRow));
+    }
 
-  XULTreeAccessible* treeAcc = mParent->AsXULTree();
-  return Relation(treeAcc->GetTreeItemAccessible(parentIndex));
+    default:
+      return Relation();
+  }
 }
 
 uint8_t
 XULTreeItemAccessibleBase::ActionCount()
 {
   // "activate" action is available for all treeitems, "expand/collapse" action
   // is avaible for treeitem which is container.
   return IsExpandable() ? 2 : 1;
--- a/accessible/src/xul/XULTreeAccessible.h
+++ b/accessible/src/xul/XULTreeAccessible.h
@@ -42,16 +42,17 @@ public:
   virtual void Value(nsString& aValue);
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
                                    EWhichChildAtPoint aWhichChild);
 
   virtual Accessible* GetChildAt(uint32_t aIndex);
   virtual uint32_t ChildCount() const;
+  virtual Relation RelationByType(uint32_t aType);
 
   // SelectAccessible
   virtual already_AddRefed<nsIArray> SelectedItems();
   virtual uint32_t SelectedItemCount();
   virtual Accessible* GetSelectedItem(uint32_t aIndex);
   virtual bool IsItemSelected(uint32_t aIndex);
   virtual bool AddItemToSelection(uint32_t aIndex);
   virtual bool RemoveItemFromSelection(uint32_t aIndex);
--- a/accessible/tests/mochitest/actions/test_general.xul
+++ b/accessible/tests/mochitest/actions/test_general.xul
@@ -16,16 +16,22 @@
           src="../common.js" />
   <script type="application/javascript"
           src="../events.js" />
   <script type="application/javascript"
           src="../actions.js" />
 
   <script type="application/javascript">
   <![CDATA[
+    if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 1);
+    } else {
+      SimpleTest.expectAssertions(1);
+    }
+
     function doTest()
     {
       var actionsArray = [
         {
           ID: "menu",
           actionName: "click",
           events: CLICK_EVENTS,
           // Wait for focus event, it guarantees us the submenu tree is created,
--- a/accessible/tests/mochitest/actions/test_link.html
+++ b/accessible/tests/mochitest/actions/test_link.html
@@ -12,16 +12,24 @@
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="../actions.js"></script>
 
   <script type="application/javascript">
+    if (navigator.platform.indexOf("Win") == 0) {
+      SimpleTest.expectAssertions(13);
+    } else if (navigator.platform.indexOf("Linux") == 0) {
+      SimpleTest.expectAssertions(18);
+    } else if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 14);
+    }
+
     function getAnchorTargetDocumentAcc()
     {
       var thisTabDocAcc = getTabDocAccessible();
       var thisDocTabPanelAcc = thisTabDocAcc.parent.parent;
       var tabPanelsAcc = thisDocTabPanelAcc.parent;
       var newDocTabPanelAcc = tabPanelsAcc.lastChild.firstChild;
       return newDocTabPanelAcc.firstChild;
     }
--- a/accessible/tests/mochitest/attributes/test_obj.html
+++ b/accessible/tests/mochitest/attributes/test_obj.html
@@ -14,16 +14,20 @@ https://bugzilla.mozilla.org/show_bug.cg
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../attributes.js"></script>
 
   <script type="application/javascript">
+    if (navigator.platform.indexOf("Linux") == 0) {
+      SimpleTest.expectAssertions(0, 1);
+    }
+
     function doTest()
     {
       // aria
       testAttrs("atomic", {"atomic" : "true"}, true);
       testAttrs("autocomplete", {"autocomplete" : "true"}, true);
       testAttrs("checkbox", {"checkable" : "true"}, true); 
       testAttrs("checkedCheckbox", {"checkable" : "true"}, true); 
       testAttrs("checkedMenuitem", {"checkable" : "true"}, true); 
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -605,16 +605,27 @@ function getTextFromClipboard()
   return "";
 }
 
 /**
  * Return pretty name for identifier, it may be ID, DOM node or accessible.
  */
 function prettyName(aIdentifier)
 {
+  if (aIdentifier instanceof Array) {
+    var msg = "";
+    for (var idx = 0; idx < aIdentifier.length; idx++) {
+      if (msg != "")
+        msg += ", ";
+
+      msg += prettyName(aIdentifier[idx]);
+    }
+    return msg;
+  }
+
   if (aIdentifier instanceof nsIAccessible) {
     var acc = getAccessible(aIdentifier);
     var msg = "[" + getNodePrettyName(acc.DOMNode);
     try {
       msg += ", role: " + roleToString(acc.role);
       if (acc.name)
         msg += ", name: '" + shortenString(acc.name) + "'";
     } catch (e) {
--- a/accessible/tests/mochitest/editabletext/test_1.html
+++ b/accessible/tests/mochitest/editabletext/test_1.html
@@ -14,16 +14,22 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="editabletext.js"></script>
 
   <script type="application/javascript">
+    if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 3);
+    } else {
+      SimpleTest.expectAssertions(3);
+    }
+
     function addTestEditable(aID, aTestRun, aTrailChar)
     {
       var et = new editableTextTest(aID);
 
       //////////////////////////////////////////////////////////////////////////
       // setTextContents
       et.scheduleTest(et.setTextContents, "hello");
       et.scheduleTest(et.setTextContents, "olleh", aTrailChar); // due to some reason this reports '\n' in the end
--- a/accessible/tests/mochitest/events/test_focus_autocomplete.xul
+++ b/accessible/tests/mochitest/events/test_focus_autocomplete.xul
@@ -27,16 +27,19 @@
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript"
           src="../autocomplete.js" />
 
   <script type="application/javascript">
   <![CDATA[
+    if (navigator.platform.indexOf("Mac") != 0) {
+      SimpleTest.expectAssertions(2);
+    }
     ////////////////////////////////////////////////////////////////////////////
     // Hacky stuffs
 
     // This is the hack needed for searchbar work outside of browser.
     function getBrowser()
     {
       return {
         mCurrentBrowser: { engines: new Array() }
--- a/accessible/tests/mochitest/events/test_focus_browserui.xul
+++ b/accessible/tests/mochitest/events/test_focus_browserui.xul
@@ -19,16 +19,19 @@
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="../browser.js"></script>
 
   <script type="application/javascript">
   <![CDATA[
+    if (navigator.platform.indexOf("Linux") == 0) {
+      SimpleTest.expectAssertions(1);
+    }
     ////////////////////////////////////////////////////////////////////////////
     // Helpers
 
     function inputInDocument()
     {
       var tabdoc = currentTabDocument();
       return tabdoc.getElementById("input");
     }
--- a/accessible/tests/mochitest/events/test_focus_doc.html
+++ b/accessible/tests/mochitest/events/test_focus_doc.html
@@ -16,16 +16,24 @@
   <script type="application/javascript"
     src="../events.js"></script>
   <script type="application/javascript"
           src="../role.js"></script>
     <script type="application/javascript"
       src="../states.js"></script>
 
   <script type="application/javascript">
+    if (navigator.platform.indexOf("Win") == 0) {
+      SimpleTest.expectAssertions(1, 2);
+    } else if (navigator.platform.indexOf("Linux") == 0) {
+      SimpleTest.expectAssertions(1);
+    } else if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 1);
+    }
+
     var gQueue = null;
 
     //var gA11yEventDumpID = "eventdump";
     //gA11yEventDumpToConsole = true;
 
     function doTests()
     {
       // setup
--- a/accessible/tests/mochitest/relations.js
+++ b/accessible/tests/mochitest/relations.js
@@ -9,16 +9,17 @@ const RELATION_DESCRIPTION_FOR = nsIAcce
 const RELATION_EMBEDDED_BY = nsIAccessibleRelation.RELATION_EMBEDDED_BY;
 const RELATION_EMBEDS = nsIAccessibleRelation.RELATION_EMBEDS;
 const RELATION_FLOWS_FROM = nsIAccessibleRelation.RELATION_FLOWS_FROM;
 const RELATION_FLOWS_TO = nsIAccessibleRelation.RELATION_FLOWS_TO;
 const RELATION_LABEL_FOR = nsIAccessibleRelation.RELATION_LABEL_FOR;
 const RELATION_LABELLED_BY = nsIAccessibleRelation.RELATION_LABELLED_BY;
 const RELATION_MEMBER_OF = nsIAccessibleRelation.RELATION_MEMBER_OF;
 const RELATION_NODE_CHILD_OF = nsIAccessibleRelation.RELATION_NODE_CHILD_OF;
+const RELATION_NODE_PARENT_OF = nsIAccessibleRelation.RELATION_NODE_PARENT_OF;
 const RELATION_PARENT_WINDOW_OF = nsIAccessibleRelation.RELATION_PARENT_WINDOW_OF;
 const RELATION_POPUP_FOR = nsIAccessibleRelation.RELATION_POPUP_FOR;
 const RELATION_SUBWINDOW_OF = nsIAccessibleRelation.RELATION_SUBWINDOW_OF;
 
 ////////////////////////////////////////////////////////////////////////////////
 // General
 
 /**
--- a/accessible/tests/mochitest/relations/test_general.html
+++ b/accessible/tests/mochitest/relations/test_general.html
@@ -66,31 +66,45 @@
       // aria_owns, multiple relations
       testRelation("treeitem1", RELATION_NODE_CHILD_OF, "tree");
       testRelation("treeitem2", RELATION_NODE_CHILD_OF, "tree");
 
       // 'node child of' relation for outlineitem role
       testRelation("treeitem3", RELATION_NODE_CHILD_OF, "tree");
       testRelation("treeitem4", RELATION_NODE_CHILD_OF, "tree");
       testRelation("treeitem5", RELATION_NODE_CHILD_OF, "treeitem4");
-      testRelation("treeitem6", RELATION_NODE_CHILD_OF, "treeitem5");
+      testRelation("treeitem6", RELATION_NODE_CHILD_OF, "tree");
+      testRelation("treeitem7", RELATION_NODE_CHILD_OF, "treeitem6");
 
       // 'node child of' relation for row role of treegrid
       testRelation("treegridrow1", RELATION_NODE_CHILD_OF, "treegrid");
       testRelation("treegridrow2", RELATION_NODE_CHILD_OF, "treegrid");
       testRelation("treegridrow3", RELATION_NODE_CHILD_OF, "treegridrow2");
 
       // 'node child of' relation for the document having window, returns
       // direct accessible parent (fixed in bug 419770).
       var iframeElmObj = {};
       var iframeAcc = getAccessible("iframe", null, iframeElmObj);
       var iframeDoc = iframeElmObj.value.contentDocument;
       var iframeDocAcc = getAccessible(iframeDoc);
       testRelation(iframeDocAcc, RELATION_NODE_CHILD_OF, iframeAcc);
 
+      // 'node parent of' relation on ARIA tree and treegrid.
+      testRelation("tree", RELATION_NODE_PARENT_OF,
+                    ["treeitem1", "treeitem2", // aria-owns
+                     "treeitem3", "treeitem4", "treeitem6"]); // children
+      testRelation("treeitem4", RELATION_NODE_PARENT_OF,
+                   "treeitem5"); // aria-level
+      testRelation("treeitem6", RELATION_NODE_PARENT_OF,
+                   "treeitem7"); // // group role
+
+      testRelation("treegridrow2", RELATION_NODE_PARENT_OF, "treegridrow3");
+      testRelation("treegrid", RELATION_NODE_PARENT_OF,
+                   ["treegridrow1", "treegridrow2"]);
+
       // aria-controls
       getAccessible("tab");
       todo(false,
            "Getting an accessible tab, otherwise relations for tabpanel aren't cached. Bug 606924 will fix that.");
       testRelation("tabpanel", RELATION_CONTROLLED_BY, "tab");
       testRelation("tab", RELATION_CONTROLLER_FOR, "tabpanel");
 
       // aria-controls, multiple relations
@@ -136,32 +150,37 @@
 
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=475298"
      title="mochitests for accessible relations">
-    Mozilla Bug 475298
+    Bug 475298
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=527461"
+     title="Implement RELATION_NODE_PARENT_OF">
+    Bug 527461
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=558036"
      title="make HTML <output> accessible">
-    Mozilla Bug 558036
+    Bug 558036
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=682790"
      title="Ignore implicit label association when it's associated explicitly">
-    Mozilla Bug 682790
+    Bug 682790
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=687393"
      title="HTML select options gets relation from containing label">
-    Mozilla Bug 687393
+    Bug 687393
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <label id="label1_1" for="control1_1">label</label>
   <input id="control1_1">
@@ -222,18 +241,19 @@
   <span role="checkbox" id="checkbox5" aria-describedby="descr2 descr3"></span>
 
   <div role="treeitem" id="treeitem1">Yellow</div>
   <div role="treeitem" id="treeitem2">Orange</div>
   <div id="tree" role="tree" aria-owns="treeitem1 treeitem2">
     <div role="treeitem" id="treeitem3">Blue</div>
     <div role="treeitem" id="treeitem4" aria-level="1">Green</div>
     <div role="treeitem" id="treeitem5" aria-level="2">Light green</div>
+    <div role="treeitem" id="treeitem6" aria-level="1">Green2</div>
     <div role="group">
-      <div role="treeitem" id="treeitem6">Super light green</div>
+      <div role="treeitem" id="treeitem7">Super light green</div>
     </div>
   </div>
 
   <div role="treegrid" id="treegrid">
     <div role="row" id="treegridrow1">
       <span role="gridcell">cell1</span><span role="gridcell">cell2</span>
     </div>
     <div role="row" id="treegridrow2" aria-level="1">
--- a/accessible/tests/mochitest/relations/test_tree.xul
+++ b/accessible/tests/mochitest/relations/test_tree.xul
@@ -42,16 +42,21 @@
       testRelation(treeitem4, RELATION_NODE_CHILD_OF, [treeitem2]);
 
       var treeitem5 = treeitem4.nextSibling;
       testRelation(treeitem5, RELATION_NODE_CHILD_OF, [tree]);
 
       var treeitem6 = treeitem5.nextSibling;
       testRelation(treeitem6, RELATION_NODE_CHILD_OF, [tree]);
 
+      testRelation(tree, RELATION_NODE_PARENT_OF,
+                   [treeitem1, treeitem2, treeitem5, treeitem6]);
+      testRelation(treeitem2, RELATION_NODE_PARENT_OF,
+                   [treeitem3, treeitem4]);
+
       // treeitems and treecells shouldn't pick up relations from tree
       testRelation(treeitem1, RELATION_LABELLED_BY, null);
       testRelation(treeitem1.firstChild, RELATION_LABELLED_BY, null);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
@@ -59,22 +64,27 @@
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
     <body xmlns="http://www.w3.org/1999/xhtml">
       <a target="_blank"
          href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
          title="Reorganize implementation of XUL tree accessibility">
-        Mozilla Bug 503727
+        Bug 503727
+      </a>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=527461"
+         title="Implement RELATION_NODE_PARENT_OF">
+        Bug 527461
       </a>
       <a target="_blank"
          href="https://bugzilla.mozilla.org/show_bug.cgi?id=691248"
          title="XUL tree items shouldn't pick up relations from XUL tree">
-        Mozilla Bug 691248
+        Bug 691248
       </a>
       <p id="display"></p>
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
--- a/accessible/tests/mochitest/relations/test_ui_modalprompt.html
+++ b/accessible/tests/mochitest/relations/test_ui_modalprompt.html
@@ -17,16 +17,22 @@
   <script type="application/javascript"
           src="../role.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="../browser.js"></script>
 
   <script type="application/javascript">
+    if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 1);
+    } else {
+      SimpleTest.expectAssertions(1);
+    }
+
     function hasTabModalPrompts() {
       try {
         return SpecialPowers.getBoolPref("prompts.tab_modal.enabled");
       } catch (ex) {
         return false;
       }
     }
 
--- a/accessible/tests/mochitest/text/test_singleline.html
+++ b/accessible/tests/mochitest/text/test_singleline.html
@@ -6,17 +6,22 @@
 
   <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="../text.js"></script>
   <script type="application/javascript">
-    
+    if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 23);
+    } else {
+      SimpleTest.expectAssertions(23);
+    }
+
     function doTest()
     {
       // __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
       //  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
 
       ////////////////////////////////////////////////////////////////////////
       // characterCount
 
--- a/accessible/tests/mochitest/text/test_whitespaces.html
+++ b/accessible/tests/mochitest/text/test_whitespaces.html
@@ -8,17 +8,22 @@
   <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="../text.js"></script>
   <script type="application/javascript">
-    
+    if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 10);
+    } else {
+      SimpleTest.expectAssertions(10);
+    }
+
     function doTest()
     {
       // __B__r__a__v__e__ __S__i__r__ __ __R__o__b__i__n__ __ __ __r__a__n
       //  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21
 
       ////////////////////////////////////////////////////////////////////////
       // characterCount
 
--- a/accessible/tests/mochitest/text/test_words.html
+++ b/accessible/tests/mochitest/text/test_words.html
@@ -7,17 +7,22 @@
 
   <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="../text.js"></script>
   <script type="application/javascript">
-    
+    if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 1);
+    } else {
+      SimpleTest.expectAssertions(1);
+    }
+
     function doTest()
     {
       // "one two"
       testWords("div1", ["one", "two"]);
 
       // "one  two"
       testWords("div2", ["one", "two"]);
 
--- a/accessible/tests/mochitest/tree/test_dockids.html
+++ b/accessible/tests/mochitest/tree/test_dockids.html
@@ -11,16 +11,20 @@
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../role.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
+  if (navigator.platform.indexOf("Win") == 0) {
+    SimpleTest.expectAssertions(0, 1);
+  }
+
   function doTest()
   {
     var tree =
      { DOCUMENT: [
        { PARAGRAPH: [ // head
          { PARAGRAPH: [ // link
            { STATICTEXT: [] }, // generated content
            { STATICTEXT: [] } // generated content
--- a/accessible/tests/mochitest/tree/test_txtctrl.xul
+++ b/accessible/tests/mochitest/tree/test_txtctrl.xul
@@ -13,16 +13,21 @@
           src="../common.js" />
   <script type="application/javascript"
           src="../role.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
+    if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 1);
+    } else {
+      SimpleTest.expectAssertions(1);
+    }
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
     function doTest()
     {
       ////////////////////
       // textbox
       ////////////////////
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -652,8 +652,10 @@ pref("webgl.can-lose-context-in-foregrou
 pref("memory_info_dumper.watch_fifo.enabled", true);
 pref("memory_info_dumper.watch_fifo.directory", "/data/local");
 
 // <input type='file'> implementation is not complete. We have to disable the
 // type to web content to help them do feature detection.
 pref("dom.disable_input_file", true);
 
 pref("general.useragent.enable_overrides", true);
+
+pref("b2g.version", @MOZ_B2G_VERSION@);
--- a/b2g/components/DirectoryProvider.js
+++ b/b2g/components/DirectoryProvider.js
@@ -43,16 +43,17 @@ let log =
 
 function DirectoryProvider() {
 }
 
 DirectoryProvider.prototype = {
   classID: Components.ID("{9181eb7c-6f87-11e1-90b1-4f59d80dd2e5}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]),
+  _xpcom_factory: XPCOMUtils.generateSingletonFactory(DirectoryProvider),
 
   getFile: function dp_getFile(prop, persistent) {
 #ifdef MOZ_WIDGET_GONK
     let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir",
                       "permissionDBPDir", "UpdRootD"];
     if (localProps.indexOf(prop) != -1) {
       let file = Cc["@mozilla.org/file/local;1"]
                    .createInstance(Ci.nsILocalFile)
@@ -100,16 +101,17 @@ DirectoryProvider.prototype = {
     }
     return requiredSpace <= stat.freeBytes;
   },
 
   findUpdateDirWithFreeSpace: function dp_findUpdateDirWithFreeSpace(requiredSpace, subdir) {
     if (!Services.volumeService) {
       return this.createUpdatesDir(LOCAL_DIR, subdir);
     }
+
     let activeUpdate = Services.um.activeUpdate;
     if (gUseSDCard) {
       if (this.volumeHasFreeSpace(gExtStorage, requiredSpace)) {
         let extUpdateDir = this.createUpdatesDir(gExtStorage, subdir);
         if (extUpdateDir !== null) {
           return extUpdateDir;
         }
         log("Warning: " + gExtStorage + " has enough free space for update " +
@@ -153,17 +155,18 @@ DirectoryProvider.prototype = {
       return updateDir;
     }
 
     // If we've gotten this far, there isn't enough free space to download the patch
     // on either external storage or /data/local. All we can do is report the
     // error and let upstream code handle it more gracefully.
     log("Error: No volume found with " + requiredSpace + " bytes for downloading"+
         " update " + activeUpdate.name);
-    throw Cr.NS_ERROR_FILE_TOO_BIG;
+    activeUpdate.errorCode = Cr.NS_ERROR_FILE_TOO_BIG;
+    return null;
   },
 
   createUpdatesDir: function dp_createUpdatesDir(root, subdir) {
       let dir = Cc["@mozilla.org/file/local;1"]
                    .createInstance(Ci.nsILocalFile);
       dir.initWithPath(root);
       if (!dir.isWritable()) {
         log("Error: " + dir.path + " isn't writable");
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -20,17 +20,16 @@ let log =
   function log_noop(msg) { };
 
 const PREF_APPLY_PROMPT_TIMEOUT          = "b2g.update.apply-prompt-timeout";
 const PREF_APPLY_IDLE_TIMEOUT            = "b2g.update.apply-idle-timeout";
 const PREF_DOWNLOAD_WATCHDOG_TIMEOUT     = "b2g.update.download-watchdog-timeout";
 const PREF_DOWNLOAD_WATCHDOG_MAX_RETRIES = "b2g.update.download-watchdog-max-retries";
 
 const NETWORK_ERROR_OFFLINE = 111;
-const FILE_ERROR_TOO_BIG    = 112;
 const HTTP_ERROR_OFFSET     = 1000;
 
 const STATE_DOWNLOADING = 'downloading';
 
 XPCOMUtils.defineLazyServiceGetter(Services, "aus",
                                    "@mozilla.org/updates/update-service;1",
                                    "nsIApplicationUpdateService");
 
@@ -309,17 +308,18 @@ UpdatePrompt.prototype = {
     // Services.aus.downloadUpdate will return immediately and not
     // call showUpdateDownloaded, so we detect this.
     if (aUpdate.state == "applied" && aUpdate.errorCode == 0) {
       this.showUpdateDownloaded(aUpdate, true);
       return;
     }
 
     log("Error downloading update " + aUpdate.name + ": " + aUpdate.errorCode);
-    if (aUpdate.errorCode == FILE_ERROR_TOO_BIG) {
+    let errorCode = aUpdate.errorCode >>> 0;
+    if (errorCode == Cr.NS_ERROR_FILE_TOO_BIG) {
       aUpdate.statusText = "file-too-big";
     }
     this.showUpdateError(aUpdate);
   },
 
   handleDownloadCancel: function UP_handleDownloadCancel() {
     log("Pausing download");
     Services.aus.pauseDownload();
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -358,18 +358,16 @@
 @BINPATH@/components/fuelApplication.js
 @BINPATH@/components/WebContentConverter.js
 @BINPATH@/components/BrowserComponents.manifest
 @BINPATH@/components/nsBrowserContentHandler.js
 @BINPATH@/components/nsBrowserGlue.js
 @BINPATH@/components/nsSetDefaultBrowser.manifest
 @BINPATH@/components/nsSetDefaultBrowser.js
 @BINPATH@/components/BrowserPlaces.manifest
-@BINPATH@/components/nsPrivateBrowsingService.manifest
-@BINPATH@/components/nsPrivateBrowsingService.js
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsTryToClose.manifest
 @BINPATH@/components/nsTryToClose.js
 @BINPATH@/components/passwordmgr.manifest
 @BINPATH@/components/nsLoginInfo.js
 @BINPATH@/components/nsLoginManager.js
 @BINPATH@/components/nsLoginManagerPrompter.js
 @BINPATH@/components/SiteSpecificUserAgent.js
--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -83,22 +83,20 @@ var FullScreen = {
   },
 
   exitDomFullScreen : function() {
     document.mozCancelFullScreen();
   },
 
   handleEvent: function (event) {
     switch (event.type) {
-      case "deactivate":
-        // We must call exitDomFullScreen asynchronously, since "deactivate" is
-        // dispatched in the middle of the focus manager's window lowering code,
-        // and the focus manager gets confused if we exit fullscreen mode in the
-        // middle of window lowering. See bug 729872.
-        setTimeout(this.exitDomFullScreen.bind(this), 0);
+      case "activate":
+        if (document.mozFullScreen) {
+          this.showWarning(this.fullscreenDoc);
+        }
         break;
       case "transitionend":
         if (event.propertyName == "opacity")
           this.cancelWarning();
         break;
     }
   },
 
@@ -133,20 +131,21 @@ var FullScreen = {
 
     this.showWarning(event.target);
 
     // Exit DOM full-screen mode upon open, close, or change tab.
     gBrowser.tabContainer.addEventListener("TabOpen", this.exitDomFullScreen);
     gBrowser.tabContainer.addEventListener("TabClose", this.exitDomFullScreen);
     gBrowser.tabContainer.addEventListener("TabSelect", this.exitDomFullScreen);
 
-    // Exit DOM full-screen mode when the browser window loses focus (ALT+TAB, etc).
-    if (!this.useLionFullScreen &&
-        gPrefService.getBoolPref("full-screen-api.exit-on-deactivate")) {
-      window.addEventListener("deactivate", this);
+    // Add listener to detect when the fullscreen window is re-focused.
+    // If a fullscreen window loses focus, we show a warning when the
+    // fullscreen window is refocused.
+    if (!this.useLionFullScreen) {
+      window.addEventListener("activate", this);
     }
 
     // Cancel any "hide the toolbar" animation which is in progress, and make
     // the toolbar hide immediately.
     this._cancelAnimation();
     this.mouseoverToggle(false);
 
     // Remove listeners on the full-screen toggler, so that mouseover
@@ -166,17 +165,18 @@ var FullScreen = {
 
       this._fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
       this._fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
       this.cancelWarning();
       gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
       gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
       gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
       if (!this.useLionFullScreen)
-        window.removeEventListener("deactivate", this);
+        window.removeEventListener("activate", this);
+      this.fullscreenDoc = null;
     }
   },
 
   observe: function(aSubject, aTopic, aData)
   {
     if (aData == "browser.fullscreen.autohide") {
       if (gPrefService.getBoolPref("browser.fullscreen.autohide")) {
         gBrowser.mPanelContainer.addEventListener("mousemove",
@@ -302,17 +302,16 @@ var FullScreen = {
     clearTimeout(this._animationTimeout);
     this._isAnimating = false;
     this._shouldAnimate = false;
   },
 
   cancelWarning: function(event) {
     if (!this.warningBox)
       return;
-    this.fullscreenDoc = null;
     this.warningBox.removeEventListener("transitionend", this);
     if (this.warningFadeOutTimeout) {
       clearTimeout(this.warningFadeOutTimeout);
       this.warningFadeOutTimeout = null;
     }
 
     // Ensure focus switches away from the (now hidden) warning box. If the user
     // clicked buttons in the fullscreen key authorization UI, it would have been
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -392,16 +392,24 @@ window[chromehidden~="toolbar"] toolbar:
 }
 
 #full-screen-warning-container[fade-warning-out] {
   transition-property: opacity !important;
   transition-duration: 500ms !important;
   opacity: 0.0;
 }
 
+/* When the modal fullscreen approval UI is showing, don't allow interaction
+   with the page, but when we're just showing the warning upon entering
+   fullscreen on an already approved page, do allow interaction with the page.
+ */
+#full-screen-warning-container:not([obscure-browser]) {
+  pointer-events: none;
+}
+
 #full-screen-warning-message {
   /* We must specify a max-width, otherwise word-wrap:break-word doesn't
      work in descendant <description> and <label> elements. Bug 630864. */
   max-width: 800px;
 }
 
 #full-screen-domain-text,
 #full-screen-remember-decision > .checkbox-label-box > .checkbox-label {
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -948,17 +948,17 @@ function startTest() {
     ok(contextMenu, "Got context menu XUL");
 
     if (chromeWin.document.getElementById("Browser:Stop").getAttribute("disabled") != "true") {
       todo(false, "Wait for subwindow to load... (This should usually happen once.)");
       SimpleTest.executeSoon(startTest);
       return;
     }
 
-    subwindow.allowfullscreen = true;
+    subwindow.allowFullscreen = true;
     lastElement = null;
 
     text   = subwindow.document.getElementById("test-text");
     link   = subwindow.document.getElementById("test-link");
     imagelink = subwindow.document.getElementById("test-image-link");
     mailto = subwindow.document.getElementById("test-mailto");
     input  = subwindow.document.getElementById("test-input");
     img    = subwindow.document.getElementById("test-image");
--- a/browser/components/privatebrowsing/moz.build
+++ b/browser/components/privatebrowsing/moz.build
@@ -1,7 +1,6 @@
 # vim: set filetype=python:
 # 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/.
 
-DIRS += ['src']
 TEST_DIRS += ['test']
deleted file mode 100644
--- a/browser/components/privatebrowsing/src/Makefile.in
+++ /dev/null
@@ -1,23 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DEPTH   = @DEPTH@
-topsrcdir = @top_srcdir@
-srcdir    = @srcdir@
-VPATH   = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MODULE = privatebrowsing
-LIBRARY_NAME = privatebrowsing_s
-
-FORCE_STATIC_LIB = 1
-USE_STATIC_LIBS = 1
-
-EXTRA_COMPONENTS = \
-  nsPrivateBrowsingServiceObsolete.manifest \
-  nsPrivateBrowsingServiceObsolete.js \
-  $(NULL)
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/browser/components/privatebrowsing/src/moz.build
+++ /dev/null
@@ -1,5 +0,0 @@
-# vim: set filetype=python:
-# 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/.
-
deleted file mode 100644
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingServiceObsolete.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/* 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]);
deleted file mode 100644
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingServiceObsolete.manifest
+++ /dev/null
@@ -1,15 +0,0 @@
-# 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
@@ -344,18 +344,16 @@
 @BINPATH@/browser/components/nsBrowserGlue.js
 @BINPATH@/browser/components/nsSetDefaultBrowser.manifest
 @BINPATH@/browser/components/nsSetDefaultBrowser.js
 @BINPATH@/browser/components/BrowserDownloads.manifest
 @BINPATH@/browser/components/DownloadsStartup.js
 @BINPATH@/browser/components/DownloadsUI.js
 @BINPATH@/browser/components/BrowserPlaces.manifest
 @BINPATH@/components/BrowserPageThumbs.manifest
-@BINPATH@/browser/components/nsPrivateBrowsingServiceObsolete.manifest
-@BINPATH@/browser/components/nsPrivateBrowsingServiceObsolete.js
 @BINPATH@/components/SiteSpecificUserAgent.js
 @BINPATH@/components/SiteSpecificUserAgent.manifest
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsSearchService.js
 @BINPATH@/components/nsSearchSuggestions.js
 @BINPATH@/components/passwordmgr.manifest
 @BINPATH@/components/nsLoginInfo.js
 @BINPATH@/components/nsLoginManager.js
--- a/browser/metro/base/content/bindings/tabs.xml
+++ b/browser/metro/base/content/bindings/tabs.xml
@@ -101,17 +101,42 @@
       <xul:arrowscrollbox anonid="tabs-scrollbox" class="tabs-scrollbox" flex="1" orient="horizontal"
         clicktoscroll="true" />
     </content>
 
     <handlers>
       <handler event="dblclick" action="this._onDoubleClick();"/>
     </handlers>
 
-    <implementation>
+    <implementation implements="nsIDOMEventListener">
+      <constructor>
+        <![CDATA[
+          window.addEventListener("MozContextUIExpand", this, true);
+        ]]>
+      </constructor>
+
+      <destructor>
+        <![CDATA[
+          window.removeEventListener("MozContextUIExpand", this, true);
+        ]]>
+      </destructor>
+
+      <method name="handleEvent">
+        <parameter name="event"/>
+        <body>
+          <![CDATA[
+            switch (event.type) {
+              case "MozContextUIExpand":
+                this.strip.ensureElementIsVisible(this.selectedTab, false);
+                break;
+            }
+          ]]>
+        </body>
+      </method>
+
       <field name="strip">document.getAnonymousElementByAttribute(this, "anonid", "tabs-scrollbox");</field>
       <field name="_selectedTab">null</field>
 
       <!-- Used by the chrome input handler -->
       <property name="anonScrollBox"
                 readonly="true"
                 onget="return this.strip;"/>
 
--- a/browser/metro/base/content/sync.js
+++ b/browser/metro/base/content/sync.js
@@ -19,25 +19,20 @@ let WeaveGlue = {
     }
 
     let service = Components.classes["@mozilla.org/weave/service;1"]
                                     .getService(Components.interfaces.nsISupports)
                                     .wrappedJSObject;
 
     if (service.ready) {
       this._init();
-      return;
+    } else {
+      Services.obs.addObserver(this, "weave:service:ready", false);
+      service.ensureLoaded();
     }
-
-    Services.obs.addObserver(function onReady() {
-      Services.obs.removeObserver(onReady, "weave:service:ready");
-      this._init();
-    }.bind(this), "weave:service:ready", false);
-
-    service.ensureLoaded();
   },
 
   _init: function () {
     this._bundle = Services.strings.createBundle("chrome://browser/locale/sync.properties");
     this._msg = document.getElementById("prefs-messages");
 
     this._addListeners();
 
@@ -420,16 +415,22 @@ let WeaveGlue = {
     });
 
     // Replace the getter with the collection of settings
     delete this._elements;
     return this._elements = elements;
   },
 
   observe: function observe(aSubject, aTopic, aData) {
+    if (aTopic == "weave:service:ready") {
+      Services.obs.removeObserver(this, aTopic);
+      this._init();
+      return;
+    }
+
     // Make sure we're online when connecting/syncing
     Util.forceOnline();
 
     // Can't do anything before settings are loaded
     if (this._elements == null)
       return;
 
     // Make some aliases
--- a/build/virtualenv/packages.txt
+++ b/build/virtualenv/packages.txt
@@ -2,14 +2,16 @@ simplejson.pth:python/simplejson-2.1.1
 marionette.pth:testing/marionette/client
 blessings.pth:python/blessings
 mach.pth:python/mach
 mozbuild.pth:python/mozbuild
 pymake.pth:build/pymake
 optional:setup.py:python/psutil:build_ext:--inplace
 optional:psutil.pth:python/psutil
 which.pth:python/which
+ply.pth:other-licenses/ply/
+codegen.pth:python/codegen/
 mock.pth:python/mock-1.0.0
 mozilla.pth:build
 mozilla.pth:config
 mozilla.pth:xpcom/typelib/xpt/tools
 copy:build/buildconfig.py
 packages.txt:testing/mozbase/packages.txt
--- a/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
+++ b/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
@@ -17,16 +17,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 <script type="application/javascript;version=1.7">
 
 /** Test for Bug 758258 **/
 
 var Ci = Components.interfaces;
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(2);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 /*
  * gData is an array of objects. Each object represents a test case.
  * - app: gives the app manifest URL, will set mozapp to it on the iframe;
  * - origin: gives the origin of the iframe. This is the URL thas is going to
  *           to be passed as iframe.src but also the expected principal's
  *           origin.
--- a/configure.in
+++ b/configure.in
@@ -4668,47 +4668,50 @@ dnl ====================================
 if test "$MOZ_ENABLE_QT"
 then
     MOZ_ARG_WITH_STRING(qtdir,
     [  --with-qtdir=\$dir       Specify Qt directory ],
     [ QTDIR=$withval])
 
     if test -z "$QTDIR"; then
         PKG_CHECK_MODULES(MOZ_QT, QtGui QtNetwork QtCore QtOpenGL)
-        PKG_CHECK_MODULES(MOZ_QT5, QtWidgets QtMultimedia QtPrintSupport,
+        PKG_CHECK_MODULES(MOZ_QT5, Qt5Widgets Qt5Multimedia Qt5PrintSupport,
                       MOZ_ENABLE_QT5=1,
                       MOZ_ENABLE_QT5=)
         if test "$MOZ_ENABLE_QT5"; then
             echo "Using qt5"
             MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS $MOZ_QT5_CFLAGS"
             MOZ_QT_LIBS="$MOZ_QT_LIBS $MOZ_QT5_LIBS"
         fi
 
         AC_CHECK_PROGS(HOST_MOC, $MOC moc, "")
         AC_CHECK_PROGS(HOST_RCC, $RCC rcc, "")
     else
-        MOZ_QT_LIBS="-L$QTDIR/lib/ -lQtGui -lQtNetwork -lQtCore -lQtXml -lQtOpenGL"
-
         MOZ_QT_CFLAGS="-DQT_SHARED"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include"
-        MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/Qt"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtGui"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtCore"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtNetwork"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtXml"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtDeclarative"
-        HOST_MOC="$QTDIR/bin/moc"
-        HOST_RCC="$QTDIR/bin/rcc"
 
         # QtWidgets was introduced only in Qt5
         if test -d $QTDIR/include/QtWidgets; then
+            echo "Using qt5"
+            MOZ_QT_LIBS="-L$QTDIR/lib/ -lQt5Gui -lQt5Network -lQt5Core -lQt5Xml -lQt5OpenGL"
+            MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtGui/5.0.1/QtGui"
             MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtWidgets"
             MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtPrintSupport"
-            MOZ_QT_LIBS="$MOZ_QT_LIBS -lQtWidgets -lQtPrintSupport"
+            MOZ_QT_LIBS="$MOZ_QT_LIBS -lQt5Widgets -lQt5PrintSupport"
+        else
+            MOZ_QT_LIBS="-L$QTDIR/lib/ -lQtGui -lQtNetwork -lQtCore -lQtXml -lQtOpenGL"
+            MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/Qt"
         fi
+        HOST_MOC="$QTDIR/bin/moc"
+        HOST_RCC="$QTDIR/bin/rcc"
     fi
     if test -z "$HOST_MOC"; then
         AC_MSG_ERROR([No acceptable moc preprocessor found. Qt SDK is not installed or --with-qt is
 incorrect])
     fi
     if test -z "$HOST_RCC"; then
         AC_MSG_ERROR([No acceptable rcc preprocessor found. Qt SDK is not installed or --with-qt is
 incorrect])
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -97,18 +97,18 @@ class HTMLBodyElement;
 class Link;
 class ProcessingInstruction;
 class UndoManager;
 template<typename> class Sequence;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID \
-{ 0x4e6f7d97, 0x091e, 0x4eda, \
-  { 0xb7, 0xd6, 0xfe, 0xb0, 0xb8, 0x01, 0x2a, 0x93 } }
+{ 0x45ce048f, 0x5970, 0x411e, \
+  { 0xaa, 0x99, 0x12, 0xed, 0x3a, 0x55, 0xc9, 0xc3 } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
@@ -881,17 +881,17 @@ public:
   virtual nsresult RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
                                                 const nsAString& aNewOrigin) = 0;
 
   /**
    * Called when a frame in a remote child document has rolled back fullscreen
    * so that all its fullscreen element stacks are empty; we must continue the
    * rollback in this parent process' doc tree branch which is fullscreen.
    * Note that only one branch of the document tree can have its documents in
-   * fullscreen state at one time. We're in inconsistent state if the a 
+   * fullscreen state at one time. We're in inconsistent state if a
    * fullscreen document has a parent and that parent isn't fullscreen. We
    * preserve this property across process boundaries.
    */
    virtual nsresult RemoteFrameFullscreenReverted() = 0;
 
   /**
    * Restores the previous full-screen element to full-screen status. If there
    * is no former full-screen element, this exits full-screen, moving the
@@ -900,30 +900,51 @@ public:
   virtual void RestorePreviousFullScreenState() = 0;
 
   /**
    * Returns true if this document is in full-screen mode.
    */
   virtual bool IsFullScreenDoc() = 0;
 
   /**
+   * Returns true if this document is a fullscreen leaf document, i.e. it
+   * is in fullscreen mode and has no fullscreen children.
+   */
+  virtual bool IsFullscreenLeaf() = 0;
+
+  /**
+   * Returns the document which is at the root of this document's branch
+   * in the in-process document tree. Returns nullptr if the document isn't
+   * fullscreen.
+   */
+  virtual nsIDocument* GetFullscreenRoot() = 0;
+
+  /**
+   * Sets the fullscreen root to aRoot. This stores a weak reference to aRoot
+   * in this document.
+   */
+  virtual void SetFullscreenRoot(nsIDocument* aRoot) = 0;
+
+  /**
    * Sets whether this document is approved for fullscreen mode.
    * Documents aren't approved for fullscreen until chrome has sent a
    * "fullscreen-approved" notification with a subject which is a pointer
    * to the approved document.
    */
   virtual void SetApprovedForFullscreen(bool aIsApproved) = 0;
 
   /**
-   * Exits all documents from DOM full-screen mode, and moves the top-level
-   * browser window out of full-screen mode. If aRunAsync is true, this runs
-   * asynchronously.
+   * Exits documents out of DOM fullscreen mode. If aDocument is non null,
+   * only its ancestors and descendants exit fullscreen, i.e. if there are
+   * multiple windows/doctrees in fullscreen mode, only the one containing
+   * aDocument exits fullscreen mode. If aDocument is null, all windows
+   * and documents exit fullscreen. If aRunAsync is true, fullscreen is
+   * executed asynchronously.
    */
-  static void ExitFullScreen(bool aRunAsync);
-
+  static void ExitFullscreen(nsIDocument* aDocument, bool aRunAsync);
 
   virtual void RequestPointerLock(Element* aElement) = 0;
 
   static void UnlockPointer();
 
 
   //----------------------------------------------------------------------
 
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -1293,17 +1293,17 @@ Element::UnbindFromTree(bool aDeep, bool
     if (IsFullScreenAncestor()) {
       // The element being removed is an ancestor of the full-screen element,
       // exit full-screen state.
       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                       "DOM", OwnerDoc(),
                                       nsContentUtils::eDOM_PROPERTIES,
                                       "RemovedFullScreenElement");
       // Fully exit full-screen.
-      nsIDocument::ExitFullScreen(false);
+      nsIDocument::ExitFullscreen(OwnerDoc(), /* async */ false);
     }
     if (HasPointerLock()) {
       nsIDocument::UnlockPointer();
     }
     if (GetParent()) {
       NS_RELEASE(mParent);
     } else {
       mParent = nullptr;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -190,23 +190,16 @@
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsViewportInfo.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 typedef nsTArray<Link*> LinkArray;
 
-// Reference to the document which requested DOM full-screen mode.
-nsWeakPtr nsDocument::sFullScreenDoc = nullptr;
-
-// Reference to the root document of the branch containing the document
-// which requested DOM full-screen mode.
-nsWeakPtr nsDocument::sFullScreenRootDoc = nullptr;
-
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDocumentLeakPRLog;
 static PRLogModuleInfo* gCspPRLog;
 #endif
 
 #define NAME_NOT_VALID ((nsSimpleContentList*)1)
 
 nsIdentifierMapEntry::~nsIdentifierMapEntry()
@@ -7777,28 +7770,36 @@ nsDocument::OnPageHide(bool aPersisted,
   mVisible = false;
 
   UpdateVisibilityState();
 
   EnumerateExternalResources(NotifyPageHide, &aPersisted);
   EnumerateFreezableElements(NotifyActivityChanged, nullptr);
 
   if (IsFullScreenDoc()) {
-    // A full-screen doc has been hidden. We need to ensure we exit
-    // full-screen, i.e. remove full-screen state from all full-screen
-    // documents, and exit the top-level window from full-screen mode.
-    // By the time a doc is hidden, it has been removed from the doc tree,
-    // so nsIDocument::ExitFullScreen() won't be able to traverse to this
-    // document to reset its state, so reset full-screen state in *this*
-    // document. OnPageHide() is called in every hidden document, so doing
-    // this ensures all hidden documents have their full-screen state reset.
+    // If this document was fullscreen, we should exit fullscreen in this
+    // doctree branch. This ensures that if the user navigates while in
+    // fullscreen mode we don't leave its still visible ancestor documents
+    // in fullscreen mode. So exit fullscreen in the document's fullscreen
+    // root document, as this will exit fullscreen in all the root's
+    // descendant documents. Note that documents are removed from the
+    // doctree by the time OnPageHide() is called, so we must store a
+    // reference to the root (in nsDocument::mFullscreenRoot) since we can't
+    // just traverse the doctree to get the root.
+    nsIDocument::ExitFullscreen(this, /* async */ false);
+
+    // Since the document is removed from the doctree before OnPageHide() is
+    // called, ExitFullscreen() can't traverse from the root down to *this*
+    // document, so we must manually call CleanupFullscreenState() below too.
+    // Note that CleanupFullscreenState() clears nsDocument::mFullscreenRoot,
+    // so we *must* call it after ExitFullscreen(), not before.
+    // OnPageHide() is called in every hidden (i.e. descendant) document,
+    // so calling CleanupFullscreenState() here will ensure all hidden
+    // documents have their fullscreen state reset.
     CleanupFullscreenState();
-
-    // Next reset full-screen state in all visible documents in the doctree.
-    nsIDocument::ExitFullScreen(false);
   }
 }
 
 void
 nsDocument::WillDispatchMutationEvent(nsINode* aTarget)
 {
   NS_ASSERTION(mSubtreeModifiedDepth != 0 ||
                mSubtreeModifiedTargets.Count() == 0,
@@ -8961,146 +8962,16 @@ nsIDocument::CreateTouchList(const Seque
 {
   nsRefPtr<nsDOMTouchList> retval = new nsDOMTouchList();
   for (uint32_t i = 0; i < aTouches.Length(); ++i) {
     retval->Append(aTouches[i]);
   }
   return retval.forget();
 }
 
-static void
-DispatchFullScreenChange(nsIDocument* aTarget)
-{
-  nsRefPtr<nsAsyncDOMEvent> e =
-    new nsAsyncDOMEvent(aTarget,
-                        NS_LITERAL_STRING("mozfullscreenchange"),
-                        true,
-                        false);
-  e->PostDOMEvent();
-}
-
-NS_IMETHODIMP
-nsDocument::MozCancelFullScreen()
-{
-  nsIDocument::MozCancelFullScreen();
-  return NS_OK;
-}
-
-void
-nsIDocument::MozCancelFullScreen()
-{
-  // Only perform fullscreen changes if we're running in a webapp
-  // same-origin to the web app, or if we're in a user generated event
-  // handler.
-  if (NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
-      nsContentUtils::IsRequestFullScreenAllowed()) {
-    RestorePreviousFullScreenState();
-  }
-}
-
-// Runnable to set window full-screen mode. Used as a script runner
-// to ensure we only call nsGlobalWindow::SetFullScreen() when it's safe to
-// run script. nsGlobalWindow::SetFullScreen() dispatches a synchronous event
-// (handled in chome code) which is unsafe to run if this is called in
-// Element::UnbindFromTree().
-class nsSetWindowFullScreen : public nsRunnable {
-public:
-  nsSetWindowFullScreen(nsIDocument* aDoc, bool aValue)
-    : mDoc(aDoc), mValue(aValue) {}
-
-  NS_IMETHOD Run()
-  {
-    if (mDoc->GetWindow()) {
-      mDoc->GetWindow()->SetFullScreenInternal(mValue, false);
-    }
-    return NS_OK;
-  }
-
-private:
-  nsCOMPtr<nsIDocument> mDoc;
-  bool mValue;
-};
-
-static void
-SetWindowFullScreen(nsIDocument* aDoc, bool aValue)
-{
-  nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue));
-}
-
-class nsCallExitFullScreen : public nsRunnable {
-public:
-  NS_IMETHOD Run()
-  {
-    nsDocument::ExitFullScreen();
-    return NS_OK;
-  }
-};
-
-/* static */
-void
-nsIDocument::ExitFullScreen(bool aRunAsync)
-{
-  if (aRunAsync) {
-    NS_DispatchToCurrentThread(new nsCallExitFullScreen());
-    return;
-  }
-  nsDocument::ExitFullScreen();
-}
-
-// Returns true if the document is a direct child of a cross process parent
-// mozbrowser iframe. This is the case when the document has a null parent,
-// and its DocShell reports that it is a browser frame.
-static bool
-HasCrossProcessParent(nsIDocument* aDocument)
-{
-  if (XRE_GetProcessType() != GeckoProcessType_Content) {
-    return false;
-  }
-  if (aDocument->GetParentDocument() != nullptr) {
-    return false;
-  }
-  nsPIDOMWindow* win = aDocument->GetWindow();
-  if (!win) {
-    return false;
-  }
-  nsCOMPtr<nsIDocShell> docShell = win->GetDocShell();
-  if (!docShell) {
-    return false;
-  }
-  return docShell->GetIsBrowserOrApp();
-}
-
-static bool
-ResetFullScreen(nsIDocument* aDocument, void* aData)
-{
-  if (aDocument->IsFullScreenDoc()) {
-    static_cast<nsDocument*>(aDocument)->CleanupFullscreenState();
-    NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen");
-    nsTArray<nsIDocument*>* changed = reinterpret_cast<nsTArray<nsIDocument*>*>(aData);
-    changed->AppendElement(aDocument);
-
-    if (HasCrossProcessParent(aDocument)) {
-      // We're at the top of the content-process side doc tree. Ask the parent
-      // process to exit fullscreen.
-      nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
-      os->NotifyObservers(aDocument, "ask-parent-to-exit-fullscreen", nullptr);
-    }
-
-    // Dispatch a notification so that if this document has any
-    // cross-process subdocuments, they'll be notified to exit fullscreen.
-    // The BrowserElementParent listens for this event and performs the
-    // cross process notification if it has a remote child process.
-    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
-    os->NotifyObservers(aDocument, "ask-children-to-exit-fullscreen", nullptr);
-
-    aDocument->EnumerateSubDocuments(ResetFullScreen, aData);
-  }
-  return true;
-}
-
 already_AddRefed<nsDOMCaretPosition>
 nsIDocument::CaretPositionFromPoint(float aX, float aY)
 {
   nscoord x = nsPresContext::CSSPixelsToAppUnits(aX);
   nscoord y = nsPresContext::CSSPixelsToAppUnits(aY);
   nsPoint pt(x, y);
 
   nsIPresShell *ps = GetShell();
@@ -9153,81 +9024,450 @@ nsIDocument::CaretPositionFromPoint(floa
 NS_IMETHODIMP
 nsDocument::CaretPositionFromPoint(float aX, float aY, nsISupports** aCaretPos)
 {
   NS_ENSURE_ARG_POINTER(aCaretPos);
   *aCaretPos = nsIDocument::CaretPositionFromPoint(aX, aY).get();
   return NS_OK;
 }
 
+namespace mozilla {
+
+// Singleton class to manage the list of fullscreen documents which are the
+// root of a branch which contains fullscreen documents. We maintain this list
+// so that we can easily exit all windows from fullscreen when the user
+// presses the escape key.
+class FullscreenRoots {
+public:
+  // Adds a root to the manager. Adding a root multiple times does not result
+  // in duplicate entries for that item, only one.
+  static void Add(nsIDocument* aRoot);
+
+  // Iterates over every root in the root list, and calls aFunction, passing
+  // each root once to aFunction. It is safe to call Add() and Remove() while
+  // iterating over the list (i.e. in aFunction). Documents that are removed
+  // from the manager during traversal are not traversed, and documents that
+  // are added to the manager during traversal are also not traversed.
+  static void ForEach(void(*aFunction)(nsIDocument* aDoc));
+
+  // Removes a specific root from the manager.
+  static void Remove(nsIDocument* aRoot);
+
+  // Returns true if all roots added to the list have been removed.
+  static bool IsEmpty();
+
+private:
+
+  FullscreenRoots() {
+    MOZ_COUNT_CTOR(FullscreenRoots);
+  }
+  ~FullscreenRoots() {
+    MOZ_COUNT_DTOR(FullscreenRoots);
+  }
+
+  enum {
+    NotFound = uint32_t(-1)
+  };
+  // Looks in mRoots for aRoot. Returns the index if found, otherwise NotFound.
+  static uint32_t Find(nsIDocument* aRoot);
+
+  // Returns true if aRoot is in the list of fullscreen roots.
+  static bool Contains(nsIDocument* aRoot);
+
+  // Singleton instance of the FullscreenRoots. This is instantiated when a
+  // root is added, and it is deleted when the last root is removed.
+  static FullscreenRoots* sInstance;
+
+  // List of weak pointers to roots.
+  nsTArray<nsWeakPtr> mRoots;
+};
+
+FullscreenRoots* FullscreenRoots::sInstance = nullptr;
+
 /* static */
 void
-nsDocument::ExitFullScreen()
-{
-  // Clear full-screen stacks in all descendant documents.
-  nsCOMPtr<nsIDocument> root(do_QueryReferent(sFullScreenRootDoc));
+FullscreenRoots::ForEach(void(*aFunction)(nsIDocument* aDoc))
+{
+  if (!sInstance) {
+    return;
+  }
+  // Create a copy of the roots array, and iterate over the copy. This is so
+  // that if an element is removed from mRoots we don't mess up our iteration.
+  nsTArray<nsWeakPtr> roots(sInstance->mRoots);
+  // Call aFunction on all entries.
+  for (uint32_t i = 0; i < roots.Length(); i++) {
+    nsCOMPtr<nsIDocument> root = do_QueryReferent(roots[i]);
+    // Check that the root isn't in the manager. This is so that new additions
+    // while we were running don't get traversed.
+    if (root && FullscreenRoots::Contains(root)) {
+      aFunction(root);
+    }
+  }
+}
+
+/* static */
+bool
+FullscreenRoots::Contains(nsIDocument* aRoot)
+{
+  return FullscreenRoots::Find(aRoot) != NotFound;
+}
+
+/* static */
+void
+FullscreenRoots::Add(nsIDocument* aRoot)
+{
+  if (!FullscreenRoots::Contains(aRoot)) {
+    if (!sInstance) {
+      sInstance = new FullscreenRoots();
+    }
+    sInstance->mRoots.AppendElement(do_GetWeakReference(aRoot));
+  }
+}
+
+/* static */
+uint32_t
+FullscreenRoots::Find(nsIDocument* aRoot)
+{
+  if (!sInstance) {
+    return NotFound;
+  }
+  nsTArray<nsWeakPtr>& roots = sInstance->mRoots;
+  for (uint32_t i = 0; i < roots.Length(); i++) {
+    nsCOMPtr<nsIDocument> otherRoot(do_QueryReferent(roots[i]));
+    if (otherRoot == aRoot) {
+      return i;
+    }
+  }
+  return NotFound;
+}
+
+/* static */
+void
+FullscreenRoots::Remove(nsIDocument* aRoot)
+{
+  uint32_t index = Find(aRoot);
+  NS_ASSERTION(index != NotFound,
+    "Should only try to remove roots which are still added!");
+  if (index == NotFound || !sInstance) {
+    return;
+  }
+  sInstance->mRoots.RemoveElementAt(index);
+  if (sInstance->mRoots.IsEmpty()) {
+    delete sInstance;
+    sInstance = nullptr;
+  }
+}
+
+/* static */
+bool
+FullscreenRoots::IsEmpty()
+{
+  return !sInstance;
+}
+
+} // end namespace mozilla.
+using mozilla::FullscreenRoots;
+
+nsIDocument*
+nsDocument::GetFullscreenRoot()
+{
+  nsCOMPtr<nsIDocument> root = do_QueryReferent(mFullscreenRoot);
+  return root;
+}
+
+void
+nsDocument::SetFullscreenRoot(nsIDocument* aRoot)
+{
+  mFullscreenRoot = do_GetWeakReference(aRoot);
+}
+
+static void
+DispatchFullScreenChange(nsIDocument* aTarget)
+{
+  nsRefPtr<nsAsyncDOMEvent> e =
+    new nsAsyncDOMEvent(aTarget,
+                        NS_LITERAL_STRING("mozfullscreenchange"),
+                        true,
+                        false);
+  e->PostDOMEvent();
+}
+
+NS_IMETHODIMP
+nsDocument::MozCancelFullScreen()
+{
+  nsIDocument::MozCancelFullScreen();
+  return NS_OK;
+}
+
+void
+nsIDocument::MozCancelFullScreen()
+{
+  // Only perform fullscreen changes if we're running in a webapp
+  // same-origin to the web app, or if we're in a user generated event
+  // handler.
+  if (NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
+      nsContentUtils::IsRequestFullScreenAllowed()) {
+    RestorePreviousFullScreenState();
+  }
+}
+
+// Runnable to set window full-screen mode. Used as a script runner
+// to ensure we only call nsGlobalWindow::SetFullScreen() when it's safe to
+// run script. nsGlobalWindow::SetFullScreen() dispatches a synchronous event
+// (handled in chome code) which is unsafe to run if this is called in
+// Element::UnbindFromTree().
+class nsSetWindowFullScreen : public nsRunnable {
+public:
+  nsSetWindowFullScreen(nsIDocument* aDoc, bool aValue)
+    : mDoc(aDoc), mValue(aValue) {}
+
+  NS_IMETHOD Run()
+  {
+    if (mDoc->GetWindow()) {
+      mDoc->GetWindow()->SetFullScreenInternal(mValue, false);
+    }
+    return NS_OK;
+  }
+
+private:
+  nsCOMPtr<nsIDocument> mDoc;
+  bool mValue;
+};
+
+static void
+SetWindowFullScreen(nsIDocument* aDoc, bool aValue)
+{
+  // Maintain list of fullscreen root documents.
+  nsCOMPtr<nsIDocument> root = nsContentUtils::GetRootDocument(aDoc);
+  if (aValue) {
+    FullscreenRoots::Add(root);
+  } else {
+    FullscreenRoots::Remove(root);
+  }
+  nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue));
+}
+
+class nsCallExitFullscreen : public nsRunnable {
+public:
+  nsCallExitFullscreen(nsIDocument* aDoc)
+    : mDoc(aDoc) {}
+  NS_IMETHOD Run()
+  {
+    nsDocument::ExitFullscreen(mDoc);
+    return NS_OK;
+  }
+private:
+  nsCOMPtr<nsIDocument> mDoc;
+};
+
+/* static */
+void
+nsIDocument::ExitFullscreen(nsIDocument* aDoc, bool aRunAsync)
+{
+  if (aDoc && !aDoc->IsFullScreenDoc()) {
+    return;
+  }
+  if (aRunAsync) {
+    NS_DispatchToCurrentThread(new nsCallExitFullscreen(aDoc));
+    return;
+  }
+  nsDocument::ExitFullscreen(aDoc);
+}
+
+// Returns true if the document is a direct child of a cross process parent
+// mozbrowser iframe. This is the case when the document has a null parent,
+// and its DocShell reports that it is a browser frame.
+static bool
+HasCrossProcessParent(nsIDocument* aDocument)
+{
+  if (XRE_GetProcessType() != GeckoProcessType_Content) {
+    return false;
+  }
+  if (aDocument->GetParentDocument() != nullptr) {
+    return false;
+  }
+  nsPIDOMWindow* win = aDocument->GetWindow();
+  if (!win) {
+    return false;
+  }
+  nsCOMPtr<nsIDocShell> docShell = win->GetDocShell();
+  if (!docShell) {
+    return false;
+  }
+  return docShell->GetIsBrowserOrApp();
+}
+
+static bool
+CountFullscreenSubDocuments(nsIDocument* aDoc, void* aData)
+{
+  if (aDoc->IsFullScreenDoc()) {
+    uint32_t* count = static_cast<uint32_t*>(aData);
+    (*count)++;
+  }
+  return true;
+}
+
+static uint32_t
+CountFullscreenSubDocuments(nsIDocument* aDoc)
+{
+  uint32_t count = 0;
+  aDoc->EnumerateSubDocuments(CountFullscreenSubDocuments, &count);
+  return count;
+}
+
+bool
+nsDocument::IsFullscreenLeaf()
+{
+  // A fullscreen leaf document is fullscreen, and has no fullscreen
+  // subdocuments.
+  if (!IsFullScreenDoc()) {
+    return false;
+  }
+  return CountFullscreenSubDocuments(this) == 0;
+}
+
+static bool
+ResetFullScreen(nsIDocument* aDocument, void* aData)
+{
+  if (aDocument->IsFullScreenDoc()) {
+    NS_ASSERTION(CountFullscreenSubDocuments(aDocument) <= 1,
+        "Should have at most 1 fullscreen subdocument.");
+    static_cast<nsDocument*>(aDocument)->CleanupFullscreenState();
+    NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen");
+    nsTArray<nsIDocument*>* changed = reinterpret_cast<nsTArray<nsIDocument*>*>(aData);
+    changed->AppendElement(aDocument);
+
+    if (HasCrossProcessParent(aDocument)) {
+      // We're at the top of the content-process side doc tree. Ask the parent
+      // process to exit fullscreen.
+      nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+      os->NotifyObservers(aDocument, "ask-parent-to-exit-fullscreen", nullptr);
+    }
+
+    // Dispatch a notification so that if this document has any
+    // cross-process subdocuments, they'll be notified to exit fullscreen.
+    // The BrowserElementParent listens for this event and performs the
+    // cross process notification if it has a remote child process.
+    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+    os->NotifyObservers(aDocument, "ask-children-to-exit-fullscreen", nullptr);
+
+    aDocument->EnumerateSubDocuments(ResetFullScreen, aData);
+  }
+  return true;
+}
+
+static void
+ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
+{
+  MOZ_ASSERT(aMaybeNotARootDoc);
+  nsCOMPtr<nsIDocument> root = aMaybeNotARootDoc->GetFullscreenRoot();
+  NS_ASSERTION(root, "Should have root when in fullscreen!");
   if (!root) {
-    // Not in full-screen mode.
     return;
   }
   NS_ASSERTION(root->IsFullScreenDoc(),
-    "Full-screen root should be a full-screen doc...");
+    "Fullscreen root should be a fullscreen doc...");
 
   // Stores a list of documents to which we must dispatch "mozfullscreenchange".
   // We're required by the spec to dispatch the events in leaf-to-root
-  // order when exiting full-screen, but we traverse the doctree in a
+  // order when exiting fullscreen, but we traverse the doctree in a
   // root-to-leaf order, so we save references to the documents we must
   // dispatch to so that we dispatch in the specified order.
   nsAutoTArray<nsIDocument*, 8> changed;
 
-  // We may also need to unlock the pointer, if it's locked.
-  nsCOMPtr<Element> pointerLockedElement =
-    do_QueryReferent(nsEventStateManager::sPointerLockedElement);
-  if (pointerLockedElement) {
-    UnlockPointer();
-  }
-
-  // Walk the tree of full-screen documents, and reset their full-screen state.
+  // Walk the tree of fullscreen documents, and reset their fullscreen state.
   ResetFullScreen(root, static_cast<void*>(&changed));
 
   // Dispatch "mozfullscreenchange" events. Note this loop is in reverse
   // order so that the events for the leaf document arrives before the root
   // document, as required by the spec.
   for (uint32_t i = 0; i < changed.Length(); ++i) {
     DispatchFullScreenChange(changed[changed.Length() - i - 1]);
   }
 
-  // Reset global state. Do this before we move the window out of full-screen
-  // mode, as that calls nsGlobalWindow::SetFullScreen() which calls back into
-  // nsIDocument::ExitFullScreen().
-  sFullScreenRootDoc = nullptr;
-  sFullScreenDoc = nullptr;
-
-  // Move the top-level window out of full-screen mode.
+  NS_ASSERTION(!root->IsFullScreenDoc(),
+    "Fullscreen root should no longer be a fullscreen doc...");
+
+  // Move the top-level window out of fullscreen mode.
   SetWindowFullScreen(root, false);
 }
 
+/* static */
+void
+nsDocument::ExitFullscreen(nsIDocument* aDoc)
+{
+  // Unlock the pointer, if it's locked.
+  nsCOMPtr<Element> pointerLockedElement =
+    do_QueryReferent(nsEventStateManager::sPointerLockedElement);
+  if (pointerLockedElement) {
+    UnlockPointer();
+  }
+
+  if (aDoc)  {
+    ExitFullscreenInDocTree(aDoc);
+    return;
+  }
+
+  // Clear fullscreen stacks in all fullscreen roots' descendant documents.
+  FullscreenRoots::ForEach(&ExitFullscreenInDocTree);
+  NS_ASSERTION(FullscreenRoots::IsEmpty(),
+      "Should have exited all fullscreen roots from fullscreen");
+}
+
+bool
+GetFullscreenLeaf(nsIDocument* aDoc, void* aData)
+{
+  if (aDoc->IsFullscreenLeaf()) {
+    nsIDocument** result = static_cast<nsIDocument**>(aData);
+    *result = aDoc;
+    return false;
+  } else if (aDoc->IsFullScreenDoc()) {
+    aDoc->EnumerateSubDocuments(GetFullscreenLeaf, aData);
+  }
+  return true;
+}
+
+static nsIDocument*
+GetFullscreenLeaf(nsIDocument* aDoc)
+{
+  nsIDocument* leaf = nullptr;
+  GetFullscreenLeaf(aDoc, &leaf);
+  if (leaf) {
+    return leaf;
+  }
+  // Otherwise we could be either in a non-fullscreen doc tree, or we're
+  // below the fullscreen doc. Start the search from the root.
+  nsIDocument* root = nsContentUtils::GetRootDocument(aDoc);
+  // Check that the root is actually fullscreen so we don't waste time walking
+  // around its descendants.
+  if (!root->IsFullScreenDoc()) {
+    return nullptr;
+  }
+  GetFullscreenLeaf(root, &leaf);
+  return leaf;
+}
+
 void
 nsDocument::RestorePreviousFullScreenState()
 {
-  NS_ASSERTION(!IsFullScreenDoc() || sFullScreenDoc != nullptr,
-               "Should have a full-screen doc when full-screen!");
-
-  if (!IsFullScreenDoc() || !GetWindow() || !sFullScreenDoc) {
+  NS_ASSERTION(!IsFullScreenDoc() || !FullscreenRoots::IsEmpty(),
+    "Should have at least 1 fullscreen root when fullscreen!");
+
+  if (!IsFullScreenDoc() || !GetWindow() || FullscreenRoots::IsEmpty()) {
     return;
   }
 
   // If fullscreen mode is updated the pointer should be unlocked
   nsCOMPtr<Element> pointerLockedElement =
     do_QueryReferent(nsEventStateManager::sPointerLockedElement);
   if (pointerLockedElement) {
     UnlockPointer();
   }
 
-  nsCOMPtr<nsIDocument> fullScreenDoc(do_QueryReferent(sFullScreenDoc));
+  nsCOMPtr<nsIDocument> fullScreenDoc = GetFullscreenLeaf(this);
 
   // The fullscreen document may contain a <iframe mozbrowser> element which
   // has a cross process child. So send a notification so that its browser
   // parent will send a message to its child process to also exit fullscreen.
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   os->NotifyObservers(fullScreenDoc, "ask-children-to-exit-fullscreen", nullptr);
 
   // Clear full-screen stacks in all descendant in process documents, bottom up.
@@ -9284,28 +9524,25 @@ nsDocument::RestorePreviousFullScreenSta
         // as necessary.
         nsAutoString origin;
         nsContentUtils::GetUTFOrigin(doc->NodePrincipal(), origin);
         nsIDocument* root = nsContentUtils::GetRootDocument(doc);
         nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
         os->NotifyObservers(root, "fullscreen-origin-change", origin.get());
       }
 
-      sFullScreenDoc = do_GetWeakReference(doc);
       break;
     }
   }
 
   if (doc == nullptr) {
-    // We moved all documents out of full-screen mode, reset global full-screen
-    // state and move the top-level window out of full-screen mode.
-    DebugOnly< nsCOMPtr<nsIDocument> > root(do_QueryReferent(sFullScreenRootDoc));
-    NS_ASSERTION(!root->IsFullScreenDoc(), "Should have cleared all docs' stacks");
-    sFullScreenDoc = nullptr;
-    sFullScreenRootDoc = nullptr;
+    // We moved all documents in this doctree out of fullscreen mode,
+    // move the top-level window out of fullscreen mode.
+    NS_ASSERTION(!nsContentUtils::GetRootDocument(this)->IsFullScreenDoc(),
+      "Should have cleared all docs' stacks");
     SetWindowFullScreen(this, false);
   }
 }
 
 bool
 nsDocument::IsFullScreenDoc()
 {
   return GetFullScreenElement() != nullptr;
@@ -9364,34 +9601,43 @@ LogFullScreenDenied(bool aLogFailure, co
                                   "DOM", aDoc,
                                   nsContentUtils::eDOM_PROPERTIES,
                                   aMessage);
 }
 
 nsresult
 nsDocument::AddFullscreenApprovedObserver()
 {
+  NS_ASSERTION(!mHasFullscreenApprovedObserver, "Don't add observer twice.");
+
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   NS_ENSURE_TRUE(os, NS_ERROR_FAILURE);
 
   nsresult res = os->AddObserver(this, "fullscreen-approved", true);
   NS_ENSURE_SUCCESS(res, res);
 
+  mHasFullscreenApprovedObserver = true;
+
   return NS_OK;
 }
 
 nsresult
 nsDocument::RemoveFullscreenApprovedObserver()
 {
+  if (!mHasFullscreenApprovedObserver) {
+    return NS_OK;
+  }
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   NS_ENSURE_TRUE(os, NS_ERROR_FAILURE);
 
   nsresult res = os->RemoveObserver(this, "fullscreen-approved");
   NS_ENSURE_SUCCESS(res, res);
 
+  mHasFullscreenApprovedObserver = false;
+
   return NS_OK;
 }
 
 void
 nsDocument::CleanupFullscreenState()
 {
   if (!mFullScreenStack.IsEmpty()) {
     // The top element in the full-screen stack will have full-screen
@@ -9401,16 +9647,17 @@ nsDocument::CleanupFullscreenState()
     NS_ASSERTION(top, "Should have a top when full-screen stack isn't empty");
     if (top) {
       nsEventStateManager::SetFullScreenState(top, false);
     }
     mFullScreenStack.Clear();
   }
   SetApprovedForFullscreen(false);
   RemoveFullscreenApprovedObserver();
+  mFullscreenRoot = nullptr;
 }
 
 bool
 nsDocument::FullScreenStackPush(Element* aElement)
 {
   NS_ASSERTION(aElement, "Must pass non-null to FullScreenStackPush()");
   Element* top = FullScreenStackTop();
   if (top == aElement || !aElement) {
@@ -9579,17 +9826,17 @@ nsDocument::RequestFullScreen(Element* a
   }
   if (!IsFullScreenEnabled(aWasCallerChrome, true)) {
     // IsFullScreenEnabled calls LogFullScreenDenied, no need to log.
     return;
   }
   if (GetFullScreenElement() &&
       !nsContentUtils::ContentIsDescendantOf(aElement, GetFullScreenElement())) {
     // If this document is full-screen, only grant full-screen requests from
-    // a descendent of the current full-screen element.
+    // a descendant of the current full-screen element.
     LogFullScreenDenied(true, "FullScreenDeniedNotDescendant", this);
     return;
   }
   if (!nsContentUtils::IsChromeDoc(this) && !IsInActiveTab(this)) {
     LogFullScreenDenied(true, "FullScreenDeniedNotFocusedTab", this);
     return;
   }
   // Deny requests when a windowed plugin is focused.
@@ -9603,33 +9850,35 @@ nsDocument::RequestFullScreen(Element* a
   if (focusedElement) {
     nsCOMPtr<nsIContent> content = do_QueryInterface(focusedElement);
     if (nsContentUtils::HasPluginWithUncontrolledEventDispatch(content)) {
       LogFullScreenDenied(true, "FullScreenDeniedFocusedPlugin", this);
       return;
     }
   }
 
+  // Stash a reference to any existing fullscreen doc, we'll use this later
+  // to detect if the origin which is fullscreen has changed.
+  nsCOMPtr<nsIDocument> previousFullscreenDoc = GetFullscreenLeaf(this);
+
   AddFullscreenApprovedObserver();
 
   // Stores a list of documents which we must dispatch "mozfullscreenchange"
   // too. We're required by the spec to dispatch the events in root-to-leaf
   // order, but we traverse the doctree in a leaf-to-root order, so we save
   // references to the documents we must dispatch to so that we get the order
   // as specified.
   nsAutoTArray<nsIDocument*, 8> changed;
 
   // Remember the root document, so that if a full-screen document is hidden
   // we can reset full-screen state in the remaining visible full-screen documents.
   nsIDocument* fullScreenRootDoc = nsContentUtils::GetRootDocument(this);
-  sFullScreenRootDoc = do_GetWeakReference(fullScreenRootDoc);
-
-  // If a document is already in fullscreen, then unlock the mouse pointer
-  // before setting a new document to fullscreen
-  if (sFullScreenDoc) {
+  if (fullScreenRootDoc->IsFullScreenDoc()) {
+    // A document is already in fullscreen, unlock the mouse pointer
+    // before setting a new document to fullscreen
     UnlockPointer();
   }
 
   // If a document is already in fullscreen, then unlock the mouse pointer
   // before setting a new document to fullscreen
   nsCOMPtr<Element> pointerLockedElement =
     do_QueryReferent(nsEventStateManager::sPointerLockedElement);
   if (pointerLockedElement) {
@@ -9645,16 +9894,19 @@ nsDocument::RequestFullScreen(Element* a
 
   // Propagate up the document hierarchy, setting the full-screen element as
   // the element's container in ancestor documents. This also sets the
   // appropriate css styles as well. Note we don't propagate down the
   // document hierarchy, the full-screen element (or its container) is not
   // visible there. Stop when we reach the root document.
   nsIDocument* child = this;
   while (true) {
+    child->SetFullscreenRoot(fullScreenRootDoc);
+    NS_ASSERTION(child->GetFullscreenRoot() == fullScreenRootDoc,
+        "Fullscreen root should be set!");
     nsIDocument* parent = child->GetParentDocument();
     if (!parent) {
       break;
     }
     Element* element = parent->FindContentForSubDocument(child)->AsElement();
     if (static_cast<nsDocument*>(parent)->FullScreenStackPush(element)) {
       changed.AppendElement(parent);
       child = parent;
@@ -9684,34 +9936,29 @@ nsDocument::RequestFullScreen(Element* a
       !Preferences::GetBool("full-screen-api.approval-required") ||
       NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
       nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen");
   }
 
   // If this document, or a document with the same principal has not
   // already been approved for fullscreen this fullscreen-session, dispatch
   // an event so that chrome knows to pop up a warning/approval UI.
-  nsCOMPtr<nsIDocument> previousFullscreenDoc(do_QueryReferent(sFullScreenDoc));
   // Note previousFullscreenDoc=nullptr upon first entry, so we always
   // take this path on the first time we enter fullscreen in a fullscreen
   // session.
   if (!mIsApprovedForFullscreen ||
       !nsContentUtils::HaveEqualPrincipals(previousFullscreenDoc, this)) {
     nsRefPtr<nsAsyncDOMEvent> e =
       new nsAsyncDOMEvent(this,
                           NS_LITERAL_STRING("MozEnteredDomFullscreen"),
                           true,
                           true);
     e->PostDOMEvent();
   }
 
-  // Remember this is the requesting full-screen document.
-  sFullScreenDoc = do_GetWeakReference(static_cast<nsIDocument*>(this));
-  NS_ASSERTION(sFullScreenDoc, "nsDocument should support weak ref!");
-
 #ifdef DEBUG
   // Note assertions must run before SetWindowFullScreen() as that does
   // synchronous event dispatch which can run script which exits full-screen!
   NS_ASSERTION(GetFullScreenElement() == aElement,
                "Full-screen element should be the requested element!");
   NS_ASSERTION(IsFullScreenDoc(), "Should be full-screen doc");
   nsCOMPtr<nsIDOMElement> fse;
   GetMozFullScreenElement(getter_AddRefs(fse));
@@ -9798,33 +10045,21 @@ nsDocument::GetMozFullScreenEnabled(bool
 
 bool
 nsDocument::MozFullScreenEnabled()
 {
   return IsFullScreenEnabled(nsContentUtils::IsCallerChrome(), false);
 }
 
 static bool
-HasFullScreenSubDocument(nsIDocument* aDoc, void* aData)
-{
-  if (aDoc->IsFullScreenDoc()) {
-    // This subdocument is full-screen. Set result and return false to
-    // stop iteration.
-    *static_cast<bool*>(aData) = true;
-    return false;
-  }
-  return true;
-}
-
-static bool
 HasFullScreenSubDocument(nsIDocument* aDoc)
 {
-  bool result = false;
-  aDoc->EnumerateSubDocuments(&HasFullScreenSubDocument, static_cast<void*>(&result));
-  return result;
+  uint32_t count = CountFullscreenSubDocuments(aDoc);
+  NS_ASSERTION(count <= 1, "Fullscreen docs should have at most 1 fullscreen child!");
+  return count >= 1;
 }
 
 bool
 nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
 {
   if (nsContentUtils::IsFullScreenApiEnabled() && aCallerIsChrome) {
     // Chrome code can always use the full-screen API, provided it's not
     // explicitly disabled. Note IsCallerChrome() returns true when running
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -938,24 +938,27 @@ public:
   bool HasAudioAvailableListeners()
   {
     return mHasAudioAvailableListener;
   }
 
   virtual Element* GetFullScreenElement();
   virtual void AsyncRequestFullScreen(Element* aElement);
   virtual void RestorePreviousFullScreenState();
+  virtual bool IsFullscreenLeaf();
   virtual bool IsFullScreenDoc();
   virtual void SetApprovedForFullscreen(bool aIsApproved);
   virtual nsresult RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
                                                 const nsAString& aNewOrigin);
 
   virtual nsresult RemoteFrameFullscreenReverted();
+  virtual nsIDocument* GetFullscreenRoot();
+  virtual void SetFullscreenRoot(nsIDocument* aRoot);
 
-  static void ExitFullScreen();
+  static void ExitFullscreen(nsIDocument* aDoc);
 
   // This is called asynchronously by nsIDocument::AsyncRequestFullScreen()
   // to move this document into full-screen mode if allowed. aWasCallerChrome
   // should be true when nsIDocument::AsyncRequestFullScreen() was called
   // by chrome code. aNotifyOnOriginChange denotes whether we should send a
   // fullscreen-origin-change notification if requesting fullscreen in this
   // document causes the origin which is fullscreen to change. We may want to
   // *not* send this notification if we're calling RequestFullscreen() as part
@@ -1158,41 +1161,34 @@ protected:
   // the script global object of the original document.
   nsWeakPtr mScriptObject;
 
   // Weak reference to the scope object (aka the script global object)
   // that, unlike mScriptGlobalObject, is never unset once set. This
   // is a weak reference to avoid leaks due to circular references.
   nsWeakPtr mScopeObject;
 
-  // The document which requested (and was granted) full-screen. All ancestors
-  // of this document will also be full-screen.
-  static nsWeakPtr sFullScreenDoc;
-
-  // The root document of the doctree containing the document which requested
-  // full-screen. This root document will also be in full-screen state, as will
-  // all the descendents down to the document which requested full-screen. This
-  // reference allows us to reset full-screen state on all documents when a
-  // document is hidden/navigation occurs.
-  static nsWeakPtr sFullScreenRootDoc;
-
   // Weak reference to the document which owned the pending pointer lock
   // element, at the time it requested pointer lock.
   static nsWeakPtr sPendingPointerLockDoc;
 
   // Weak reference to the element which requested pointer lock. This request
   // is "pending", and will be processed once the element's document has had
   // the "fullscreen" permission granted.
   static nsWeakPtr sPendingPointerLockElement;
 
   // Stack of full-screen elements. When we request full-screen we push the
   // full-screen element onto this stack, and when we cancel full-screen we
   // pop one off this stack, restoring the previous full-screen state
   nsTArray<nsWeakPtr> mFullScreenStack;
 
+  // The root of the doc tree in which this document is in. This is only
+  // non-null when this document is in fullscreen mode.
+  nsWeakPtr mFullscreenRoot;
+
   nsRefPtr<nsEventListenerManager> mListenerManager;
   nsCOMPtr<nsIDOMStyleSheetList> mDOMStyleSheets;
   nsRefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
   nsRefPtr<nsScriptLoader> mScriptLoader;
   nsDocHeaderData* mHeaderData;
   /* mIdentifierMap works as follows for IDs:
    * 1) Attribute changes affect the table immediately (removing and adding
    *    entries as needed).
@@ -1252,16 +1248,21 @@ protected:
   // flag.
   //
   // Note we must track this separately from the "fullscreen" permission,
   // so that pending pointer lock requests can determine whether documents
   // whose principal doesn't have a host (i.e. those which can't store
   // permissions in the permission manager) have been approved for fullscreen.
   bool mIsApprovedForFullscreen:1;
 
+  // Whether this document has a fullscreen approved observer. Only documents
+  // which request fullscreen and which don't have a pre-existing approval for
+  // fullscreen will have an observer.
+  bool mHasFullscreenApprovedObserver:1;
+
   uint8_t mXMLDeclarationBits;
 
   nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject> *mBoxObjectTable;
 
   // The channel that got passed to StartDocumentLoad(), if any
   nsCOMPtr<nsIChannel> mChannel;
   nsRefPtr<nsHTMLCSSStyleSheet> mStyleAttrStyleSheet;
 
--- a/content/base/test/test_bug527896.html
+++ b/content/base/test/test_bug527896.html
@@ -17,16 +17,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 527896 **/
 
 SimpleTest.waitForExplicitFinish();
 
+SimpleTest.expectAssertions(1);
+
 var docWrittenSrcExecuted = false;
 var scriptInsertedSrcExecuted = false;
 
 // the iframe test runs with the HTML5 parser
 
 var iframe = document.getElementsByTagName('iframe')[0];
 iframe.contentWindow.document.open();
 iframe.contentWindow.document.write("<!DOCTYPE html>");
--- a/content/base/test/test_bug548193.html
+++ b/content/base/test/test_bug548193.html
@@ -8,16 +8,18 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 
 <iframe style="width:200px;height:200px;" id='cspframe'></iframe>
 <script class="testbody" type="text/javascript">
 
+SimpleTest.expectAssertions(1);
+
 // This is used to watch requests go out so we can see if the report is
 // sent correctly
 function examiner() {
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
   var obsvc = Components.classes['@mozilla.org/observer-service;1']
                         .getService(Components.interfaces.nsIObserverService);
   obsvc.addObserver(this, "http-on-modify-request", false);
 }
--- a/content/base/test/test_bug638112.html
+++ b/content/base/test/test_bug638112.html
@@ -11,16 +11,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=638112">Mozilla Bug 638112</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script type="text/javascript">
 
+SimpleTest.expectAssertions(1);
+
 /** Test for Bug 638112 **/
 
 function run_test() {
   var req = new XMLHttpRequest();
   req.open("GET", "bug638112.sjs", false);
   req.send(null);
   var statusText = req.statusText;
 
--- a/content/base/test/test_mutationobservers.html
+++ b/content/base/test/test_mutationobservers.html
@@ -13,16 +13,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641821">Mozilla Bug 641821</a>
 <p id="display"></p>
 <div id="content" style="display: none">
                                 
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  // for non-Windows
+  SimpleTest.expectAssertions(1);
+}
+
 /** Test for Bug 641821 **/
 
 var div = document.createElement("div");
 
 var M;
 if ("MozMutationObserver" in window) {
   M = window.MozMutationObserver;
 } else if ("WebKitMutationObserver" in window) {
--- a/content/events/test/test_bug457672.html
+++ b/content/events/test/test_bug457672.html
@@ -12,16 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=457672">Mozilla Bug 457672</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+SimpleTest.expectAssertions(1);
+
 /** Test for Bug 457672 **/
 
 var windowBlurCount = 0;
 
 function setUserPref(reset) {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   const prefSvcContractID = "@mozilla.org/preferences-service;1";
   const prefSvcIID = Components.interfaces.nsIPrefService;
--- a/content/html/content/src/HTMLIFrameElement.cpp
+++ b/content/html/content/src/HTMLIFrameElement.cpp
@@ -51,17 +51,17 @@ NS_IMPL_STRING_ATTR(HTMLIFrameElement, F
 NS_IMPL_STRING_ATTR(HTMLIFrameElement, Height, height)
 NS_IMPL_URI_ATTR(HTMLIFrameElement, LongDesc, longdesc)
 NS_IMPL_STRING_ATTR(HTMLIFrameElement, MarginHeight, marginheight)
 NS_IMPL_STRING_ATTR(HTMLIFrameElement, MarginWidth, marginwidth)
 NS_IMPL_STRING_ATTR(HTMLIFrameElement, Name, name)
 NS_IMPL_STRING_ATTR(HTMLIFrameElement, Scrolling, scrolling)
 NS_IMPL_URI_ATTR(HTMLIFrameElement, Src, src)
 NS_IMPL_STRING_ATTR(HTMLIFrameElement, Width, width)
-NS_IMPL_BOOL_ATTR(HTMLIFrameElement, Allowfullscreen, allowfullscreen)
+NS_IMPL_BOOL_ATTR(HTMLIFrameElement, AllowFullscreen, allowfullscreen)
 NS_IMPL_STRING_ATTR(HTMLIFrameElement, Sandbox, sandbox)
 
 void
 HTMLIFrameElement::GetItemValueText(nsAString& aValue)
 {
   GetSrc(aValue);
 }
 
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -2354,16 +2354,19 @@ nsresult nsHTMLMediaElement::FinishDecod
   // The new stream has not been suspended by us.
   mPausedForInactiveDocumentOrChannel = false;
   mEventDeliveryPaused = false;
   mPendingEvents.Clear();
 
   aDecoder->SetAudioChannelType(mAudioChannelType);
   aDecoder->SetAudioCaptured(mAudioCaptured);
   aDecoder->SetVolume(mMuted ? 0.0 : mVolume);
+  aDecoder->SetPreservesPitch(mPreservesPitch);
+  aDecoder->SetPlaybackRate(mPlaybackRate);
+
   for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) {
     OutputMediaStream* ms = &mOutputStreams[i];
     aDecoder->AddOutputStream(ms->mStream->GetStream()->AsProcessedStream(),
         ms->mFinishWhenEnded);
   }
 
   nsresult rv = aDecoder->Load(aStream, aListener, aCloneDonor);
   if (NS_FAILED(rv)) {
@@ -3576,17 +3579,19 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMoz
 {
   *aPreservesPitch = mPreservesPitch;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsHTMLMediaElement::SetMozPreservesPitch(bool aPreservesPitch)
 {
   mPreservesPitch = aPreservesPitch;
-  mDecoder->SetPreservesPitch(aPreservesPitch);
+  if (mDecoder) {
+    mDecoder->SetPreservesPitch(mPreservesPitch);
+  }
   return NS_OK;
 }
 
 ImageContainer* nsHTMLMediaElement::GetImageContainer()
 {
   VideoFrameContainer* container = GetVideoFrameContainer();
   return container ? container->GetImageContainer() : nullptr;
 }
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -238,16 +238,18 @@ MOCHITEST_FILES = \
 		file_fullscreen-denied.html \
 		file_fullscreen-denied-inner.html \
 		file_fullscreen-hidden.html \
 		file_fullscreen-navigation.html \
 		file_fullscreen-esc-exit.html \
 		file_fullscreen-esc-exit-inner.html \
 		file_fullscreen-rollback.html \
 		file_fullscreen-svg-element.html \
+		file_fullscreen-multiple.html \
+		file_fullscreen-multiple-inner.html \
 		test_li_attributes_reflection.html \
 		test_link_attributes_reflection.html \
 		test_ol_attributes_reflection.html \
 		test_dl_attributes_reflection.html \
 		test_ul_attributes_reflection.html \
 		test_param_attributes_reflection.html \
 		test_base_attributes_reflection.html \
 		test_dir_attributes_reflection.html \
--- a/content/html/content/test/file_fullscreen-api.html
+++ b/content/html/content/test/file_fullscreen-api.html
@@ -73,17 +73,17 @@ function enter1(event) {
   is(document.mozFullScreenElement, null, "8. Full-screen element should still be null after re-adding former FSE.");
 }
 
 function exit1(event) {
   ok(!document.mozFullScreen, "9. Should have left full-screen mode (first time)");
   is(event.target, document, "10. Event target should be full-screen document #2");
   is(document.mozFullScreenElement, null, "11. Full-screen element should be null.");
   iframe = document.createElement("iframe");
-  iframe.allowfullscreen = true;
+  iframe.allowFullscreen = true;
   addFullscreenChangeContinuation("enter", enter2);
   document.body.appendChild(iframe);
   iframe.src = iframeContents;
 }
 
 function enter2(event) {
   ok(document.mozFullScreen, "12. Should be back in full-screen mode (second time)");
   is(event.target, document, "13. Event target should be full-screen document #3");
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/file_fullscreen-multiple-inner.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Bug 724554</title>
+  <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+</head>
+<body>
+
+<script type="application/javascript">
+
+
+/** Test for Bug 545812 **/
+function begin(id) {
+  addFullscreenErrorContinuation(function() {
+    opener.ok(false, "Fullscreen denied " + id);
+    });
+  addFullscreenChangeContinuation("enter",
+    function() {
+      opener.enteredFullscreen(id);
+    });
+  document.body.mozRequestFullScreen();
+}
+
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/file_fullscreen-multiple.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=724554
+
+Test that multiple windows can be fullscreen at the same time.
+
+Open one window, focus it and enter fullscreen, then open another, focus
+it and enter fullscreen, and check that both are still fullscreen.
+
+-->
+<head>
+  <title>Test for Bug 724554</title>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+</head>
+<body>
+
+<script type="application/javascript">
+
+/** Test for Bug 545812 **/
+
+function ok(condition, msg) {
+  opener.ok(condition, "[multiple] " + msg);
+}
+
+function is(a, b, msg) {
+  opener.is(a, b, "[multiple] " + msg);
+}
+
+var window1, window2;
+
+function openWindow(id) {
+  var w = window.open("file_fullscreen-multiple-inner.html", "", "width=500,height=500");
+  w.addEventListener("load", function onload() {
+    w.focus();
+    SimpleTest.waitForFocus(function(){w.begin(id)}, w);
+  });
+  return w;
+}
+
+function begin() {
+  window1 = openWindow("one");
+}
+
+function enteredFullscreen(id) {
+  if (id == "one") {
+    window2 = openWindow("two");
+  } else if (id == "two") {
+    ok(window1.document.mozFullScreenElement &&
+       window2.document.mozFullScreenElement,
+       "Both windows should be fullscreen concurrently");
+    window1.close();
+    window2.close();
+    opener.nextTest();
+  }
+}
+
+</script>
+</pre>
+<div id="full-screen-element"></div>
+</body>
+</html>
--- a/content/html/content/test/forms/test_meter_element.html
+++ b/content/html/content/test/forms/test_meter_element.html
@@ -16,16 +16,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="visibility: hidden;">
   <form id='f' method='get' target='submit_frame' action='foo'>
     <meter id='m' value=0.5></meter>
   </form>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+} else {
+  SimpleTest.expectAssertions(1);
+}
+
 /** Test for <meter> **/
 
 function checkFormIDLAttribute(aElement)
 {
   is('form' in aElement, false, "<meter> shouldn't have a form attribute");
 }
 
 function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL)
--- a/content/html/content/test/forms/test_progress_element.html
+++ b/content/html/content/test/forms/test_progress_element.html
@@ -18,16 +18,18 @@ and
 <div id="content" style="visibility: hidden;">
   <form id='f' method='get' target='submit_frame' action='foo'>
     <progress id='p'></progress>
   </form>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+SimpleTest.expectAssertions(1);
+
 /** Test for progress element content and layout **/
 
 function checkFormIDLAttribute(aElement)
 {
   is("form" in aElement, false, "<progress> shouldn't have a form attribute");
 }
 
 function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL)
--- a/content/html/content/test/test_bug242709.html
+++ b/content/html/content/test/test_bug242709.html
@@ -12,16 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=242709">Mozilla Bug 242709</a>
 <p id="display"></p>
 <div id="content">
 <iframe src="bug242709_iframe.html" id="a"></iframe> 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+SimpleTest.expectAssertions(1);
+
 /** Test for Bug 242709 **/
 
 SimpleTest.waitForExplicitFinish();
 
 var submitted = function() {
   ok(true, "Disabling button after form submission doesn't prevent submitting");
   SimpleTest.finish();
 }
--- a/content/html/content/test/test_bug277890.html
+++ b/content/html/content/test/test_bug277890.html
@@ -12,16 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=277890">Mozilla Bug 277890</a>
 <p id="display"></p>
 <div id="content">
 <iframe src="bug277890_iframe.html" id="a"></iframe> 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+SimpleTest.expectAssertions(1);
+
 /** Test for Bug 277890 **/
 
 SimpleTest.waitForExplicitFinish();
 
 var submitted = function() {
   ok(true, "Disabling button after form submission doesn't prevent submitting");
   SimpleTest.finish();
 }
--- a/content/html/content/test/test_bug523771.html
+++ b/content/html/content/test/test_bug523771.html
@@ -14,16 +14,23 @@ https://bugzilla.mozilla.org/show_bug.cg
 <iframe name="target_iframe" id="target_iframe"></iframe>
 <form action="form_submit_server.sjs" target="target_iframe" id="form"
 method="POST" enctype="multipart/form-data">
   <input id=singleFile name=singleFile type=file>
   <input id=multiFile name=multiFile type=file multiple>
 </form>
 <pre id="test">
 <script class="testbody" type="text/javascript">
+
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+} else {
+  SimpleTest.expectAssertions(1);
+}
+
 var filesToKill = [];
 singleFileInput = document.getElementById('singleFile');
 multiFileInput = document.getElementById('multiFile');
 var input1File = { name: "523771_file1", type: "", body: "file1 contents"};
 var input2Files =
   [{ name: "523771_file2", type: "", body: "second file contents" },
    { name: "523771_file3.txt", type: "text/plain", body: "123456" },
    { name: "523771_file4.html", type: "text/html", body: "<html>content</html>" }
--- a/content/html/content/test/test_fullscreen-api.html
+++ b/content/html/content/test/test_fullscreen-api.html
@@ -29,16 +29,17 @@ SpecialPowers.setBoolPref("full-screen-a
 // Disable the requirement for trusted contexts only, so the tests are easier
 // to write.
 SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
 
 // Run the tests which go full-screen in new windows, as mochitests normally
 // run in an iframe, which by default will not have the allowfullscreen
 // attribute set, so full-screen won't work.
 var gTestWindows = [
+  "file_fullscreen-multiple.html",
   "file_fullscreen-rollback.html",
   "file_fullscreen-esc-exit.html",
   "file_fullscreen-denied.html",
   "file_fullscreen-api.html",
   "file_fullscreen-api-keys.html",
   "file_fullscreen-plugins.html",
   "file_fullscreen-hidden.html",
   "file_fullscreen-svg-element.html",
--- a/content/html/content/test/test_iframe_sandbox_general.html
+++ b/content/html/content/test/test_iframe_sandbox_general.html
@@ -7,16 +7,19 @@ Implement HTML5 sandbox attribute for IF
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 341604</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <script type="application/javascript">
+
+SimpleTest.expectAssertions(1);
+
 /** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs - general tests **/
 
 SimpleTest.waitForExplicitFinish();
 
 // a postMessage handler that is used by sandboxed iframes without
 // 'allow-same-origin' to communicate pass/fail back to this main page.
 // it expects to be called with an object like {ok: true/false, desc:
 // <description of the test> which it then forwards to ok()
--- a/content/html/content/test/test_iframe_sandbox_navigation.html
+++ b/content/html/content/test/test_iframe_sandbox_navigation.html
@@ -7,16 +7,19 @@ Implement HTML5 sandbox attribute for IF
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 341604 - navigation</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 	<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <script type="application/javascript">
+
+SimpleTest.expectAssertions(1, 2);
+
 /** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/
 /** Navigation tests **/
 
 SimpleTest.waitForExplicitFinish();
 // a postMessage handler that is used by sandboxed iframes without
 // 'allow-same-origin'/other windows to communicate pass/fail back to this main page.
 // it expects to be called with an object like {ok: true/false, desc:
 // <description of the test> which it then forwards to ok()
--- a/content/html/document/test/test_bug391777.html
+++ b/content/html/document/test/test_bug391777.html
@@ -8,16 +8,21 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=391777">Mozilla Bug 391777</a>
 <p id="display"></p>
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  // not Windows
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 391777 **/
 var arg = {};
 arg.testVal = "foo";
 var result = window.showModalDialog("javascript:window.returnValue = window.dialogArguments.testVal; window.close(); 'This window should close on its own.';", arg);
 ok(true, "We should get here without user interaction");
 is(result, "foo", "Unexpected result from showModalDialog");
 </script>
 </body>
--- a/content/html/document/test/test_bug402680.html
+++ b/content/html/document/test/test_bug402680.html
@@ -16,16 +16,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content">
   <input type="text">
   <textarea></textarea>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 402680 **/
 
 ok(activeElementIsNull,
    "Before document has body, active element should be null");
 
 function testActiveElement() {
   ok(document.body == document.activeElement,
      "After page load body element should be the active element!");
--- a/content/html/document/test/test_bug403868.html
+++ b/content/html/document/test/test_bug403868.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=403868">Mozilla Bug 403868</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 403868 **/
 function createSpan(id, insertionPoint) {
   var s = document.createElement("span");
   s.id = id;
   $("content").insertBefore(s, insertionPoint);
   return s;
 }
 
--- a/content/html/document/test/test_bug446483.html
+++ b/content/html/document/test/test_bug446483.html
@@ -12,16 +12,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=446483">Mozilla Bug 446483</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  // not Windows
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 446483 **/
 
 function gc() {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
         .getInterface(Components.interfaces.nsIDOMWindowUtils)
         .garbageCollect();
 }
--- a/content/html/document/test/test_bug448564.html
+++ b/content/html/document/test/test_bug448564.html
@@ -15,16 +15,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <iframe src="bug448564-iframe-2.html"></iframe>
   <iframe src="bug448564-iframe-3.html"></iframe>
 </p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+SimpleTest.expectAssertions(3);
+
 /** Test for Bug 448564 **/
 
 /**
  * The three iframes are going to be loaded with some dirty constructed forms.
  * Each of them will be submitted before the load event and a SJS will replace
  * the frame content with the query string.
  * Then, on the load event, our test file will check the content of each iframes
  * and check if the query string were correctly formatted (implying that all
--- a/content/html/document/test/test_bug478251.html
+++ b/content/html/document/test/test_bug478251.html
@@ -12,16 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=478251">Mozilla Bug 478251</a>
 <p id="display"><iframe id="t"></iframe></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+SimpleTest.expectAssertions(10);
+
 /** Test for Bug 478251 **/
 var doc = $("t").contentDocument;
 doc.open();
 doc.write();
 doc.close();
 is(doc.documentElement.textContent, "", "Writing || failed");
 
 doc.open();
--- a/content/html/document/test/test_bug741266.html
+++ b/content/html/document/test/test_bug741266.html
@@ -13,16 +13,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741266">Mozilla Bug 741266</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+SimpleTest.expectAssertions(1);
+
 /** Test for Bug 741266 **/
 var w = window.open("", "", "width=100,height=100");
 is(w.innerHeight, 100, "Popup height should be 100 when opened with window.open");
 // XXXbz On at least some platforms, the innerWidth is off by the scrollbar
 // width for some reason.  So just make sure it's the same for both popups.
 var width = w.innerWidth;
 w.close();
 w = document.open("", "", "width=100,height=100");
--- a/content/html/document/test/test_document-element-inserted.html
+++ b/content/html/document/test/test_document-element-inserted.html
@@ -5,16 +5,21 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <iframe id = 'media'>
 </iframe>
 <pre id="test">
 <script class="testbody" type="text/javascript">
+
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 SimpleTest.waitForExplicitFinish();
 var loc;
 
 var observe = function(doc){
     if (doc == media.contentDocument) {
         ok(media.contentDocument.location.toString().indexOf(loc) != -1,
           "The loaded media should be " + loc);
         next();
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -322,16 +322,18 @@ bool MediaDecoder::IsInfinite()
   return mInfiniteStream;
 }
 
 MediaDecoder::MediaDecoder() :
   mDecoderPosition(0),
   mPlaybackPosition(0),
   mCurrentTime(0.0),
   mInitialVolume(0.0),
+  mInitialPlaybackRate(1.0),
+  mInitialPreservesPitch(true),
   mRequestedSeekTime(-1.0),
   mDuration(-1),
   mTransportSeekable(true),
   mMediaSeekable(true),
   mReentrantMonitor("media.decoder"),
   mPlayState(PLAY_STATE_PAUSED),
   mNextState(PLAY_STATE_PAUSED),
   mCalledResourceLoaded(false),
@@ -463,16 +465,18 @@ nsresult MediaDecoder::InitializeStateMa
   }
   {
     ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
     mDecoderStateMachine->SetTransportSeekable(mTransportSeekable);
     mDecoderStateMachine->SetMediaSeekable(mMediaSeekable);
     mDecoderStateMachine->SetDuration(mDuration);
     mDecoderStateMachine->SetVolume(mInitialVolume);
     mDecoderStateMachine->SetAudioCaptured(mInitialAudioCaptured);
+    SetPlaybackRate(mInitialPlaybackRate);
+    mDecoderStateMachine->SetPreservesPitch(mInitialPreservesPitch);
 
     if (mFrameBufferLength > 0) {
       // The valid mFrameBufferLength value was specified earlier
       mDecoderStateMachine->SetFrameBufferLength(mFrameBufferLength);
     }
   }
 
   ChangeState(PLAY_STATE_LOADING);
@@ -1396,23 +1400,27 @@ void MediaDecoder::SetPlaybackRate(doubl
     if (mOwner && !mOwner->GetPaused()) {
       Play();
     }
     mPausedForPlaybackRateNull = false;
   }
 
   if (mDecoderStateMachine) {
     mDecoderStateMachine->SetPlaybackRate(aPlaybackRate);
+  } else {
+    mInitialPlaybackRate = aPlaybackRate;
   }
 }
 
 void MediaDecoder::SetPreservesPitch(bool aPreservesPitch)
 {
   if (mDecoderStateMachine) {
     mDecoderStateMachine->SetPreservesPitch(aPreservesPitch);
+  } else {
+    mInitialPreservesPitch = aPreservesPitch;
   }
 }
 
 bool MediaDecoder::OnDecodeThread() const {
   NS_WARN_IF_FALSE(mDecoderStateMachine, "mDecoderStateMachine is null");
   return mDecoderStateMachine ? mDecoderStateMachine->OnDecodeThread() : false;
 }
 
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -896,16 +896,21 @@ public:
   // video (if it is a video) or the callback period of the audio.
   // It is read and written from the main thread only.
   double mCurrentTime;
 
   // Volume that playback should start at.  0.0 = muted. 1.0 = full
   // volume.  Readable/Writeable from the main thread.
   double mInitialVolume;
 
+  // PlaybackRate and pitch preservation status we should start at.
+  // Readable/Writeable from the main thread.
+  double mInitialPlaybackRate;
+  bool mInitialPreservesPitch;
+
   // Position to seek to when the seek notification is received by the
   // decode thread. Written by the main thread and read via the
   // decode thread. Synchronised using mReentrantMonitor. If the
   // value is negative then no seek has been requested. When a seek is
   // started this is reset to negative.
   double mRequestedSeekTime;
 
   // Duration of the media resource. Set to -1 if unknown.
new file mode 100644
--- /dev/null
+++ b/content/media/test/crashtests/844563.html
@@ -0,0 +1,5 @@
+<script>
+var a = document.createElementNS("http://www.w3.org/1999/xhtml", "audio");
+a.mozPreservesPitch = a;
+</script>
+
--- a/content/media/test/crashtests/crashtests.list
+++ b/content/media/test/crashtests/crashtests.list
@@ -7,8 +7,9 @@ HTTP load 481136-1.html # needs to be HT
 load 493915-1.html
 skip-if(Android) load 495794-1.html
 load 492286-1.xhtml
 load 576612-1.html
 skip-if(Android) load 691096-1.html # Android sound API can't handle playing large number of sounds at once.
 load 752784-1.html
 skip-if(Android||B2G) HTTP load 795892-1.html # load failed, bug 833371 for B2G
 skip-if(Android||B2G) load 789075-1.html # load failed, bug 833371 for B2G
+load 844563.html
--- a/content/media/test/test_bug495300.html
+++ b/content/media/test/test_bug495300.html
@@ -10,16 +10,21 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript" src="manifest.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=495300">Mozilla Bug 495300</a>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") != 0) {
+  // not Mac
+  SimpleTest.expectAssertions(0, 1);
+}
+
 var manager = new MediaTestManager;
 
 function filename(uri) {
   return uri.substr(uri.lastIndexOf("/")+1);
 }
 
 function mediaEnded(event) {
   ok(true, "Got expected 'ended' event: " + filename(event.target.currentSrc));
--- a/content/media/test/test_bug686942.html
+++ b/content/media/test/test_bug686942.html
@@ -10,16 +10,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript" src="manifest.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=686942">Mozilla Bug 686942</a>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 var manager = new MediaTestManager;
 
 function onloaded(event) {
   var v = event.target;
   v.currentTime = v.duration;
   return;
 }
 
--- a/content/media/test/test_playback_rate.html
+++ b/content/media/test/test_playback_rate.html
@@ -5,16 +5,20 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript" src="manifest.js"></script>
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type='application/javascript;version=1.8'>
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 let manager = new MediaTestManager;
 
 function rangeCheck(lhs, rhs, threshold) {
   var diff = Math.abs(lhs - rhs);
   if (diff < threshold) {
     return true;
   }
   return false;
--- a/content/media/test/test_seek.html
+++ b/content/media/test/test_seek.html
@@ -18,16 +18,18 @@
   <script type="text/javascript" src="seek11.js"></script>
   <script type="text/javascript" src="seek12.js"></script>
   <script type="text/javascript" src="seek13.js"></script>
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+SimpleTest.expectAssertions(120, 400);
+
 var manager = new MediaTestManager;
 
 const NUM_SEEK_TESTS = 13;
 
 function createTestArray() {
   var tests = [];
   var tmpVid = document.createElement("video");
 
--- a/content/media/test/test_seek_out_of_range.html
+++ b/content/media/test/test_seek_out_of_range.html
@@ -5,16 +5,20 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript" src="manifest.js"></script>
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 var manager = new MediaTestManager;
 
 // Test if the ended event works correctly.
 
 function startTest(e) {
   var v = e.target;
   checkMetadata(v._name, v, v._test);
   is(v._loadedMetadata, false, "Should only receive one loadedmetadata event for " + v._name);
--- a/content/xbl/test/test_bug378518.xul
+++ b/content/xbl/test/test_bug378518.xul
@@ -40,16 +40,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <box id="myExtendedBox" command="myExtendedBoxCommand"
     style="-moz-binding:url(#mybinding)">
     <label>myExtendedBox</label>
   </box>
 
   <!-- test code goes here -->
   <script type="application/javascript"> <![CDATA[
 
+    SimpleTest.expectAssertions(1);
+
     var myBoxClicked = false;
     var myCheckBoxClicked = false;
     var myExtendedBoxClicked = false;
 
     function testClick(elemName) {
       netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
       var wu  =
         window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
--- a/content/xul/templates/tests/chrome/test_tmpl_listboxelement.xul
+++ b/content/xul/templates/tests/chrome/test_tmpl_listboxelement.xul
@@ -44,16 +44,18 @@
       <listcell label=""/>
     </listitem>
   </data>
 
 <script src="templates_shared.js"/>
 
 <script>
 <![CDATA[
+SimpleTest.expectAssertions(4);
+
 SimpleTest.waitForExplicitFinish();
 
 var testid ="listbox element";
 var queryType = "rdf";
 var isTreeBuilder = false;
 var needsOpen = false;
 var notWorkingYet = false;
 var notWorkingYetDynamic = false;
--- a/content/xul/templates/tests/chrome/test_tmpl_storage_dynamicparameters.xul
+++ b/content/xul/templates/tests/chrome/test_tmpl_storage_dynamicparameters.xul
@@ -21,16 +21,18 @@
     <listitem anyid="true" label="Emu"/>
     <listitem anyid="true" label="Raven"/>
   </data>
 
 <script src="templates_shared.js"/>
 
 <script>
 <![CDATA[
+SimpleTest.expectAssertions(1, 2);
+
 SimpleTest.waitForExplicitFinish();
 
 copyToProfile('animals.sqlite');
 
 function test_storage_template()
 {
   var root = document.getElementById("root");
   expectedOutput = document.getElementById("output");
--- a/docshell/test/chrome/test_bug303267.xul
+++ b/docshell/test/chrome/test_bug303267.xul
@@ -23,16 +23,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+SimpleTest.expectAssertions(0, 1);
+
 /** Test for Bug 303267 **/
 
 SimpleTest.waitForExplicitFinish();
 window.open("bug303267_window.xul", "bug303267",
             "chrome,width=600,height=600");
 
 ]]>
 </script>
--- a/docshell/test/chrome/test_bug456980.xul
+++ b/docshell/test/chrome/test_bug456980.xul
@@ -15,16 +15,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml">
   <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=456980"
      target="_blank">Mozilla Bug 396519</a>
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
+    SimpleTest.expectAssertions(1);
+
     SimpleTest.waitForExplicitFinish();
 
     addLoadEvent(function() {
       window.open("bug113934_window.xul?chrome", "bug456980",
                   "chrome,width=800,height=800");
     });
 
   ]]></script>
--- a/docshell/test/chrome/test_bug608669.xul
+++ b/docshell/test/chrome/test_bug608669.xul
@@ -34,16 +34,17 @@ function setCachePref(enabled) {
     gOrigMaxTotalViewers = undefined;
     try {
       prefBranch.clearUserPref("browser.sessionhistory.cache_subframes");
     } catch (e) { /* Pref didn't exist, meh */ }
   }
 }
 
 
+SimpleTest.expectAssertions(1);
 
     /** Test for Bug 608669 **/
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(nextTest);
 
 gen = doTest();
 
--- a/docshell/test/chrome/test_mozFrameType.xul
+++ b/docshell/test/chrome/test_mozFrameType.xul
@@ -22,16 +22,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 769771 **/
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(function () {
   window.open("mozFrameType_window.xul", "mozFrameType",
               "chrome,width=600,height=600");
 });
 
--- a/docshell/test/navigation/test_child.html
+++ b/docshell/test/navigation/test_child.html
@@ -4,16 +4,20 @@
     <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
     <script type="text/javascript" src="NavigationUtils.js"></script>        
     <style type="text/css">
       iframe { width: 90%; height: 50px; }
     </style>
 <script>
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 window.onload = function() {
   navigateByLocation(frames[0]);
   navigateByOpen("child1");
   navigateByForm("child2");
   navigateByHyperlink("child3");
 
   xpcWaitForFinishedFrames(function() {
     isNavigated(frames[0], "Should be able to navigate off-domain child by setting location.");
--- a/docshell/test/navigation/test_grandchild.html
+++ b/docshell/test/navigation/test_grandchild.html
@@ -4,16 +4,20 @@
     <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
     <script type="text/javascript" src="NavigationUtils.js"></script>        
     <style type="text/css">
       iframe { width: 90%; height: 200px; }
     </style>
 <script>
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 window.onload = function () {
   navigateByLocation(frames[0].frames[0]);
   navigateByOpen("child1_child0");
   navigateByForm("child2_child0");
   navigateByHyperlink("child3_child0");
 
   xpcWaitForFinishedFrames(function() {
     isNavigated(frames[0].frames[0], "Should be able to navigate off-domain grandchild by setting location.");
--- a/docshell/test/navigation/test_reserved.html
+++ b/docshell/test/navigation/test_reserved.html
@@ -4,16 +4,20 @@
     <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
     <script type="text/javascript" src="NavigationUtils.js"></script>        
     <style type="text/css">
       iframe { width: 90%; height: 200px; }
     </style>
 <script>
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 function testTop() {
   window0 = window.open("iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#top,location", "_blank", "width=10,height=10");
 
   xpcWaitForFinishedFrames(function() {
     isInaccessible(window0, "Should be able to navigate off-domain top by setting location.");
     window0.close();
     xpcCleanupWindows();
 
--- a/docshell/test/test_bug580069.html
+++ b/docshell/test/test_bug580069.html
@@ -10,16 +10,19 @@ https://bugzilla.mozilla.org/show_bug.cg
   <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=580069">Mozilla Bug 580069</a>
 
 <iframe id='iframe' src='file_bug580069_1.html'></iframe>
 
 <script type="application/javascript">
+
+SimpleTest.expectAssertions(1);
+
 SimpleTest.waitForExplicitFinish();
 
 var iframe = document.getElementById('iframe');
 var iframeCw = iframe.contentWindow;
 
 // Called when file_bug580069_1.html loads.
 function page1Load() {
   // This should cause us to load file 2.
--- a/docshell/test/test_bug668513.html
+++ b/docshell/test/test_bug668513.html
@@ -3,16 +3,20 @@
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=668513
 -->
 <head>
   <title>Test for Bug 668513</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 <script>
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
   function onload_test()
   {
     var win = frames[0];
     ok(win.performance, 'Window.performance should be defined');
     ok(win.performance.navigation, 'Window.performance.navigation should be defined');
     var navigation = win.performance && win.performance.navigation;
     if (navigation === undefined)
     {
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2950,17 +2950,17 @@ nsDOMWindowUtils::RemoteFrameFullscreenR
 
 nsresult
 nsDOMWindowUtils::ExitFullscreen()
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  nsIDocument::ExitFullScreen(/* async = */ false);
+  nsIDocument::ExitFullscreen(nullptr, /* async */ false);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SelectAtPoint(float aX, float aY, uint32_t aSelectBehavior,
                                 bool *_retval)
 {
   *_retval = false;
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1161,17 +1161,17 @@ nsFocusManager::SetFocusInner(nsIContent
   if (contentToFocus &&
       nsContentUtils::GetRootDocument(contentToFocus->OwnerDoc())->IsFullScreenDoc() &&
       nsContentUtils::HasPluginWithUncontrolledEventDispatch(contentToFocus)) {
     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                     "DOM",
                                     contentToFocus->OwnerDoc(),
                                     nsContentUtils::eDOM_PROPERTIES,
                                     "FocusedWindowedPluginWhileFullScreen");
-    nsIDocument::ExitFullScreen(true);
+    nsIDocument::ExitFullscreen(contentToFocus->OwnerDoc(), /* async */ true);
   }
 #endif
 
   // if the FLAG_NOSWITCHFRAME flag is used, only allow the focus to be
   // shifted away from the current element if the new shell to focus is
   // the same or an ancestor shell of the currently focused shell.
   bool allowFrameSwitch = !(aFlags & FLAG_NOSWITCHFRAME) ||
                             IsSameOrAncestor(newWindow, mFocusedWindow);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4726,17 +4726,17 @@ nsGlobalWindow::SetFullScreenInternal(bo
   FORWARD_TO_OUTER(SetFullScreen, (aFullScreen), NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   bool rootWinFullScreen;
   GetFullScreen(&rootWinFullScreen);
   // Only chrome can change our fullScreen mode, unless we're running in
   // untrusted mode.
-  if (aFullScreen == rootWinFullScreen || 
+  if (aFullScreen == rootWinFullScreen ||
       (aRequireTrust && !nsContentUtils::IsCallerChrome())) {
     return NS_OK;
   }
 
   // SetFullScreen needs to be called on the root window, so get that
   // via the DocShell tree, and if we are not already the root,
   // call SetFullScreen on that window instead.
   nsCOMPtr<nsIDocShellTreeItem> rootItem;
@@ -4787,17 +4787,18 @@ nsGlobalWindow::SetFullScreenInternal(bo
       widget->MakeFullScreen(aFullScreen);
   }
 
   if (!mFullScreen) {
     // Force exit from DOM full-screen mode. This is so that if we're in
     // DOM full-screen mode and the user exits full-screen mode with
     // the browser full-screen mode toggle keyboard-shortcut, we'll detect
     // that and leave DOM API full-screen mode too.
-    nsIDocument::ExitFullScreen(false);
+    nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
+    nsIDocument::ExitFullscreen(doc, /* async */ false);
   }
 
   if (!mWakeLock && mFullScreen) {
     nsCOMPtr<nsIPowerManagerService> pmService =
       do_GetService(POWERMANAGERSERVICE_CONTRACTID);
     NS_ENSURE_TRUE(pmService, NS_OK);
 
     pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"), this, getter_AddRefs(mWakeLock));
--- a/dom/bindings/test/test_bug773326.html
+++ b/dom/bindings/test/test_bug773326.html
@@ -1,11 +1,16 @@
 <!doctype html>
 <meta charset=utf-8>
 <title>Test for Bug 773326</title>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <div id=log></div>
 <script>
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+} else {
+  SimpleTest.expectAssertions(2);
+}
 test(function() {
   new Worker("data:text/javascript,new XMLHttpRequest(42)");
 }, "Should not crash")
 </script>
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -155,33 +155,33 @@ public:
     mAvailablePacketSize = aRemoteMaxPacketSize - kPutRequestHeaderSize;
   }
 
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(!NS_IsMainThread());
 
     uint32_t numRead;
-    char* buf = new char[mAvailablePacketSize];
+    nsAutoArrayPtr<char> buf(new char[mAvailablePacketSize]);
 
     // function inputstream->Read() only works on non-main thread
     nsresult rv = mInputStream->Read(buf, mAvailablePacketSize, &numRead);
     if (NS_FAILED(rv)) {
       // Needs error handling here
       NS_WARNING("Failed to read from input stream");
       return NS_ERROR_FAILURE;
     }
 
     if (numRead > 0) {
       if (sSentFileLength + numRead >= sFileLength) {
         sWaitingToSendPutFinal = true;
       }
 
       nsRefPtr<SendSocketDataTask> task =
-        new SendSocketDataTask((uint8_t*)buf, numRead);
+        new SendSocketDataTask((uint8_t*)buf.forget(), numRead);
       if (NS_FAILED(NS_DispatchToMainThread(task))) {
         NS_WARNING("Failed to dispatch to main thread!");
         return NS_ERROR_FAILURE;
       }
     }
 
     return NS_OK;
   };
--- a/dom/browser-element/mochitest/test_browserElement_inproc_PurgeHistory.html
+++ b/dom/browser-element/mochitest/test_browserElement_inproc_PurgeHistory.html
@@ -2,12 +2,15 @@
 <html>
 <head>
   <title>Test of browser element.</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="browserElementTestHelpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
+<script type="application/javascript;version=1.7">
+SimpleTest.expectAssertions(1);
+</script>
 <script type="application/javascript;version=1.7" src="browserElement_PurgeHistory.js">
 </script>
 </body>
 </html>
--- a/dom/encoding/test/test_TextDecoder.html
+++ b/dom/encoding/test/test_TextDecoder.html
@@ -8,16 +8,18 @@
   <script type="text/javascript" src="test_TextDecoder.js"></script>
   <script type="text/javascript" src="test_BOMEncoding.js"></script>
   <script type="text/javascript" src="worker_helper.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 
+SimpleTest.expectAssertions(0, 2);
+
 setup({explicit_done: true});
 runTest();
 
 function runTest()
 {
   runTextDecoderOptions();
   runTextDecoderBOMEnoding();
 }
--- a/dom/encoding/test/test_TextEncoder.html
+++ b/dom/encoding/test/test_TextEncoder.html
@@ -7,16 +7,22 @@
   <script type="text/javascript" src="/resources/testharnessreport.js"></script>
   <script type="text/javascript" src="test_TextEncoder.js"></script>
   <script type="text/javascript" src="worker_helper.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+} else {
+  SimpleTest.expectAssertions(2);
+}
+
 setup({explicit_done: true});
 runTest();
 
 function runTest()
 {
   runTextEncoderTests();
 }
 
--- a/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLIFrameElement.idl
@@ -11,17 +11,17 @@
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
-[scriptable, uuid(a7bd1e34-3969-47ae-8c1d-2970132ba925)]
+[scriptable, uuid(39298082-9657-48be-b119-4dc9c84ce685)]
 interface nsIDOMHTMLIFrameElement : nsIDOMHTMLElement
 {
            attribute DOMString        align;
            attribute DOMString        frameBorder;
            attribute DOMString        height;
            attribute DOMString        longDesc;
            attribute DOMString        marginHeight;
            attribute DOMString        marginWidth;
@@ -29,14 +29,11 @@ interface nsIDOMHTMLIFrameElement : nsID
            attribute DOMString        scrolling;
            attribute DOMString        src;
            attribute DOMString        width;
   // Introduced in DOM Level 2:
   readonly attribute nsIDOMDocument   contentDocument;
   readonly attribute nsIDOMWindow     contentWindow;
 
            attribute DOMString        sandbox;
-  // Mozilla extensions
-  // iframe elements require the allowfullscreen attribute to be present
-  // if they're to allow content in the sub document to go into DOM full-screen
-  // mode. See https://wiki.mozilla.org/index.php?title=Gecko:FullScreenAPI
-           attribute boolean          allowfullscreen;
+
+           attribute boolean          allowFullscreen;
 };
--- a/dom/media/tests/mochitest/test_getUserMedia_basicAudio.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_basicAudio.html
@@ -15,16 +15,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=781534">mozGetUserMedia Basic Audio Test</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   <audio id="testAudio"></audio>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
   /**
    * Run a test to verify that we can complete a start and stop media playback
    * cycle for an audio LocalMediaStream on an audio HTMLMediaElement.
    */
   runTest(function () {
     var testAudio = document.getElementById('testAudio');
 
     getUserMedia({audio: true}, function (aStream) {
--- a/dom/media/tests/mochitest/test_getUserMedia_basicVideo.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_basicVideo.html
@@ -15,16 +15,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=781534">mozGetUserMedia Basic Video Test</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   <video id="testVideo"></video>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
   /**
    * Run a test to verify that we can complete a start and stop media playback
    * cycle for an video LocalMediaStream on a video HTMLMediaElement.
    */
   runTest(function () {
     var testVideo = document.getElementById('testVideo');
 
     getUserMedia({video: true}, function (aStream) {
--- a/dom/media/tests/mochitest/test_getUserMedia_basicVideoAudio.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_basicVideoAudio.html
@@ -15,16 +15,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=781534">mozGetUserMedia Basic Video & Audio Test</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   <video id="testVideoAudio"></video>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
   /**
    * Run a test to verify that we can complete a start and stop media playback
    * cycle for a video and audio LocalMediaStream on a video HTMLMediaElement.
    */
   runTest(function () {
     var testVideoAudio = document.getElementById('testVideoAudio');
 
     getUserMedia({video: true, audio: true}, function (aStream) {
--- a/dom/media/tests/mochitest/test_getUserMedia_exceptions.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_exceptions.html
@@ -14,16 +14,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795367">Test mozGetUserMedia Exceptions</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /**
   These tests verify that the appropriate exception is thrown when incorrect
   values are provided to the immediate mozGetUserMedia call.
 */
 var exceptionTests = [
   // Each test here verifies that a caller is required to have all
   // three arguments in order to call mozGetUserMedia
   { params: undefined,
--- a/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStream.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStream.html
@@ -15,16 +15,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=822109">mozGetUserMedia Stop Video Audio Stream</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   <video id="testVideo"></video>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
   /**
    * Run a test to verify that we can start a video+audio stream in a
    * media element, call stop() on the stream, and successfully get an
    * ended event fired.
    */
   runTest(function () {
     getUserMedia({video: true, audio: true}, function(stream) {
       var testVideo = document.getElementById('testVideo');
--- a/dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html
+++ b/dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html
@@ -18,16 +18,23 @@ https://bugzilla.mozilla.org/show_bug.cg
   <audio id="audioLocal" controls></audio>
 
   <video id="videoPCLocal" width="160" height="120" controls></video>
   <video id="videoPCRemote" width="160" height="120" controls></video>
   <video id="videoLocal" width="160" height="120" controls></video>
 </div>
 <pre id="test">
 <script type="application/javascript">
+
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 9);
+} else {
+  SimpleTest.expectAssertions(0, 1);
+}
+
   var audioLocal;
   var audioPCLocal;
   var audioPCRemote;
 
   var videoLocal;
   var videoPCLocal;
   var videoPCRemote;
 
--- a/dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html
+++ b/dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html
@@ -18,16 +18,21 @@ https://bugzilla.mozilla.org/show_bug.cg
   <audio id="audioLocal" controls></audio>
 
   <video id="videoPCLocal" width="160" height="120" controls></video>
   <video id="videoPCRemote" width="160" height="120" controls></video>
   <video id="videoLocal" width="160" height="120" controls></video>
 </div>
 <pre id="test">
 <script type="application/javascript">
+
+if (navigator.platform.indexOf("Linux") != 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
   var audioLocal;
   var videoLocal;
   var videoPCLocal;
   var videoPCRemote;
 
   var pcLocal;
   var pcRemote;
 
--- a/dom/network/tests/test_network_basics.html
+++ b/dom/network/tests/test_network_basics.html
@@ -7,16 +7,18 @@
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+SimpleTest.expectAssertions(11);
+
 /** Test for Network API **/
 
 function checkInterface(aInterface) {
   ok(!(aInterface in window), aInterface + " should be prefixed");
   ok(("Moz" + aInterface) in window, aInterface + " should be prefixed");
 }
 
 ok('mozConnection' in navigator, "navigator.mozConnection should exist");
--- a/dom/network/tests/test_tcpsocket_enabled_with_perm.html
+++ b/dom/network/tests/test_tcpsocket_enabled_with_perm.html
@@ -7,16 +7,20 @@
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test to ensure TCPSocket permission being turned on enables 
   navigator.mozTCPSocket, and mozTCPSocket.open works when
   the tcp-socket permission has been granted.
 **/
 SpecialPowers.setBoolPref("dom.mozTCPSocket.enabled", true);
 SpecialPowers.addPermission("tcp-socket", true, document);
 
 ok('mozTCPSocket' in navigator, "navigator.mozTCPSocket should be accessible if dom.mozTCPSocket.enabled is true");
--- a/dom/plugins/test/mochitest/test_GCrace.html
+++ b/dom/plugins/test/mochitest/test_GCrace.html
@@ -15,16 +15,22 @@
 
     function start() {
       if (!SimpleTest.testPluginIsOOP()) {
         ok(true, "Skipping this test when test plugin is not OOP.");
         SimpleTest.finish();
         return;
       }
       else {
+        if (navigator.platform.indexOf("Win") == 0) {
+          SimpleTest.expectAssertions(0, 66);
+        } else {
+          SimpleTest.expectAssertions(0, 1);
+        }
+
         setTimeout(checkGCRace, 1000);
       }
     }
 
     var nested = false;
 
     function cb(f) {
       ok(!nested, "Callback shouldn't occur in a nested stack frame");
--- a/dom/plugins/test/mochitest/test_cocoa_focus.html
+++ b/dom/plugins/test/mochitest/test_cocoa_focus.html
@@ -1,16 +1,18 @@
 <html>
 <head>
   <title>NPCocoaEventFocusChanged Tests</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 </head>
 
 <body onload="runTests()">
   <script class="testbody" type="application/javascript">
+    SimpleTest.expectAssertions(1);
+
     SimpleTest.waitForExplicitFinish();
 
     var gOtherWindow;
 
     function runTests() {
       // We have to have two top-level windows in play in order to run these tests.
       gOtherWindow = window.open("cocoa_focus.html", "", "width=250,height=250");
     }
--- a/dom/plugins/test/mochitest/test_cookies.html
+++ b/dom/plugins/test/mochitest/test_cookies.html
@@ -2,16 +2,19 @@
 <head>
   <title>NPAPI Cookie Tests</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 </head>
 
 <body onload="runTests()">
   <embed id="plugin1" type="application/x-test" width="400" height="400"></embed>
   <script class="testbody" type="application/javascript">
+if (navigator.platform.indexOf("Mac") != 0) {
+  SimpleTest.expectAssertions(1);
+}
     SimpleTest.waitForExplicitFinish();
     function runTests() {
       var pluginElement = document.getElementById("plugin1");
       pluginElement.setCookie("foo");
       is(pluginElement.getCookie(), "foo", "Cookie was set and retrieved correctly via NPAPI.");
       SimpleTest.finish();
     }
   </script>
--- a/dom/plugins/test/mochitest/test_pluginstream_seek_close.html
+++ b/dom/plugins/test/mochitest/test_pluginstream_seek_close.html
@@ -1,16 +1,20 @@
 <body>
 <head>
   <title>NPAPI Seekable NPStream Test</title>
   <script type="text/javascript" 
           src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" 
         href="/tests/SimpleTest/test.css" />
 <script>
+  if (navigator.platform.indexOf("Linux") == 0) {
+    SimpleTest.expectAssertions(0, 1);
+  }
+
   SimpleTest.waitForExplicitFinish();
 
   function frameLoaded() {
     var testframe = document.getElementById('testframe');
     var content = testframe.contentDocument.body.innerHTML;
     if (!content.length)
       return;
 
--- a/dom/plugins/test/mochitest/test_twostreams.html
+++ b/dom/plugins/test/mochitest/test_twostreams.html
@@ -5,16 +5,22 @@
           src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" 
         href="/tests/SimpleTest/test.css" />
 </head>
 <body>
   <p id="display"></p>
 
   <script type="text/javascript">
+  if (navigator.platform.indexOf("Win") == 0) {
+    SimpleTest.expectAssertions(1, 2);
+  } else {
+    SimpleTest.expectAssertions(1);
+  }
+
   SimpleTest.waitForExplicitFinish();
 
   var framesToLoad = 2;
   function frameLoaded(id) {
     var frame = document.getElementById('testframe' + id);
     if (!frame.contentDocument.body.innerHTML.length)
       return;
 
--- a/dom/tests/mochitest/bugs/test_bug291653.html
+++ b/dom/tests/mochitest/bugs/test_bug291653.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=291653">Mozilla Bug 291653</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 291653 **/
 SimpleTest.waitForExplicitFinish();
 
 var secondListenerDidRun = false;
 
 var w = window.open("file_bug291653.html", "foo", "width=300,height=300");
 
 function closeTest() {
--- a/dom/tests/mochitest/bugs/test_bug304459.html
+++ b/dom/tests/mochitest/bugs/test_bug304459.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=304459">Mozilla Bug 304459</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   <iframe id="frame"></iframe>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 304459 **/
 
 function iframeLoaded()
 {
   var frame = document.getElementById("frame");
   frame.onload = undefined;
   frame.src = "http://example.org/tests/dom/tests/mochitest/bugs/iframe_bug304459-2.html";
 }
--- a/dom/tests/mochitest/bugs/test_bug308856.html
+++ b/dom/tests/mochitest/bugs/test_bug308856.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=308856">Mozilla Bug 308856</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 308856 **/
 
 var monkey = 12;
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   is(12,window.monkey,"Window global is correct value");
   var found = false;
--- a/dom/tests/mochitest/bugs/test_bug327891.html
+++ b/dom/tests/mochitest/bugs/test_bug327891.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=327891">Mozilla Bug 327891</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 var pass = false;
 
 try {
   new HTMLDocument();
 } catch(e) {
   pass = true;
 }
 
--- a/dom/tests/mochitest/bugs/test_bug333983.html
+++ b/dom/tests/mochitest/bugs/test_bug333983.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=333983">Mozilla Bug 333983</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 333983 **/
 HTMLElement.prototype.foopy = function () { return "foopy"; }
 
 var foopy = "";
 try {
   foopy = document.body.foopy()
 } catch (ex) {
   foopy = ex + "";
--- a/dom/tests/mochitest/bugs/test_bug342448.html
+++ b/dom/tests/mochitest/bugs/test_bug342448.html
@@ -14,16 +14,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=342448">Mozilla Bug 342448</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 342448 **/
 SimpleTest.waitForExplicitFinish();
 try {
 setTimeout(1, 0);
 } catch (ex) {}
 callLater(.1, function() { ok(true, "shouldn't crash when passing a number as the first arg to setTimeout"); SimpleTest.finish(); })
 
 
--- a/dom/tests/mochitest/bugs/test_bug346659.html
+++ b/dom/tests/mochitest/bugs/test_bug346659.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=346659">Mozilla Bug 346659</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 346659 **/
 // do the tests in two batches, because otherwise the popup blocker kills off
 // our test because it opens too many windows.
 var numTestsSet1 = 6;
 var numTestsSet2 = 4;
 var numTestsSet3 = 2;
 var complete = 0;
 SimpleTest.waitForExplicitFinish();
--- a/dom/tests/mochitest/bugs/test_bug406375.html
+++ b/dom/tests/mochitest/bugs/test_bug406375.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=406375">Mozilla Bug 406375</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(2, 3);
+}
+
 /** Test for Bug 406375 **/
 
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   window.showModalDialog("file_bug406375.html");
   ok(true, "This test should not hang");
--- a/dom/tests/mochitest/bugs/test_bug411103.html
+++ b/dom/tests/mochitest/bugs/test_bug411103.html
@@ -18,16 +18,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 <!-- for good measure... -->
 <iframe src="data:application/xhtml+xml,%3Chtml%20xmlns=%22http://www.w3.org/1999/xhtml%22%3E%3Cbody%3E%3Cp%3EXHTML%3C/p%3E%3C/body%3E%3C/html%3E"
         name="xhtmlWindow"></iframe>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 /** Test for Bug 411103 **/
 var allNSTests =
   [
    { args: [undefined, undefined] },
    { args: [null, undefined] },
    { args: [undefined, null] },
--- a/dom/tests/mochitest/bugs/test_bug414291.html
+++ b/dom/tests/mochitest/bugs/test_bug414291.html
@@ -7,16 +7,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 414291</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=414291">Mozilla Bug 414291</a>
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 414291 **/
 
 var result1 = 0;
 var result2 = 0;
 var result3 = 0;
 
 window.open("data:text/html,<html><body onload='close(); opener.result1 = 1;'>", "w1");
 is(result1, 0, "window either opened as modal or loaded synchronously.");
--- a/dom/tests/mochitest/bugs/test_bug427744.html
+++ b/dom/tests/mochitest/bugs/test_bug427744.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=427744">Mozilla Bug 427744</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 427744 **/
 
 var found = false;
 for (var i = 0; i < navigator.plugins.length; i++) {
   if (navigator.plugins[i].name == "Test Plug-in") {
     found = true;
     is(navigator.plugins[i].version, "1.0.0.0", "Should have seen the right version");
   }
--- a/dom/tests/mochitest/bugs/test_bug42976.html
+++ b/dom/tests/mochitest/bugs/test_bug42976.html
@@ -17,16 +17,20 @@ https://bugzilla.mozilla.org/show_bug.cg
     <iframe id=htmlstd src="data:text/html;charset=ISO-8859-3,<!DOCTYPE html><html><body><div></div></body></html>"></iframe>
     <iframe id=textplain src="data:text/plain;charset=ISO-8859-4,asdf%0Azxcv%0A"></iframe>
     <iframe id=xhtmlstd src="data:application/xhtml+xml;charset=ISO-8859-5,<!DOCTYPE html><html xmlns='http://www.w3.org/1999/xhtml'><body><div></div></body></html>"></iframe>
     <iframe id=xmlstd src="data:image/svg+xml;charset=ISO-8859-6,<svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width='300' height='300'><text x='60' y='150' fill='blue'>Hello, World!</text><text x='60' y='250' fill='blue'>Hello, World!</text></svg>"></iframe>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
 
   var iframes = document.getElementsByTagName("iframe");
   for (var i = 1; i < iframes.length; i++) {
     var doc = iframes[i].contentDocument;
     var clonefalse = doc.cloneNode(false);
--- a/dom/tests/mochitest/bugs/test_bug430276.html
+++ b/dom/tests/mochitest/bugs/test_bug430276.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=430276">Mozilla Bug 430276</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 430276 **/
 
 function startTest() {
   document.getElementById("testFrame")
     .setAttribute("src", "iframe_bug430276.html");
 }
 
 function nextTest() {
--- a/dom/tests/mochitest/bugs/test_bug437361.html
+++ b/dom/tests/mochitest/bugs/test_bug437361.html
@@ -5,16 +5,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 -->
 <head>
   <title>Test for Bug 437361</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   
   <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
   /** Test for Bug 437361 **/
 
   function testModalDialogBlockedCleanly() {
     is(true, SpecialPowers.getBoolPref("dom.disable_open_during_load"), "mozprefs sanity check");
     var rv = window.showModalDialog( // should be blocked without exception
       "data:text/html,<html><body onload='close(); returnValue = 1;' /></html>");
     is(rv, null, "Modal dialog opened unexpectedly.");
   }
--- a/dom/tests/mochitest/bugs/test_bug440572.html
+++ b/dom/tests/mochitest/bugs/test_bug440572.html
@@ -8,16 +8,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body onload="runtests()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=440572">Mozilla Bug 440572</a>
 
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 /** Test for Bug 440572 **/
 
 var messages = [];
 
 function receiveMessage(e)
 {
   is(e.origin, "http://example.org", "wrong sender!");
   messages.push(e.data);
--- a/dom/tests/mochitest/bugs/test_bug456151.html
+++ b/dom/tests/mochitest/bugs/test_bug456151.html
@@ -14,16 +14,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=456151">Mozilla Bug 456151</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 456151 **/
 var intercepted = false;
 
 // Set up our new addEventListener
 var proto = HTMLParagraphElement.prototype;
 proto.oldAdd = proto.addEventListener;
 proto.addEventListener = function(ev, list, capt) {
   intercepted = true;
--- a/dom/tests/mochitest/bugs/test_bug458091.html
+++ b/dom/tests/mochitest/bugs/test_bug458091.html
@@ -16,16 +16,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 </div>
 <pre id="test">
 <a id="testlink1" target="_blank" href="javascript:window.opener.finish(sessionStorage['testItem']);window.close();">Javascript Link</a>
 <a id="testlink2" target="_blank" href="bug458091_child.html">HTTP Link</a>
 <a id="testlink3" target="alreadyOpened" href="bug458091_child.html">Target Link</a>
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 458091 **/
 
 var gTestWin;
 var gRunningTests = 0;
 
 function runNextTest()
 {
   if (gTests.length > 0) {
--- a/dom/tests/mochitest/bugs/test_bug459848.html
+++ b/dom/tests/mochitest/bugs/test_bug459848.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=459848">Mozilla Bug 459848</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 /** Test for Bug 459848 **/
 
 var ifr1, irf2;
 var doc1, doc2;
 
 function testDocument(d) {
   d.documentElement.setAttribute("onload", "this.setAttribute('didRun', 'true');");
   var e = d.createEvent("Events");
--- a/dom/tests/mochitest/bugs/test_bug465263.html
+++ b/dom/tests/mochitest/bugs/test_bug465263.html
@@ -17,16 +17,22 @@ https://bugzilla.mozilla.org/show_bug.cg
   <iframe src="http://mochi.test:8888"></iframe>
 </p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 465263 **/
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   window.frames[0].location.hash = '';
   is(window.frames[0].location.href, "http://mochi.test:8888/#",
      "Should have '#' in href now");
   window.frames[1].location.hash = '#';
   is(window.frames[1].location.href, "http://mochi.test:8888/#",
--- a/dom/tests/mochitest/bugs/test_bug479143.html
+++ b/dom/tests/mochitest/bugs/test_bug479143.html
@@ -11,16 +11,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=479143">Mozilla Bug 479143</a>
 <p id="display"></p>
 <div id="content" style="display: none"></div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
   SimpleTest.waitForExplicitFinish();
 
   setTimeout(function() {
     var interval = setInterval(function() { var i = 0; i++; }, 10);
 
     var xhr = new XMLHttpRequest();
     xhr.open("GET", "test_bug479143.html", false);
     xhr.send(null);
--- a/dom/tests/mochitest/bugs/test_bug484775.html
+++ b/dom/tests/mochitest/bugs/test_bug484775.html
@@ -13,16 +13,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=484775">Mozilla Bug 484775</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+} else if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 484775 **/
 
 var expectedTarget = null;
 var expectedType = null;
 var eventCount = 0;
 
 function listener(evt) {
   ++eventCount;
--- a/dom/tests/mochitest/bugs/test_bug492925.html
+++ b/dom/tests/mochitest/bugs/test_bug492925.html
@@ -19,16 +19,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=492925">Mozilla Bug 492925</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 492925 **/
 
 var sheet = document.styleSheets[1];
 var rule = sheet.cssRules[0];
 var media = rule.media;
 
 is(media.mediaText, "tv, print", "Unexpected media string");
 is(media[0], "tv", "[0] should be 'tv'");
--- a/dom/tests/mochitest/bugs/test_bug49312.html
+++ b/dom/tests/mochitest/bugs/test_bug49312.html
@@ -32,16 +32,22 @@ https://bugzilla.mozilla.org/show_bug.cg
   <iframe src="javascript:'<script>location=\'iframe_bug49312.html\'</script>'"></iframe>
 </p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 /** Test for Bug 49312 **/
 SimpleTest.waitForExplicitFinish();
 var opened = window.open("javascript:'<script>location=\\\'iframe_bug49312.html\\\'</" + "script>'", "", "width=100,height=100")
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/tests/mochitest/bugs/test_bug495219.html
+++ b/dom/tests/mochitest/bugs/test_bug495219.html
@@ -10,16 +10,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
 <a target="_blank"
    href="https://bugzilla.mozilla.org/show_bug.cgi?id=495219">Mozilla
    Bug 495219</a>
 <iframe onload="this.style.display='none'"></iframe>
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 SimpleTest.waitForExplicitFinish();
 window.onload = function () {
   is(window.frames[0].innerWidth, 0, "width should be zero");
   is(window.frames[0].innerHeight, 0, "height should be zero");
   SimpleTest.finish();
 }
 
 </script>
--- a/dom/tests/mochitest/bugs/test_bug504862.html
+++ b/dom/tests/mochitest/bugs/test_bug504862.html
@@ -7,16 +7,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 504862</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body onload="runTest()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=504862">Mozilla Bug 504862</a>
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 5);
+}
+
 /** Test for Bug 504862 **/
 SimpleTest.waitForExplicitFinish();
 function onMsgRcv(event)
 {
   is(event.data, "args: undefined", "Unexpected cross origin dialog arguments.");
 }
 
 function runTest() {
--- a/dom/tests/mochitest/bugs/test_bug529328.html
+++ b/dom/tests/mochitest/bugs/test_bug529328.html
@@ -10,16 +10,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529328">Mozilla Bug 529328</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script type="application/javascript">
+
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 529328 **/
 function testDOMTokenList() {
   is(document.body.classList[-1], undefined, "Wrong value for out of bounds access (DOMTokenList)");
   is(document.body.classList[0], undefined, "Wrong value for out of bounds access (DOMTokenList)");
   is(document.body.classList[1], undefined, "Wrong value for out of bounds access (DOMTokenList)");
   is(document.body.classList[2], undefined, "Wrong value for out of bounds access (DOMTokenList)");
   is(document.body.classList.item(-1), null, "Wrong value for out of bounds access (DOMTokenList)");
   is(document.body.classList.item(0), null, "Wrong value for out of bounds access (DOMTokenList)");
--- a/dom/tests/mochitest/bugs/test_bug531176.html
+++ b/dom/tests/mochitest/bugs/test_bug531176.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=531176">Mozilla Bug 531176</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 531176 **/
 
 var errorCount = 0;
 function errorHandler(msg, filename, linenr) {
   is(msg, "SyntaxError: syntax error", "Wrong error!");
   is(filename, window.location, "Wrong filename!");
   is(linenr, 1, "Wrong linenr!");
   ++errorCount;
--- a/dom/tests/mochitest/bugs/test_bug531542.html
+++ b/dom/tests/mochitest/bugs/test_bug531542.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=531542">Mozilla Bug 531542</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 531542 **/
 
 var negativeTimeoutFired = false;
 function negativeTimeout()
 {
   negativeTimeoutFired = true;
 }
 function testFinished()
--- a/dom/tests/mochitest/bugs/test_bug534149.html
+++ b/dom/tests/mochitest/bugs/test_bug534149.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=534149">Mozilla Bug 534149</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 534149 **/
 function getIDs(iframe) {
   var win = iframe.contentWindow;
   // Force inner creation
   win.document;
 
   var util = SpecialPowers.getDOMWindowUtils(win);
   return [util.outerWindowID, util.currentInnerWindowID];
--- a/dom/tests/mochitest/bugs/test_bug541530.html
+++ b/dom/tests/mochitest/bugs/test_bug541530.html
@@ -11,16 +11,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=541530">Mozilla Bug 541530</a>
 <p id="display"></p>
 <div id="content" style="display: none"></div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 5);
+}
+
 var orig = window;
 window = {};
 
 var origLocation = location;
 
 ok(window === orig, "can't override window");
 ok(window.location === location, "properties are properly aliased");
 ok(document.location === location, "properties are properly aliased");
--- a/dom/tests/mochitest/bugs/test_bug545314.html
+++ b/dom/tests/mochitest/bugs/test_bug545314.html
@@ -13,16 +13,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <iframe id="ifr"></iframe>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 545314 **/
 var frame = window.frames[0];
 frame.location.assign("http://localhost:8888/");
 ok(true, "location.assign didn't throw");
 
 </script>
 </pre>
 </body>
--- a/dom/tests/mochitest/bugs/test_bug548828.html
+++ b/dom/tests/mochitest/bugs/test_bug548828.html
@@ -13,16 +13,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=548828">Mozilla Bug 548828</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 5);
+}
+
 /** Test for Bug 548828 **/
   var head = document.getElementsByTagName("head")[0];
   is(document.head, head, "document.head and document.getElementsByTagName(\"head\")[0] should match");
   document.head = "";
   is(document.head, head, "document.head reassigned");
   document.head = document.createElement("head");
   is(document.head, head, "new element created with the name \"head\"");
   document.documentElement.appendChild(document.createElement("head"));
--- a/dom/tests/mochitest/bugs/test_bug562433.html
+++ b/dom/tests/mochitest/bugs/test_bug562433.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562433">Mozilla Bug 562433</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 562433 **/
 
 var w = window.open("");
 
 // The new window's location.host and location.hostname must be the empty
 // string (instead of throwing an exception)
 
 is(w.location.host, "", 'w.location.host should be ""');
--- a/dom/tests/mochitest/bugs/test_bug563487.html
+++ b/dom/tests/mochitest/bugs/test_bug563487.html
@@ -21,14 +21,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=563487">Mozilla Bug 563487</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 563487 **/
 is(exception, null, "removeEventListener threw");
 </script>
 </pre>
 </body>
 </html>
--- a/dom/tests/mochitest/bugs/test_bug583225.html
+++ b/dom/tests/mochitest/bugs/test_bug583225.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583225">Mozilla Bug 583225</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 583225 **/
 
 function clicked()
 {
   ok(true, "Event fired on DocumentFragment.");
   SimpleTest.finish();
 }
 
--- a/dom/tests/mochitest/bugs/test_bug585240.html
+++ b/dom/tests/mochitest/bugs/test_bug585240.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=585240">Mozilla Bug 585240</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 585240 **/
 
   SimpleTest.waitForExplicitFinish();
 
   window.onmessage = function(event) {
     ok(true, "message event should fire!");
     SimpleTest.finish();
   }
--- a/dom/tests/mochitest/bugs/test_bug585819.html
+++ b/dom/tests/mochitest/bugs/test_bug585819.html
@@ -13,16 +13,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=585819">Mozilla Bug 585819</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   <iframe></iframe>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 585819 **/
 
 var range = document.createRange();
 range.setStartBefore(document.body);
 var fragment = range.createContextualFragment("<span></span>");
 is(fragment.firstChild.localName, "span", "We don't want tag inference here!");
 
 var iframeDoc = document.getElementsByTagName("iframe")[0].contentDocument;
--- a/dom/tests/mochitest/bugs/test_bug593174.html
+++ b/dom/tests/mochitest/bugs/test_bug593174.html
@@ -8,16 +8,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=593174">Mozilla Bug 593174</a>
 
 <script>
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var loadCount = 0;
 var popup = null;
 
 const kOriginalLocation = location.href;
 
 function iframeLoaded(identifier) {
--- a/dom/tests/mochitest/bugs/test_bug597809.html
+++ b/dom/tests/mochitest/bugs/test_bug597809.html
@@ -9,16 +9,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <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=597809">Mozilla Bug 597809</a>
 <p id="display"></p>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 597809 **/
 
 SimpleTest.waitForExplicitFinish();
 
 SpecialPowers.addCategoryEntry("JavaScript-global-property", "testSNSM", "@mozilla.org/embedcomp/prompt-service;1",
                     false, true);
 
 SimpleTest.executeSoon(function () {
--- a/dom/tests/mochitest/bugs/test_bug61098.html
+++ b/dom/tests/mochitest/bugs/test_bug61098.html
@@ -16,16 +16,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 </p>
 <div id="content" style="display: none"> 
 </div>
 <pre id="test">
 </pre>
 <script class="testbody" type="text/javascript">
 /** Test for Bug 61098 **/
 
+SimpleTest.expectAssertions(8, 13);
+
 SimpleTest.waitForExplicitFinish();
 
 var mockPromptServiceRegisterer, mockPromptFactoryRegisterer;
 
 var promptState;
 
 function registerMockPromptService()
 {
--- a/dom/tests/mochitest/bugs/test_bug612267.html
+++ b/dom/tests/mochitest/bugs/test_bug612267.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=612267">Mozilla Bug 612267</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 Window.prototype.test = 'PASS';
 is(window.test, 'PASS', "setting Window.prototype affects window.__proto__");
 is(test, 'PASS', "setting Window.prototype affects the inner window lookup for sure");
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/tests/mochitest/bugs/test_bug620947.html
+++ b/dom/tests/mochitest/bugs/test_bug620947.html
@@ -12,16 +12,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=620947">Mozilla Bug 620947</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 620947 **/
 is(-1 in document.all, false, "shouldn't be there");
 is(document.all[-1], undefined, "shouldn't be able to get it");
 
 
 
 
 
--- a/dom/tests/mochitest/bugs/test_bug622361.html
+++ b/dom/tests/mochitest/bugs/test_bug622361.html
@@ -1,15 +1,22 @@
 <!DOCTYPE html>
 <html>
 <head>
 <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 <script>
+
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 var w;
 var counter = 0;
 
 function doNext()
 {
   counter++;
   postMessage("ohai", "*");
 }
--- a/dom/tests/mochitest/bugs/test_bug633133.html
+++ b/dom/tests/mochitest/bugs/test_bug633133.html
@@ -17,16 +17,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <select id="select" onchange="var foo = 'bar';">
     <option>option1</option>
     <option>option2</option>
   </select>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 633133 **/
 
 var divCollection = document.getElementsByTagName('div');
 
 ok("foo" in divCollection, "'foo' should be in the div collection");
 ok("bar" in divCollection, "'bar' should be in the div collection");
 ok(!("" in divCollection), "empty string shouldn't be in the div collection");
 ok(!("foobar" in divCollection), "'foobar' shouldn't be in the div collection");
--- a/dom/tests/mochitest/bugs/test_bug641552.html
+++ b/dom/tests/mochitest/bugs/test_bug641552.html
@@ -10,16 +10,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <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=641552">Mozilla Bug 641552</a>
 <p id="display"></p>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 641552 **/
 
 SimpleTest.waitForExplicitFinish();
 
 SpecialPowers.addCategoryEntry("JavaScript-global-property", "randomname", "@mozilla.org/embedcomp/prompt-service;1",
                     false, true);
 
 SpecialPowers.addCategoryEntry("JavaScript-navigator-property", "randomname1", "@mozilla.org/embedcomp/prompt-service;1",
--- a/dom/tests/mochitest/bugs/test_bug642026.html
+++ b/dom/tests/mochitest/bugs/test_bug642026.html
@@ -33,16 +33,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=642026">Mozilla Bug 642026</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 642026 **/
 
 var expResult = ["NaN", "Infinity", "undefined", "eval", "parseInt", "parseFloat", "isNaN", "isFinite", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "Object", "Function", "Array", "String", "Boolean", "Number", "Date", "Date", "RegExp", "Error", "EvalError", "RangeError", "ReferenceError", "SyntaxError", "TypeError", "URIError", "Math", "JSON"];
 
 var result = Object.getOwnPropertyNames(window);
 var result1 = {};
 for (var p in result) {
     result1[result[p]] = true;
--- a/dom/tests/mochitest/bugs/test_bug648465.html
+++ b/dom/tests/mochitest/bugs/test_bug648465.html
@@ -14,16 +14,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   Mozilla Bug 648465</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 648465 **/
 var w = window.open('about:blank');
 try {
   is(w.fullScreen, false, "can access non-allAccess properties of w");
 } finally {
   w.close();
 }
 
--- a/dom/tests/mochitest/bugs/test_bug664737.html
+++ b/dom/tests/mochitest/bugs/test_bug664737.html
@@ -13,16 +13,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=664737">Mozilla Bug 664737</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 664737 **/
 function shouldfail(name) {
     try {
         var rv = history[name];
         fail(false, "able to access history." + name);
     } catch (e) {
         ok(e.message.indexOf("Permission denied") >= 0, "cannot access history." + name);
     }
--- a/dom/tests/mochitest/chrome/test_focus.xul
+++ b/dom/tests/mochitest/chrome/test_focus.xul
@@ -5,16 +5,20 @@
 <window title="Focus Tests"
   onload="setTimeout(runTest, 0);"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
 <script>
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 SimpleTest.waitForExplicitFinish();
 function runTest()
 {
   window.open("window_focus.xul", "_blank", "chrome,width=600,height=550");
 }
 </script>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
--- a/dom/workers/test/test_fileReadSlice.xul
+++ b/dom/workers/test/test_fileReadSlice.xul
@@ -20,16 +20,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   </div>
 
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
 
+  if (navigator.platform.indexOf("Win") == 0) {
+    SimpleTest.expectAssertions(0, 1);
+  }
+
   /** Test for Bug 664783 **/
 
   var fileNum = 0;
 
   /**
    * Create a file which contains the given data.
    */
   function createFileWithData(fileData) {
--- a/editor/libeditor/base/tests/test_bug646194.xul
+++ b/editor/libeditor/base/tests/test_bug646194.xul
@@ -18,16 +18,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <iframe id="i" src="data:text/html,&lt;div contenteditable=true id=t&gt;test me now&lt;/div&gt;"/>
   <p/>
   <pre id="test">
   </pre>
   </body>
   <script class="testbody" type="application/javascript">
   <![CDATA[
 
+SimpleTest.expectAssertions(1);
+
 function runTest() {
   function doCommand(aCmd) {
     var controller = top.document.commandDispatcher
                      .getControllerForCommand(aCmd);
     ok((controller && controller.isCommandEnabled(aCmd)), "command available");
     controller.doCommand(aCmd);
   }
 
--- a/editor/libeditor/html/tests/test_bug537046.html
+++ b/editor/libeditor/html/tests/test_bug537046.html
@@ -18,16 +18,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   </div>
   <div id="source" contenteditable="true">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 537046 **/
 
+SimpleTest.expectAssertions(1);
+
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   var ed = document.getElementById("editor");
   var src = document.getElementById("source");
   ed.addEventListener("DOMSubtreeModified", function() {
     src.textContent = ed.innerHTML;
   }, false);
   src.addEventListener("DOMSubtreeModified", function() {
--- a/editor/libeditor/html/tests/test_bug599322.html
+++ b/editor/libeditor/html/tests/test_bug599322.html
@@ -16,16 +16,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="src">src<img src="/tests/editor/libeditor/html/tests/green.png"></div>
 <iframe id="dst" src="javascript:;"></iframe>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 599322.patch **/
 
+SimpleTest.expectAssertions(1);
+
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   var src = document.getElementById("src");
   var dst = document.getElementById("dst");
   var doc = dst.contentDocument;
   doc.open();
   doc.write("<html><head><base href='http://mochi.test:8888/'></head><body></body></html>");
   doc.close();
--- a/editor/libeditor/html/tests/test_bug674770-1.html
+++ b/editor/libeditor/html/tests/test_bug674770-1.html
@@ -17,16 +17,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a href="file_bug674770-1.html" id="link1">test</a>
 <div contenteditable>
 <a href="file_bug674770-1.html" id="link2">test</a>
 </div>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") != 0) {
+  SimpleTest.expectAssertions(1);
+}
+
 /** Test for Bug 674770 **/
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(function() {
   SpecialPowers.setBoolPref("middlemouse.paste", true);
   localStorage.removeItem("clicked");
   window.linkWasClicked = false;
 
   var link = document.querySelector("#link1");
--- a/editor/libeditor/text/tests/test_bug638596.html
+++ b/editor/libeditor/text/tests/test_bug638596.html
@@ -13,16 +13,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=638596">Mozilla Bug 638596</a>
 <p id="display"></p>
 <div id="content">
   <input type="password" style="font-size: 0">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(1);
+}
+
 /** Test for Bug 638596 **/
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(function() {
   var i = document.querySelector("input");
   i.focus();
   synthesizeKey("t", {});
   synthesizeKey("e", {});
   synthesizeKey("s", {});
--- a/extensions/universalchardet/tests/test_bug426271-utf-8.html
+++ b/extensions/universalchardet/tests/test_bug426271-utf-8.html
@@ -15,16 +15,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426271">Mozilla Bug 426271</a>
 <p id="display"></p>
 <div id="content" style="display: none">  
 </div>
 <iframe id="testframe"></iframe>
 <pre id="test">
 <script class="testbody" type="text/javascript">
+SimpleTest.expectAssertions(6);
 /** Test for Bug 426271 **/
 CharsetDetectionTests("bug426271_text-utf-8.html",
 		      "UTF-8",
 		      new Array("ja_parallel_state_machine",
 				"zhtw_parallel_state_machine",
 				"zhcn_parallel_state_machine",
 				"zh_parallel_state_machine",
 				"cjk_parallel_state_machine",
--- a/gfx/cairo/cairo/src/cairo-qt-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-qt-surface.cpp
@@ -723,17 +723,17 @@ static void
 	QRegion qr;
 	int num_rects = cairo_region_num_rectangles (clip_region);
 	for (int i = 0; i < num_rects; ++i) {
 	    cairo_rectangle_int_t rect;
 
 	    cairo_region_get_rectangle (clip_region, i, &rect);
 
 	    QRect r(rect.x, rect.y, rect.width, rect.height);
-	    qr = qr.unite(r);
+	    qr = qr.united(r);
 	}
 
 	qs->p->setClipRegion (qr, Qt::IntersectClip);
     }
 }
 
 static cairo_int_status_t
 _cairo_qt_surface_set_clip (cairo_qt_surface_t *qs,
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -33,28 +33,33 @@ namespace layers {
 typedef nsTArray<SurfaceDescriptor> BufferArray; 
 typedef std::vector<Edit> EditVector;
 typedef std::set<ShadowableLayer*> ShadowableLayerSet;
 
 class Transaction
 {
 public:
   Transaction()
-    : mSwapRequired(false)
+    : mTargetRotation(ROTATION_0)
+    , mSwapRequired(false)
     , mOpen(false)
     , mRotationChanged(false)
   {}
 
   void Begin(const nsIntRect& aTargetBounds, ScreenRotation aRotation,
              const nsIntRect& aClientBounds, ScreenOrientation aOrientation)
   {
     mOpen = true;
     mTargetBounds = aTargetBounds;
     if (aRotation != mTargetRotation) {
-        mRotationChanged = true;
+      // the first time this is called, mRotationChanged will be false if
+      // aRotation is 0, but we should be OK because for the first transaction
+      // we should only compose if it is non-empty. See the caller(s) of
+      // RotationChanged.
+      mRotationChanged = true;
     }
     mTargetRotation = aRotation;
     mClientBounds = aClientBounds;
     mTargetOrientation = aOrientation;
   }
 
   void AddEdit(const Edit& aEdit)
   {
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1466,19 +1466,25 @@ public:
 
     // This is called by the default Draw() implementation above.
     virtual bool SetupCairoFont(gfxContext *aContext) = 0;
 
     virtual bool AllowSubpixelAA() { return true; }
 
     bool IsSyntheticBold() { return mApplySyntheticBold; }
 
-    // Amount by which synthetic bold "fattens" the glyphs: 1/16 of the em-size
+    // Amount by which synthetic bold "fattens" the glyphs:
+    // For size S up to a threshold size T, we use (0.25 + 3S / 4T),
+    // so that the result ranges from 0.25 to 1.0; thereafter,
+    // simply use (S / T).
     gfxFloat GetSyntheticBoldOffset() {
-        return GetAdjustedSize() * (1.0 / 16.0);
+        gfxFloat size = GetAdjustedSize();
+        const gfxFloat threshold = 48.0;
+        return size < threshold ? (0.25 + 0.75 * size / threshold) :
+                                  (size / threshold);
     }
 
     gfxFontEntry *GetFontEntry() { return mFontEntry.get(); }
     bool HasCharacter(uint32_t ch) {
         if (!mIsValid)
             return false;
         return mFontEntry->HasCharacter(ch); 
     }
--- a/gfx/thebes/gfxQtPlatform.cpp
+++ b/gfx/thebes/gfxQtPlatform.cpp
@@ -3,17 +3,18 @@
  * 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 <QPixmap>
 #include <qglobal.h>
 #if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
 #  include <QX11Info>
 #else
-#  include <QPlatformNativeInterface>
+#  include <qpa/qplatformnativeinterface.h>
+#  include <qpa/qplatformintegration.h>
 #endif
 #include <QApplication>
 #include <QDesktopWidget>
 #include <QPaintEngine>
 
 #include "gfxQtPlatform.h"
 
 #include "gfxFontconfigUtils.h"
--- a/intl/locale/src/nsLocaleService.cpp
+++ b/intl/locale/src/nsLocaleService.cpp
@@ -123,17 +123,17 @@ nsLocaleService::nsLocaleService(void)
     rv = NewLocale(xpLocale, getter_AddRefs(mApplicationLocale));
     NS_ENSURE_SUCCESS_VOID(rv);
 #endif
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
     nsRefPtr<nsLocale> resultLocale(new nsLocale());
     NS_ENSURE_TRUE_VOID(resultLocale);
 
 #ifdef MOZ_WIDGET_QT
-    const char* lang = QLocale::system().name().toAscii();
+    const char* lang = QLocale::system().name().toUtf8();
 #else
     // Get system configuration
     const char* lang = getenv("LANG");
 #endif
 
     nsAutoString xpLocale, platformLocale;
     nsAutoString category, category_platform;
     int i;
--- a/js/ipc/Makefile.in
+++ b/js/ipc/Makefile.in
@@ -9,16 +9,17 @@ VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = js
 LIBRARY_NAME = jsipc_s
 LIBXUL_LIBRARY = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
+FAIL_ON_WARNINGS = 1
 
 EXPORTS_NAMESPACES = mozilla/jsipc
 
 EXPORTS_mozilla/jsipc = \
   CPOWTypes.h \
   ContextWrapperChild.h \
   ContextWrapperParent.h \
   ObjectWrapperParent.h \
--- a/js/src/assembler/assembler/ARMAssembler.cpp
+++ b/js/src/assembler/assembler/ARMAssembler.cpp
@@ -322,29 +322,38 @@ void ARMAssembler::dataTransferN(bool is
         moveImm(offset, ARMRegisters::S0);
         mem_reg_off(isLoad, isSigned, size, posOffset, rt, base, ARMRegisters::S0);
         return;
     }
     if (offset < 0) {
         offset = - offset;
         posOffset = false;
     }
-    if (offset <= 0xfff) {
+
+    // max_ldr is also a mask.
+    int max_ldr = 0xfff;
+    int ldr_bits = 12;
+    if (size == 16 || (size == 8 && isSigned)) {
+        max_ldr = 0xff;
+        ldr_bits = 8;
+    }
+
+    if (offset <= max_ldr) {
         // LDR rd, [rb, #+offset]
         mem_imm_off(isLoad, isSigned, size, posOffset, rt, base, offset);
-    } else if (offset <= 0xfffff) {
+    } else if (offset <= ((max_ldr << 8) | 0xff)) {
         // Add upper bits of offset to the base, and store the result into the temp register.
         if (posOffset) {
-            add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | getOp2RotLSL(12));
+            add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> ldr_bits) | getOp2RotLSL(ldr_bits));
         } else {
-            sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | getOp2RotLSL(12));
+            sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> ldr_bits) | getOp2RotLSL(ldr_bits));
         }
-        // Load using the lower bits of the offset.
+        // Load using the lower bits of the offset, using max_ldr as a mask.
         mem_imm_off(isLoad, isSigned, size, posOffset, rt,
-                    ARMRegisters::S0, (offset & 0xfff));
+                    ARMRegisters::S0, (offset & max_ldr));
     } else {
         // For even bigger offsets, load the entire offset into a register, then do an
         // indexed load using the base register and the index register.
         moveImm(offset, ARMRegisters::S0);
         mem_reg_off(isLoad, isSigned, size, posOffset, rt, base, ARMRegisters::S0);
     }
 }
 
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -3232,24 +3232,22 @@ IonBuilder::makeInliningDecision(AutoObj
     //  3. Do not inline functions which are not called as frequently as their
     //     callers.
 
     uint32_t callerUses = script()->getUseCount();
 
     uint32_t totalSize = 0;
     uint32_t maxInlineDepth = js_IonOptions.maxInlineDepth;
     bool allFunctionsAreSmall = true;
-    RootedFunction target(cx);
-    RootedScript targetScript(cx);
     for (size_t i = 0; i < targets.length(); i++) {
-        target = targets[i]->toFunction();
+        JSFunction *target = targets[i]->toFunction();
         if (!target->isInterpreted())
             return false;
 
-        targetScript = target->nonLazyScript();
+        JSScript *targetScript = target->nonLazyScript();
         uint32_t calleeUses = targetScript->getUseCount();
 
         totalSize += targetScript->length;
         if (totalSize > js_IonOptions.inlineMaxTotalBytecodeLength)
             return false;
 
         if (targetScript->length > js_IonOptions.smallFunctionMaxBytecodeLength)
             allFunctionsAreSmall = false;
@@ -3276,16 +3274,17 @@ IonBuilder::makeInliningDecision(AutoObj
     if (!oracle->canInlineCall(scriptRoot, pc)) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to uninlineable call site");
         return false;
     }
 
     JSOp op = JSOp(*pc);
     for (size_t i = 0; i < targets.length(); i++) {
         JSFunction *target = targets[i]->toFunction();
+        JSScript *targetScript = target->nonLazyScript();
 
         if (!canInlineTarget(target)) {
             IonSpew(IonSpew_Inlining, "Decided not to inline");
             return false;
         }
 
         // For fun.apply we need to make sure the types of the argument is a subset
         // of the types used in the callee. Because adding a typeset in the callee,
--- a/js/src/ion/LICM.cpp
+++ b/js/src/ion/LICM.cpp
@@ -31,17 +31,17 @@ LICM::analyze()
     for (ReversePostorderIterator i(graph.rpoBegin()); i != graph.rpoEnd(); i++) {
         MBasicBlock *header = *i;
 
         // Skip non-headers and self-loops.
         if (!header->isLoopHeader() || header->numPredecessors() < 2)
             continue;
 
         // Attempt to optimize loop.
-        Loop loop(mir, header->backedge(), header, graph);
+        Loop loop(mir, header->backedge(), header);
 
         Loop::LoopReturn lr = loop.init();
         if (lr == Loop::LoopReturn_Error)
             return false;
         if (lr == Loop::LoopReturn_Skip) {
             graph.unmarkBlocks();
             continue;
         }
@@ -50,19 +50,18 @@ LICM::analyze()
             return false;
 
         graph.unmarkBlocks();
     }
 
     return true;
 }
 
-Loop::Loop(MIRGenerator *mir, MBasicBlock *footer, MBasicBlock *header, MIRGraph &graph)
+Loop::Loop(MIRGenerator *mir, MBasicBlock *footer, MBasicBlock *header)
   : mir(mir),
-    graph(graph),
     footer_(footer),
     header_(header)
 {
     preLoop_ = header_->getPredecessor(0);
 }
 
 Loop::LoopReturn
 Loop::init()
--- a/js/src/ion/LICM.h
+++ b/js/src/ion/LICM.h
@@ -31,29 +31,28 @@ class LICM
   public:
     LICM(MIRGenerator *mir, MIRGraph &graph);
     bool analyze();
 };
 
 class Loop
 {
     MIRGenerator *mir;
-    MIRGraph &graph;
 
   public:
     // Loop code may return three values:
     enum LoopReturn {
         LoopReturn_Success,
         LoopReturn_Error, // Compilation failure.
         LoopReturn_Skip   // The loop is not suitable for LICM, but there is no error.
     };
 
   public:
     // A loop is constructed on a backedge found in the control flow graph.
-    Loop(MIRGenerator *mir, MBasicBlock *header, MBasicBlock *footer, MIRGraph &graph);
+    Loop(MIRGenerator *mir, MBasicBlock *header, MBasicBlock *footer);
 
     // Initializes the loop, finds all blocks and instructions contained in the loop.
     LoopReturn init();
 
     // Identifies hoistable loop invariant instructions and moves them out of the loop.
     bool optimize();
 
   private:
--- a/js/src/ion/TypeOracle.cpp
+++ b/js/src/ion/TypeOracle.cpp
@@ -598,19 +598,21 @@ TypeInferenceOracle::callArgsBarrier(Han
 }
 
 bool
 TypeInferenceOracle::canEnterInlinedFunction(RawScript caller, jsbytecode *pc, RawFunction target)
 {
     AssertCanGC();
     RootedScript targetScript(cx, target->nonLazyScript());
 
-    // Always permit the empty script.
-    if (targetScript->length == 1)
-        return true;
+    // Make sure empty script has type information, to allow inlining in more cases.
+    if (targetScript->length == 1) {
+        if (!targetScript->ensureRanInference(cx))
+            return false;
+    }
 
     if (!targetScript->hasAnalysis() ||
         !targetScript->analysis()->ranInference() ||
         !targetScript->analysis()->ranSSA())
     {
         return false;
     }
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug842482.js
@@ -0,0 +1,2 @@
+var g = newGlobal();
+new g.DataView(new g.ArrayBuffer());
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug843866.js
@@ -0,0 +1,8 @@
+function g(f) {}
+function f(b) {
+  g.apply(null, arguments);
+
+  if (b < 10)
+    f(b+1);
+}
+f(0);
--- a/js/src/jstypedarrayinlines.h
+++ b/js/src/jstypedarrayinlines.h
@@ -208,20 +208,22 @@ InitTypedArrayDataPointer(JSObject *obj,
     if (obj->runtime()->gcNursery.isInside(buffer))
         obj->runtime()->gcStoreBuffer.putGeneric(TypedArrayPrivateRef(obj, buffer, byteOffset));
 #endif
 }
 
 static NewObjectKind
 DataViewNewObjectKind(JSContext *cx, uint32_t byteLength, JSObject *proto)
 {
+    if (!proto && byteLength >= TypedArray::SINGLETON_TYPE_BYTE_LENGTH)
+        return SingletonObject;
     jsbytecode *pc;
     JSScript *script = cx->stack.currentScript(&pc);
-    if (!proto && byteLength >= TypedArray::SINGLETON_TYPE_BYTE_LENGTH)
-        return SingletonObject;
+    if (!script)
+        return GenericObject;
     return types::UseNewTypeForInitializer(cx, script, pc, &DataViewClass);
 }
 
 inline DataViewObject *
 DataViewObject::create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength,
                        Handle<ArrayBufferObject*> arrayBuffer, JSObject *protoArg)
 {
     JS_ASSERT(byteOffset <= INT32_MAX);
--- a/js/xpconnect/src/dictionary_helper_gen.py
+++ b/js/xpconnect/src/dictionary_helper_gen.py
@@ -1,64 +1,42 @@
 #!/usr/bin/env python
 # header.py - Generate C++ header files from IDL.
 #
 # 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/.
 
-import sys, os, xpidl
-
-# --makedepend-output support.
-make_dependencies = []
-make_targets = []
+import sys, os, xpidl, makeutils
 
 def strip_begin(text, suffix):
     if not text.startswith(suffix):
         return text
     return text[len(suffix):]
 
 def strip_end(text, suffix):
     if not text.endswith(suffix):
         return text
     return text[:-len(suffix)]
 
-# Copied from dombindingsgen.py
-def makeQuote(filename):
-    return filename.replace(' ', '\\ ')  # enjoy!
-
-def writeMakeDependOutput(filename):
-    print "Creating makedepend file", filename
-    f = open(filename, 'w')
-    try:
-        if len(make_targets) > 0:
-            f.write("%s:" % makeQuote(make_targets[0]))
-            for filename in make_dependencies:
-                f.write(' \\\n\t\t%s' % makeQuote(filename))
-            f.write('\n\n')
-            for filename in make_targets[1:]:
-                f.write('%s: %s\n' % (makeQuote(filename), makeQuote(make_targets[0])))
-    finally:
-        f.close()
-
 def findIDL(includePath, interfaceFileName):
     for d in includePath:
         # Not os.path.join: we need a forward slash even on Windows because
         # this filename ends up in makedepend output.
         path = d + '/' + interfaceFileName
         if os.path.exists(path):
             return path
     raise BaseException("No IDL file found for interface %s "
                         "in include path %r"
                         % (interfaceFileName, includePath))
 
 def loadIDL(parser, includePath, filename):
     idlFile = findIDL(includePath, filename)
-    if not idlFile in make_dependencies:
-        make_dependencies.append(idlFile)
+    if not idlFile in makeutils.dependencies:
+        makeutils.dependencies.append(idlFile)
     idl = p.parse(open(idlFile).read(), idlFile)
     idl.resolve(includePath, p)
     return idl
 
 class Configuration:
     def __init__(self, filename):
         config = {}
         execfile(filename, config)
@@ -475,15 +453,15 @@ if __name__ == '__main__':
             conf.dictionaries.append([eventdict, eventidl]);
 
 
     if options.header_output is not None:
         outfd = open(options.header_output, 'w')
         print_header_file(outfd, conf)
         outfd.close()
     if options.stub_output is not None:
-        make_targets.append(options.stub_output)
+        makeutils.targets.append(options.stub_output)
         outfd = open(options.stub_output, 'w')
         print_cpp_file(outfd, conf)
         outfd.close()
         if options.makedepend_output is not None:
-            writeMakeDependOutput(options.makedepend_output)
+            makeutils.writeMakeDependOutput(options.makedepend_output)
 
--- a/js/xpconnect/src/event_impl_gen.py
+++ b/js/xpconnect/src/event_impl_gen.py
@@ -1,68 +1,46 @@
 #!/usr/bin/env python
 # header.py - Generate C++ header files from IDL.
 #
 # 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/.
 
-import sys, os, xpidl
-
-# --makedepend-output support.
-make_dependencies = []
-make_targets = []
+import sys, os, xpidl, makeutils
 
 def strip_end(text, suffix):
     if not text.endswith(suffix):
         return text
     return text[:-len(suffix)]
 
-# Copied from dombindingsgen.py
-def makeQuote(filename):
-    return filename.replace(' ', '\\ ')  # enjoy!
-
-def writeMakeDependOutput(filename):
-    print "Creating makedepend file", filename
-    f = open(filename, 'w')
-    try:
-        if len(make_targets) > 0:
-            f.write("%s:" % makeQuote(make_targets[0]))
-            for filename in make_dependencies:
-                f.write(' \\\n\t\t%s' % makeQuote(filename))
-            f.write('\n\n')
-            for filename in make_targets[1:]:
-                f.write('%s: %s\n' % (makeQuote(filename), makeQuote(make_targets[0])))
-    finally:
-        f.close()
-
 def findIDL(includePath, interfaceFileName):
     for d in includePath:
         # Not os.path.join: we need a forward slash even on Windows because
         # this filename ends up in makedepend output.
         path = d + '/' + interfaceFileName
         if os.path.exists(path):
             return path
     raise BaseException("No IDL file found for interface %s "
                         "in include path %r"
                         % (interfaceFileName, includePath))
 
 def loadIDL(parser, includePath, filename):
     idlFile = findIDL(includePath, filename)
-    if not idlFile in make_dependencies:
-        make_dependencies.append(idlFile)
+    if not idlFile in makeutils.dependencies:
+        makeutils.dependencies.append(idlFile)
     idl = p.parse(open(idlFile).read(), idlFile)
     idl.resolve(includePath, p)
     return idl
 
 def loadEventIDL(parser, includePath, eventname):
     eventidl = ("nsIDOM%s.idl" % eventname)
     idlFile = findIDL(includePath, eventidl)
-    if not idlFile in make_dependencies:
-        make_dependencies.append(idlFile)
+    if not idlFile in makeutils.dependencies:
+        makeutils.dependencies.append(idlFile)
     idl = p.parse(open(idlFile).read(), idlFile)
     idl.resolve(includePath, p)
     return idl
 
 class Configuration:
     def __init__(self, filename):
         config = {}
         execfile(filename, config)
@@ -360,19 +338,19 @@ if __name__ == '__main__':
         sys.path.append(options.cachedir)
 
     # Instantiate the parser.
     p = xpidl.IDLParser(outputdir=options.cachedir)
 
     conf = readConfigFile(filename)
 
     if options.stub_output is not None:
-        make_targets.append(options.stub_output)
+        makeutils.targets.append(options.stub_output)
         outfd = open(options.stub_output, 'w')
         print_cpp_file(outfd, conf)
         outfd.close()
         if options.makedepend_output is not None:
-            writeMakeDependOutput(options.makedepend_output)
+            makeutils.writeMakeDependOutput(options.makedepend_output)
     if options.header_output is not None:
         outfd = open(options.header_output, 'w')
         print_header_file(outfd, conf)
         outfd.close()
 
--- a/js/xpconnect/src/qsgen.py
+++ b/js/xpconnect/src/qsgen.py
@@ -79,25 +79,22 @@
 #   an opportunity to veto accesses to members for which quick stubs exist.
 #
 # - There are many features of IDL that XPConnect supports but qsgen does not,
 #   including dependent types, arrays, and out parameters.
 
 
 import xpidl
 import header
+import makeutils
 import os, re
 import sys
 
 # === Preliminaries
 
-# --makedepend-output support.
-make_dependencies = []
-make_targets = []
-
 def warn(msg):
     sys.stderr.write(msg + '\n')
 
 def unaliasType(t):
     while t.kind == 'typedef':
         t = t.realtype
     assert t is not None
     return t
@@ -145,17 +142,17 @@ def findIDL(includePath, irregularFilena
         path = d + '/' + filename
         if os.path.exists(path):
             return path
     raise UserError("No IDL file found for interface %s "
                     "in include path %r"
                     % (interfaceName, includePath))
 
 def loadIDL(parser, includePath, filename):
-    make_dependencies.append(filename)
+    makeutils.dependencies.append(filename)
     text = open(filename, 'r').read()
     idl = parser.parse(text, filename=filename)
     idl.resolve(includePath, parser)
     return idl
 
 def removeStubMember(memberId, member):
     if member not in member.iface.stubMembers:
         raise UserError("Trying to remove member %s from interface %s, but it was never added"
@@ -1239,17 +1236,17 @@ stubTopTemplate = '''\
 #include "xpcprivate.h"  // for XPCCallContext
 #include "XPCQuickStubs.h"
 #include "nsWrapperCacheInlines.h"
 #include <algorithm>
 '''
 
 def writeStubFile(filename, headerFilename, conf, interfaces):
     print "Creating stub file", filename
-    make_targets.append(filename)
+    makeutils.targets.append(filename)
 
     f = open(filename, 'w')
     filesIncluded = set()
 
     def includeType(type):
         type = unaliasType(type)
         if type.kind in ('builtin', 'native'):
             return None
@@ -1291,33 +1288,16 @@ def writeStubFile(filename, headerFilena
         writeResultXPCInterfacesArray(f, conf, frozenset(resulttypes))
         stringtable = StringTable()
         for iface in interfaces:
             writeStubsForInterface(f, conf.customMethodCalls, stringtable, iface)
         writeDefiner(f, conf, stringtable, interfaces)
     finally:
         f.close()
 
-def makeQuote(filename):
-    return filename.replace(' ', '\\ ')  # enjoy!
-
-def writeMakeDependOutput(filename):
-    print "Creating makedepend file", filename
-    f = open(filename, 'w')
-    try:
-        if len(make_targets) > 0:
-            f.write("%s:" % makeQuote(make_targets[0]))
-            for filename in make_dependencies:
-                f.write(' \\\n\t\t%s' % makeQuote(filename))
-            f.write('\n\n')
-            for filename in make_targets[1:]:
-                f.write('%s: %s\n' % (makeQuote(filename), makeQuote(make_targets[0])))
-    finally:
-        f.close()
-
 def main():
     from optparse import OptionParser
     o = OptionParser(usage="usage: %prog [options] configfile")
     o.add_option('-o', "--stub-output",
                  type='string', dest='stub_output', default=None,
                  help="Quick stub C++ source output file", metavar="FILE")
     o.add_option('--header-output', type='string', default=None,
                  help="Quick stub header output file", metavar="FILE")
@@ -1354,17 +1334,17 @@ def main():
         includePath = options.idlpath.split(':')
         conf, interfaces = readConfigFile(filename,
                                           includePath=includePath,
                                           cachedir=options.cachedir)
         writeStubFile(options.stub_output, options.header_output,
                       conf, interfaces)
         writeHeaderFile(options.header_output, conf.name)
         if options.makedepend_output is not None:
-            writeMakeDependOutput(options.makedepend_output)
+            makeutils.writeMakeDependOutput(options.makedepend_output)
     except Exception, exc:
         if options.verbose_errors:
             raise
         elif isinstance(exc, (UserError, xpidl.IDLError)):
             warn(str(exc))
         elif isinstance(exc, OSError):
             warn("%s: %s" % (exc.__class__.__name__, exc))
         else:
--- a/js/xpconnect/tests/chrome/test_bug503926.xul
+++ b/js/xpconnect/tests/chrome/test_bug503926.xul
@@ -16,16 +16,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   <iframe id="ifr" type="content" onload="iframe_loaded()" src="bug503926.xul#iframe"/>
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
 
+  SimpleTest.expectAssertions(1);
+
   /** Test for Bug 503926 **/
   function iframe_loaded() {
     var gWindowUtils  = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
                                getInterface(Components.interfaces.nsIDOMWindowUtils);
     var passed = false;
     var obj = { QueryInterface: function() { passed = true; } };
     try { gWindowUtils.dispatchDOMEventViaPresShell(obj, obj, false); } catch (e) {}
     ok(passed, "trusted QIs should be called");
--- a/js/xpconnect/tests/mochitest/test_bug393269.html
+++ b/js/xpconnect/tests/mochitest/test_bug393269.html
@@ -8,16 +8,23 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=393269">Mozilla Bug 393269</a>
 <iframe id="ifr"></iframe>
 <pre id="test">
 <script class="testbody" type="text/javascript">
+
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(1, 2);
+} else {
+  SimpleTest.expectAssertions(2);
+}
+
 (function () {
     /** Test for Bug 393269 **/
     var doc = $("ifr").contentDocument;
     is("UTF-8", doc.characterSet, "control, getting a property");
     doc.open();
     try {
         is("UTF-8", doc.characterSet,
            "can get a property after 1 document.open")
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -6625,26 +6625,27 @@ PresShell::HandleEventInternal(nsEvent* 
       case NS_KEY_UP: {
         nsIDocument *doc = mCurrentEventContent ?
                            mCurrentEventContent->OwnerDoc() : nullptr;
         nsIDocument* root = nullptr;
         if (static_cast<const nsKeyEvent*>(aEvent)->keyCode == NS_VK_ESCAPE &&
             (root = nsContentUtils::GetRootDocument(doc)) &&
             root->IsFullScreenDoc()) {
           // Prevent default action on ESC key press when exiting
-          // DOM full-screen mode. This prevents the browser ESC key
+          // DOM fullscreen mode. This prevents the browser ESC key
           // handler from stopping all loads in the document, which
           // would cause <video> loads to stop.
           aEvent->mFlags.mDefaultPrevented = true;
           aEvent->mFlags.mOnlyChromeDispatch = true;
 
           if (aEvent->message == NS_KEY_UP) {
-             // ESC key released while in DOM full-screen mode.
-             // Exit full-screen mode.
-            nsIDocument::ExitFullScreen(true);
+            // ESC key released while in DOM fullscreen mode.
+            // Fully exit all browser windows and documents from
+            // fullscreen mode.
+            nsIDocument::ExitFullscreen(nullptr, /* async */ true);
           }
         }
         // Else not full-screen mode or key code is unrestricted, fall
         // through to normal handling.
       }
       case NS_MOUSE_BUTTON_DOWN:
       case NS_MOUSE_BUTTON_UP:
         isHandlingUserInput = true;
--- a/layout/base/tests/chrome/test_bug495648.xul
+++ b/layout/base/tests/chrome/test_bug495648.xul
@@ -12,16 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <body xmlns="http://www.w3.org/1999/xhtml">
   <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=495648"
      target="_blank">Mozilla Bug 495648</a>
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
+  SimpleTest.expectAssertions(18, 24);
+
   /** Test for Bug 495648 **/
   var uri = window.location.href.replace(/test_bug495648.xul/, "bug495648.rdf");
 
   function doTest() {
     var list = document.getElementById('l');
     var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
     var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
     var rdf = rdfService.GetDataSourceBlocking(uri);
--- a/layout/base/tests/chrome/test_printpreview.xul
+++ b/layout/base/tests/chrome/test_printpreview.xul
@@ -5,12 +5,15 @@
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 <body xmlns="http://www.w3.org/1999/xhtml">
 </body>
   <!-- test code goes here -->
 <script type="application/javascript">
 <![CDATA[
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
 SimpleTest.waitForExplicitFinish();
 window.open("printpreview_helper.xul", "printpreview", "chrome,width=100,height=100");
 ]]></script>
 </window>
--- a/layout/base/tests/chrome/test_printpreview_bug396024.xul
+++ b/layout/base/tests/chrome/test_printpreview_bug396024.xul
@@ -11,12 +11,15 @@ https://bugzilla.mozilla.org/show_bug.cg
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 <body xmlns="http://www.w3.org/1999/xhtml">
 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=396024"
    target="_blank">Mozilla Bug 396024</a>
 </body>
   <!-- test code goes here -->
 <script type="application/javascript">
 <![CDATA[
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
 SimpleTest.waitForExplicitFinish();
 window.open("printpreview_bug396024_helper.xul", "bug396024", "chrome,width=100,height=100");
 ]]></script>
 </window>
--- a/layout/base/tests/chrome/test_transformed_scrolling_repaints.html
+++ b/layout/base/tests/chrome/test_transformed_scrolling_repaints.html
@@ -10,16 +10,19 @@
 <body onload="setTimeout(startTest,0)">
 <div id="t" style="-moz-transform: scale(1.2, 1.2); -moz-transform-origin:top left; width:200px; height:100px; background:yellow; overflow:hidden">
   <div style="height:40px;">Hello</div>
   <div id="e" style="height:30px; background:lime">Kitty</div>
   <div style="height:300px; background:yellow">Kitty</div>
 </div>
 <pre id="test">
 <script type="application/javascript">
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
 SimpleTest.waitForExplicitFinish();
 
 var t = document.getElementById("t");
 var e = document.getElementById("e");
 var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
                getInterface(Components.interfaces.nsIDOMWindowUtils);
 const isLinux = navigator.platform.indexOf("Linux") >= 0;
 const is64 = navigator.platform.indexOf("x86_64") >= 0;
--- a/layout/base/tests/test_bug93077-6.html
+++ b/layout/base/tests/test_bug93077-6.html
@@ -15,16 +15,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=93077">Mozilla Bug 93077</a>
 <p id="display"></p>
 <div id=filler>...</div>
 <p id=below></p>
 <p><a name=TOP>Top</a></p>
 <pre id="test">
 <script type="application/javascript">
+
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 93077 **/
 ["#top", "#Top"].forEach(function(fragid) {
   document.getElementById("below").scrollIntoView()
   isnot(window.scrollY, 0)
   location.hash = fragid
   is(window.scrollY, 0)
 })
 location.hash = "#TOP"
--- a/layout/base/tests/test_image_layers.html
+++ b/layout/base/tests/test_image_layers.html
@@ -6,16 +6,20 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body onload="changeImage()">
 <div>
 <img id="image" src="./image_rgrg-256x256.png" style="-moz-transform: translatex(1px)"></img>
 </div>
 <pre id="test">
 <script type="application/javascript">
+if (navigator.platform.indexOf("Linux") != 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var image = document.getElementById("image");
 var lastPaintCount;
 
 function changeImage() {
   lastPaintCount = window.mozPaintCount;
   
--- a/layout/base/tests/test_mozPaintCount.html
+++ b/layout/base/tests/test_mozPaintCount.html
@@ -11,16 +11,20 @@
        drawmode="solid" color="FF00FF00"></embed>
 </p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var startPaintCount = window.mozPaintCount;
 ok(true, "Got to initial paint count: " + startPaintCount);
 var color = 0;
 
 function doPluginFlicker() {
   ok(true, "Plugin color iteration " + color + ", paint count: " + window.mozPaintCount);
--- a/layout/base/tests/test_reftests_with_caret.html
+++ b/layout/base/tests/test_reftests_with_caret.html
@@ -9,16 +9,20 @@
   <style>
     iframe {
       width: 600px;
       height: 600px;
     }
   </style>
 <script type="text/javascript">
 
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var canvases = [];
 function callbackTestCanvas(canvas)
 {
   canvases.push(canvas);
 
   if (canvases.length != 2)
--- a/layout/base/tests/test_scroll_selection_into_view.html
+++ b/layout/base/tests/test_scroll_selection_into_view.html
@@ -62,16 +62,20 @@
     <div style="height:800px;"></div>
   </div>
   <div style="height:800px;"></div>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 var ANCHOR = 0;
 var FOCUS = 1;
 
 function testCollapsed(id, vPercent, startAt, expected) {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   var selection = window.getSelection().QueryInterface(Components.interfaces.nsISelectionPrivate);
 
   var c = document.getElementById("c" + id);
--- a/layout/forms/test/test_bug536567_perwindowpb.html
+++ b/layout/forms/test/test_bug536567_perwindowpb.html
@@ -10,16 +10,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=536567">Mozilla Bug 536567</a>
 <p id="display"></p>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Mac") != 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 /** Test for Bug 536567 **/
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cm = Components.manager;
 
 Cu.import("resource://gre/modules/Services.jsm");
--- a/layout/forms/test/test_bug665540.html
+++ b/layout/forms/test/test_bug665540.html
@@ -13,16 +13,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=665540">Mozilla Bug 665540</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 /** Test for Bug 665540 **/
 
 SimpleTest.waitForExplicitFinish();
 
 var win;
 var select;
 var optiona;
 var eventType = "mouseover";
--- a/layout/generic/test/test_bug394239.html
+++ b/layout/generic/test/test_bug394239.html
@@ -21,16 +21,19 @@ https://bugzilla.mozilla.org/show_bug.cg
   <div style="position: absolute;">
     <span style="position: fixed;">t</span>
   </div>
  </object>
 </div>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=394239">Mozilla Bug 394239</a>
 <pre id="test">
 <script class="testbody" type="text/javascript">
+
+SimpleTest.expectAssertions(1);
+
 /** Test for Bug 394239 **/
 function test()
 {
   $("a").style.direction="rtl";
   ok(true, "Should not crash");
   SimpleTest.finish();
 }
   setTimeout(test, 500);
--- a/layout/generic/test/test_bug469613.xul
+++ b/layout/generic/test/test_bug469613.xul
@@ -19,16 +19,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 </body>
 
 <vbox style="height: 100px; overflow: auto;" id="scrollbox">
   <hbox style="height: 200px;"/>
 </vbox>
 
 <script class="testbody" type="application/javascript;version=1.7"><![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 /** Test for Bug 469613 **/
 
 function doTest() {
   let scrollbox = document.getElementById("scrollbox");
   scrollbox.scrollTop = 0;
 
   // Make sure that the "scroll focus" is inside the scrollbox by moving the
   // mouse in the scrollbox.
--- a/layout/generic/test/test_bug469774.xul
+++ b/layout/generic/test/test_bug469774.xul
@@ -22,16 +22,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 </body>
 
 <script class="testbody" type="application/javascript;version=1.7"><![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 /** Test for Bug 469774 **/
 
 // Test whether menu popups are blocked from being painted in their parent window.
 
 // Like snapshotWindow, but with DRAWWINDOW_DRAW_CARET
 function snapShot() {
   var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
   canvas.setAttribute("width", 200);
--- a/layout/generic/test/test_bug508115.xul
+++ b/layout/generic/test/test_bug508115.xul
@@ -15,16 +15,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body  xmlns="http://www.w3.org/1999/xhtml">
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=508115">Mozilla Bug 508115</a>
 
   <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 </body>
 <script class="testbody" type="application/javascript"><![CDATA[
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 function doTest() {
   document.getElementById("panel").style.display = '';
   document.getElementById("deck").selectedIndex = 1;
   document.getElementById("anchor").open = true;
   document.getElementById("container").style.width = "0";
   document.getElementById("anchor2").open = true;
 }
 var count = 0;
--- a/layout/generic/test/test_bug514732-2.xul
+++ b/layout/generic/test/test_bug514732-2.xul
@@ -25,16 +25,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 /** Test for Bug 514732 **/
 
 SimpleTest.waitForExplicitFinish();
 window.open("file_bug514732_window.xul", "bug514732",
             "chrome,width=600,height=600,scrollbars");
 
 ]]>
 </script>
--- a/layout/generic/test/test_bug632379.xul
+++ b/layout/generic/test/test_bug632379.xul
@@ -161,16 +161,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 </body>
 
 
 <script class="testbody" type="application/javascript"><![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 632379 **/
 // Tests whether scrolling a menu affects the position at which popups appear
 var pos = new Array(2);
 var count=0;
 
 function snapshot(elem)
 {
     pos[count] = elem.getBoundingClientRect().top;
--- a/layout/generic/test/test_selection_underline.html
+++ b/layout/generic/test/test_selection_underline.html
@@ -3,16 +3,22 @@
 <head>
   <title>Test for selection underline</title>
   <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
 <script type="text/javascript">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 // Canvas related code stolen from layout/base/tests/bidi_numeral_test.js which
 // stole from http://developer.mozilla.org/en/docs/Code_snippets:Canvas
 
 var RemoteCanvas = function(aIFrame, aTest) {
   this.iframe = aIFrame;
   this.test = aTest;
   this.snapshot = null;
 };
--- a/layout/mathml/tests/test_bug553917.html
+++ b/layout/mathml/tests/test_bug553917.html
@@ -4,16 +4,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 -->
 <html>
   <head>
     <title>Test for Bug 553917</title>
     <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
     <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
     <script type="application/javascript">
+      SimpleTest.expectAssertions(204);
+
       var stringBundleService = 
         SpecialPowers.Cc["@mozilla.org/intl/stringbundle;1"]
                     .getService(SpecialPowers.Ci.nsIStringBundleService);
       var g_bundl =
         stringBundleService.createBundle("chrome://global/locale/mathml/mathml.properties");
       
       var g_errorInfo = {
       /*<math><mroot></mroot></math>
--- a/layout/style/AnimationCommon.h
+++ b/layout/style/AnimationCommon.h
@@ -130,16 +130,17 @@ private:
 
 struct CommonElementAnimationData : public PRCList
 {
   CommonElementAnimationData(dom::Element *aElement, nsIAtom *aElementProperty,
                              CommonAnimationManager *aManager)
     : mElement(aElement)
     , mElementProperty(aElementProperty)
     , mManager(aManager)
+    , mAnimationGeneration(0)
 #ifdef DEBUG
     , mCalledPropertyDtor(false)
 #endif
   {
     MOZ_COUNT_CTOR(CommonElementAnimationData);
     PR_INIT_CLIST(this);
   }
   ~CommonElementAnimationData()
--- a/layout/style/test/test_pointer-events.html
+++ b/layout/style/test/test_pointer-events.html
@@ -45,16 +45,22 @@
     iframe.contentDocument.writeln("<"+"/script>");
     iframe.contentDocument.close();
   </script>
 
 </div>
 <pre id="test">
 <script type="application/javascript;version=1.8">
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+} else {
+  SimpleTest.expectAssertions(1);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 function catches_pointer_events(element_id)
 {
     // we just assume the element is on top here.
     var element = document.getElementById(element_id);
     var bounds = element.getBoundingClientRect();
     var point = { x: bounds.left + bounds.width/2, y: bounds.top + bounds.height/2 };
--- a/layout/style/test/test_value_computation.html
+++ b/layout/style/test/test_value_computation.html
@@ -8,16 +8,17 @@
   <script type="text/javascript" src="property_database.js"></script>
   <style type="text/css" id="stylesheet"></style>
   <style type="text/css">
   /* For 'width', 'height', etc., need a constant size container. */
   #display { width: 500px; height: 200px }
   </style>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript">
+  SimpleTest.expectAssertions(7);
   SimpleTest.waitForExplicitFinish();
 
   var load_count = 0;
   function load_done() {
     if (++load_count == 3)
       run_tests();
   }
   </script>
--- a/layout/xul/base/src/crashtests/crashtests.list
+++ b/layout/xul/base/src/crashtests/crashtests.list
@@ -42,17 +42,17 @@ load 383236-1.xul
 load 384037-1.xhtml
 load 384105-1.html
 load 384491-1.xhtml
 load 384871-1.html
 load 387033-1.xhtml
 load 387080-1.xul
 load 391974-1.html
 load 394120-1.xhtml
-skip-if(B2G) load 395609.xul # bug 844549
+skip-if(B2G||browserIsRemote) load 395609.xul # bug 844549
 load 397304-1.html
 load 398326-1.xhtml
 load 399013.xul
 load 400779-1.xhtml
 load 402912-1.xhtml
 load 408904-1.xul
 load 412479-1.xhtml
 asserts(4) load 415394-1.xhtml # Bug 163838
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -273,18 +273,16 @@
 @BINPATH@/components/fuelApplication.manifest
 @BINPATH@/components/fuelApplication.js
 @BINPATH@/components/WebContentConverter.js
 @BINPATH@/components/BrowserComponents.manifest
 @BINPATH@/components/nsBrowserContentHandler.js
 @BINPATH@/components/nsBrowserGlue.js
 @BINPATH@/components/nsSetDefaultBrowser.manifest
 @BINPATH@/components/nsSetDefaultBrowser.js
-@BINPATH@/components/nsPrivateBrowsingService.manifest
-@BINPATH@/components/nsPrivateBrowsingService.js
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsSearchService.js
 @BINPATH@/components/nsSearchSuggestions.js
 @BINPATH@/components/passwordmgr.manifest
 @BINPATH@/components/nsLoginInfo.js
 @BINPATH@/components/nsLoginManager.js
 @BINPATH@/components/nsLoginManagerPrompter.js
 @BINPATH@/components/SiteSpecificUserAgent.js
--- a/mobile/xul/installer/package-manifest.in
+++ b/mobile/xul/installer/package-manifest.in
@@ -315,18 +315,16 @@
 @BINPATH@/components/fuelApplication.js
 @BINPATH@/components/WebContentConverter.js
 @BINPATH@/components/BrowserComponents.manifest
 @BINPATH@/components/nsBrowserContentHandler.js
 @BINPATH@/components/nsBrowserGlue.js
 @BINPATH@/components/nsSetDefaultBrowser.manifest
 @BINPATH@/components/nsSetDefaultBrowser.js
 @BINPATH@/components/BrowserPlaces.manifest
-@BINPATH@/components/nsPrivateBrowsingService.manifest
-@BINPATH@/components/nsPrivateBrowsingService.js
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsSearchService.js
 @BINPATH@/components/nsSearchSuggestions.js
 @BINPATH@/components/passwordmgr.manifest
 @BINPATH@/components/nsLoginInfo.js
 @BINPATH@/components/nsLoginManager.js
 @BINPATH@/components/nsLoginManagerPrompter.js
 @BINPATH@/components/SiteSpecificUserAgent.js
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3977,17 +3977,16 @@ pref("network.buffer.cache.size",  32768
 pref("notification.feature.enabled", false);
 
 // Alert animation effect, name is disableSlidingEffect for backwards-compat.
 pref("alerts.disableSlidingEffect", false);
 
 // DOM full-screen API.
 pref("full-screen-api.enabled", false);
 pref("full-screen-api.allow-trusted-requests-only", true);
-pref("full-screen-api.exit-on-deactivate", true);
 pref("full-screen-api.pointer-lock.enabled", true);
 
 // DOM idle observers API
 pref("dom.idle-observers-api.enabled", true);
 
 // Time limit, in milliseconds, for nsEventStateManager::IsHandlingUserInput().
 // Used to detect long running handlers of user-generated events.
 pref("dom.event.handling-user-input-time-limit", 1000);
--- a/netwerk/base/public/Makefile.in
+++ b/netwerk/base/public/Makefile.in
@@ -57,17 +57,16 @@ XPIDLSRCS	= \
 		nsIInputStreamChannel.idl \
 		nsIIOService2.idl \
 		nsIMIMEInputStream.idl \
 		nsINetAddr.idl \
 		nsINetworkLinkService.idl \
 		nsIPermission.idl \
 		nsIPermissionManager.idl \
 		nsIPrivateBrowsingChannel.idl \
-		nsIPrivateBrowsingServiceObsolete.idl \
 		nsIProgressEventSink.idl \
 		nsIPrompt.idl \
 		nsIProtocolProxyService.idl \
 		nsIProtocolProxyService2.idl \
 		nsIProtocolProxyFilter.idl \
 		nsIProtocolProxyCallback.idl \
 		nsIProxiedProtocolHandler.idl \
 		nsIProxyInfo.idl \
deleted file mode 100644
--- a/netwerk/base/public/nsIPrivateBrowsingServiceObsolete.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(7ad4b7f1-5a88-41aa-9b40-713009bc57b3)]
-interface nsIPrivateBrowsingService : nsISupports
-{
-  // This space is intentionally left blank!
-
-  // This is a remnant from the old dying global private browsing service.
-  // You should fix your code to not rely on this interface, as it will
-  // be removed completely soon.
-};
-
--- a/parser/htmlparser/tests/mochitest/test_bug460437.xhtml
+++ b/parser/htmlparser/tests/mochitest/test_bug460437.xhtml
@@ -12,16 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"><b id="test460437">orig</b></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 <![CDATA[
 
+SimpleTest.expectAssertions(1);
+
 /** Test for Bug 460437 **/
 
 var s = '<i>invalid</i';
 try {
   document.getElementById('test460437').innerHTML = s;
 } catch (e) {
 }
 is(document.getElementById('test460437').innerHTML, "", "setting invalid innerHTML should clear it");
--- a/parser/htmlparser/tests/mochitest/test_bug613662.xhtml
+++ b/parser/htmlparser/tests/mochitest/test_bug613662.xhtml
@@ -7,16 +7,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <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=613662">Mozilla Bug 613662</a>
 <p id="display"></p><div id="content" style="display: none"></div><div id="content2" style="display: none"></div><pre id="test">
 <script type="application/javascript"><![CDATA[
 
+SimpleTest.expectAssertions(1);
+
 /** Test for Bug 613662 **/
 
 function testPositions(node) {
   node.insertAdjacentHTML("beforeBegin", "\u003Cscript>ok(false, 'script should not have run');\u003C/script><i></i>");
   is(node.previousSibling.localName, "i", "Should have had <i> as previous sibling");
   node.insertAdjacentHTML("Afterbegin", "<b></b>\u003Cscript>ok(false, 'script should not have run');\u003C/script>");
   is(node.firstChild.localName, "b", "Should have had <b> as first child");
   node.insertAdjacentHTML("BeforeEnd", "\u003Cscript>ok(false, 'script should not have run');\u003C/script><u></u>");
new file mode 100644
--- /dev/null
+++ b/python/codegen/makeutils.py
@@ -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/.
+
+dependencies = []
+targets = []
+
+def makeQuote(filename):
+    return filename.replace(' ', '\\ ')  # enjoy!
+
+def writeMakeDependOutput(filename):
+    print "Creating makedepend file", filename
+    with open(filename, 'w') as f:
+        if len(targets) > 0:
+            f.write("%s:" % makeQuote(targets[0]))
+            for filename in dependencies:
+                f.write(' \\\n\t\t%s' % makeQuote(filename))
+            f.write('\n\n')
+            for filename in targets[1:]:
+                f.write('%s: %s\n' % (makeQuote(filename), makeQuote(targets[0])))
+
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_bug472986.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_bug472986.html
@@ -7,16 +7,18 @@
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
 
+  SimpleTest.expectAssertions(3);
+
   // Clear the default onload assigned to test start because we must
   // wait for replaced image to load and only after that test the security state
   var onLoadFunction = window.onload;
   window.onload = function()
   {
     var img1 = document.getElementById("img1");
     img1.addEventListener("load", onLoadFunction, false);
     img1.src = "https://example.com/tests/security/ssl/mixedcontent/moonsurface.jpg";
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_cssContent2.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_cssContent2.html
@@ -7,16 +7,20 @@
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
 
+  if (navigator.platform.indexOf("Mac") == 0) {
+    SimpleTest.expectAssertions(0, 1);
+  }
+
   function runTest()
   {
     isSecurityState("secure");
     document.getElementById("para").style.content =
       "url('http://example.com/tests/security/ssl/mixedcontent/moonsurface.jpg')";
 
     waitForSecurityState("broken", function()
     {
--- a/toolkit/components/aboutmemory/tests/test_aboutmemory.xul
+++ b/toolkit/components/aboutmemory/tests/test_aboutmemory.xul
@@ -14,16 +14,18 @@
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml"></body>
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
   "use strict";
 
+  SimpleTest.expectAssertions(27);
+
   const Cc = Components.classes;
   const Ci = Components.interfaces;
   const Cr = Components.results;
   let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
             getService(Ci.nsIMemoryReporterManager);
 
   // Remove all the real reporters and multi-reporters;  save them to
   // restore at the end.
--- a/toolkit/components/passwordmgr/test/test_notifications.html
+++ b/toolkit/components/passwordmgr/test/test_notifications.html
@@ -13,16 +13,18 @@ Login Manager test: notifications
 
 <div id="content" style="display: none">
   <iframe id="iframe"></iframe>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+SimpleTest.expectAssertions(23);
+
 /** Test for Login Manager: notifications. **/
 
 // Set testpath to the directory where we live. Used to load tests from
 // alternate Mochitest servers (different hostnames, same content).
 var testpath = document.location.pathname + "/../";
 
 var subtests = [
                    "subtst_notifications_1.html", // 1
--- a/toolkit/content/tests/chrome/test_bug437844.xul
+++ b/toolkit/content/tests/chrome/test_bug437844.xul
@@ -34,16 +34,22 @@ https://bugzilla.mozilla.org/show_bug.cg
     </div>
     <pre id="test">
     </pre>
   </body>
 
   <script class="testbody" type="application/javascript">
     <![CDATA[
 
+      if (navigator.platform.indexOf("Linux") == 0) {
+        SimpleTest.expectAssertions(5, 6);
+      } else {
+        SimpleTest.expectAssertions(4);
+      }
+
       /** Test for Bug 437844 and Bug 348233 **/
       SimpleTest.waitForExplicitFinish();
 
       let prefs = Components.classes["@mozilla.org/preferences-service;1"]
                             .getService(Components.interfaces.nsIPrefBranch);
       prefs.setCharPref("intl.uidirection.en-US", "rtl");
 
       let rootDir = getRootDirectory(window.location.href);
--- a/toolkit/content/tests/chrome/test_bug509732.xul
+++ b/toolkit/content/tests/chrome/test_bug509732.xul
@@ -12,16 +12,20 @@
 
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"
         onload="test()"/>
 
   <!-- test code goes here -->
 <script type="application/javascript">
 <![CDATA[
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 5);
+}
+
 var gNotificationBox;
 
 // Tests that a notification that is added in an hidden box didn't throw the animation
 function test() {
   SimpleTest.waitForExplicitFinish();
   gNotificationBox = document.getElementById("nb");
 
   is(gNotificationBox.allNotifications.length, 0, "There should be no initial notifications");
--- a/toolkit/content/tests/chrome/test_bug557987.xul
+++ b/toolkit/content/tests/chrome/test_bug557987.xul
@@ -17,16 +17,20 @@
   <menulist id="menulist" editable="true" value="Test bug 557987" 
                                           onfocus="eventReceived('focus')" />
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
 
 <script type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 SimpleTest.waitForFocus(test);
 
 // Tests that mouse events are correctly dispatched to <toolbarbutton type="menu-button"/>
 function test() {
   
   disableNonTestMouseEvents(true);
--- a/toolkit/content/tests/chrome/test_bug562554.xul
+++ b/toolkit/content/tests/chrome/test_bug562554.xul
@@ -21,16 +21,20 @@
   </toolbarbutton>
 
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
 
 <script type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(test);
 
 // Tests that mouse events are correctly dispatched to <toolbarbutton type="menu"/>
 function test() {
   disableNonTestMouseEvents(true);
   nextTest();
 }
--- a/toolkit/content/tests/chrome/test_bug570192.xul
+++ b/toolkit/content/tests/chrome/test_bug570192.xul
@@ -30,16 +30,22 @@ https://bugzilla.mozilla.org/show_bug.cg
     </div>
     <pre id="test">
     </pre>
   </body>
 
   <script type="application/javascript">
     <![CDATA[
 
+    if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(0, 2);
+    } else if (navigator.platform.indexOf("Linux") == 0) {
+      SimpleTest.expectAssertions(0, 5);
+    }
+
     addLoadEvent(function() {
       try {
         var content = document.getElementById("content");
         content.innerHTML = '<textbox newlines="pasteintact" ' +
           'xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>';
         var textbox = content.firstChild;
         ok(textbox, "created the textbox");
         ok(!textbox.editor, "do we have an editor?");
--- a/toolkit/content/tests/chrome/test_bug585946.xul
+++ b/toolkit/content/tests/chrome/test_bug585946.xul
@@ -18,16 +18,20 @@
 
   <!-- test resuls are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml"
         style="height: 300px; overflow: auto;"/>
   
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 function startTest() {
   var toolbar = $("toolbar");
 
   var splitter = document.createElement("splitter");
   splitter.setAttribute("id", "dynsplitter");
   splitter.setAttribute("skipintoolbarset", "true");
--- a/toolkit/content/tests/chrome/test_bug624329.xul
+++ b/toolkit/content/tests/chrome/test_bug624329.xul
@@ -16,16 +16,20 @@ https://bugzilla.mozilla.org/show_bug.cg
      target="_blank">Mozilla Bug 624329</a>
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
   /** Test for Bug 624329 **/
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var win;
 var timeoutID;
 var menu;
 
 function openTestWindow() {
     win = open("bug624329_window.xul", "_blank", "width=300,resizable=yes,chrome");
--- a/toolkit/content/tests/chrome/test_bug792324.xul
+++ b/toolkit/content/tests/chrome/test_bug792324.xul
@@ -33,16 +33,20 @@ https://bugzilla.mozilla.org/show_bug.cg
           accesskey="X"
           oncommand="clicked(event)"
           label="Button in panel 2"
   />
 </panel>
 
 <script class="testbody" type="application/javascript;version=1.7"><![CDATA[
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 /** Test for Bug 792324 **/
 let after_click;
 
 function clicked(event) {
   after_click(event);
 }
 
 function checkAccessKeyOnPanel(panelid, buttonid, cb) {
--- a/toolkit/content/tests/chrome/test_button.xul
+++ b/toolkit/content/tests/chrome/test_button.xul
@@ -23,16 +23,22 @@
 </hbox>
 
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
 
 <script type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+} else {
+  SimpleTest.expectAssertions(0, 5);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 function test_button()
 {
   synthesizeMouseExpectEvent($("one"), 2, 2, {}, $("one"), "command", "button press");
   $("one").focus();
   synthesizeKeyExpectEvent("VK_SPACE", { }, $("one"), "command", "key press");
   $("two").disabled = true;
--- a/toolkit/content/tests/chrome/test_chromemargin.xul
+++ b/toolkit/content/tests/chrome/test_chromemargin.xul
@@ -12,16 +12,20 @@
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
 <script>
 
 // Tests parsing of the chrome margin attrib on a window.
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 SimpleTest.waitForExplicitFinish();
 function runTest()
 {
   window.open("window_chromemargin.xul", "_blank", "chrome,width=600,height=600");
 }
 </script>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
--- a/toolkit/content/tests/chrome/test_closemenu_attribute.xul
+++ b/toolkit/content/tests/chrome/test_closemenu_attribute.xul
@@ -23,16 +23,22 @@
       </menupopup>
     </menu>
   </menupopup>
 </button>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 5);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var gExpectedId = "p3";
 var gMode = -1;
 var gModes = ["", "auto", "single", "none"];
 
 function nextTest()
 {
--- a/toolkit/content/tests/chrome/test_colorpicker_popup.xul
+++ b/toolkit/content/tests/chrome/test_colorpicker_popup.xul
@@ -16,16 +16,22 @@
 <colorpicker id="colorpicker-popup" type="button" color="#FF0000" tabindex="1"/>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
 var gTestPhase = -1;
 var gCp = null;
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+} else if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 5);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 function preventDefault(event) {
   event.preventDefault();
 }
 
 function runTests()
 {
--- a/toolkit/content/tests/chrome/test_contextmenu_list.xul
+++ b/toolkit/content/tests/chrome/test_contextmenu_list.xul
@@ -68,16 +68,22 @@
 <menupopup id="themenu" onpopupshowing="if (gTestId == -1) event.preventDefault()"
                         onpopupshown="checkPopup()" onpopuphidden="setTimeout(nextTest, 0);">
   <menuitem label="Item"/>
 </menupopup>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 5);
+} else {
+  SimpleTest.expectAssertions(0, 7);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var gTestId = -1;
 var gTestElement = "list";
 var gSelectionStep = 0;
 var gContextMenuFired = false;
 
 function startTest()
--- a/toolkit/content/tests/chrome/test_datepicker.xul
+++ b/toolkit/content/tests/chrome/test_datepicker.xul
@@ -32,16 +32,20 @@
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script>
 <![CDATA[
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 5);
+}
+
 var mouseScrolled = false;
 
 SimpleTest.waitForExplicitFinish();
 
 function testtag_datepickers()
 {
   var dppopup = document.getElementById("datepicker-popup");
   testtag_datepicker(document.getElementById("datepicker"), "", "datepicker");
--- a/toolkit/content/tests/chrome/test_deck.xul
+++ b/toolkit/content/tests/chrome/test_deck.xul
@@ -22,16 +22,20 @@
 </deck>
 
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
 
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 function test_deck()
 {
   var deck = $("deck1");
   ok(deck.selectedIndex === '0', "deck one selectedIndex");
   // this size is the button height, 80, plus the button padding of 1px on each side,
   // plus the deck's 5px top padding and the 12px bottom padding.
--- a/toolkit/content/tests/chrome/test_dialogfocus.xul
+++ b/toolkit/content/tests/chrome/test_dialogfocus.xul
@@ -18,16 +18,22 @@
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script>
 <![CDATA[
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+} else {
+  SimpleTest.expectAssertions(0, 5);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var expected = [ "one", "_extra2", "tab", "one", "tabbutton2", "tabbutton", "two", "textbox-yes", "one" ];
 // non-Mac will always focus the default button if any of the dialog buttons
 // would be focused
 if (navigator.platform.indexOf("Mac") == -1)
   expected[1] = "_accept";
 
--- a/toolkit/content/tests/chrome/test_findbar.xul
+++ b/toolkit/content/tests/chrome/test_findbar.xul
@@ -23,16 +23,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+SimpleTest.expectAssertions(0, 5);
+
 /** Test for Bug 288254 **/
 SimpleTest.waitForExplicitFinish();
 window.open("findbar_window.xul", "findbartest", 
             "chrome,width=600,height=600");
 
 ]]>
 </script>
 
--- a/toolkit/content/tests/chrome/test_findbar_events.xul
+++ b/toolkit/content/tests/chrome/test_findbar_events.xul
@@ -25,16 +25,20 @@ https://bugzilla.mozilla.org/show_bug.cg
     </div>
     <pre id="test">
     </pre>
   </body>
 
   <script class="testbody" type="application/javascript">
     <![CDATA[
 
+      if (navigator.platform.indexOf("Mac") == 0) {
+        SimpleTest.expectAssertions(0, 4);
+      }
+
       /** Test for Bug 793275 **/
       SimpleTest.waitForExplicitFinish();
       window.open("findbar_events_window.xul", "793275test",
                   "chrome,width=600,height=600");
 
     ]]>
   </script>
 
--- a/toolkit/content/tests/chrome/test_focus_anons.xul
+++ b/toolkit/content/tests/chrome/test_focus_anons.xul
@@ -19,16 +19,22 @@
   </menupopup>
 </menulist>
 <textbox id="textbox"/>
 <scale id="scale"/>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 4);
+} else if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var gBlurs = 0, gFocuses = 0;
 var gExpectedBlur = "";
 var gExpectedFocus = "";
 
 function blurOccurred(event) {
   gBlurs++;
--- a/toolkit/content/tests/chrome/test_hiddenitems.xul
+++ b/toolkit/content/tests/chrome/test_hiddenitems.xul
@@ -33,16 +33,20 @@ https://bugzilla.mozilla.org/show_bug.cg
     <listitem id="listbox_item5" label="Item 5" collapsed="true"/>
     <listitem id="listbox_item6" label="Item 6"/>
     <listitem id="listbox_item7" label="Item 7" hidden="true"/>
   </listbox>
   
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 317422 **/
 SimpleTest.waitForExplicitFinish();
 
 function testListbox(id)
 {
   var listbox = document.getElementById(id);
   listbox.focus();
   is(listbox.getRowCount(), 7, id + ": Returned the wrong number of rows");
--- a/toolkit/content/tests/chrome/test_hiddenpaging.xul
+++ b/toolkit/content/tests/chrome/test_hiddenpaging.xul
@@ -59,16 +59,20 @@ https://bugzilla.mozilla.org/show_bug.cg
     <listitem id="listbox_item13" label="Item 13"/>
     <listitem id="listbox_item14" label="Item 14"/>
     <listitem id="listbox_item15" label="Item 15" hidden="true"/>
   </listbox>
   
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 /** Test for Bug 317422 **/
 SimpleTest.waitForExplicitFinish();
 
 function testRichlistbox()
 {
   var id = "richlistbox";
   var listbox = document.getElementById(id);
   listbox.focus();
--- a/toolkit/content/tests/chrome/test_keys.xul
+++ b/toolkit/content/tests/chrome/test_keys.xul
@@ -5,16 +5,19 @@
 <window title="Keys Test"
   onload="setTimeout(runTest, 0);"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
 <script>
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
 SimpleTest.waitForExplicitFinish();
 function runTest()
 {
   window.open("window_keys.xul", "_blank", "chrome,width=200,height=200");
 }
 </script>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
--- a/toolkit/content/tests/chrome/test_largemenu.xul
+++ b/toolkit/content/tests/chrome/test_largemenu.xul
@@ -7,16 +7,20 @@
   xmlns:html="http://www.w3.org/1999/xhtml"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <title>Large Menu Tests</title>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
 <script>
+if (navigator.platform.indexOf("Win") != 0) {
+  SimpleTest.expectAssertions(0, 3);
+}
+
 SimpleTest.waitForExplicitFinish();
 function runTest()
 {
   window.open("window_largemenu.xul", "_blank", "chrome,width=200,height=200");
 }
 </script>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
--- a/toolkit/content/tests/chrome/test_menu.xul
+++ b/toolkit/content/tests/chrome/test_menu.xul
@@ -22,16 +22,20 @@
         </menu>
       </menupopup>
     </menu>
   </menubar>
 
   <script class="testbody" type="application/javascript">
   <![CDATA[
 
+  if (navigator.platform.indexOf("Mac") == 0) {
+    SimpleTest.expectAssertions(0, 2);
+  }
+
   SimpleTest.waitForExplicitFinish();
 
   function runTests()
   {
     var menu = document.getElementById("nested");
 
     // nsIDOMXULContainerElement::getIndexOfItem();
     var item = document.getElementById("item2");
--- a/toolkit/content/tests/chrome/test_menuchecks.xul
+++ b/toolkit/content/tests/chrome/test_menuchecks.xul
@@ -31,16 +31,20 @@
   </hbox>
 
   <!--
   This test checks that checkbox and radio menu items work properly
   -->
   <script class="testbody" type="application/javascript">
   <![CDATA[
 
+  if (navigator.platform.indexOf("Mac") == 0) {
+    SimpleTest.expectAssertions(0, 2);
+  }
+
   SimpleTest.waitForExplicitFinish();
   var gTestIndex = 0;
 
   // tests to perform
   var tests = [
     {
       testname: "select unchecked checkbox",
       item: "toolbar",
--- a/toolkit/content/tests/chrome/test_menuitem_blink.xul
+++ b/toolkit/content/tests/chrome/test_menuitem_blink.xul
@@ -11,16 +11,20 @@
   <menulist id="menulist">
     <menupopup id="menupopup">
       <menuitem label="Menu Item" id="menuitem"/>
     </menupopup>
   </menulist>
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(startTest);
 
 function startTest() {
   if (!/Mac/.test(navigator.platform)) {
     ok(true, "Nothing to test on non-Mac.");
     SimpleTest.finish();
     return;
--- a/toolkit/content/tests/chrome/test_menuitem_commands.xul
+++ b/toolkit/content/tests/chrome/test_menuitem_commands.xul
@@ -6,16 +6,20 @@
         onload="runOrOpen()"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
 <script>
 <![CDATA[
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 function checkAttributes(elem, label, accesskey, disabled, hidden, isAfter)
 {
   var is = window.opener.wrappedJSObject.SimpleTest.is;
 
   is(elem.getAttribute("label"), label, elem.id + " label " + (isAfter ? "after" : "before") + " open");
   is(elem.getAttribute("accesskey"), accesskey, elem.id + " accesskey " + (isAfter ? "after" : "before") + " open");
--- a/toolkit/content/tests/chrome/test_menulist_keynav.xul
+++ b/toolkit/content/tests/chrome/test_menulist_keynav.xul
@@ -18,16 +18,20 @@
     <menuitem id="i4" label="Four"/>
   </menupopup>
 </menulist>
 <button id="button2" label="Two"/>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Linux") != 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var gShowPopup = false;
 var gModifiers = 0;
 
 var iswin = (navigator.platform.indexOf("Win") == 0);
 
 function runTests()
--- a/toolkit/content/tests/chrome/test_mousecapture.xul
+++ b/toolkit/content/tests/chrome/test_mousecapture.xul
@@ -6,16 +6,22 @@
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
 <script>
 <![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(6);
+} else {
+  SimpleTest.expectAssertions(6, 8);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var captureRetargetMode = false;
 var cachedMouseDown = null;
 var previousWidth = 0, originalWidth = 0;
 var loadInWindow = false;
 
 function splitterCallback(adjustment)
--- a/toolkit/content/tests/chrome/test_notificationbox.xul
+++ b/toolkit/content/tests/chrome/test_notificationbox.xul
@@ -13,16 +13,22 @@
     <menuitem label="One"/>
   </menupopup>
 
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
 
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(0, 3);
+} else {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var testtag_notificationbox_buttons = [
   {
     label: "Button 1",
     accesskey: "u",
     callback: testtag_notificationbox_buttonpressed,
     popup: "menupopup"
--- a/toolkit/content/tests/chrome/test_panel.xul
+++ b/toolkit/content/tests/chrome/test_panel.xul
@@ -7,16 +7,20 @@
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
 <script>
+if (navigator.platform.indexOf("Mac") == 0) {
+  SimpleTest.expectAssertions(0, 2);
+}
+
 SimpleTest.waitForExplicitFinish();
 function runTest()
 {
   window.open("window_panel.xul", "_blank", "chrome,left=200,top=200,width=200,height=200");
 }
 </script>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
--- a/toolkit/content/tests/chrome/test_preferences.xul
+++ b/toolkit/content/tests/chrome/test_preferences.xul
@@ -7,16 +7,19 @@
         onload="RunTest();">
   <title>Preferences Window Tests</title>
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
   <script type="application/javascript">
   <![CDATA[
+    if (navigator.platform.indexOf("Mac") == 0) {
+      SimpleTest.expectAssertions(4);
+    }
     SimpleTest.waitForExplicitFinish();
 
     const kPref = Components.classes["@mozilla.org/preferences-service;1"]
                             .getService(Components.interfaces.nsIPrefBranch);
 
     // preference values, set 1
     const kPrefValueSet1 =
     {
--- a/toolkit/content/tests/widgets/test_mousecapture_area.html
+++ b/toolkit/content/tests/widgets/test_mousecapture_area.html
@@ -47,16 +47,18 @@
 
 
   <div id="otherelement" style="width: 100px; height: 100px;"></div>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+SimpleTest.expectAssertions(1);
+
 SimpleTest.waitForExplicitFinish();
 
 function runTests()
 {
   //XXX We send a useless click to each image to force it to setup its image
   // map, because flushing layout won't do it. Hopefully bug 135040 will make
   // this not suck.
   synthesizeMouse($("image"), 5, 5, { type: "mousedown" });
--- a/toolkit/content/tests/widgets/test_videocontrols.html
+++ b/toolkit/content/tests/widgets/test_videocontrols.html
@@ -12,16 +12,18 @@
 <div id="content">
   <video width="320" height="240" id="video" src="seek_with_sound.ogg" controls mozNoDynamicControls preload="auto"></video>
 </div>
 
 <pre id="test">
 <script type="text/javascript" src="use_large_cache.js"></script>
 <script class="testbody" type="text/javascript">
 
+SimpleTest.expectAssertions(2);
+
 /*
  * Positions of the  UI elements, relative to the upper-left corner of the
  * <video> box.
  */
 const videoWidth = 320;
 const videoHeight = 240;
 const videoDuration = 3.8329999446868896;
 
--- a/toolkit/identity/tests/chrome/test_sandbox.xul
+++ b/toolkit/identity/tests/chrome/test_sandbox.xul
@@ -21,16 +21,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <!-- test code goes here -->
   <script type="application/javascript;version=1.8">
   <![CDATA[
 
   /** Test for Bug 762993 **/
 
 "use strict";
 
+SimpleTest.expectAssertions(2);
+
 SimpleTest.waitForExplicitFinish();
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const OSX_10_5 = navigator.oscpu == "Intel Mac OS X 10.5";
 
 const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
--- a/toolkit/mozapps/downloads/tests/chrome/test_bug_412360.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_bug_412360.xul
@@ -17,16 +17,20 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
   <script type="application/javascript"
           src="utils.js"/>
 
   <script type="application/javascript">
   <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(1);
+}
+
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 let didFail = false;
 var file;
 
 let prefBranch = Cc["@mozilla.org/preferences-service;1"].
                  getService(Ci.nsIPrefBranch);
 
--- a/toolkit/mozapps/downloads/tests/chrome/test_bug_462172.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_bug_462172.xul
@@ -27,16 +27,20 @@ close window
           src="utils.js"/>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
   <script type="application/javascript">
   <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(1);
+}
+
   /** Test for Bug 462172 **/
 var missingFileElid;
 var realFileElid;
 const kFiller = "notApplicable";
 const kFillerURL = "https://bugzilla.mozilla.org/show_bug.cgi?id=462172"
 var realFile = Cc["@mozilla.org/file/directory_service;1"].
                   getService(Ci.nsIProperties).get("CurWorkD", Ci.nsIFile);
 var missingFile = Cc["@mozilla.org/file/directory_service;1"].
--- a/toolkit/mozapps/downloads/tests/chrome/test_cleanup_search.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_cleanup_search.xul
@@ -17,16 +17,20 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
   <script type="application/javascript"
           src="utils.js"/>
 
   <script type="application/javascript">
   <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(1);
+}
+
 function test()
 {
   var dmui = getDMUI();
   if (!dmui) {
     todo(false, "skip test for toolkit download manager UI");
     return;
   }
 
--- a/toolkit/mozapps/downloads/tests/chrome/test_close_on_last_window.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_close_on_last_window.xul
@@ -18,16 +18,20 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
   <script type="application/javascript"
           src="utils.js"/>
 
   <script type="application/javascript">
   <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(2);
+}
+
 const DLMGR_UI_DONE = "download-manager-ui-done";
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 let gGen, dm, dmui, chromeWindow, testCleanup;
 
 function test()
 {
--- a/toolkit/mozapps/downloads/tests/chrome/test_multiword_search.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_multiword_search.xul
@@ -15,16 +15,20 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
   <script type="application/javascript"
           src="utils.js"/>
 
   <script type="application/javascript">
   <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(1, 2);
+}
+
 function test()
 {
   var dmui = getDMUI();
   if (!dmui) {
     todo(false, "skip test for toolkit download manager UI");
     return;
   }
 
--- a/toolkit/mozapps/downloads/tests/chrome/test_search_clearlist.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_search_clearlist.xul
@@ -14,16 +14,20 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
   <script type="application/javascript"
           src="utils.js"/>
 
   <script type="application/javascript">
   <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(1);
+}
+
 function test()
 {
   var dmui = getDMUI();
   if (!dmui) {
     todo(false, "skip test for toolkit download manager UI");
     return;
   }
 
--- a/toolkit/mozapps/downloads/tests/chrome/test_search_keys.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_search_keys.xul
@@ -17,16 +17,20 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
   <script type="application/javascript"
           src="utils.js"/>
 
   <script type="application/javascript">
   <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(1);
+}
+
 function test_meta_k(aWin)
 {
   let doc = aWin.document;
   let searchbox = doc.getElementById("searchbox");
   let richlistbox = doc.getElementById("downloadView");
 
   // Enusre the serachbox is not focused
   richlistbox.focus();
--- a/toolkit/mozapps/downloads/tests/chrome/test_select_all.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_select_all.xul
@@ -16,16 +16,20 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
   <script type="application/javascript"
           src="utils.js"/>
 
   <script type="application/javascript">
   <![CDATA[
 
+if (navigator.platform.indexOf("Linux") == 0) {
+  SimpleTest.expectAssertions(1);
+}
+
 function test()
 {
   var dmui = getDMUI();
   if (!dmui) {
     todo(false, "skip test for toolkit download manager UI");
     return;
   }
 
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -578,30 +578,31 @@ endif
 ifndef MOZ_PACKAGER_FORMAT
 MOZ_PACKAGER_FORMAT = $(error MOZ_PACKAGER_FORMAT is not set)
 endif
 
 ifneq (android,$(MOZ_WIDGET_TOOLKIT))
 OPTIMIZEJARS = 1
 endif
 
-export NO_PKG_FILES USE_ELF_HACK ELF_HACK_FLAGS _BINPATH
+export NO_PKG_FILES USE_ELF_HACK ELF_HACK_FLAGS
+
 stage-package: $(MOZ_PKG_MANIFEST)
 	@rm -rf $(DIST)/$(PKG_PATH)$(PKG_BASENAME).tar $(DIST)/$(PKG_PATH)$(PKG_BASENAME).dmg $@ $(EXCLUDE_LIST)
 	$(PYTHON) $(MOZILLA_DIR)/toolkit/mozapps/installer/packager.py $(DEFINES) \
 		--format $(MOZ_PACKAGER_FORMAT) \
 		$(addprefix --removals ,$(MOZ_PKG_REMOVALS)) \
 		$(if $(filter-out 0,$(MOZ_PKG_FATAL_WARNINGS)),,--ignore-errors) \
 		$(if $(MOZ_PACKAGER_MINIFY),--minify) \
 		$(if $(JARLOG_DIR),$(addprefix --jarlog ,$(wildcard $(JARLOG_FILE_AB_CD)))) \
 		$(if $(OPTIMIZEJARS),--optimizejars) \
 		$(addprefix --unify ,$(UNIFY_DIST)) \
-		$(MOZ_PKG_MANIFEST) $(DIST) $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR) \
+		$(MOZ_PKG_MANIFEST) $(DIST) $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(if $(MOZ_PKG_MANIFEST),,$(_BINPATH)) \
 		$(if $(filter omni,$(MOZ_PACKAGER_FORMAT)),$(if $(NON_OMNIJAR_FILES),--non-resource $(NON_OMNIJAR_FILES)))
-	$(PYTHON) $(MOZILLA_DIR)/toolkit/mozapps/installer/find-dupes.py $(DIST)/$(MOZ_PKG_DIR)
+	$(PYTHON) $(MOZILLA_DIR)/toolkit/mozapps/installer/find-dupes.py $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)
 ifndef LIBXUL_SDK
 ifdef MOZ_PACKAGE_JSSHELL
 # Package JavaScript Shell
 	@echo "Packaging JavaScript Shell..."
 	$(RM) $(PKG_JSSHELL)
 	$(MAKE_JSSHELL)
 endif # MOZ_PACKAGE_JSSHELL
 endif # LIBXUL_SDK
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -50,16 +50,18 @@ const PREF_APP_UPDATE_SERVICE_ENABLED   
 const PREF_APP_UPDATE_SERVICE_ERRORS      = "app.update.service.errors";
 const PREF_APP_UPDATE_SERVICE_MAX_ERRORS  = "app.update.service.maxErrors";
 const PREF_APP_UPDATE_SOCKET_ERRORS       = "app.update.socket.maxErrors";
 const PREF_APP_UPDATE_RETRY_TIMEOUT       = "app.update.socket.retryTimeout";
 
 const PREF_APP_DISTRIBUTION               = "distribution.id";
 const PREF_APP_DISTRIBUTION_VERSION       = "distribution.version";
 
+const PREF_APP_B2G_VERSION                = "b2g.version";
+
 const PREF_EM_HOTFIX_ID                   = "extensions.hotfix.id";
 
 const URI_UPDATE_PROMPT_DIALOG  = "chrome://mozapps/content/update/updates.xul";
 const URI_UPDATE_HISTORY_DIALOG = "chrome://mozapps/content/update/history.xul";
 const URI_BRAND_PROPERTIES      = "chrome://branding/locale/brand.properties";
 const URI_UPDATES_PROPERTIES    = "chrome://mozapps/locale/update/updates.properties";
 const URI_UPDATE_NS             = "http://www.mozilla.org/2005/app-update";
 
@@ -3020,16 +3022,17 @@ Checker.prototype = {
     url = url.replace(/%DISTRIBUTION%/g,
                       getDistributionPrefValue(PREF_APP_DISTRIBUTION));
     url = url.replace(/%DISTRIBUTION_VERSION%/g,
                       getDistributionPrefValue(PREF_APP_DISTRIBUTION_VERSION));
     url = url.replace(/\+/g, "%2B");
 
 #ifdef MOZ_WIDGET_GONK
     url = url.replace(/%PRODUCT_MODEL%/g, gProductModel);
+    url = url.replace(/%B2G_VERSION%/g, getPref("getCharPref", PREF_APP_B2G_VERSION, null));
 #endif
 
     if (force)
       url += (url.indexOf("?") != -1 ? "&" : "?") + "force=1";
 
     LOG("Checker:getUpdateURL - update URL: " + url);
     return url;
   },
@@ -3491,19 +3494,16 @@ Downloader.prototype = {
    * Get the nsIFile to use for downloading the active update's selected patch
    */
   _getUpdateArchiveFile: function Downloader__getUpdateArchiveFile() {
     var updateArchive;
 #ifdef USE_UPDATE_ARCHIVE_DIR
     try {
       updateArchive = FileUtils.getDir(KEY_UPDATE_ARCHIVE_DIR, [], true);
     } catch (e) {
-      if (e == Cr.NS_ERROR_FILE_TOO_BIG) {
-        this._update.errorCode = FILE_ERROR_TOO_BIG;
-      }
       return null;
     }
 #else
     updateArchive = getUpdatesDir().clone();
 #endif
 
     updateArchive.append(FILE_UPDATE_ARCHIVE);
     return updateArchive;
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/test/unit/test_bug833708.js
@@ -0,0 +1,100 @@
+/* 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/.
+ */
+
+AUS_Cu.import("resource://gre/modules/FileUtils.jsm");
+const KEY_UPDATE_ARCHIVE_DIR = "UpdArchD"
+
+let gActiveUpdate = null;
+
+function FakeDirProvider() {}
+FakeDirProvider.prototype = {
+  classID: Components.ID("{f30b43a7-2bfa-4e5f-8c4f-abc7dd4ac486}"),
+  QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIDirectoryServiceProvider]),
+
+  getFile: function(prop, persistent) {
+    if (prop == KEY_UPDATE_ARCHIVE_DIR) {
+      if (gActiveUpdate) {
+        gActiveUpdate.errorCode = AUS_Cr.NS_ERROR_FILE_TOO_BIG;
+      }
+    }
+    return null;
+  }
+};
+
+function run_test() {
+  do_test_pending();
+  do_register_cleanup(end_test);
+  DEBUG_AUS_TEST = true;
+
+  removeUpdateDirsAndFiles();
+  setUpdateURLOverride();
+  overrideXHR(xhr_pt1);
+  standardInit();
+
+  logTestInfo("testing that error codes set from a directory provider propagate" +
+              "up to AUS.downloadUpdate() correctly");
+
+  gDirProvider = new FakeDirProvider();
+  gOldProvider = AUS_Cc["@mozilla.org/browser/directory-provider;1"]
+                       .createInstance(AUS_Ci.nsIDirectoryServiceProvider);
+
+  gDirService = AUS_Cc["@mozilla.org/file/directory_service;1"]
+                       .getService(AUS_Ci.nsIProperties);
+
+  gDirService.unregisterProvider(gOldProvider);
+  gDirService.registerProvider(gDirProvider);
+
+  Services.prefs.setBoolPref(PREF_APP_UPDATE_SILENT, true);
+  do_execute_soon(run_test_pt1);
+}
+
+function xhr_pt1() {
+  gXHR.status = 200;
+  gXHR.responseText = gResponseBody;
+  try {
+    var parser = AUS_Cc["@mozilla.org/xmlextras/domparser;1"].
+                 createInstance(AUS_Ci.nsIDOMParser);
+    gXHR.responseXML = parser.parseFromString(gResponseBody, "application/xml");
+  }
+  catch(e) {
+    gXHR.responseXML = null;
+  }
+  var e = { target: gXHR };
+  gXHR.onload(e);
+}
+
+function run_test_pt1() {
+  gUpdates = null;
+  gUpdateCount = null;
+  gCheckFunc = check_test_pt1;
+
+
+  let patches = getRemotePatchString();
+  let updates = getRemoteUpdateString(patches);
+  gResponseBody = getRemoteUpdatesXMLString(updates);
+  gUpdateChecker.checkForUpdates(updateCheckListener, true);
+}
+
+function check_test_pt1() {
+  do_check_eq(gUpdateCount, 1);
+
+  gActiveUpdate = gUpdates[0];
+  do_check_neq(gActiveUpdate, null);
+
+  let state = gAUS.downloadUpdate(gActiveUpdate, true);
+  do_check_eq(state, "null");
+  do_check_eq(gActiveUpdate.errorCode >>> 0 , AUS_Cr.NS_ERROR_FILE_TOO_BIG);
+  do_test_finished();
+}
+
+function end_test() {
+  gDirService.unregisterProvider(gDirProvider);
+  gDirService.registerProvider(gOldProvider);
+  gActiveUpdate = null;
+  gDirService = null;
+  gDirProvider = null;
+
+  cleanUp();
+}
--- a/toolkit/mozapps/update/test/unit/xpcshell.ini
+++ b/toolkit/mozapps/update/test/unit/xpcshell.ini
@@ -27,8 +27,10 @@ skip-if = os == 'android'
 [include:xpcshell_updater_windows.ini]
 run-if = os == 'win'
 [include:xpcshell_updater_xp_unix.ini]
 run-if = os == 'linux' || os == 'mac' || os == 'sunos'
 [test_bug595059.js]
 skip-if = toolkit == "gonk"
 reason = custom nsIUpdatePrompt
 [test_bug794211.js]
+[test_bug833708.js]
+run-if = toolkit == "gonk"
--- a/toolkit/xre/nsQAppInstance.cpp
+++ b/toolkit/xre/nsQAppInstance.cpp
@@ -18,20 +18,22 @@ QApplication *nsQAppInstance::sQAppInsta
 MComponentData* nsQAppInstance::sMComponentData = NULL;
 #endif
 int nsQAppInstance::sQAppRefCount = 0;
 
 void nsQAppInstance::AddRef(int& aArgc, char** aArgv, bool aDefaultProcess) {
   if (qApp)
     return;
   if (!sQAppInstance) {
+#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
     const char *graphicsSystem = getenv("MOZ_QT_GRAPHICSSYSTEM");
     if (graphicsSystem) {
       QApplication::setGraphicsSystem(QString(graphicsSystem));
     }
+#endif
 #if (MOZ_PLATFORM_MAEMO == 6)
     // Should create simple windows style for non chrome process
     // otherwise meegotouch style initialize and crash happen
     // because we don't initialize MComponent for child process
     if (!aDefaultProcess) {
       QApplication::setStyle(QLatin1String("windows"));
     }
     if (!aArgc) {
--- a/widget/qt/nsBidiKeyboard.cpp
+++ b/widget/qt/nsBidiKeyboard.cpp
@@ -19,17 +19,22 @@ nsBidiKeyboard::nsBidiKeyboard() : nsIBi
 nsBidiKeyboard::~nsBidiKeyboard()
 {
 }
 
 NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(bool *aIsRTL)
 {
     *aIsRTL = false;
 
+#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
     Qt::LayoutDirection layoutDir = QApplication::keyboardInputDirection();
+#else
+    QInputMethod* input = qApp->inputMethod();
+    Qt::LayoutDirection layoutDir = input ? input->inputDirection() : Qt::LeftToRight;
+#endif
 
     if (layoutDir == Qt::RightToLeft) {
         *aIsRTL = true;
     }
     
     return NS_OK;
 }
 
--- a/widget/qt/nsDeviceContextSpecQt.cpp
+++ b/widget/qt/nsDeviceContextSpecQt.cpp
@@ -82,17 +82,17 @@ NS_IMETHODIMP nsDeviceContextSpecQt::Get
 
     QTemporaryFile file;
     if(!file.open()) {
         return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE;
     }
     file.setAutoRemove(false);
 
     nsresult rv = NS_NewNativeLocalFile(
-            nsDependentCString(file.fileName().toAscii().constData()),
+            nsDependentCString(file.fileName().toUtf8().constData()),
             false,
             getter_AddRefs(mSpoolFile));
     if (NS_FAILED(rv)) {
         file.remove();
         return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE;
     }
 
     mSpoolName = file.fileName().toUtf8().constData();
--- a/widget/qt/nsNativeThemeQt.cpp
+++ b/widget/qt/nsNativeThemeQt.cpp
@@ -507,17 +507,17 @@ nsNativeThemeQt::GetMinimumWidgetSize(ns
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNativeThemeQt::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
                                     nsIAtom* aAttribute, bool* aShouldRepaint)
 {
-    *aShouldRepaint = TRUE;
+    *aShouldRepaint = true;
     return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsNativeThemeQt::ThemeChanged()
 {
     QStyle *s = qApp->style();
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -2165,17 +2165,17 @@ nsWindow::OnDragLeaveEvent(QGraphicsScen
     return DispatchEvent(&event);
 }
 
 nsEventStatus
 nsWindow::OnDragDropEvent(QGraphicsSceneDragDropEvent *aDropEvent)
 {
     if (aDropEvent->proposedAction() == Qt::CopyAction)
     {
-        printf("text version of the data: %s\n", aDropEvent->mimeData()->text().toAscii().data());
+        printf("text version of the data: %s\n", aDropEvent->mimeData()->text().toUtf8().data());
         aDropEvent->acceptProposedAction();
     }
 
     LOG(("nsWindow::OnDragDropSignal\n"));
     nsMouseEvent event(true, NS_DRAGDROP_OVER, 0,
                        nsMouseEvent::eReal);
     return nsEventStatus_eIgnore;
 }
@@ -3244,17 +3244,21 @@ nsWindow::SetInputContext(const InputCon
 }
 
 NS_IMETHODIMP_(InputContext)
 nsWindow::GetInputContext()
 {
     mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
     // Our qt widget looks like using only one context per process.
     // However, it's better to set the context's pointer.
+#if (QT_VERSION <= QT_VERSION_CHECK(5, 0, 0))
     mInputContext.mNativeIMEContext = qApp->inputContext();
+#else
+    mInputContext.mNativeIMEContext = nullptr;
+#endif
     return mInputContext;
 }
 
 void
 nsWindow::SetSoftwareKeyboardState(bool aOpen,
                                    const InputContextAction& aAction)
 {
     if (aOpen) {
--- a/widget/tests/test_bug538242.xul
+++ b/widget/tests/test_bug538242.xul
@@ -19,16 +19,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+if (navigator.platform.indexOf("Win") == 0) {
+  SimpleTest.expectAssertions(0, 1);
+}
+
 SimpleTest.waitForExplicitFinish();
 
 SimpleTest.waitForFocus(function () {
   if (navigator.platform.indexOf("Lin") != -1) {
     ok(true, "This test is disabled on Linux because it expects moving windows to be synchronous which is not guaranteed on Linux.");
     SimpleTest.finish();
     return;
   }
--- a/widget/tests/test_composition_text_querycontent.xul
+++ b/widget/tests/test_composition_text_querycontent.xul
@@ -14,15 +14,17 @@
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
+SimpleTest.expectAssertions(8);
+
 SimpleTest.waitForExplicitFinish();
 window.open("window_composition_text_querycontent.xul", "_blank", 
             "chrome,width=600,height=600");
 
 ]]>
 </script>
 </window>
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -25,16 +25,17 @@
 #include "nsIXULWindow.h"
 #include "nsIBaseWindow.h"
 #include "nsXULPopupManager.h"
 #include "nsEventStateManager.h"
 #include "nsIWidgetListener.h"
 #include "nsIGfxInfo.h"
 #include "npapi.h"
 #include "base/thread.h"
+#include "prdtoa.h"
 #include "prenv.h"
 #include "mozilla/Attributes.h"
 #include "nsContentUtils.h"
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
@@ -378,24 +379,24 @@ float nsBaseWidget::GetDPI()
   return 96.0f;
 }
 
 double nsIWidget::GetDefaultScale()
 {
   // The number of device pixels per CSS pixel. A value <= 0 means choose
   // automatically based on the DPI. A positive value is used as-is. This effectively
   // controls the size of a CSS "px".
-  float devPixelsPerCSSPixel = -1.0;
+  double devPixelsPerCSSPixel = -1.0;
 
   nsAdoptingCString prefString = Preferences::GetCString("layout.css.devPixelsPerPx");
   if (!prefString.IsEmpty()) {
-    devPixelsPerCSSPixel = static_cast<float>(atof(prefString));
+    devPixelsPerCSSPixel = PR_strtod(prefString, nullptr);
   }
 
-  if (devPixelsPerCSSPixel <= 0) {
+  if (devPixelsPerCSSPixel <= 0.0) {
     devPixelsPerCSSPixel = GetDefaultScaleInternal();
   }
 
   return devPixelsPerCSSPixel;
 }
 
 //-------------------------------------------------------------------------
 //