Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 28 Aug 2012 20:07:15 -0400
changeset 109992 0b4bc3760d51cbb235f01b737c67efd9728a9dd7
parent 109944 9e267fbca9fb42fe17e199bc83c44f79b1333107 (current diff)
parent 109991 1ec9c51ac5a1210ce547165d0814a9120f53421a (diff)
child 109993 0eebcc79ee058a6f01e76487df88b524f56d179e
child 110030 a0e30800ea3ac30abfe36ba94b74ccfddd96a60b
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone18.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 the last PGO-green inbound changeset to m-c.
accessible/src/base/filters.cpp
accessible/src/base/filters.h
dom/wifi/WifiWorker.js
--- a/accessible/src/base/AccCollector.cpp
+++ b/accessible/src/base/AccCollector.cpp
@@ -1,16 +1,18 @@
 /* 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 "AccCollector.h"
 
 #include "Accessible.h"
 
+using namespace mozilla::a11y;
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccCollector
 ////////////////////////////////////////////////////////////////////////////////
 
 AccCollector::
   AccCollector(Accessible* aRoot, filters::FilterFuncPtr aFilterFunc) :
   mFilterFunc(aFilterFunc), mRoot(aRoot), mRootChildIdx(0)
 {
@@ -51,34 +53,34 @@ AccCollector::GetIndexAt(Accessible* aAc
 // nsAccCollector protected
 
 Accessible*
 AccCollector::EnsureNGetObject(uint32_t aIndex)
 {
   uint32_t childCount = mRoot->ChildCount();
   while (mRootChildIdx < childCount) {
     Accessible* child = mRoot->GetChildAt(mRootChildIdx++);
-    if (!mFilterFunc(child))
+    if (!(mFilterFunc(child) & filters::eMatch))
       continue;
 
     AppendObject(child);
     if (mObjects.Length() - 1 == aIndex)
       return mObjects[aIndex];
   }
 
   return nullptr;
 }
 
 int32_t
 AccCollector::EnsureNGetIndex(Accessible* aAccessible)
 {
   uint32_t childCount = mRoot->ChildCount();
   while (mRootChildIdx < childCount) {
     Accessible* child = mRoot->GetChildAt(mRootChildIdx++);
-    if (!mFilterFunc(child))
+    if (!(mFilterFunc(child) & filters::eMatch))
       continue;
 
     AppendObject(child);
     if (child == aAccessible)
       return mObjects.Length() - 1;
   }
 
   return -1;
@@ -98,17 +100,18 @@ int32_t
 EmbeddedObjCollector::GetIndexAt(Accessible* aAccessible)
 {
   if (aAccessible->mParent != mRoot)
     return -1;
 
   if (aAccessible->mIndexOfEmbeddedChild != -1)
     return aAccessible->mIndexOfEmbeddedChild;
 
-  return mFilterFunc(aAccessible) ? EnsureNGetIndex(aAccessible) : -1;
+  return mFilterFunc(aAccessible) & filters::eMatch ?
+    EnsureNGetIndex(aAccessible) : -1;
 }
 
 void
 EmbeddedObjCollector::AppendObject(Accessible* aAccessible)
 {
   aAccessible->mIndexOfEmbeddedChild = mObjects.Length();
   mObjects.AppendElement(aAccessible);
 }
--- a/accessible/src/base/AccCollector.h
+++ b/accessible/src/base/AccCollector.h
@@ -1,19 +1,23 @@
 /* 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 AccCollector_h_
-#define AccCollector_h_
+#ifndef mozilla_a11y_AccCollector_h__
+#define mozilla_a11y_AccCollector_h__
+
+#include "AccFilters.h"
 
-#include "filters.h"
+#include "nsTArray.h"
 
-#include "nscore.h"
-#include "nsTArray.h"
+class Accessible;
+
+namespace mozilla {
+namespace a11y {
 
 /**
  * Collect accessible children complying with filter function. Provides quick
  * access to accessible by index.
  */
 class AccCollector
 {
 public:
@@ -77,12 +81,15 @@ public:
 
 protected:
   // Make sure it's used by Accessible class only.
   EmbeddedObjCollector(Accessible* aRoot) :
     AccCollector(aRoot, filters::GetEmbeddedObject) { }
 
   virtual void AppendObject(Accessible* aAccessible);
 
-  friend class Accessible;
+  friend class ::Accessible;
 };
 
+} // namespace a11y
+} // namespace mozilla
+
 #endif
rename from accessible/src/base/filters.cpp
rename to accessible/src/base/AccFilters.cpp
--- a/accessible/src/base/filters.cpp
+++ b/accessible/src/base/AccFilters.cpp
@@ -1,44 +1,60 @@
 /* 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 "filters.h"
+#include "AccFilters.h"
 
 #include "Accessible-inl.h"
 #include "nsAccUtils.h"
 #include "Role.h"
 #include "States.h"
 
 using namespace mozilla::a11y;
+using namespace mozilla::a11y::filters;
 
-bool
+uint32_t
 filters::GetSelected(Accessible* aAccessible)
 {
-  return aAccessible->State() & states::SELECTED;
+  if (aAccessible->State() & states::SELECTED)
+    return eMatch | eSkipSubtree;
+
+  return eSkip;
 }
 
-bool
+uint32_t
 filters::GetSelectable(Accessible* aAccessible)
 {
-  return aAccessible->InteractiveState() & states::SELECTABLE;
+  if (aAccessible->InteractiveState() & states::SELECTABLE)
+    return eMatch | eSkipSubtree;
+
+  return eSkip;
 }
 
-bool
+uint32_t
 filters::GetRow(Accessible* aAccessible)
 {
-  return aAccessible->Role() == roles::ROW;
+  a11y::role role = aAccessible->Role();
+  if (role == roles::ROW)
+    return eMatch | eSkipSubtree;
+
+  // Look for rows inside rowgroup.
+  if (role == roles::SECTION)
+    return eSkip;
+
+  return eSkipSubtree;
 }
 
-bool
+uint32_t
 filters::GetCell(Accessible* aAccessible)
 {
-  roles::Role role = aAccessible->Role();
+  a11y::role role = aAccessible->Role();
   return role == roles::GRID_CELL || role == roles::ROWHEADER ||
-      role == roles::COLUMNHEADER;
+    role == roles::COLUMNHEADER ? eMatch : eSkipSubtree;
 }
 
-bool
+uint32_t
 filters::GetEmbeddedObject(Accessible* aAccessible)
 {
-  return nsAccUtils::IsEmbeddedObject(aAccessible);
+  return nsAccUtils::IsEmbeddedObject(aAccessible) ?
+    eMatch | eSkipSubtree : eSkipSubtree;
 }
rename from accessible/src/base/filters.h
rename to accessible/src/base/AccFilters.h
--- a/accessible/src/base/filters.h
+++ b/accessible/src/base/AccFilters.h
@@ -1,27 +1,55 @@
 /* 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 a11yFilters_h_
-#define a11yFilters_h_
+#ifndef mozilla_a11y_Filters_h__
+#define mozilla_a11y_Filters_h__
+
+#include "mozilla/StandardInteger.h"
 
 class Accessible;
 
 /**
  * Predefined filters used for nsAccIterator and nsAccCollector.
  */
+namespace mozilla {
+namespace a11y {
 namespace filters {
 
-  /**
-   * Return true if the traversed accessible complies with filter.
-   */
-  typedef bool (*FilterFuncPtr) (Accessible*);
+enum EResult {
+  eSkip = 0,
+  eMatch = 1,
+  eSkipSubtree = 2
+};
+
+/**
+ * Return true if the traversed accessible complies with filter.
+ */
+typedef uint32_t (*FilterFuncPtr) (Accessible*);
+
+/**
+ * Matches selected/selectable accessibles in subtree.
+ */
+uint32_t GetSelected(Accessible* aAccessible);
+uint32_t GetSelectable(Accessible* aAccessible);
 
-  bool GetSelected(Accessible* aAccessible);
-  bool GetSelectable(Accessible* aAccessible);
-  bool GetRow(Accessible* aAccessible);
-  bool GetCell(Accessible* aAccessible);
-  bool GetEmbeddedObject(Accessible* aAccessible);
-}
+/**
+ * Matches row accessibles in subtree.
+ */
+uint32_t GetRow(Accessible* aAccessible);
+
+/**
+ * Matches cell accessibles in children.
+ */
+uint32_t GetCell(Accessible* aAccessible);
+
+/**
+ * Matches embedded objects in children.
+ */
+uint32_t GetEmbeddedObject(Accessible* aAccessible);
+
+} // namespace filters
+} // namespace a11y
+} // namespace mozilla
 
 #endif
--- a/accessible/src/base/AccIterator.cpp
+++ b/accessible/src/base/AccIterator.cpp
@@ -13,19 +13,18 @@
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccIterator
 ////////////////////////////////////////////////////////////////////////////////
 
 AccIterator::AccIterator(Accessible* aAccessible,
-                         filters::FilterFuncPtr aFilterFunc,
-                         IterationType aIterationType) :
-  mFilterFunc(aFilterFunc), mIsDeep(aIterationType != eFlatNav)
+                         filters::FilterFuncPtr aFilterFunc) :
+  mFilterFunc(aFilterFunc)
 {
   mState = new IteratorState(aAccessible);
 }
 
 AccIterator::~AccIterator()
 {
   while (mState) {
     IteratorState *tmp = mState;
@@ -35,29 +34,29 @@ AccIterator::~AccIterator()
 }
 
 Accessible*
 AccIterator::Next()
 {
   while (mState) {
     Accessible* child = mState->mParent->GetChildAt(mState->mIndex++);
     if (!child) {
-      IteratorState *tmp = mState;
+      IteratorState* tmp = mState;
       mState = mState->mParentState;
       delete tmp;
 
       continue;
     }
 
-    bool isComplying = mFilterFunc(child);
-    if (isComplying)
+    uint32_t result = mFilterFunc(child);
+    if (result & filters::eMatch)
       return child;
 
-    if (mIsDeep) {
-      IteratorState *childState = new IteratorState(child, mState);
+    if (!(result & filters::eSkipSubtree)) {
+      IteratorState* childState = new IteratorState(child, mState);
       mState = childState;
     }
   }
 
   return nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/base/AccIterator.h
+++ b/accessible/src/base/AccIterator.h
@@ -1,21 +1,23 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef nsAccIterator_h_
-#define nsAccIterator_h_
+#ifndef mozilla_a11y_AccIterator_h__
+#define mozilla_a11y_AccIterator_h__
 
+#include "DocAccessible.h"
+#include "AccFilters.h"
 #include "nsAccessibilityService.h"
-#include "filters.h"
-#include "nscore.h"
-#include "DocAccessible.h"
+
+namespace mozilla {
+namespace a11y {
 
 /**
  * AccIterable is a basic interface for iterators over accessibles.
  */
 class AccIterable
 {
 public:
   virtual ~AccIterable() { }
@@ -28,34 +30,17 @@ private:
 
 /**
  * Allows to iterate through accessible children or subtree complying with
  * filter function.
  */
 class AccIterator : public AccIterable
 {
 public:
-  /**
-   * Used to define iteration type.
-   */
-  enum IterationType {
-    /**
-     * Navigation happens through direct children.
-     */
-    eFlatNav,
-
-    /**
-     * Navigation through subtree excluding iterator root; if the accessible
-     * complies with filter, iterator ignores its children.
-     */
-    eTreeNav
-  };
-
-  AccIterator(Accessible* aRoot, filters::FilterFuncPtr aFilterFunc,
-              IterationType aIterationType = eFlatNav);
+  AccIterator(Accessible* aRoot, filters::FilterFuncPtr aFilterFunc);
   virtual ~AccIterator();
 
   /**
    * Return next accessible complying with filter function. Return the first
    * accessible for the first time.
    */
   virtual Accessible* Next();
 
@@ -65,22 +50,21 @@ private:
   AccIterator& operator =(const AccIterator&);
 
   struct IteratorState
   {
     IteratorState(Accessible* aParent, IteratorState* mParentState = nullptr);
 
     Accessible* mParent;
     int32_t mIndex;
-    IteratorState *mParentState;
+    IteratorState* mParentState;
   };
 
   filters::FilterFuncPtr mFilterFunc;
-  bool mIsDeep;
-  IteratorState *mState;
+  IteratorState* mState;
 };
 
 
 /**
  * Allows to traverse through related accessibles that are pointing to the given
  * dependent accessible by relation attribute.
  */
 class RelatedAccIterator : public AccIterable
@@ -277,9 +261,12 @@ public:
 private:
   SingleAccIterator();
   SingleAccIterator(const SingleAccIterator&);
   SingleAccIterator& operator = (const SingleAccIterator&);
 
   nsRefPtr<Accessible> mAcc;
 };
 
+} // namespace a11y
+} // namespace mozilla
+
 #endif
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -14,18 +14,18 @@ LIBRARY_NAME = accessibility_base_s
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS = \
   AccCollector.cpp \
   AccEvent.cpp \
   AccGroupInfo.cpp \
   AccIterator.cpp \
+  AccFilters.cpp \
   ARIAStateMap.cpp \
-  filters.cpp \
   FocusManager.cpp \
   NotificationController.cpp \
   nsAccDocManager.cpp \
   nsAccessNode.cpp \
   nsARIAMap.cpp \
   nsCoreUtils.cpp \
   nsAccUtils.cpp \
   nsAccessibilityService.cpp \
--- a/accessible/src/base/Relation.h
+++ b/accessible/src/base/Relation.h
@@ -14,36 +14,38 @@ 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(AccIterable* aFirstIter, AccIterable* aLastIter) :
+  RelationCopyHelper(mozilla::a11y::AccIterable* aFirstIter,
+                     mozilla::a11y::AccIterable* aLastIter) :
     mFirstIter(aFirstIter), mLastIter(aLastIter) { }
 
-  AccIterable* mFirstIter;
-  AccIterable* mLastIter;
+  mozilla::a11y::AccIterable* mFirstIter;
+  mozilla::a11y::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(AccIterable* aIter) : mFirstIter(aIter), mLastIter(aIter) { }
+  Relation(mozilla::a11y::AccIterable* aIter) :
+    mFirstIter(aIter), mLastIter(aIter) { }
 
   Relation(Accessible* aAcc) :
     mFirstIter(nullptr), mLastIter(nullptr)
     { AppendTarget(aAcc); }
 
   Relation(DocAccessible* aDocument, nsIContent* aContent) :
     mFirstIter(nullptr), mLastIter(nullptr)
     { AppendTarget(aDocument, aContent); }
@@ -62,33 +64,33 @@ public:
     return *this;
   }
 
   operator RelationCopyHelper()
   {
     return RelationCopyHelper(mFirstIter.forget(), mLastIter);
   }
 
-  inline void AppendIter(AccIterable* aIter)
+  inline void AppendIter(mozilla::a11y::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 SingleAccIterator(aAcc));
+      AppendIter(new mozilla::a11y::SingleAccIterator(aAcc));
   }
 
   /**
    * Append the one accessible for this content node to the set of related
    * accessibles.
    */
   void AppendTarget(DocAccessible* aDocument, nsIContent* aContent)
   {
@@ -111,17 +113,17 @@ public:
       mLastIter = nullptr;
 
     return target;
   }
 
 private:
   Relation& operator = (const Relation&);
 
-  nsAutoPtr<AccIterable> mFirstIter;
-  AccIterable* mLastIter;
+  nsAutoPtr<mozilla::a11y::AccIterable> mFirstIter;
+  mozilla::a11y::AccIterable* mLastIter;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
 
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -98,17 +98,17 @@ public:
 
   /**
    * Return true if the accessible is primary accessible for the given DOM node.
    *
    * Accessible hierarchy may be complex for single DOM node, in this case
    * these accessibles share the same DOM node. The primary accessible "owns"
    * that DOM node in terms it gets stored in the accessible to node map.
    */
-  virtual bool IsPrimaryForNode() const;
+  virtual bool IsPrimaryForNode() const;//hello
 
   /**
    * Interface methods on nsIAccessible shared with ISimpleDOM.
    */
   void Language(nsAString& aLocale);
 
 protected:
   void LastRelease();
new file mode 100644
--- /dev/null
+++ b/accessible/src/generic/ARIAGridAccessible-inl.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_ARIAGridAccessible_inl_h__
+#define mozilla_a11y_ARIAGridAccessible_inl_h__
+
+#include "ARIAGridAccessible.h"
+
+#include "AccIterator.h"
+
+inline Accessible*
+mozilla::a11y::ARIAGridCellAccessible::TableFor(Accessible* aRow) const
+{
+  if (aRow) {
+    Accessible* table = aRow->Parent();
+    if (table) {
+      roles::Role tableRole = table->Role();
+      if (tableRole == roles::SECTION) { // if there's a rowgroup.
+        table = table->Parent();
+        if (table)
+          tableRole = table->Role();
+      }
+
+      return tableRole == roles::TABLE || tableRole == roles::TREE_TABLE ?
+        table : nullptr;
+    }
+  }
+
+  return nullptr;
+}
+
+inline int32_t
+mozilla::a11y::ARIAGridCellAccessible::RowIndexFor(Accessible* aRow) const
+{
+  Accessible* table = TableFor(aRow);
+  if (table) {
+    int32_t rowIdx = 0;
+    Accessible* row = nullptr;
+    AccIterator rowIter(table, filters::GetRow);
+    while ((row = rowIter.Next()) && row != aRow)
+      rowIdx++;
+
+    if (row)
+      return rowIdx;
+  }
+
+  return -1;
+}
+
+#endif
--- a/accessible/src/generic/ARIAGridAccessible.cpp
+++ b/accessible/src/generic/ARIAGridAccessible.cpp
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "ARIAGridAccessible.h"
+#include "ARIAGridAccessible-inl.h"
 
 #include "Accessible-inl.h"
 #include "AccIterator.h"
 #include "nsAccUtils.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsIMutableArray.h"
@@ -546,29 +546,20 @@ NS_IMPL_ISUPPORTS_INHERITED1(ARIAGridCel
 // nsIAccessibleTableCell
 
 NS_IMETHODIMP
 ARIAGridCellAccessible::GetTable(nsIAccessibleTable** aTable)
 {
   NS_ENSURE_ARG_POINTER(aTable);
   *aTable = nullptr;
 
-  Accessible* thisRow = Parent();
-  if (!thisRow || thisRow->Role() != roles::ROW)
-    return NS_OK;
+  Accessible* table = TableFor(Row());
+  if (table)
+    CallQueryInterface(table, aTable);
 
-  Accessible* table = thisRow->Parent();
-  if (!table)
-    return NS_OK;
-
-  roles::Role tableRole = table->Role();
-  if (tableRole != roles::TABLE && tableRole != roles::TREE_TABLE)
-    return NS_OK;
-
-  CallQueryInterface(table, aTable);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ARIAGridCellAccessible::GetColumnIndex(int32_t* aColumnIndex)
 {
   NS_ENSURE_ARG_POINTER(aColumnIndex);
   *aColumnIndex = -1;
@@ -598,33 +589,17 @@ NS_IMETHODIMP
 ARIAGridCellAccessible::GetRowIndex(int32_t* aRowIndex)
 {
   NS_ENSURE_ARG_POINTER(aRowIndex);
   *aRowIndex = -1;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  Accessible* row = Parent();
-  if (!row)
-    return NS_OK;
-
-  Accessible* table = row->Parent();
-  if (!table)
-    return NS_OK;
-
-  *aRowIndex = 0;
-
-  int32_t indexInTable = row->IndexInParent();
-  for (int32_t idx = 0; idx < indexInTable; idx++) {
-    row = table->GetChildAt(idx);
-    if (row->Role() == roles::ROW)
-      (*aRowIndex)++;
-  }
-
+  *aRowIndex = RowIndexFor(Row());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ARIAGridCellAccessible::GetColumnExtent(int32_t* aExtentCount)
 {
   NS_ENSURE_ARG_POINTER(aExtentCount);
   *aExtentCount = 0;
@@ -733,62 +708,42 @@ ARIAGridCellAccessible::ApplyARIAState(u
     *aState |= states::SELECTABLE | states::SELECTED;
 }
 
 nsresult
 ARIAGridCellAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
-  
+
   nsresult rv = HyperTextAccessibleWrap::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Expose "table-cell-index" attribute.
-
-  Accessible* thisRow = Parent();
-  if (!thisRow || thisRow->Role() != roles::ROW)
+  Accessible* thisRow = Row();
+  if (!thisRow)
     return NS_OK;
 
   int32_t colIdx = 0, colCount = 0;
   uint32_t childCount = thisRow->ChildCount();
   for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
     Accessible* child = thisRow->GetChildAt(childIdx);
     if (child == this)
       colIdx = colCount;
 
     roles::Role role = child->Role();
     if (role == roles::GRID_CELL || role == roles::ROWHEADER ||
         role == roles::COLUMNHEADER)
       colCount++;
   }
 
-  Accessible* table = thisRow->Parent();
-  if (!table)
-    return NS_OK;
-
-  roles::Role tableRole = table->Role();
-  if (tableRole != roles::TABLE && tableRole != roles::TREE_TABLE)
-    return NS_OK;
-
-  int32_t rowIdx = 0;
-  childCount = table->ChildCount();
-  for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
-    Accessible* child = table->GetChildAt(childIdx);
-    if (child == thisRow)
-      break;
-
-    if (child->Role() == roles::ROW)
-      rowIdx++;
-  }
-
-  int32_t idx = rowIdx * colCount + colIdx;
+  int32_t rowIdx = RowIndexFor(thisRow);
 
   nsAutoString stringIdx;
-  stringIdx.AppendInt(idx);
+  stringIdx.AppendInt(rowIdx * colCount + colIdx);
   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex,
                          stringIdx);
 
   return NS_OK;
 }
 
 void
 ARIAGridCellAccessible::Shutdown()
--- a/accessible/src/generic/ARIAGridAccessible.h
+++ b/accessible/src/generic/ARIAGridAccessible.h
@@ -55,16 +55,17 @@ public:
   virtual void SelectedColIndices(nsTArray<uint32_t>* aCols);
   virtual void SelectedRowIndices(nsTArray<uint32_t>* aRows);
   virtual void SelectCol(uint32_t aColIdx);
   virtual void SelectRow(uint32_t aRowIdx);
   virtual void UnselectCol(uint32_t aColIdx);
   virtual void UnselectRow(uint32_t aRowIdx);
 
 protected:
+
   /**
    * Return true if the given row index is valid.
    */
   bool IsValidRow(int32_t aRow);
 
   /**
    * Retrn true if the given column index is valid.
    */
@@ -109,14 +110,35 @@ public:
 
   // nsIAccessibleTableCell
   NS_DECL_OR_FORWARD_NSIACCESSIBLETABLECELL_WITH_XPCACCESSIBLETABLECELL
 
   // Accessible
   virtual void Shutdown();
   virtual void ApplyARIAState(uint64_t* aState) const;
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+
+protected:
+
+  /**
+   * Return a containing row.
+   */
+  Accessible* Row() const
+  {
+    Accessible* row = Parent();
+    return row && row->Role() == roles::ROW ? row : nullptr;
+  }
+
+  /**
+   * Return a table for the given row.
+   */
+  Accessible* TableFor(Accessible* aRow) const;
+
+  /**
+   * Return index of the given row.
+   */
+  int32_t RowIndexFor(Accessible* aRow) const;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -2723,115 +2723,115 @@ Accessible::IsSelect()
 
 already_AddRefed<nsIArray>
 Accessible::SelectedItems()
 {
   nsCOMPtr<nsIMutableArray> selectedItems = do_CreateInstance(NS_ARRAY_CONTRACTID);
   if (!selectedItems)
     return nullptr;
 
-  AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
+  AccIterator iter(this, filters::GetSelected);
   nsIAccessible* selected = nullptr;
   while ((selected = iter.Next()))
     selectedItems->AppendElement(selected, false);
 
   nsIMutableArray* items = nullptr;
   selectedItems.forget(&items);
   return items;
 }
 
 uint32_t
 Accessible::SelectedItemCount()
 {
   uint32_t count = 0;
-  AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
+  AccIterator iter(this, filters::GetSelected);
   Accessible* selected = nullptr;
   while ((selected = iter.Next()))
     ++count;
 
   return count;
 }
 
 Accessible*
 Accessible::GetSelectedItem(uint32_t aIndex)
 {
-  AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
+  AccIterator iter(this, filters::GetSelected);
   Accessible* selected = nullptr;
 
   uint32_t index = 0;
   while ((selected = iter.Next()) && index < aIndex)
     index++;
 
   return selected;
 }
 
 bool
 Accessible::IsItemSelected(uint32_t aIndex)
 {
   uint32_t index = 0;
-  AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
+  AccIterator iter(this, filters::GetSelectable);
   Accessible* selected = nullptr;
   while ((selected = iter.Next()) && index < aIndex)
     index++;
 
   return selected &&
     selected->State() & states::SELECTED;
 }
 
 bool
 Accessible::AddItemToSelection(uint32_t aIndex)
 {
   uint32_t index = 0;
-  AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
+  AccIterator iter(this, filters::GetSelectable);
   Accessible* selected = nullptr;
   while ((selected = iter.Next()) && index < aIndex)
     index++;
 
   if (selected)
     selected->SetSelected(true);
 
   return static_cast<bool>(selected);
 }
 
 bool
 Accessible::RemoveItemFromSelection(uint32_t aIndex)
 {
   uint32_t index = 0;
-  AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
+  AccIterator iter(this, filters::GetSelectable);
   Accessible* selected = nullptr;
   while ((selected = iter.Next()) && index < aIndex)
     index++;
 
   if (selected)
     selected->SetSelected(false);
 
   return static_cast<bool>(selected);
 }
 
 bool
 Accessible::SelectAll()
 {
   bool success = false;
   Accessible* selectable = nullptr;
 
-  AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
+  AccIterator iter(this, filters::GetSelectable);
   while((selectable = iter.Next())) {
     success = true;
     selectable->SetSelected(true);
   }
   return success;
 }
 
 bool
 Accessible::UnselectAll()
 {
   bool success = false;
   Accessible* selected = nullptr;
 
-  AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
+  AccIterator iter(this, filters::GetSelected);
   while ((selected = iter.Next())) {
     success = true;
     selected->SetSelected(false);
   }
   return success;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -18,25 +18,25 @@
 #include "nsIContent.h"
 
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "nsRefPtrHashtable.h"
 
 class AccEvent;
 class AccGroupInfo;
-class EmbeddedObjCollector;
 class KeyBinding;
 class Accessible;
 class HyperTextAccessible;
 struct nsRoleMapEntry;
 
 namespace mozilla {
 namespace a11y {
 
+class EmbeddedObjCollector;
 class HTMLImageMapAccessible;
 class HTMLLIAccessible;
 class ImageAccessible;
 class Relation;
 class TableAccessible;
 class TextLeafAccessible;
 class XULTreeAccessible;
 
@@ -870,19 +870,19 @@ protected:
   int32_t mIndexInParent;
 
   static const uint32_t kChildrenFlagsMask =
     eChildrenUninitialized | eMixedChildren | eEmbeddedChildren;
 
   uint32_t mFlags;
   friend class DocAccessible;
 
-  nsAutoPtr<EmbeddedObjCollector> mEmbeddedObjCollector;
+  nsAutoPtr<mozilla::a11y::EmbeddedObjCollector> mEmbeddedObjCollector;
   int32_t mIndexOfEmbeddedChild;
-  friend class EmbeddedObjCollector;
+  friend class mozilla::a11y::EmbeddedObjCollector;
 
   nsAutoPtr<AccGroupInfo> mGroupInfo;
   friend class AccGroupInfo;
 
   /**
    * Non-null indicates author-supplied role; possibly state & value as well
    */
   nsRoleMapEntry* mRoleMapEntry;
--- a/accessible/src/generic/DocAccessible.h
+++ b/accessible/src/generic/DocAccessible.h
@@ -28,16 +28,24 @@ template<class Class, class Arg>
 class TNotification;
 class NotificationController;
 
 class nsIScrollableView;
 class nsAccessiblePivot;
 
 const uint32_t kDefaultCacheSize = 256;
 
+namespace mozilla {
+namespace a11y {
+
+class RelatedAccIterator;
+
+} // namespace a11y
+} // namespace mozilla
+
 class DocAccessible : public HyperTextAccessibleWrap,
                       public nsIAccessibleDocument,
                       public nsIDocumentObserver,
                       public nsIObserver,
                       public nsIScrollPositionListener,
                       public nsSupportsWeakReference,
                       public nsIAccessibleCursorable,
                       public nsIAccessiblePivotObserver
@@ -562,17 +570,17 @@ protected:
   };
 
   /**
    * The cache of IDs pointed by relation attributes.
    */
   typedef nsTArray<nsAutoPtr<AttrRelProvider> > AttrRelProviderArray;
   nsClassHashtable<nsStringHashKey, AttrRelProviderArray> mDependentIDsHash;
 
-  friend class RelatedAccIterator;
+  friend class mozilla::a11y::RelatedAccIterator;
 
   /**
    * Used for our caching algorithm. We store the list of nodes that should be
    * invalidated.
    *
    * @see ProcessInvalidationList
    */
   nsTArray<nsIContent*> mInvalidationList;
--- a/accessible/tests/mochitest/table/test_indexes_ariagrid.html
+++ b/accessible/tests/mochitest/table/test_indexes_ariagrid.html
@@ -23,16 +23,24 @@
       var idxes = [
         [0, 1, 2],
         [3, 4, 5],
         [6, 7, 8],
         [9, 10, 11]
       ];
       testTableIndexes("grid", idxes);
 
+      idxes = [
+        [0, 1, 2],
+        [3, 4, 5],
+        [6, 7, 8],
+        [9, 10, 11]
+      ];
+      testTableIndexes("grid-rowgroups", idxes);
+
       //////////////////////////////////////////////////////////////////////////
       // a bit crazy ARIA grid
       idxes = [
         [0, 1],
         [2, 3]
       ];
       testTableIndexes("grid2", idxes);
 
@@ -46,16 +54,19 @@
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=386813"
      title="support nsIAccessibleTable on ARIA grid/treegrid">Mozilla Bug 386813</a>
   <a target="_blank"
      title="nsHTMLTableCellAccessible is used in dojo's crazy ARIA grid"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=513848">Mozilla Bug 513848</a>
+  <a target="_blank"
+     title="ARIA grid with rowgroup breaks table row/col counting and indices"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=761853">Mozilla Bug 761853</a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div role="grid" id="grid">
     <div role="row">
@@ -75,16 +86,41 @@
     </div>
     <div role="row">
       <span role="rowheader">row3</span>
       <span role="gridcell">cell5</span>
       <span role="gridcell">cell6</span>
     </div>
   </div>
 
+  <div role="grid" id="grid-rowgroups">
+    <div role="row">
+      <span role="columnheader">grid-rowgroups-col1</span>
+      <span role="columnheader">grid-rowgroups-col2</span>
+      <span role="columnheader">grid-rowgroups-col3</span>
+    </div>
+    <div role="rowgroup">
+      <div role="row">
+        <span role="rowheader">grid-rowgroups-row1</span>
+        <span role="gridcell">grid-rowgroups-cell1</span>
+        <span role="gridcell">grid-rowgroups-cell2</span>
+      </div>
+      <div role="row">
+        <span role="rowheader">grid-rowgroups-row2</span>
+        <span role="gridcell">grid-rowgroups-cell3</span>
+        <span role="gridcell">grid-rowgroups-cell4</span>
+      </div>
+    </div>
+    <div role="row">
+      <span role="rowheader">grid-rowgroups-row3</span>
+      <span role="gridcell">grid-rowgroups-cell5</span>
+      <span role="gridcell">grid-rowgroups-cell6</span>
+    </div>
+  </div>
+
   <div role="grid" id="grid2">
     <div role="row">
       <table role="presentation">
         <tr>
           <td role="columnheader">header1</td>
           <td role="columnheader">header2</td>
         </tr>
       </table>
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -41,18 +41,21 @@ let keysbundle = Services.strings.create
 
 function SP_Pretty_Key(aElemKey) {
 
   let elemString = "";
   let elemMod = aElemKey.getAttribute("modifiers");
 
   if (elemMod.match("accel")) {
     if (navigator.platform.indexOf("Mac") !== -1) {
-      elemString += keysbundle.GetStringFromName("VK_META") +
-                    keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
+      // XXX bug 779642 Use "Cmd-" literal vs cloverleaf meta-key until
+      // Orion adds variable height lines
+      // elemString += keysbundle.GetStringFromName("VK_META_CMD") +
+      //               keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
+      elemString += "Cmd-";
     } else {
       elemString += keysbundle.GetStringFromName("VK_CONTROL") +
                     keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
     }
   }
 
   if (elemMod.match("shift")) {
     elemString += keysbundle.GetStringFromName("VK_SHIFT") +
--- a/chrome/src/RegistryMessageUtils.h
+++ b/chrome/src/RegistryMessageUtils.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_RegistryMessageUtils_h
 #define mozilla_RegistryMessageUtils_h
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsStringGlue.h"
 
 struct SerializedURI
 {
   nsCString spec;
   nsCString charset;
 };
 
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1478,20 +1478,22 @@ public:
    * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
    * parser-module is linked with gklayout-module.  aCrossOriginAttr should
    * be a void string if the attr is not present.
    */
   virtual void MaybePreLoadImage(nsIURI* uri,
                                  const nsAString& aCrossOriginAttr) = 0;
 
   /**
-   * Called by nsParser to preload style sheets.  Can also be merged into
-   * the parser if and when the parser is merged with libgklayout.
+   * Called by nsParser to preload style sheets.  Can also be merged into the
+   * parser if and when the parser is merged with libgklayout.  aCrossOriginAttr
+   * should be a void string if the attr is not present.
    */
-  virtual void PreloadStyle(nsIURI* aURI, const nsAString& aCharset) = 0;
+  virtual void PreloadStyle(nsIURI* aURI, const nsAString& aCharset,
+                            const nsAString& aCrossOriginAttr) = 0;
 
   /**
    * Called by the chrome registry to load style sheets.  Can be put
    * back there if and when when that module is merged with libgklayout.
    *
    * This always does a synchronous load.  If aIsAgentSheet is true,
    * it also uses the system principal and enables unsafe rules.
    * DO NOT USE FOR UNTRUSTED CONTENT.
--- a/content/base/src/FileIOObject.cpp
+++ b/content/base/src/FileIOObject.cpp
@@ -33,25 +33,27 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(FileIOObj
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileIOObject,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressNotifier)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(abort)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(progress)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mError)
+  // Can't traverse mChannel because it's a multithreaded object.
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileIOObject,
                                                 nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressNotifier)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(abort)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(progress)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mError)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 FileIOObject::FileIOObject()
   : mProgressEventWasDelayed(false),
     mTimerIsActive(false),
     mReadyState(0),
     mTotal(0), mTransferred(0)
 {}
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -345,17 +345,17 @@ nsContentSink::ProcessHeaderData(nsIAtom
 }
 
 
 void
 nsContentSink::DoProcessLinkHeader()
 {
   nsAutoString value;
   mDocument->GetHeaderData(nsGkAtoms::link, value);
-  ProcessLinkHeader(nullptr, value);
+  ProcessLinkHeader(value);
 }
 
 // check whether the Link header field applies to the context resource
 // see <http://tools.ietf.org/html/rfc5988#section-5.2>
 
 bool
 nsContentSink::LinkContextIsOurDocument(const nsSubstring& aAnchor)
 {
@@ -435,18 +435,17 @@ nsContentSink::Decode5987Format(nsAStrin
   if (NS_FAILED(rv))
     return false;
 
   aEncoded = decoded;
   return true;
 }
 
 nsresult
-nsContentSink::ProcessLinkHeader(nsIContent* aElement,
-                                 const nsAString& aLinkData)
+nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
 {
   nsresult rv = NS_OK;
 
   // keep track where we are within the header field
   bool seenParameters = false;
 
   // parse link content and call process style link
   nsAutoString href;
@@ -635,17 +634,17 @@ nsContentSink::ProcessLinkHeader(nsICont
       }
     }
 
     if (endCh == kComma) {
       // hit a comma, process what we've got so far
 
       href.Trim(" \t\n\r\f"); // trim HTML5 whitespace
       if (!href.IsEmpty() && !rel.IsEmpty()) {
-        rv = ProcessLink(aElement, anchor, href, rel,
+        rv = ProcessLink(anchor, href, rel,
                          // prefer RFC 5987 variant over non-I18zed version
                          titleStar.IsEmpty() ? title : titleStar,
                          type, media);
       }
 
       href.Truncate();
       rel.Truncate();
       title.Truncate();
@@ -656,59 +655,58 @@ nsContentSink::ProcessLinkHeader(nsICont
       seenParameters = false;
     }
 
     start = ++end;
   }
                 
   href.Trim(" \t\n\r\f"); // trim HTML5 whitespace
   if (!href.IsEmpty() && !rel.IsEmpty()) {
-    rv = ProcessLink(aElement, anchor, href, rel,
+    rv = ProcessLink(anchor, href, rel,
                      // prefer RFC 5987 variant over non-I18zed version
                      titleStar.IsEmpty() ? title : titleStar,
                      type, media);
   }
 
   return rv;
 }
 
 
 nsresult
-nsContentSink::ProcessLink(nsIContent* aElement,
-                           const nsSubstring& aAnchor, const nsSubstring& aHref,
+nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
                            const nsSubstring& aRel, const nsSubstring& aTitle,
                            const nsSubstring& aType, const nsSubstring& aMedia)
 {
   uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(aRel);
 
   // The link relation may apply to a different resource, specified
   // in the anchor parameter. For the link relations supported so far,
   // we simply abort if the link applies to a resource different to the
   // one we've loaded
   if (!LinkContextIsOurDocument(aAnchor)) {
     return NS_OK;
   }
   
   bool hasPrefetch = linkTypes & PREFETCH;
   // prefetch href if relation is "next" or "prefetch"
   if (hasPrefetch || (linkTypes & NEXT)) {
-    PrefetchHref(aHref, aElement, hasPrefetch);
+    PrefetchHref(aHref, nullptr, hasPrefetch);
   }
 
   if (!aHref.IsEmpty() && (linkTypes & DNS_PREFETCH)) {
     PrefetchDNS(aHref);
   }
 
   // is it a stylesheet link?
   if (!(linkTypes & STYLESHEET)) {
     return NS_OK;
   }
 
   bool isAlternate = linkTypes & ALTERNATE;
-  return ProcessStyleLink(aElement, aHref, isAlternate, aTitle, aType,
+  return ProcessStyleLink(nullptr, aHref, isAlternate, aTitle, aType,
                           aMedia);
 }
 
 nsresult
 nsContentSink::ProcessStyleLink(nsIContent* aElement,
                                 const nsSubstring& aHref,
                                 bool aAlternate,
                                 const nsSubstring& aTitle,
@@ -734,19 +732,25 @@ nsContentSink::ProcessStyleLink(nsIConte
   nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr,
                           mDocument->GetDocBaseURI());
   
   if (NS_FAILED(rv)) {
     // The URI is bad, move along, don't propagate the error (for now)
     return NS_OK;
   }
 
+  NS_ASSERTION(!aElement ||
+               aElement->NodeType() == nsIDOMNode::PROCESSING_INSTRUCTION_NODE,
+               "We only expect processing instructions here");
+
   // If this is a fragment parser, we don't want to observe.
+  // We don't support CORS for processing instructions
   bool isAlternate;
   rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate,
+                                 CORS_NONE,
                                  mRunsToCompletion ? nullptr : this, &isAlternate);
   NS_ENSURE_SUCCESS(rv, rv);
   
   if (!isAlternate && !mRunsToCompletion) {
     ++mPendingSheetCount;
     mScriptLoader->AddExecuteBlocker();
   }
 
--- a/content/base/src/nsContentSink.h
+++ b/content/base/src/nsContentSink.h
@@ -141,19 +141,18 @@ protected:
   };
 
   nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
                 nsISupports* aContainer, nsIChannel* aChannel);
 
   nsresult ProcessHTTPHeaders(nsIChannel* aChannel);
   nsresult ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue,
                              nsIContent* aContent = nullptr);
-  nsresult ProcessLinkHeader(nsIContent* aElement,
-                             const nsAString& aLinkData);
-  nsresult ProcessLink(nsIContent* aElement, const nsSubstring& aAnchor,
+  nsresult ProcessLinkHeader(const nsAString& aLinkData);
+  nsresult ProcessLink(const nsSubstring& aAnchor,
                        const nsSubstring& aHref, const nsSubstring& aRel,
                        const nsSubstring& aTitle, const nsSubstring& aType,
                        const nsSubstring& aMedia);
 
   virtual nsresult ProcessStyleLink(nsIContent* aElement,
                                     const nsSubstring& aHref,
                                     bool aAlternate,
                                     const nsSubstring& aTitle,
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -57,17 +57,16 @@ using namespace mozilla;
 using mozilla::dom::FileIOObject;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileReader)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileReader,
                                                   FileIOObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFile)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(load)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(loadstart)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(loadend)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileReader,
                                                 FileIOObject)
   tmp->mResultArrayBuffer = nullptr;
@@ -333,16 +332,23 @@ nsDOMFileReader::DoOnDataAvailable(nsIRe
 
 nsresult
 nsDOMFileReader::DoOnStopRequest(nsIRequest *aRequest,
                                  nsISupports *aContext,
                                  nsresult aStatus,
                                  nsAString& aSuccessEvent,
                                  nsAString& aTerminationEvent)
 {
+  // Make sure we drop all the objects that could hold files open now.
+  nsCOMPtr<nsIChannel> channel;
+  mChannel.swap(channel);
+
+  nsCOMPtr<nsIDOMBlob> file;
+  mFile.swap(file);
+
   aSuccessEvent = NS_LITERAL_STRING(LOAD_STR);
   aTerminationEvent = NS_LITERAL_STRING(LOADEND_STR);
 
   // Clear out the data if necessary
   if (NS_FAILED(aStatus)) {
     FreeFileData();
     return NS_OK;
   }
@@ -352,17 +358,17 @@ nsDOMFileReader::DoOnStopRequest(nsIRequ
     case FILE_AS_ARRAYBUFFER:
       break; //Already accumulated mResultArrayBuffer
     case FILE_AS_BINARY:
       break; //Already accumulated mResult
     case FILE_AS_TEXT:
       rv = GetAsText(mCharset, mFileData, mDataLen, mResult);
       break;
     case FILE_AS_DATAURL:
-      rv = GetAsDataURL(mFile, mFileData, mDataLen, mResult);
+      rv = GetAsDataURL(file, mFileData, mDataLen, mResult);
       break;
   }
   
   mResult.SetIsVoid(false);
 
   FreeFileData();
 
   return rv;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -7757,25 +7757,27 @@ public:
   }
   NS_DECL_ISUPPORTS
 };
 NS_IMPL_ISUPPORTS1(StubCSSLoaderObserver, nsICSSLoaderObserver)
 
 }
 
 void
-nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset)
+nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset,
+                         const nsAString& aCrossOriginAttr)
 {
   // The CSSLoader will retain this object after we return.
   nsCOMPtr<nsICSSLoaderObserver> obs = new StubCSSLoaderObserver();
 
   // Charset names are always ASCII.
   CSSLoader()->LoadSheet(uri, NodePrincipal(),
                          NS_LossyConvertUTF16toASCII(charset),
-                         obs);
+                         obs,
+                         nsGenericElement::StringToCORSMode(aCrossOriginAttr));
 }
 
 nsresult
 nsDocument::LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet,
                                 nsCSSStyleSheet** sheet)
 {
   return CSSLoader()->LoadSheetSync(uri, isAgentSheet, isAgentSheet, sheet);
 }
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -872,17 +872,18 @@ public:
 
   void MaybeInitializeFinalizeFrameLoaders();
 
   void MaybeEndOutermostXBLUpdate();
 
   virtual void MaybePreLoadImage(nsIURI* uri,
                                  const nsAString &aCrossOriginAttr);
 
-  virtual void PreloadStyle(nsIURI* uri, const nsAString& charset);
+  virtual void PreloadStyle(nsIURI* uri, const nsAString& charset,
+                            const nsAString& aCrossOriginAttr);
 
   virtual nsresult LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet,
                                        nsCSSStyleSheet** sheet);
 
   virtual nsISupports* GetCurrentContentSink();
 
   virtual nsEventStates GetDocumentState();
 
--- a/content/base/src/nsStyleLinkElement.cpp
+++ b/content/base/src/nsStyleLinkElement.cpp
@@ -271,18 +271,18 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
                       aObserver, &doneLoading, &isAlternate);
   }
   else {
     // XXXbz clone the URI here to work around content policies modifying URIs.
     nsCOMPtr<nsIURI> clonedURI;
     uri->Clone(getter_AddRefs(clonedURI));
     NS_ENSURE_TRUE(clonedURI, NS_ERROR_OUT_OF_MEMORY);
     rv = doc->CSSLoader()->
-      LoadStyleLink(thisContent, clonedURI, title, media, isAlternate, aObserver,
-                    &isAlternate);
+      LoadStyleLink(thisContent, clonedURI, title, media, isAlternate,
+                    GetCORSMode(), aObserver, &isAlternate);
     if (NS_FAILED(rv)) {
       // Don't propagate LoadStyleLink() errors further than this, since some
       // consumers (e.g. nsXMLContentSink) will completely abort on innocuous
       // things like a stylesheet load being blocked by the security system.
       doneLoading = true;
       isAlternate = false;
       rv = NS_OK;
     }
--- a/content/base/src/nsStyleLinkElement.h
+++ b/content/base/src/nsStyleLinkElement.h
@@ -14,16 +14,17 @@
 #define nsStyleLinkElement_h___
 
 #include "nsCOMPtr.h"
 #include "nsIDOMLinkStyle.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsIStyleSheet.h"
 #include "nsIURI.h"
 #include "nsTArray.h"
+#include "mozilla/CORSMode.h"
 
 #define PREFETCH      0x00000001
 #define DNS_PREFETCH  0x00000002
 #define STYLESHEET    0x00000004
 #define NEXT          0x00000008
 #define ALTERNATE     0x00000010
 
 class nsIDocument;
@@ -71,16 +72,22 @@ protected:
   virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) = 0;
   virtual void GetStyleSheetInfo(nsAString& aTitle,
                                  nsAString& aType,
                                  nsAString& aMedia,
                                  bool* aIsAlternate) = 0;
 
   nsIStyleSheet* GetStyleSheet() { return mStyleSheet; }
 
+  virtual mozilla::CORSMode GetCORSMode() const
+  {
+    // Default to no CORS
+    return mozilla::CORS_NONE;
+  }
+
 private:
   /**
    * @param aOldDocument should be non-null only if we're updating because we
    *                     removed the node from the document.
    * @param aForceUpdate true will force the update even if the URI has not
    *                     changed.  This should be used in cases when something
    *                     about the content that affects the resulting sheet
    *                     changed but the URI may not have changed.
--- a/content/base/src/nsTreeSanitizer.cpp
+++ b/content/base/src/nsTreeSanitizer.cpp
@@ -1115,17 +1115,17 @@ nsTreeSanitizer::SanitizeStyleSheet(cons
                                     nsIURI* aBaseURI)
 {
   nsresult rv;
   aSanitized.Truncate();
   // aSanitized will hold the permitted CSS text.
   // -moz-binding is blacklisted.
   bool didSanitize = false;
   // Create a sheet to hold the parsed CSS
-  nsRefPtr<nsCSSStyleSheet> sheet = new nsCSSStyleSheet();
+  nsRefPtr<nsCSSStyleSheet> sheet = new nsCSSStyleSheet(CORS_NONE);
   sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
   sheet->SetPrincipal(aDocument->NodePrincipal());
   // Create the CSS parser, and parse the CSS text.
   nsCSSParser parser(nullptr, sheet);
   rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
                          aDocument->NodePrincipal(), 0, false);
   NS_ENSURE_SUCCESS(rv, true);
   // Mark the sheet as complete.
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -16120,22 +16120,19 @@ var _thrown = undefined; try {
 <canvas id="c496" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 
 function test_2d_pattern_repeat_undefined() {
 
 var canvas = document.getElementById('c496');
 var ctx = canvas.getContext('2d');
 
-var undefinedHandler = IsAzureEnabled() ? todo : ok;
-
 var _thrown = undefined; try {
   ctx.createPattern(canvas, undefined);
-  // XXXbz TODO fix bug 784869
-} catch (e) { _thrown = e }; undefinedHandler(_thrown && _thrown.name == "SyntaxError" && _thrown.code == DOMException.SYNTAX_ERR, "should throw SyntaxError");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "SyntaxError" && _thrown.code == DOMException.SYNTAX_ERR, "should throw SyntaxError");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.pattern.repeat.unrecognised.html ]]] -->
 
 <p>Canvas test: 2d.pattern.repeat.unrecognised</p>
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -3,17 +3,17 @@
  * 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 "base/basictypes.h"
 
 /* This must occur *after* base/basictypes.h to avoid typedefs conflicts. */
 #include "mozilla/Util.h"
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsCOMPtr.h"
 #include "nsError.h"
 #include "nsDOMEvent.h"
 #include "nsEventStateManager.h"
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsIDocument.h"
--- a/content/events/src/nsDOMNotifyPaintEvent.cpp
+++ b/content/events/src/nsDOMNotifyPaintEvent.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsDOMNotifyPaintEvent.h"
 #include "nsContentUtils.h"
 #include "nsClientRect.h"
 #include "nsPaintRequest.h"
 #include "nsIFrame.h"
 #include "nsDOMClassInfoID.h"
 
 nsDOMNotifyPaintEvent::nsDOMNotifyPaintEvent(nsPresContext* aPresContext,
--- a/content/events/src/nsDOMScrollAreaEvent.cpp
+++ b/content/events/src/nsDOMScrollAreaEvent.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 #include "nsDOMScrollAreaEvent.h"
 #include "nsGUIEvent.h"
 #include "nsClientRect.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIClassInfo.h"
 #include "nsIXPCScriptable.h"
 
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsCOMPtr.h"
 #include "nsDOMUIEvent.h"
 #include "nsIPresShell.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMNode.h"
 #include "nsIContent.h"
 #include "nsContentUtils.h"
--- a/content/html/content/src/nsHTMLLinkElement.cpp
+++ b/content/html/content/src/nsHTMLLinkElement.cpp
@@ -19,16 +19,18 @@
 #include "nsIDocument.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsContentUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsAsyncDOMEvent.h"
 
 #include "Link.h"
+
+using namespace mozilla;
 using namespace mozilla::dom;
 
 class nsHTMLLinkElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLLinkElement,
                           public nsILink,
                           public nsStyleLinkElement,
                           public Link
 {
@@ -58,16 +60,20 @@ public:
   NS_IMETHOD    LinkAdded();
   NS_IMETHOD    LinkRemoved();
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true);
+  virtual bool ParseAttribute(int32_t aNamespaceID,
+                              nsIAtom* aAttribute,
+                              const nsAString& aValue,
+                              nsAttrValue& aResult);
   void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
   nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, bool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
@@ -89,16 +95,17 @@ public:
   virtual nsXPCClassInfo* GetClassInfo();
   virtual nsIDOMNode* AsDOMNode() { return this; }
 protected:
   virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline);
   virtual void GetStyleSheetInfo(nsAString& aTitle,
                                  nsAString& aType,
                                  nsAString& aMedia,
                                  bool* aIsAlternate);
+  virtual CORSMode GetCORSMode() const;
 protected:
   virtual void GetItemValueText(nsAString& text);
   virtual void SetItemValueText(const nsAString& text);
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Link)
 
@@ -237,16 +244,32 @@ nsHTMLLinkElement::UnbindFromTree(bool a
   if (oldDoc) {
     oldDoc->UnregisterPendingLinkUpdate(this);
   }
   CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved"));
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
   UpdateStyleSheetInternal(oldDoc);
 }
 
+bool
+nsHTMLLinkElement::ParseAttribute(int32_t aNamespaceID,
+                                  nsIAtom* aAttribute,
+                                  const nsAString& aValue,
+                                  nsAttrValue& aResult)
+{
+  if (aNamespaceID == kNameSpaceID_None &&
+      aAttribute == nsGkAtoms::crossorigin) {
+    ParseCORSValue(aValue, aResult);
+    return true;
+  }
+
+  return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
+                                              aResult);
+}
+
 void
 nsHTMLLinkElement::CreateAndDispatchEvent(nsIDocument* aDoc,
                                           const nsAString& aEventName)
 {
   if (!aDoc)
     return;
 
   // In the unlikely case that both rev is specified *and* rel=stylesheet,
@@ -438,16 +461,22 @@ nsHTMLLinkElement::GetStyleSheetInfo(nsA
 
   // If we get here we assume that we're loading a css file, so set the
   // type to 'text/css'
   aType.AssignLiteral("text/css");
 
   return;
 }
 
+CORSMode
+nsHTMLLinkElement::GetCORSMode() const
+{
+  return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); 
+}
+
 nsEventStates
 nsHTMLLinkElement::IntrinsicState() const
 {
   return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
 }
 
 size_t
 nsHTMLLinkElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
--- a/content/svg/content/src/nsSVGStyleElement.cpp
+++ b/content/svg/content/src/nsSVGStyleElement.cpp
@@ -6,16 +6,18 @@
 #include "nsSVGElement.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMSVGStyleElement.h"
 #include "nsUnicharUtils.h"
 #include "nsIDocument.h"
 #include "nsStyleLinkElement.h"
 #include "nsContentUtils.h"
 
+using namespace mozilla;
+
 typedef nsSVGElement nsSVGStyleElementBase;
 
 class nsSVGStyleElement : public nsSVGStyleElementBase,
                           public nsIDOMSVGStyleElement,
                           public nsStyleLinkElement,
                           public nsStubMutationObserver
 {
 protected:
@@ -43,16 +45,20 @@ public:
   {
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify);
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify);
+  virtual bool ParseAttribute(int32_t aNamespaceID,
+                              nsIAtom* aAttribute,
+                              const nsAString& aValue,
+                              nsAttrValue& aResult);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
@@ -71,16 +77,18 @@ protected:
 
   // nsStyleLinkElement overrides
   already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline);
 
   void GetStyleSheetInfo(nsAString& aTitle,
                          nsAString& aType,
                          nsAString& aMedia,
                          bool* aIsAlternate);
+  virtual CORSMode GetCORSMode() const;
+
   /**
    * Common method to call from the various mutation observer methods.
    * aContent is a content node that's either the one that changed or its
    * parent; we should only respond to the change if aContent is non-anonymous.
    */
   void ContentChanged(nsIContent* aContent);
 };
 
@@ -179,16 +187,32 @@ nsSVGStyleElement::UnsetAttr(int32_t aNa
                              (aAttribute == nsGkAtoms::title ||
                               aAttribute == nsGkAtoms::media ||
                               aAttribute == nsGkAtoms::type));
   }
 
   return rv;
 }
 
+bool
+nsSVGStyleElement::ParseAttribute(int32_t aNamespaceID,
+                                  nsIAtom* aAttribute,
+                                  const nsAString& aValue,
+                                  nsAttrValue& aResult)
+{
+  if (aNamespaceID == kNameSpaceID_None &&
+      aAttribute == nsGkAtoms::crossorigin) {
+    ParseCORSValue(aValue, aResult);
+    return true;
+  }
+
+  return nsSVGStyleElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
+                                               aResult);
+}
+
 //----------------------------------------------------------------------
 // nsIMutationObserver methods
 
 void
 nsSVGStyleElement::CharacterDataChanged(nsIDocument* aDocument,
                                         nsIContent* aContent,
                                         CharacterDataChangeInfo* aInfo)
 {
@@ -312,8 +336,14 @@ nsSVGStyleElement::GetStyleSheetInfo(nsA
 
   GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
   if (aType.IsEmpty()) {
     aType.AssignLiteral("text/css");
   }
 
   return;
 }
+
+CORSMode
+nsSVGStyleElement::GetCORSMode() const
+{
+  return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
+}
--- a/docshell/base/SerializedLoadContext.h
+++ b/docshell/base/SerializedLoadContext.h
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef SerializedLoadContext_h
 #define SerializedLoadContext_h
 
 #include "base/basictypes.h"
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsILoadContext.h"
 
 /*
  *  This file contains the IPC::SerializedLoadContext class, which is used to
  *  copy data across IPDL from Child process contexts so it is available in the
  *  Parent.
  */
 
--- a/dom/base/ScreenOrientation.h
+++ b/dom/base/ScreenOrientation.h
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_ScreenOrientation_h
 #define mozilla_dom_ScreenOrientation_h
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 // Make sure that any change here is also made in
 // * mobile/android/base/GeckoScreenOrientationListener.java
 // * embedding/android/GeckoScreenOrientationListener.java
 enum ScreenOrientation {
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -5,17 +5,24 @@
 # DOM Bindings Configuration.
 #
 # The WebIDL interfaces are defined in dom/webidl. For each such interface, there
 # is a corresponding entry in the configuration table below. The configuration
 # table maps each interface name to a |descriptor| or list of |descriptor|s.
 #
 # Valid fields for all descriptors:
 #   * nativeType - The native type (concrete class or XPCOM interface) that
-#                  instances of this interface will unwrap to (required).
+#                  instances of this interface will unwrap to.  If not
+#                  specified, defaults to "mozilla::dom::InterfaceName" for
+#                  non-worker non-external-or-callback interfaces, to
+#                  "mozilla::dom::workers::InterfaceName" for worker
+#                  non-external interfaces, to 'nsIDOM' followed by the
+#                  interface name for non-worker external-or-callback
+#                  interfaces, and to "JSObject" for worker external-or-callback
+#                  interfaces.
 #   * headerFile - The file in which the nativeType is declared (defaults
 #                  to an educated guess).
 #   * castable - Indicates whether the value in the wrapper can be cast to
 #                nativeType, or whether it needs to be QI-ed (defaults to True
 #                for everything but callback interfaces and external interfaces,
 #                for which it defaults to false and is not allowed to be set
 #                at all).
 #   * concrete - Indicates whether there exist objects with this interface as
@@ -51,23 +58,20 @@
 #                         that require a JSContext as the first argument
 #   * resultNotAddRefed - attributes and methods specified in the .webidl file
 #                         that do not AddRef the return value
 
 DOMInterfaces = {
 
 'Blob': [
 {
-    'nativeType': 'nsIDOMBlob',
     'headerFile': 'nsIDOMFile.h',
 },
 {
     'workers': True,
-    'nativeType': 'JSObject',
-    'headerFile': 'jsapi.h',
 }],
 
 'CanvasRenderingContext2D': [
 {
     'nativeType': 'nsCanvasRenderingContext2DAzure',
     # Making this non-prefable requires that we ensure that nothing takes this
     # type as an argument or that the non-Azure variant is removed.
     'prefable': True,
@@ -93,96 +97,77 @@ DOMInterfaces = {
 },
 
 'Document': [
 {
     'nativeType': 'nsIDocument',
 },
 {
     'workers': True,
-    'nativeType': 'JSObject',
-    'headerFile': 'jsapi.h',
 }],
 
 'Event': [
 {
-    'nativeType': 'nsIDOMEvent',
 },
 {
     'workers': True,
-    'nativeType': 'JSObject',
-    'headerFile': 'jsapi.h',
 }],
 
 'EventListener': [
 {
-    'nativeType': 'nsIDOMEventListener',
-    'prefable': True
 },
 {
     'workers': True,
-    'nativeType': 'JSObject',
-    'headerFile': 'jsapi.h'
 }],
 
 'EventTarget': [
 {
     'nativeType': 'nsDOMEventTargetHelper',
     'hasInstanceInterface': 'nsIDOMEventTarget',
     'concrete': False,
     'prefable': True,
 },
 {
     'workers': True,
-    'nativeType': 'mozilla::dom::workers::EventTarget',
     'headerFile': 'mozilla/dom/workers/bindings/EventTarget.h',
     'concrete': False
 }],
 
 'FormData': [
 {
-    'nativeType': 'nsIDOMFormData',
 },
 {
     'workers': True,
-    'nativeType': 'JSObject',
-    'headerFile': 'jsapi.h',
 }],
 
 'IID': [
 {
     'nativeType': 'nsIJSIID',
     'headerFile': 'xpcjsid.h',
 },
 {
     'workers': True,
-    'nativeType': 'JSObject',
-    'headerFile': 'jsapi.h',
 }],
 
 'InputStream': [
 {
     'nativeType': 'nsIInputStream',
     'notflattened': True
 },
 {
     'workers': True,
-    'nativeType': 'JSObject',
-    'headerFile': 'jsapi.h',
 }],
 
 'MozChannel': [
 {
     'nativeType': 'nsIChannel',
     'notflattened': True
 },
 {
     'workers': True,
-    'nativeType': 'JSObject',
-    'headerFile': 'jsapi.h',
 }],
 
 'Performance': {
     'nativeType': 'nsPerformance',
     'resultNotAddRefed': [ 'timing', 'navigation' ]
 },
 
 'PerformanceTiming': {
@@ -214,52 +199,48 @@ DOMInterfaces = {
 {
     'nativeType': 'nsXMLHttpRequest',
     'prefable': True,
     'implicitJSContext': [ 'constructor', ],
     'resultNotAddRefed': [ 'upload', 'responseXML' ]
 },
 {
     'workers': True,
-    'nativeType': 'mozilla::dom::workers::XMLHttpRequest',
     'headerFile': 'mozilla/dom/workers/bindings/XMLHttpRequest.h',
 }],
 
 'XMLHttpRequestEventTarget': [
 {
     'nativeType': 'nsXHREventTarget',
     'headerFile': 'nsXMLHttpRequest.h',
     'concrete': False,
     'prefable': True,
 },
 {
     'workers': True,
     'concrete': False,
-    'nativeType': 'mozilla::dom::workers::XMLHttpRequestEventTarget',
     'headerFile': 'mozilla/dom/workers/bindings/XMLHttpRequestEventTarget.h'
 }],
 
 'XMLHttpRequestUpload': [
 {
     'nativeType': 'nsXMLHttpRequestUpload',
     'headerFile': 'nsXMLHttpRequest.h',
     'prefable': True
 },
 {
     'workers': True,
-    'nativeType': 'mozilla::dom::workers::XMLHttpRequestUpload',
     'headerFile': 'mozilla/dom/workers/bindings/XMLHttpRequestUpload.h'
 }],
 
 ####################################
 # Test Interfaces of various sorts #
 ####################################
 
 'TestInterface' : {
-        'nativeType': 'mozilla::dom::TestInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'resultNotAddRefed': [ 'receiveWeakSelf', 'receiveWeakNullableSelf',
                                'receiveWeakOther', 'receiveWeakNullableOther',
                                'receiveWeakExternal', 'receiveWeakNullableExternal',
                                'ReceiveWeakCallbackInterface',
                                'ReceiveWeakNullableCallbackInterface',
                                'receiveWeakCastableObjectSequence',
@@ -267,111 +248,99 @@ DOMInterfaces = {
                                'receiveWeakCastableObjectNullableSequence',
                                'receiveWeakNullableCastableObjectNullableSequence' ],
         'binaryNames': { 'methodRenamedFrom': 'methodRenamedTo',
                          'attributeGetterRenamedFrom': 'attributeGetterRenamedTo',
                          'attributeRenamedFrom': 'attributeRenamedTo' }
         },
 
 'TestNonCastableInterface' : {
-        'nativeType': 'mozilla::dom::TestNonCastableInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'castable': False
         },
 
 'TestExternalInterface' : {
         'nativeType': 'mozilla::dom::TestExternalInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 'TestNonWrapperCacheInterface' : {
-        'nativeType': 'mozilla::dom::TestNonWrapperCacheInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'wrapperCache': False
         },
 
 'TestCallbackInterface': {
         'nativeType': 'mozilla::dom::TestCallbackInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 'IndirectlyImplementedInterface': {
-        'nativeType': 'mozilla::dom::IndirectlyImplementedInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'castable': False,
         'concrete': False
         },
 
 'OnlyForUseInConstructor' : {
-        'nativeType': 'mozilla::dom::OnlyForUseInConstructor',
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 
 'TestIndexedGetterInterface' : {
-        'nativeType': 'mozilla::dom::TestIndexedGetterInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'infallible': [ 'length' ]
         },
 
 'TestNamedGetterInterface' : {
-        'nativeType': 'mozilla::dom::TestNamedGetterInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 'TestIndexedAndNamedGetterInterface' : {
-        'nativeType': 'mozilla::dom::TestIndexedAndNamedGetterInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'infallible': [ 'length' ]
         },
 
 'TestIndexedSetterInterface' : {
-        'nativeType': 'mozilla::dom::TestIndexedSetterInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 'TestNamedSetterInterface' : {
-        'nativeType': 'mozilla::dom::TestNamedSetterInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 'TestIndexedAndNamedSetterInterface' : {
-        'nativeType': 'mozilla::dom::TestIndexedAndNamedSetterInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 'TestIndexedAndNamedGetterAndSetterInterface' : {
-        'nativeType': 'mozilla::dom::TestIndexedAndNamedGetterAndSetterInterface',
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'infallible': [ 'length', '__stringifier' ],
         'binaryNames': { '__stringifier': 'Stringify' }
         },
 }
 
 # These are temporary, until they've been converted to use new DOM bindings
 def addExternalIface(iface, nativeType=None, headerFile=None):
-    if nativeType is None:
-        nativeType = 'nsIDOM' + iface
     domInterface = {
-        'nativeType': nativeType,
         'concrete': False
     }
+    if not nativeType is None:
+        domInterface['nativeType'] = nativeType
     if not headerFile is None:
         domInterface['headerFile'] = headerFile
     DOMInterfaces[iface] = domInterface
 
 # If you add one of these, you need to make sure nsDOMQS.h has the relevant
 # macros added for it
 def addExternalHTMLElement(element):
    nativeElement = 'ns' + element
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1465,21 +1465,39 @@ class CastableObjectUnwrapper():
     A class for unwrapping an object named by the "source" argument
     based on the passed-in descriptor and storing it in a variable
     called by the name in the "target" argument.
 
     codeOnFailure is the code to run if unwrapping fails.
     """
     def __init__(self, descriptor, source, target, codeOnFailure):
         assert descriptor.castable
+
         self.substitution = { "type" : descriptor.nativeType,
                               "protoID" : "prototypes::id::" + descriptor.name,
                               "source" : source,
                               "target" : target,
                               "codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure), 4).define() }
+        if descriptor.hasXPConnectImpls:
+            # We don't use xpc_qsUnwrapThis because it will always throw on
+            # unwrap failure, whereas we want to control whether we throw or
+            # not.
+            self.substitution["codeOnFailure"] = CGIndenter(CGGeneric(string.Template(
+                "${type} *objPtr;\n"
+                "xpc_qsSelfRef objRef;\n"
+                "JS::Value val = JS::ObjectValue(*${source});\n"
+                "nsresult rv = xpc_qsUnwrapArg<${type}>(cx, val, &objPtr, &objRef.ptr, &val);\n"
+                "if (NS_FAILED(rv)) {\n"
+                "${codeOnFailure}\n"
+                "}\n"
+                "// We should be castable!\n"
+                "MOZ_ASSERT(!objRef.ptr);\n"
+                "// We should have an object, too!\n"
+                "MOZ_ASSERT(objPtr);\n"
+                "${target} = objPtr;").substitute(self.substitution)), 4).define()
 
     def __str__(self):
         return string.Template(
 """{
   nsresult rv = UnwrapObject<${protoID}, ${type}>(cx, ${source}, ${target});
   if (NS_FAILED(rv)) {
 ${codeOnFailure}
   }
@@ -2665,17 +2683,17 @@ if (!%(resultStr)s) {
         return (setValue("JS::ObjectOrNullValue(%s)" % result, True), False)
 
     if type.tag() == IDLType.Tags.any:
         # See comments in WrapNewBindingObject explaining why we need
         # to wrap here.
         # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
         return (setValue(result, True), False)
 
-    if type.isObject():
+    if type.isObject() or type.isSpiderMonkeyInterface():
         # See comments in WrapNewBindingObject explaining why we need
         # to wrap here.
         if type.nullable():
             toValue = "JS::ObjectOrNullValue(%s)"
         else:
             toValue = "JS::ObjectValue(*%s)"
         # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
         return (setValue(toValue % result, True), False)
@@ -2789,17 +2807,17 @@ def getRetvalDeclarationForType(returnTy
             result = CGWrapper(result, post="*")
         return result, False
     if returnType.isCallback():
         # XXXbz we're going to assume that callback types are always
         # nullable for now.
         return CGGeneric("JSObject*"), False
     if returnType.tag() is IDLType.Tags.any:
         return CGGeneric("JS::Value"), False
-    if returnType.isObject():
+    if returnType.isObject() or returnType.isSpiderMonkeyInterface():
         return CGGeneric("JSObject*"), False
     if returnType.isSequence():
         nullable = returnType.nullable()
         if nullable:
             returnType = returnType.inner
         # If our result is already addrefed, use the right type in the
         # sequence argument here.
         (result, _) = getRetvalDeclarationForType(returnType.inner,
@@ -3296,16 +3314,17 @@ class CGSetterCall(CGPerSignatureCall):
         return ""
 
 class FakeCastableDescriptor():
     def __init__(self, descriptor):
         self.castable = True
         self.workers = descriptor.workers
         self.nativeType = descriptor.nativeType
         self.name = descriptor.name
+        self.hasXPConnectImpls = descriptor.hasXPConnectImpls
 
 class CGAbstractBindingMethod(CGAbstractStaticMethod):
     """
     Common class to generate the JSNatives for all our methods, getters, and
     setters.  This will generate the function declaration and unwrap the
     |this| object.  Subclasses are expected to override the generate_code
     function to do the rest of the work.  This function should return a
     CGThing which is already properly indented.
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -122,34 +122,52 @@ class Descriptor(DescriptorProvider):
     """
     Represents a single descriptor for an interface. See Bindings.conf.
     """
     def __init__(self, config, interface, desc):
         DescriptorProvider.__init__(self, config, desc.get('workers', False))
         self.interface = interface
 
         # Read the desc, and fill in the relevant defaults.
-        self.nativeType = desc['nativeType']
+        ifaceName = self.interface.identifier.name
+        if self.interface.isExternal() or self.interface.isCallback():
+            if self.workers:
+                nativeTypeDefault = "JSObject"
+            else:
+                nativeTypeDefault = "nsIDOM" + ifaceName
+        else:
+            if self.workers:
+                nativeTypeDefault = "mozilla::dom::workers::" + ifaceName
+            else:
+                nativeTypeDefault = "mozilla::dom::" + ifaceName
+
+        self.nativeType = desc.get('nativeType', nativeTypeDefault)
         self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
 
-        headerDefault = self.nativeType
-        headerDefault = headerDefault.replace("::", "/") + ".h"
+        # Do something sane for JSObject
+        if self.nativeType == "JSObject":
+            headerDefault = "jsapi.h"
+        else:
+            headerDefault = self.nativeType
+            headerDefault = headerDefault.replace("::", "/") + ".h"
         self.headerFile = desc.get('headerFile', headerDefault)
 
         if self.interface.isCallback() or self.interface.isExternal():
             if 'castable' in desc:
                 raise TypeError("%s is external or callback but has a castable "
                                 "setting" % self.interface.identifier.name)
             self.castable = False
         else:
             self.castable = desc.get('castable', True)
 
         self.notflattened = desc.get('notflattened', False)
         self.register = desc.get('register', True)
 
+        self.hasXPConnectImpls = desc.get('hasXPConnectImpls', False)
+
         # If we're concrete, we need to crawl our ancestor interfaces and mark
         # them as having a concrete descendant.
         self.concrete = desc.get('concrete', not self.interface.isExternal())
         if self.concrete:
             self.proxy = False
             operations = {
                 'IndexedGetter': None,
                 'IndexedSetter': None,
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -89,17 +89,17 @@ bindinggen_dependencies := \
   $(NULL)
 
 CSS2Properties.webidl: $(topsrcdir)/layout/style/nsCSSPropList.h \
                        $(topsrcdir)/layout/style/nsCSSPropAliasList.h \
                        $(webidl_base)/CSS2Properties.webidl.in \
                        $(webidl_base)/CSS2PropertiesProps.h \
                        $(srcdir)/GenerateCSS2PropertiesWebIDL.py \
                        $(GLOBAL_DEPS)
-	$(CPP) -I$(topsrcdir)/layout/style $(webidl_base)/CSS2PropertiesProps.h | \
+	$(CPP) $(DEFINES) $(ACDEFINES) -I$(topsrcdir)/layout/style $(webidl_base)/CSS2PropertiesProps.h | \
 	  PYTHONDONTWRITEBYTECODE=1 $(PYTHON) \
 	  $(srcdir)/GenerateCSS2PropertiesWebIDL.py $(webidl_base)/CSS2Properties.webidl.in > CSS2Properties.webidl
 
 $(webidl_files): %: $(webidl_base)/%
 	$(INSTALL) $(IFLAGS1) $(webidl_base)/$* .
 
 $(test_webidl_files): %: $(srcdir)/test/%
 	$(INSTALL) $(IFLAGS1) $(srcdir)/test/$* .
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -325,16 +325,17 @@ public:
   void PassInt16Array(Int16Array&, ErrorResult&);
   void PassInt32Array(Int32Array&, ErrorResult&);
   void PassUint8Array(Uint8Array&, ErrorResult&);
   void PassUint16Array(Uint16Array&, ErrorResult&);
   void PassUint32Array(Uint32Array&, ErrorResult&);
   void PassUint8ClampedArray(Uint8ClampedArray&, ErrorResult&);
   void PassFloat32Array(Float32Array&, ErrorResult&);
   void PassFloat64Array(Float64Array&, ErrorResult&);
+  JSObject* ReceiveUint8Array(ErrorResult&);
 
   // String types
   void PassString(const nsAString&, ErrorResult&);
   void PassNullableString(const nsAString&, ErrorResult&);
   void PassOptionalString(const Optional<nsAString>&, ErrorResult&);
   void PassOptionalStringWithDefaultValue(const nsAString&, ErrorResult&);
   void PassOptionalNullableString(const Optional<nsAString>&, ErrorResult&);
   void PassOptionalNullableStringWithDefaultValue(const nsAString&, ErrorResult&);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -223,16 +223,17 @@ interface TestInterface {
   void passInt16Array(Int16Array arg);
   void passInt32Array(Int32Array arg);
   void passUint8Array(Uint8Array arg);
   void passUint16Array(Uint16Array arg);
   void passUint32Array(Uint32Array arg);
   void passUint8ClampedArray(Uint8ClampedArray arg);
   void passFloat32Array(Float32Array arg);
   void passFloat64Array(Float64Array arg);
+  Uint8Array receiveUint8Array();
 
   // String types
   void passString(DOMString arg);
   void passNullableString(DOMString? arg);
   void passOptionalString(optional DOMString arg);
   void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
   void passOptionalNullableString(optional DOMString? arg);
   void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
--- a/dom/devicestorage/DeviceStorageRequestParent.cpp
+++ b/dom/devicestorage/DeviceStorageRequestParent.cpp
@@ -12,16 +12,18 @@
 #include "ContentParent.h"
 #include "nsProxyRelease.h"
 
 namespace mozilla {
 namespace dom {
 namespace devicestorage {
 
 DeviceStorageRequestParent::DeviceStorageRequestParent(const DeviceStorageParams& aParams)
+  : mMutex("DeviceStorageRequestParent::mMutex")
+  , mActorDestoryed(false)
 {
   MOZ_COUNT_CTOR(DeviceStorageRequestParent);
 
   switch (aParams.type()) {
     case DeviceStorageParams::TDeviceStorageAddParams:
     {
       DeviceStorageAddParams p = aParams;
 
@@ -122,16 +124,18 @@ DeviceStorageRequestParent::~DeviceStora
 }
 
 NS_IMPL_THREADSAFE_ADDREF(DeviceStorageRequestParent);
 NS_IMPL_THREADSAFE_RELEASE(DeviceStorageRequestParent);
 
 void
 DeviceStorageRequestParent::ActorDestroy(ActorDestroyReason)
 {
+  MutexAutoLock lock(mMutex);
+  mActorDestoryed = true;
   int32_t count = mRunnables.Length();
   for (int32_t index = 0; index < count; index++) {
     mRunnables[index]->Cancel();
   }
 }
 
 DeviceStorageRequestParent::PostErrorEvent::PostErrorEvent(DeviceStorageRequestParent* aParent,
                                                            const char* aError)
--- a/dom/devicestorage/DeviceStorageRequestParent.h
+++ b/dom/devicestorage/DeviceStorageRequestParent.h
@@ -32,39 +32,32 @@ protected:
 private:
   nsAutoRefCnt mRefCnt;
 
   class CancelableRunnable : public nsRunnable
   {
   public:
     CancelableRunnable(DeviceStorageRequestParent* aParent)
       : mParent(aParent)
-      , mCanceled(false)
     {
-      mParent->AddRunnable(this);
+      mCanceled = !(mParent->AddRunnable(this));
     }
 
     virtual ~CancelableRunnable() {
     }
 
     NS_IMETHOD Run() {
       nsresult rv = NS_OK;
       if (!mCanceled) {
         rv = CancelableRun();
-
-        nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &CancelableRunnable::RemoveRunnable);
-        NS_DispatchToMainThread(event);
+        mParent->RemoveRunnable(this);
       }
       return rv;
     }
 
-    void RemoveRunnable() {
-      mParent->RemoveRunnable(this);
-    }
-
     void Cancel() {
       mCanceled = true;
     }
 
     virtual nsresult CancelableRun() = 0;
 
   protected:
     nsRefPtr<DeviceStorageRequestParent> mParent;
@@ -184,24 +177,32 @@ private:
                           int64_t aTotalBytes);
       virtual ~PostStatResultEvent();
       virtual nsresult CancelableRun();
     private:
       int64_t mFreeBytes, mTotalBytes;
    };
 
 protected:
-  void AddRunnable(CancelableRunnable* aRunnable) {
-    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  bool AddRunnable(CancelableRunnable* aRunnable) {
+    MutexAutoLock lock(mMutex);
+    if (mActorDestoryed)
+      return false;
+
     mRunnables.AppendElement(aRunnable);
+    return true;
   }
+
   void RemoveRunnable(CancelableRunnable* aRunnable) {
-    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+    MutexAutoLock lock(mMutex);
     mRunnables.RemoveElement(aRunnable);
   }
+
+  Mutex mMutex;
+  bool mActorDestoryed;
   nsTArray<nsRefPtr<CancelableRunnable> > mRunnables;
 };
 
 } // namespace devicestorage
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -203,21 +203,16 @@ IDBFactory::Create(ContentParent* aConte
       NS_ASSERTION(!lastCx, "We should only be called from C++!");
     }
     else {
       NS_ERROR("nsIThreadJSContextStack::Peek should never fail!");
     }
   }
 #endif
 
-  nsCString origin;
-  nsresult rv =
-    IndexedDatabaseManager::GetASCIIOriginFromWindow(nullptr, origin);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   nsCOMPtr<nsIPrincipal> principal =
     do_CreateInstance("@mozilla.org/nullprincipal;1");
   NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
 
   JSContext* cx = nsContentUtils::GetSafeJSContext();
   NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
 
   nsCxPusher pusher;
@@ -227,17 +222,17 @@ IDBFactory::Create(ContentParent* aConte
   }
 
   JSAutoRequest ar(cx);
 
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   NS_ASSERTION(xpc, "This should never be null!");
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> globalHolder;
-  rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
+  nsresult rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSObject* global;
   rv = globalHolder->GetJSObject(&global);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The CreateSandbox call returns a proxy to the actual sandbox object. We
   // don't need a proxy here.
@@ -626,9 +621,9 @@ IDBFactory::Cmp(const jsval& aFirst,
   }
 
   if (first.IsUnset() || second.IsUnset()) {
     return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
   }
 
   *_retval = Key::CompareKeys(first, second);
   return NS_OK;
-}
\ No newline at end of file
+}
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -981,17 +981,17 @@ IndexedDatabaseManager::GetASCIIOriginFr
 
   nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
   NS_ENSURE_TRUE(principal, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   if (nsContentUtils::IsSystemPrincipal(principal)) {
     aASCIIOrigin.AssignLiteral("chrome");
   }
   else {
-    nsresult rv = nsContentUtils::GetASCIIOrigin(principal, aASCIIOrigin);
+    nsresult rv = principal->GetExtendedOrigin(aASCIIOrigin);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     if (aASCIIOrigin.EqualsLiteral("null")) {
       NS_WARNING("IndexedDB databases not allowed for this principal!");
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
   }
 
--- a/dom/indexedDB/ipc/SerializationHelpers.h
+++ b/dom/indexedDB/ipc/SerializationHelpers.h
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_indexeddb_serializationhelpers_h__
 #define mozilla_dom_indexeddb_serializationhelpers_h__
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 #include "mozilla/dom/indexedDB/DatabaseInfo.h"
 #include "mozilla/dom/indexedDB/Key.h"
 #include "mozilla/dom/indexedDB/KeyPath.h"
 #include "mozilla/dom/indexedDB/IDBCursor.h"
 #include "mozilla/dom/indexedDB/IDBTransaction.h"
 
 namespace IPC {
--- a/dom/indexedDB/test/Makefile.in
+++ b/dom/indexedDB/test/Makefile.in
@@ -24,16 +24,17 @@ MOCHITEST_FILES = \
   helpers.js \
   leaving_page_iframe.html \
   test_add_put.html \
   test_add_twice_failure.html \
   test_advance.html \
   test_autoIncrement_indexes.html \
   test_autoIncrement.html \
   test_bfcache.html \
+  test_blob_archive.html \
   test_blob_simple.html \
   test_clear.html \
   test_complex_keyPaths.html \
   test_count.html \
   test_create_index.html \
   test_create_index_with_integer_keys.html \
   test_create_objectStore.html \
   test_cursors.html \
@@ -96,16 +97,20 @@ MOCHITEST_FILES = \
   test_transaction_ordering.html \
   test_setVersion.html \
   test_setVersion_abort.html \
   test_setVersion_events.html \
   test_setVersion_exclusion.html \
   test_unique_index_update.html \
   third_party_iframe1.html \
   third_party_iframe2.html \
+  test_app_isolation_inproc.html \
+  test_app_isolation_oop.html \
+  file_app_isolation.html \
+  file_app_isolation.js \
   $(NULL)
 
 #   test_writer_starvation.html  disabled for infinite loops, bug 595368
 
 ifeq (browser,$(MOZ_BUILD_APP))
 MOCHITEST_BROWSER_FILES = \
   browser_forgetThisSite.js \
   browser_forgetThisSiteAdd.html \
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/file_app_isolation.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    foobar!
+  </body>
+  <script>
+    var data = [
+      { id: "0", name: "foo" },
+    ];
+
+    var action = window.location.search.substring(1);
+    var finished = false;
+    var created = false; // We use that for 'read-no' action.
+
+    function finish(value) {
+      value ? alert('success') : alert('failure');
+      finished = true;
+    }
+
+    var request = window.indexedDB.open('AppIsolationTest');
+
+    request.onupgradeneeded = function(event) {
+      if (finished) {
+        finish(false);
+        return;
+      }
+
+      switch (action) {
+        case 'read-no':
+          created = true;
+          break;
+        case 'read-yes':
+          finish(false);
+          break;
+        case 'write':
+          created = true;
+
+          var db = event.target.result;
+
+          var objectStore = db.createObjectStore("test", { keyPath: "id" });
+          for (var i in data) {
+            objectStore.add(data[i]);
+          }
+          break;
+      }
+    }
+
+    request.onsuccess = function(event) {
+      if (finished) {
+        finish(false);
+        return;
+      }
+
+      var db = event.target.result;
+
+      // Think about close the db!
+      switch (action) {
+        case 'read-no':
+          db.close();
+
+          if (created) { // That means we have created it.
+            indexedDB.deleteDatabase('AppIsolationTest').onsuccess = function() {
+              finish(true);
+            };
+          } else {
+            finish(false);
+          }
+          break;
+        case 'read-yes':
+          db.transaction("test").objectStore("test").get("0").onsuccess = function(event) {
+            var name = event.target.result.name;
+            db.close();
+
+            indexedDB.deleteDatabase('AppIsolationTest').onsuccess = function() {
+              finish(name == 'foo');
+            };
+          };
+          break;
+        case 'write':
+          db.close();
+
+          // Success only if the db was actually created.
+          finish(created);
+          break;
+      }
+    };
+  </script>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/file_app_isolation.js
@@ -0,0 +1,163 @@
+SimpleTest.waitForExplicitFinish();
+
+var fileTestOnCurrentOrigin = (location.protocol + '//' + location.host + location.pathname)
+                              .replace('test_', 'file_')
+                              .replace('_inproc', '').replace('_oop', '');
+
+var previousPrefs = {
+  mozBrowserFramesEnabled: undefined,
+  oop_by_default: undefined,
+};
+
+try {
+  previousPrefs.mozBrowserFramesEnabled = SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
+} catch(e)
+{
+}
+
+try {
+  previousPrefs.oop_by_default = SpecialPowers.getBoolPref('dom.ipc.browser_frames.oop_by_default');
+} catch(e) {
+}
+
+SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
+SpecialPowers.setBoolPref("dom.ipc.browser_frames.oop_by_default", location.pathname.indexOf('_inproc') == -1);
+
+SpecialPowers.addPermission("browser", true, window.document);
+
+var gData = [
+  // APP 1
+  {
+    app: 'http://example.org/manifest.webapp',
+    action: 'read-no',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    app: 'http://example.org/manifest.webapp',
+    action: 'write',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    app: 'http://example.org/manifest.webapp',
+    action: 'read-yes',
+    src: fileTestOnCurrentOrigin,
+  },
+  // APP 2
+  {
+    app: 'https://example.com/manifest.webapp',
+    action: 'read-no',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    app: 'https://example.com/manifest.webapp',
+    action: 'write',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    app: 'https://example.com/manifest.webapp',
+    action: 'read-yes',
+    src: fileTestOnCurrentOrigin,
+  },
+  // Browser
+  {
+    browser: true,
+    action: 'read-no',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    browser: true,
+    action: 'write',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    browser: true,
+    action: 'read-yes',
+    src: fileTestOnCurrentOrigin,
+  },
+];
+
+function runTest() {
+  for (var i in gData) {
+    var iframe = document.createElement('iframe');
+    var data = gData[i];
+
+    if (data.app) {
+      iframe.setAttribute('mozbrowser', '');
+      iframe.setAttribute('mozapp', data.app);
+    } else if (data.browser) {
+      iframe.setAttribute('mozbrowser', '');
+    }
+
+    if (data.app || data.browser) {
+      iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
+        is(e.detail.message, 'success', 'test number ' + i);
+
+//        document.getElementById('content').removeChild(iframe);
+
+        i++;
+        if (i >= gData.length) {
+          if (previousPrefs.mozBrowserFramesEnabled !== undefined) {
+            SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', previousPrefs.mozBrowserFramesEnabled);
+          }
+          if (previousPrefs.oop_by_default !== undefined) {
+            SpecialPowers.setBoolPref("dom.ipc.browser_frames.oop_by_default", previousPrefs.oop_by_default);
+          }
+
+          SpecialPowers.removePermission("browser", window.document);
+
+          indexedDB.deleteDatabase('AppIsolationTest').onsuccess = function() {
+            SimpleTest.finish();
+          };
+        } else {
+          gTestRunner.next();
+        }
+      });
+    }
+
+    iframe.src = data.src + '?' + data.action;
+
+    document.getElementById('content').appendChild(iframe);
+
+    yield;
+  }
+}
+
+var gTestRunner = runTest();
+
+function startTest() {
+  var request = window.indexedDB.open('AppIsolationTest');
+  var created = false;
+
+  request.onupgradeneeded = function(event) {
+    created = true;
+    var db = event.target.result;
+    var data = [
+      { id: "0", name: "foo" },
+    ];
+    var objectStore = db.createObjectStore("test", { keyPath: "id" });
+    for (var i in data) {
+      objectStore.add(data[i]);
+    }
+  }
+
+  request.onsuccess = function(event) {
+    var db = event.target.result;
+    is(created, true, "we should have created the db");
+
+    db.transaction("test").objectStore("test").get("0").onsuccess = function(event) {
+      is(event.target.result.name, 'foo', 'data have been written');
+      db.close();
+
+      gTestRunner.next();
+    };
+  }
+}
+
+// test_ipc.html executes all the tests in this directory in content process.
+// It will fail on this one for the moment.
+if (!SpecialPowers.isMainProcess()) {
+  todo(false, "We should make this work on content process");
+  SimpleTest.finish();
+} else {
+  startTest();
+}
--- a/dom/indexedDB/test/helpers.js
+++ b/dom/indexedDB/test/helpers.js
@@ -36,18 +36,19 @@ function clearAllDatabases(callback) {
     comp.classes["@mozilla.org/dom/indexeddb/manager;1"]
         .getService(comp.interfaces.nsIIndexedDatabaseManager);
 
   let uri = SpecialPowers.getDocumentURIObject(document);
 
   idbManager.clearDatabasesForURI(uri);
   idbManager.getUsageForURI(uri, function(uri, usage, fileUsage) {
     if (usage) {
-      throw new Error("getUsageForURI returned non-zero usage after " +
-                      "clearing all databases!");
+      ok(false,
+         "getUsageForURI returned non-zero usage after clearing all " +
+         "databases!");
     }
     runCallback();
   });
 }
 
 if (!window.runTest) {
   window.runTest = function(limitedQuota)
   {
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_app_isolation_inproc.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=756645
+-->
+<head>
+  <title>Test for IndexedDB app isolation (unique process)</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=756645">Mozilla Bug 756645</a>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7" src="file_app_isolation.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_app_isolation_oop.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=756645
+-->
+<head>
+  <title>Test for IndexedDB app isolation (unique process)</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=756645">Mozilla Bug 756645</a>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7" src="file_app_isolation.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_blob_archive.html
@@ -0,0 +1,127 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Indexed Database Property Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7">
+
+  function testSteps()
+  {
+    const BLOB_DATA =
+      "504B03040A00000000002E6BF14000000000000000000000000005001C00746573742F" +
+      "555409000337CA055039CA055075780B000104E803000004E8030000504B0304140000" +
+      "0008002D6BF1401780E15015000000580200000A001C00746573742F612E7478745554" +
+      "09000336CA05503ACA055075780B000104E803000004E8030000CB48CDC9C95728CF2F" +
+      "CA49E1CA18658FB2A9C40600504B03040A00000000002F88EC40662E84701000000010" +
+      "0000000A001C00746573742F622E74787455540900035A65FF4F42C5055075780B0001" +
+      "04E803000004E803000068656C6C6F20776F726C642C2032210A504B01021E030A0000" +
+      "0000002E6BF140000000000000000000000000050018000000000000001000FD410000" +
+      "0000746573742F555405000337CA055075780B000104E803000004E8030000504B0102" +
+      "1E031400000008002D6BF1401780E15015000000580200000A00180000000000010000" +
+      "00B4813F000000746573742F612E747874555405000336CA055075780B000104E80300" +
+      "0004E8030000504B01021E030A00000000002F88EC40662E847010000000100000000A" +
+      "0018000000000001000000B48198000000746573742F622E74787455540500035A65FF" +
+      "4F75780B000104E803000004E8030000504B05060000000003000300EB000000EC0000" +
+      "000000";
+
+    const TEST_FILE_1 = "test/a.txt";
+    const TEST_FILE_2 = "test/b.txt";
+
+    let TEST_FILE_1_CONTENTS = "";
+    for (let i = 0; i < 50; i++) {
+      TEST_FILE_1_CONTENTS += "hello world\n";
+    }
+    const TEST_FILE_2_CONTENTS = "hello world, 2!\n";
+
+    let binaryData = new Uint8Array(BLOB_DATA.length / 2);
+    for (let i = 0, len = BLOB_DATA.length / 2; i < len; i++) {
+      let hex = BLOB_DATA[i * 2] + BLOB_DATA[i * 2 + 1];
+      binaryData[i] = parseInt(hex, 16);
+    }
+
+    let request = indexedDB.open(window.location.pathname, 1);
+    request.onerror = errorHandler;
+    request.onupgradeneeded = grabEventAndContinueHandler;
+    request.onsuccess = unexpectedSuccessHandler;
+    let event = yield;
+
+    let db = event.target.result;
+    db.onerror = errorHandler;
+
+    let objectStore = db.createObjectStore("foo", { autoIncrement: true });
+    let index = objectStore.createIndex("foo", "index");
+
+    request.onsuccess = grabEventAndContinueHandler;
+    event = yield;
+
+    let data = new Blob([binaryData]);
+
+    objectStore = db.transaction("foo", "readwrite").objectStore("foo");
+    objectStore.add(data).onsuccess = grabEventAndContinueHandler;
+    event = yield;
+
+    let key = event.target.result;
+
+    objectStore = db.transaction("foo").objectStore("foo");
+    objectStore.get(key).onsuccess = grabEventAndContinueHandler;
+    event = yield;
+
+    let archiveReader = new ArchiveReader(event.target.result);
+    ok(archiveReader, "Got an ArchiveReader");
+
+    request = archiveReader.getFilenames();
+    request.onsuccess = grabEventAndContinueHandler;
+    request.onerror = errorHandler;
+    event = yield;
+
+    is(event.target.result.length, 2, "Got 2 archive items");
+    is(event.target.result[0], TEST_FILE_1,
+       "First file is '" + TEST_FILE_1 + "'");
+    is(event.target.result[1], TEST_FILE_2,
+       "Second file is '" + TEST_FILE_2 + "'");
+
+    request = archiveReader.getFile(TEST_FILE_1);
+    request.onsuccess = grabEventAndContinueHandler;
+    request.onerror = errorHandler;
+    event = yield;
+
+    let fileReader = new FileReader();
+    fileReader.readAsText(event.target.result);
+    fileReader.onload = grabEventAndContinueHandler;
+    fileReader.onerror = errorHandler;
+    event = yield;
+
+    // Don't use is() because it prints out 100 lines of text...
+    ok(event.target.result == TEST_FILE_1_CONTENTS, "Correct text");
+
+    request = archiveReader.getFile(TEST_FILE_2);
+    request.onsuccess = grabEventAndContinueHandler;
+    request.onerror = errorHandler;
+    event = yield;
+
+    fileReader = new FileReader();
+    fileReader.readAsText(event.target.result);
+    fileReader.onload = grabEventAndContinueHandler;
+    fileReader.onerror = errorHandler;
+    event = yield;
+
+    // Don't use is() because it prints out a newline...
+    ok(event.target.result == TEST_FILE_2_CONTENTS, "Correct text");
+
+    finishTest();
+    yield;
+  }
+  </script>
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+
+</head>
+
+<body onload="runTest();"></body>
+
+</html>
--- a/dom/indexedDB/test/test_blob_simple.html
+++ b/dom/indexedDB/test/test_blob_simple.html
@@ -48,16 +48,34 @@
 
     let fileReader = new FileReader();
     fileReader.onload = grabEventAndContinueHandler;
     fileReader.readAsText(event.target.result.blob);
     event = yield;
 
     is(event.target.result, BLOB_DATA.join(""), "Correct text");
 
+    info("Trying blob url");
+
+    objectStore = db.transaction("foo").objectStore("foo");
+    objectStore.get(key).onsuccess = grabEventAndContinueHandler;
+    event = yield;
+
+    let blobURL = URL.createObjectURL(event.target.result.blob);
+
+    let xhr = new XMLHttpRequest();
+    xhr.open("GET", blobURL);
+    xhr.onload = grabEventAndContinueHandler;
+    xhr.send();
+    yield;
+
+    URL.revokeObjectURL(blobURL);
+
+    is(xhr.responseText, BLOB_DATA.join(""), "Correct responseText");
+
     objectStore = db.transaction("foo").objectStore("foo");
     objectStore.mozGetAll().onsuccess = grabEventAndContinueHandler;
     event = yield;
 
     is(event.target.result.length, 2, "Got right number of items");
 
     fileReader = new FileReader();
     fileReader.onload = grabEventAndContinueHandler;
--- a/dom/ipc/PermissionMessageUtils.h
+++ b/dom/ipc/PermissionMessageUtils.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_permission_message_utils_h__
 #define mozilla_dom_permission_message_utils_h__
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsCOMPtr.h"
 #include "nsIPrincipal.h"
 
 namespace IPC {
 
 class Principal {
   friend struct ParamTraits<Principal>;
 
--- a/dom/ipc/TabMessageUtils.h
+++ b/dom/ipc/TabMessageUtils.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef TABMESSAGE_UTILS_H
 #define TABMESSAGE_UTILS_H
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsIDOMEvent.h"
 #include "nsCOMPtr.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 namespace mozilla {
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -167,16 +167,21 @@ TabParent::RecvEvent(const RemoteDOMEven
 
 bool
 TabParent::AnswerCreateWindow(PBrowserParent** retval)
 {
     if (!mBrowserDOMWindow) {
         return false;
     }
 
+    // Only non-app, non-browser processes may call CreateWindow.
+    if (GetApp() || IsBrowserElement()) {
+        return false;
+    }
+
     // Get a new rendering area from the browserDOMWin.  We don't want
     // to be starting any loads here, so get it with a null URI.
     nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
     mBrowserDOMWindow->OpenURIInFrame(nullptr, nullptr,
                                       nsIBrowserDOMWindow::OPEN_NEWTAB,
                                       nsIBrowserDOMWindow::OPEN_NEW,
                                       getter_AddRefs(frameLoaderOwner));
     if (!frameLoaderOwner) {
--- a/dom/plugins/ipc/PluginMessageUtils.h
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -2,17 +2,17 @@
  * vim: sw=4 ts=4 et :
  * 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 DOM_PLUGINS_PLUGINMESSAGEUTILS_H
 #define DOM_PLUGINS_PLUGINMESSAGEUTILS_H
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "base/message_loop.h"
 
 #include "mozilla/ipc/RPCChannel.h"
 #include "mozilla/ipc/CrossProcessMutex.h"
 #include "gfxipc/ShadowLayerUtils.h"
 
 #include "npapi.h"
 #include "npruntime.h"
--- a/dom/src/geolocation/nsGeoPositionIPCSerialiser.h
+++ b/dom/src/geolocation/nsGeoPositionIPCSerialiser.h
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef dom_src_geolocation_IPC_serialiser
 #define dom_src_geolocation_IPC_serialiser
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsGeoPosition.h"
 #include "nsIDOMGeoPosition.h"
 
 typedef nsGeoPositionCoords       *GeoPositionCoords;
 typedef nsIDOMGeoPosition         *GeoPosition;
 
 namespace IPC {
 
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -1719,17 +1719,16 @@ let RILNetworkInterface = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface,
                                          Ci.nsIRILDataCallback]),
 
   // nsINetworkInterface
 
   NETWORK_STATE_UNKNOWN:       Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN,
   NETWORK_STATE_CONNECTING:    Ci.nsINetworkInterface.CONNECTING,
   NETWORK_STATE_CONNECTED:     Ci.nsINetworkInterface.CONNECTED,
-  NETWORK_STATE_SUSPENDED:     Ci.nsINetworkInterface.SUSPENDED,
   NETWORK_STATE_DISCONNECTING: Ci.nsINetworkInterface.DISCONNECTING,
   NETWORK_STATE_DISCONNECTED:  Ci.nsINetworkInterface.DISCONNECTED,
 
   state: Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN,
 
   NETWORK_TYPE_WIFI:       Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
   NETWORK_TYPE_MOBILE:     Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
   NETWORK_TYPE_MOBILE_MMS: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS,
@@ -1824,19 +1823,17 @@ let RILNetworkInterface = {
                          .getInterface(Ci.nsIRadioInterfaceLayer);
   },
 
   get connected() {
     return this.state == RIL.GECKO_NETWORK_STATE_CONNECTED;
   },
 
   connect: function connect(options) {
-    if (this.connecting ||
-        this.state == RIL.GECKO_NETWORK_STATE_CONNECTED ||
-        this.state == RIL.GECKO_NETWORK_STATE_SUSPENDED) {
+    if (this.connecting || this.connected) {
       return;
     }
 
     if (!this.registeredAsDataCallCallback) {
       this.mRIL.registerDataCallCallback(this);
       this.registeredAsDataCallCallback = true;
     }
 
--- a/dom/system/gonk/nsINetworkManager.idl
+++ b/dom/system/gonk/nsINetworkManager.idl
@@ -2,25 +2,24 @@
  * 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"
 
 /**
  * Information about networks that is exposed to network manager API consumers.
  */
-[scriptable, uuid(49cc227c-3fe7-40a2-bdb5-55e9af797fde)]
+[scriptable, uuid(463ed2f3-1739-41bc-a967-1e816764f915)]
 interface nsINetworkInterface : nsISupports
 {
   const long NETWORK_STATE_UNKNOWN = -1;
   const long NETWORK_STATE_CONNECTING = 0;
   const long NETWORK_STATE_CONNECTED = 1;
-  const long NETWORK_STATE_SUSPENDED = 2;
-  const long NETWORK_STATE_DISCONNECTING = 3;
-  const long NETWORK_STATE_DISCONNECTED = 4;
+  const long NETWORK_STATE_DISCONNECTING = 2;
+  const long NETWORK_STATE_DISCONNECTED = 3;
 
   /**
    * Current network state, one of the NETWORK_STATE_* constants.
    *
    * When this changes, network interface implementations notify the
    * 'network-interface-state-changed' observer notification.
    */
   readonly attribute long state;
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -1411,19 +1411,18 @@ const DATACALL_FAIL_PREF_RADIO_TECH_CHAN
 const DATACALL_FAIL_RADIO_POWER_OFF = -5;
 const DATACALL_FAIL_TETHERED_CALL_ACTIVE = -6;
 const DATACALL_FAIL_ERROR_UNSPECIFIED = 0xffff;
 
 // Keep consistent with nsINetworkManager.NETWORK_STATE_*.
 const GECKO_NETWORK_STATE_UNKNOWN = -1;
 const GECKO_NETWORK_STATE_CONNECTING = 0;
 const GECKO_NETWORK_STATE_CONNECTED = 1;
-const GECKO_NETWORK_STATE_SUSPENDED = 2;
-const GECKO_NETWORK_STATE_DISCONNECTING = 3;
-const GECKO_NETWORK_STATE_DISCONNECTED = 4;
+const GECKO_NETWORK_STATE_DISCONNECTING = 2;
+const GECKO_NETWORK_STATE_DISCONNECTED = 3;
 
 // Used for QUERY_AVAILABLE_NETWORKS status of "unknown"
 const GECKO_QAN_STATE_UNKNOWN = null;
 
 const CALL_FAIL_UNOBTAINABLE_NUMBER = 1;
 const CALL_FAIL_NORMAL = 16;
 const CALL_FAIL_BUSY = 17;
 const CALL_FAIL_CONGESTION = 34;
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -49,17 +49,16 @@ const UINT16_SIZE = 2;
 const UINT32_SIZE = 4;
 const PARCEL_SIZE_SIZE = UINT32_SIZE;
 
 const PDU_HEX_OCTET_SIZE = 4;
 
 const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"];
 
 let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = libcutils.property_get("ro.moz.ril.callstate_extra_int");
-let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = libcutils.property_get("ro.moz.ril.callstate_down_is_up");
 // This may change at runtime since in RIL v6 and later, we get the version
 // number via the UNSOLICITED_RIL_CONNECTED parcel.
 let RILQUIRKS_V5_LEGACY = libcutils.property_get("ro.moz.ril.v5_legacy");
 let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = libcutils.property_get("ro.moz.ril.dial_emergency_call");
 let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = libcutils.property_get("ro.moz.ril.emergency_by_default");
 let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = libcutils.property_get("ro.moz.ril.simstate_extra_field");
 
 // Marker object.
@@ -2490,21 +2489,16 @@ let RIL = {
   },
 
   _setDataCallGeckoState: function _setDataCallGeckoState(datacall) {
     switch (datacall.active) {
       case DATACALL_INACTIVE:
         datacall.state = GECKO_NETWORK_STATE_DISCONNECTED;
         break;
       case DATACALL_ACTIVE_DOWN:
-        datacall.state = GECKO_NETWORK_STATE_SUSPENDED;
-        if (RILQUIRKS_DATACALLSTATE_DOWN_IS_UP) {
-          datacall.state = GECKO_NETWORK_STATE_CONNECTED;
-        }
-        break;
       case DATACALL_ACTIVE_UP:
         datacall.state = GECKO_NETWORK_STATE_CONNECTED;
         break;
     }
   },
 
   _processNetworks: function _processNetworks() {
     let strings = Buf.readStringList();
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -50,17 +50,17 @@ interface CanvasRenderingContext2D {
 
   // colors and styles (see also the CanvasDrawingStyles interface)
            [SetterInfallible]
            attribute any strokeStyle; // (default black)
            [SetterInfallible]
            attribute any fillStyle; // (default black)
   CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1);
   CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1);
-  CanvasPattern createPattern((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, DOMString? repetition);
+  CanvasPattern createPattern((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, [TreatNullAs=EmptyString] DOMString repetition);
 
   // shadows
            [Infallible]
            attribute double shadowOffsetX; // (default 0)
            [Infallible]
            attribute double shadowOffsetY; // (default 0)
            [Infallible]
            attribute double shadowBlur; // (default 0)
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1339,17 +1339,16 @@ let WifiNetworkInterface = {
 
   registered: false,
 
   // nsINetworkInterface
 
   NETWORK_STATE_UNKNOWN:       Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN,
   NETWORK_STATE_CONNECTING:    Ci.nsINetworkInterface.CONNECTING,
   NETWORK_STATE_CONNECTED:     Ci.nsINetworkInterface.CONNECTED,
-  NETWORK_STATE_SUSPENDED:     Ci.nsINetworkInterface.SUSPENDED,
   NETWORK_STATE_DISCONNECTING: Ci.nsINetworkInterface.DISCONNECTING,
   NETWORK_STATE_DISCONNECTED:  Ci.nsINetworkInterface.DISCONNECTED,
 
   state: Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN,
 
   NETWORK_TYPE_WIFI:       Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
   NETWORK_TYPE_MOBILE:     Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
   NETWORK_TYPE_MOBILE_MMS: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS,
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -48,24 +48,18 @@ using mozilla::Preferences;
 
 // The size of the worker runtime heaps in bytes. May be changed via pref.
 #define WORKER_DEFAULT_RUNTIME_HEAPSIZE 32 * 1024 * 1024
 
 // The C stack size. We use the same stack size on all platforms for
 // consistency.
 #define WORKER_STACK_SIZE 256 * sizeof(size_t) * 1024
 
-// The stack limit the JS engine will check. 
-#ifdef MOZ_ASAN
-// For ASan, we need more stack space, so we use all that is available
-#define WORKER_CONTEXT_NATIVE_STACK_LIMIT WORKER_STACK_SIZE
-#else
 // Half the size of the actual C stack, to be safe.
 #define WORKER_CONTEXT_NATIVE_STACK_LIMIT 128 * sizeof(size_t) * 1024
-#endif
 
 // The maximum number of threads to use for workers, overridable via pref.
 #define MAX_WORKERS_PER_DOMAIN 10
 
 MOZ_STATIC_ASSERT(MAX_WORKERS_PER_DOMAIN >= 1,
                   "We should allow at least one worker per domain.");
 
 // The default number of seconds that close handlers will be allowed to run.
--- a/embedding/browser/webBrowser/nsWebBrowserContentPolicy.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowserContentPolicy.cpp
@@ -89,15 +89,14 @@ nsWebBrowserContentPolicy::ShouldProcess
     // Object tags will always open channels with TYPE_OBJECT, but may end up
     // loading with TYPE_IMAGE or TYPE_DOCUMENT as their final type, so we block
     // actual-plugins at the process stage
     if (contentType != nsIContentPolicy::TYPE_OBJECT) {
         return NS_OK;
     }
 
     nsIDocShell *shell = NS_CP_GetDocShellFromContext(requestingContext);
-    bool allowed;
     if (shell && (!shell->PluginsAllowedInCurrentDoc())) {
         *shouldProcess = nsIContentPolicy::REJECT_TYPE;
     }
 
     return NS_OK;
 }
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -9,16 +9,17 @@ VPATH           = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE          = cairo
 LIBRARY_NAME    = mozcairo
 LIBXUL_LIBRARY = 1
 
 ifdef GNU_CC
+OS_CFLAGS := $(filter-out -pedantic,$(OX_CFLAGS))
 OS_CXXFLAGS := $(filter-out -pedantic,$(OS_CXXFLAGS))
 ifeq ($(OS_TARGET),Android)
 MODULE_OPTIMIZE_FLAGS = -O2
 endif
 endif
 
 
 CSRCS   = \
--- a/gfx/layers/ipc/ShadowLayerUtils.h
+++ b/gfx/layers/ipc/ShadowLayerUtils.h
@@ -3,17 +3,17 @@
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef IPC_ShadowLayerUtils_h
 #define IPC_ShadowLayerUtils_h
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "GLContext.h"
 #include "mozilla/WidgetUtils.h"
 
 #if defined(MOZ_ENABLE_D3D10_LAYER)
 # include "mozilla/layers/ShadowLayerUtilsD3D10.h"
 #endif
 
 #if defined(MOZ_X11)
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
@@ -6,17 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_ShadowLayerUtilsGralloc_h
 #define mozilla_layers_ShadowLayerUtilsGralloc_h
 
 #include <unistd.h>
 #include <ui/GraphicBuffer.h>
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "mozilla/layers/PGrallocBufferChild.h"
 #include "mozilla/layers/PGrallocBufferParent.h"
 
 #define MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
 #define MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
 
 class gfxASurface;
 
--- a/gfx/layers/ipc/ShadowLayerUtilsX11.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsX11.h
@@ -6,17 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_ShadowLayerUtilsX11_h
 #define mozilla_layers_ShadowLayerUtilsX11_h
 
 #include <X11/extensions/Xrender.h>
 #include <X11/Xlib.h>
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 #define MOZ_HAVE_SURFACEDESCRIPTORX11
 #define MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
 
 class gfxXlibSurface;
 
 namespace mozilla {
 namespace layers {
--- a/hal/HalSensor.h
+++ b/hal/HalSensor.h
@@ -45,17 +45,17 @@ enum SensorAccuracyType {
 
 class SensorAccuracy;
 
 typedef Observer<SensorAccuracy> ISensorAccuracyObserver;
 
 }
 }
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 namespace IPC {
   /**
    * Serializer for SensorType
    */
   template <>
   struct ParamTraits<mozilla::hal::SensorType>:
     public EnumSerializer<mozilla::hal::SensorType,
--- a/ipc/glue/InputStreamParams.ipdlh
+++ b/ipc/glue/InputStreamParams.ipdlh
@@ -1,13 +1,13 @@
 /* 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 "IPC/IPCMessageUtils.h";
+include "ipc/IPCMessageUtils.h";
 
 using mozilla::void_t;
 
 namespace mozilla {
 namespace ipc {
 
 struct StringInputStreamParams
 {
--- a/ipc/glue/Makefile.in
+++ b/ipc/glue/Makefile.in
@@ -12,19 +12,19 @@ include $(DEPTH)/config/autoconf.mk
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/crashreporter
 
 MODULE = ipc
 LIBRARY_NAME = mozipc_s
 FORCE_STATIC_LIB = 1
 LIBXUL_LIBRARY = 1
 EXPORT_LIBRARY = 1
 
-EXPORTS_NAMESPACES = IPC mozilla/ipc
+EXPORTS_NAMESPACES = ipc mozilla/ipc
 
-EXPORTS_IPC = IPCMessageUtils.h
+EXPORTS_ipc = IPCMessageUtils.h
 
 EXPORTS_mozilla/ipc = \
   AsyncChannel.h \
   BrowserProcessSubThread.h \
   CrossProcessMutex.h \
   FileDescriptor.h \
   GeckoChildProcessHost.h \
   InputStreamUtils.h \
--- a/ipc/glue/Shmem.h
+++ b/ipc/glue/Shmem.h
@@ -11,17 +11,17 @@
 #include "mozilla/Attributes.h"
 
 #include "base/basictypes.h"
 #include "base/process.h"
 
 #include "nscore.h"
 #include "nsDebug.h"
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "mozilla/ipc/SharedMemory.h"
 
 /**
  * |Shmem| is one agent in the IPDL shared memory scheme.  The way it
     works is essentially
  *
  *  (1) C++ code calls, say, |parentActor->AllocShmem(size)|
 
--- a/ipc/glue/Transport_posix.h
+++ b/ipc/glue/Transport_posix.h
@@ -3,17 +3,17 @@
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ipc_Transport_posix_h
 #define mozilla_ipc_Transport_posix_h 1
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 
 namespace mozilla {
 namespace ipc {
 
 struct TransportDescriptor
 {
   base::FileDescriptor mFd;
--- a/ipc/glue/Transport_win.h
+++ b/ipc/glue/Transport_win.h
@@ -5,17 +5,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ipc_Transport_win_h
 #define mozilla_ipc_Transport_win_h 1
 
 #include <string>
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 
 namespace mozilla {
 namespace ipc {
 
 struct TransportDescriptor
 {
   std::wstring mPipeName;
--- a/ipc/glue/URIParams.ipdlh
+++ b/ipc/glue/URIParams.ipdlh
@@ -1,13 +1,13 @@
 /* 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 "IPC/IPCMessageUtils.h";
+include "ipc/IPCMessageUtils.h";
 
 using mozilla::void_t;
 
 namespace mozilla {
 namespace ipc {
 
 struct SimpleURIParams
 {
--- a/ipc/ipdl/ipdl/builtin.py
+++ b/ipc/ipdl/ipdl/builtin.py
@@ -54,15 +54,15 @@ Types = (
 
 
 Includes = (
     'mozilla/Attributes.h',
     'base/basictypes.h',
     'prtime.h',
     'nscore.h',
     'IPCMessageStart.h',
-    'IPC/IPCMessageUtils.h',
+    'ipc/IPCMessageUtils.h',
     'nsAutoPtr.h',
     'nsStringGlue.h',
     'nsTArray.h',
     'nsIFile.h',
     'mozilla/ipc/ProtocolUtils.h',
 )
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -330,17 +330,17 @@ frontend::CompileFunctionBody(JSContext 
         return false;
 
     BytecodeEmitter funbce(/* parent = */ NULL, &parser, &funsc, script, /* callerFrame = */ NULL,
                            /* hasGlobalScope = */ false, options.lineno);
     if (!funbce.init())
         return false;
 
     if (!NameFunctions(cx, pn))
-        return NULL;
+        return false;
 
     if (fn->pn_body) {
         JS_ASSERT(fn->pn_body->isKind(PNK_ARGSBODY));
         fn->pn_body->append(pn);
         fn->pn_body->pn_pos = pn->pn_pos;
         pn = fn->pn_body;
     }
 
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -509,23 +509,16 @@ js::TraceWeakMaps(WeakMapTracer *trc)
 
 JS_FRIEND_API(bool)
 js::GCThingIsMarkedGray(void *thing)
 {
     JS_ASSERT(thing);
     return reinterpret_cast<gc::Cell *>(thing)->isMarked(gc::GRAY);
 }
 
-JS_FRIEND_API(JSCompartment*)
-js::GetGCThingCompartment(void *thing)
-{
-    JS_ASSERT(thing);
-    return reinterpret_cast<gc::Cell *>(thing)->compartment();
-}
-
 JS_FRIEND_API(void)
 js::VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure)
 {
     for (WrapperMap::Enum e(comp->crossCompartmentWrappers); !e.empty(); e.popFront()) {
         gc::Cell *thing = e.front().key.wrapped;
         if (thing->isMarked(gc::GRAY))
             callback(closure, thing);
     }
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -272,19 +272,16 @@ struct WeakMapTracer {
 };
 
 extern JS_FRIEND_API(void)
 TraceWeakMaps(WeakMapTracer *trc);
 
 extern JS_FRIEND_API(bool)
 GCThingIsMarkedGray(void *thing);
 
-extern JS_FRIEND_API(JSCompartment*)
-GetGCThingCompartment(void *thing);
-
 typedef void
 (GCThingCallback)(void *closure, void *gcthing);
 
 extern JS_FRIEND_API(void)
 VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure);
 
 /*
  * Shadow declarations of JS internal structures, for access by inline access
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1193,13 +1193,23 @@ MaybeVerifyBarriers(JSContext *cx, bool 
 {
 }
 
 #endif
 
 } /* namespace gc */
 
 static inline JSCompartment *
-GetObjectCompartment(JSObject *obj) { return reinterpret_cast<js::gc::Cell *>(obj)->compartment(); }
+GetGCThingCompartment(void *thing)
+{
+    JS_ASSERT(thing);
+    return reinterpret_cast<gc::Cell *>(thing)->compartment();
+}
+
+static inline JSCompartment *
+GetObjectCompartment(JSObject *obj)
+{
+    return GetGCThingCompartment(obj);
+}
 
 } /* namespace js */
 
 #endif /* jsgc_h___ */
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -533,27 +533,26 @@ js::Int32ToString(JSContext *cx, int32_t
     JSCompartment *c = cx->compartment;
     if (JSFixedString *str = c->dtoaCache.lookup(10, si))
         return str;
 
     JSShortString *str = js_NewGCShortString(cx);
     if (!str)
         return NULL;
 
-    jschar *storage = str->inlineStorageBeforeInit();
-    RangedPtr<jschar> end(storage + JSShortString::MAX_SHORT_LENGTH,
-                          storage, JSShortString::MAX_SHORT_LENGTH + 1);
+    jschar buffer[JSShortString::MAX_SHORT_LENGTH + 1];
+    RangedPtr<jschar> end(buffer + JSShortString::MAX_SHORT_LENGTH,
+                          buffer, JSShortString::MAX_SHORT_LENGTH + 1);
     *end = '\0';
-
     RangedPtr<jschar> start = BackfillIndexInCharBuffer(ui, end);
-
     if (si < 0)
         *--start = '-';
 
-    str->initAtOffsetInBuffer(start.get(), end - start);
+    jschar *dst = str->init(end - start);
+    PodCopy(dst, start.get(), end - start + 1);
 
     c->dtoaCache.cache(10, si, str);
     return str;
 }
 
 /* Returns a non-NULL pointer to inside cbuf.  */
 static char *
 IntToCString(ToCStringBuf *cbuf, int i, int base = 10)
@@ -1298,24 +1297,24 @@ IndexToString(JSContext *cx, uint32_t in
     JSCompartment *c = cx->compartment;
     if (JSFixedString *str = c->dtoaCache.lookup(10, index))
         return str;
 
     JSShortString *str = js_NewGCShortString(cx);
     if (!str)
         return NULL;
 
-    jschar *storage = str->inlineStorageBeforeInit();
-    size_t length = JSShortString::MAX_SHORT_LENGTH;
-    const RangedPtr<jschar> end(storage + length, storage, length + 1);
+    jschar buffer[JSShortString::MAX_SHORT_LENGTH + 1];
+    RangedPtr<jschar> end(buffer + JSShortString::MAX_SHORT_LENGTH,
+                          buffer, JSShortString::MAX_SHORT_LENGTH + 1);
     *end = '\0';
-
     RangedPtr<jschar> start = BackfillIndexInCharBuffer(index, end);
 
-    str->initAtOffsetInBuffer(start.get(), end - start);
+    jschar *dst = str->init(end - start);
+    PodCopy(dst, start.get(), end - start + 1);
 
     c->dtoaCache.cache(10, index, str);
     return str;
 }
 
 bool JS_FASTCALL
 NumberValueToStringBuffer(JSContext *cx, const Value &v, StringBuffer &sb)
 {
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1134,17 +1134,17 @@ ContextStack::popGeneratorFrame(const Ge
     JS_ASSERT(ImplicitCast<const FrameGuard>(gfg).pushed());
 }
 
 bool
 ContextStack::saveFrameChain()
 {
     bool pushedSeg;
     if (!ensureOnTop(cx_, REPORT_ERROR, 0, CANT_EXTEND, &pushedSeg))
-        return NULL;
+        return false;
 
     JS_ASSERT(pushedSeg);
     JS_ASSERT(!hasfp());
     JS_ASSERT(onTop());
     JS_ASSERT(seg_->isEmpty());
     return true;
 }
 
--- a/js/src/vm/String-inl.h
+++ b/js/src/vm/String-inl.h
@@ -263,25 +263,16 @@ JSInlineString::resetLength(size_t lengt
 
 JS_ALWAYS_INLINE JSShortString *
 JSShortString::new_(JSContext *cx)
 {
     return js_NewGCShortString(cx);
 }
 
 JS_ALWAYS_INLINE void
-JSShortString::initAtOffsetInBuffer(const jschar *chars, size_t length)
-{
-    JS_ASSERT(lengthFits(length + (chars - d.inlineStorage)));
-    JS_ASSERT(chars >= d.inlineStorage && chars < d.inlineStorage + MAX_SHORT_LENGTH);
-    d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
-    d.u1.chars = chars;
-}
-
-JS_ALWAYS_INLINE void
 JSExternalString::init(const jschar *chars, size_t length, const JSStringFinalizer *fin)
 {
     JS_ASSERT(fin);
     JS_ASSERT(fin->finalize);
     d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
     d.u1.chars = chars;
     d.s.u2.externalFinalizer = fin;
 }
@@ -425,38 +416,37 @@ JSString::finalize(js::FreeOp *fop)
         JS_ASSERT(isDependent() || isRope());
 }
 
 inline void
 JSFlatString::finalize(js::FreeOp *fop)
 {
     JS_ASSERT(!isShort());
 
-    /*
-     * This check depends on the fact that 'chars' is only initialized to the
-     * beginning of inlineStorage. E.g., this is not the case for short strings.
-     */
     if (chars() != d.inlineStorage)
         fop->free_(const_cast<jschar *>(chars()));
 }
 
 inline void
 JSShortString::finalize(js::FreeOp *fop)
 {
-    JS_ASSERT(JSString::isShort());
+    JS_ASSERT(isShort());
+
+    if (chars() != d.inlineStorage)
+        fop->free_(const_cast<jschar *>(chars()));
 }
 
 inline void
 JSAtom::finalize(js::FreeOp *fop)
 {
     JS_ASSERT(JSString::isAtom());
-    if (getAllocKind() == js::gc::FINALIZE_STRING)
-        JSFlatString::finalize(fop);
-    else
-        JS_ASSERT(getAllocKind() == js::gc::FINALIZE_SHORT_STRING);
+    JS_ASSERT(JSString::isFlat());
+
+    if (chars() != d.inlineStorage)
+        fop->free_(const_cast<jschar *>(chars()));
 }
 
 inline void
 JSExternalString::finalize(js::FreeOp *fop)
 {
     const JSStringFinalizer *fin = externalFinalizer();
     fin->finalize(fin, const_cast<jschar *>(chars()));
 }
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -12,35 +12,25 @@
 #include "String.h"
 #include "String-inl.h"
 
 #include "jsobjinlines.h"
 
 using namespace mozilla;
 using namespace js;
 
+#ifdef DEBUG
 bool
 JSString::isShort() const
 {
     bool is_short = (getAllocKind() == gc::FINALIZE_SHORT_STRING);
     JS_ASSERT_IF(is_short, isFixed());
     return is_short;
 }
-
-bool
-JSString::isFixed() const
-{
-    return isFlat() && !isExtensible();
-}
-
-bool
-JSString::isInline() const
-{
-    return isFixed() && (d.u1.chars == d.inlineStorage || isShort());
-}
+#endif
 
 bool
 JSString::isExternal() const
 {
     bool is_external = (getAllocKind() == gc::FINALIZE_EXTERNAL_STRING);
     JS_ASSERT_IF(is_external, isFixed());
     return is_external;
 }
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -181,17 +181,17 @@ class JSString : public js::gc::Cell
      *   Rope         0000       0000
      *   Linear       -         !0000
      *   HasBase      -          xxx1
      *   Dependent    0001       0001
      *   Flat         -          isLinear && !isDependent
      *   Undepended   0011       0011
      *   Extensible   0010       0010
      *   Fixed        0100       isFlat && !isExtensible
-     *   Inline       0100       isFixed && (u1.chars == inlineStorage || isShort || isInt32)
+     *   Inline       0100       isFixed && (u1.chars == inlineStorage) || isInt32)
      *   Short        0100       header in FINALIZE_SHORT_STRING arena
      *   External     0100       header in FINALIZE_EXTERNAL_STRING arena
      *   Int32        0110       x110 (NYI, Bug 654190)
      *   Atom         1000       1xxx
      *   InlineAtom   1000       1000 && is Inline
      *   ShortAtom    1000       1000 && is Short
      *   Int32Atom    1110       1110 (NYI, Bug 654190)
      *
@@ -325,27 +325,33 @@ class JSString : public js::gc::Cell
     }
 
     JS_ALWAYS_INLINE
     JSExtensibleString &asExtensible() const {
         JS_ASSERT(isExtensible());
         return *(JSExtensibleString *)this;
     }
 
-    /* For hot code, prefer other type queries. */
-    bool isShort() const;
-    bool isFixed() const;
-    bool isInline() const;
+    JS_ALWAYS_INLINE
+    bool isFixed() const {
+        return isFlat() && !isExtensible();
+    }
 
     JS_ALWAYS_INLINE
     JSFixedString &asFixed() const {
         JS_ASSERT(isFixed());
         return *(JSFixedString *)this;
     }
 
+    JS_ALWAYS_INLINE
+    bool isInline() const {
+        return isFixed() && (d.u1.chars == d.inlineStorage);
+    }
+
+    /* For hot code, prefer other type queries. */
     bool isExternal() const;
 
     JS_ALWAYS_INLINE
     JSExternalString &asExternal() const {
         JS_ASSERT(isExternal());
         return *(JSExternalString *)this;
     }
 
@@ -397,16 +403,17 @@ class JSString : public js::gc::Cell
     static inline void writeBarrierPre(JSString *str);
     static inline void writeBarrierPost(JSString *str, void *addr);
     static inline bool needWriteBarrierPre(JSCompartment *comp);
     static inline void readBarrier(JSString *str);
 
     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_STRING; }
 
 #ifdef DEBUG
+    bool isShort() const;
     void dump();
     bool equals(const char *s);
 #endif
 
   private:
     JSString() MOZ_DELETE;
     JSString(const JSString &other) MOZ_DELETE;
     void operator=(const JSString &other) MOZ_DELETE;
@@ -588,31 +595,25 @@ class JSShortString : public JSInlineStr
     }
 
   protected: /* to fool clang into not warning this is unused */
     jschar inlineStorageExtension[INLINE_EXTENSION_CHARS];
 
   public:
     static inline JSShortString *new_(JSContext *cx);
 
-    jschar *inlineStorageBeforeInit() {
-        return d.inlineStorage;
-    }
-
-    inline void initAtOffsetInBuffer(const jschar *chars, size_t length);
-
     static const size_t MAX_SHORT_LENGTH = JSString::NUM_INLINE_CHARS +
                                            INLINE_EXTENSION_CHARS
                                            -1 /* null terminator */;
 
     static bool lengthFits(size_t length) {
         return length <= MAX_SHORT_LENGTH;
     }
 
-    /* Only called by the GC for strings with the FINALIZE_EXTERNAL_STRING kind. */
+    /* Only called by the GC for strings with the FINALIZE_SHORT_STRING kind. */
 
     JS_ALWAYS_INLINE void finalize(js::FreeOp *fop);
 };
 
 JS_STATIC_ASSERT(sizeof(JSShortString) == 2 * sizeof(JSString));
 
 class JSExternalString : public JSFixedString
 {
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -934,27 +934,16 @@ xpc_qsJsvalToWcharStr(JSContext *cx, jsv
 
     *pstr = static_cast<const PRUnichar *>(chars);
     return true;
 }
 
 namespace xpc {
 
 bool
-StringToJsval(JSContext *cx, nsAString &str, JS::Value *rval)
-{
-    // From the T_DOMSTRING case in XPCConvert::NativeData2JS.
-    if (str.IsVoid()) {
-        *rval = JSVAL_NULL;
-        return true;
-    }
-    return NonVoidStringToJsval(cx, str, rval);
-}
-
-bool
 NonVoidStringToJsval(JSContext *cx, nsAString &str, JS::Value *rval)
 {
     nsStringBuffer* sharedBuffer;
     jsval jsstr = XPCStringConvert::ReadableToJSVal(cx, str, &sharedBuffer);
     if (JSVAL_IS_NULL(jsstr))
         return false;
     *rval = jsstr;
     if (sharedBuffer) {
--- a/js/xpconnect/src/XPCString.cpp
+++ b/js/xpconnect/src/XPCString.cpp
@@ -16,20 +16,33 @@
  * Wrap the JSString with a root-holding XPCJSReadableStringWrapper, which roots
  * the string and exposes its buffer via the nsAString interface, as
  * well as providing refcounting support.
  */
 
 #include "xpcprivate.h"
 #include "nsStringBuffer.h"
 
+// One-slot cache, because it turns out it's common for web pages to
+// get the same string a few times in a row.  We get about a 40% cache
+// hit rate on this cache last it was measured.  We'd get about 70%
+// hit rate with a hashtable with removal on finalization, but that
+// would take a lot more machinery.
+static nsStringBuffer* sCachedBuffer = nullptr;
+static JSString* sCachedString = nullptr;
+
 static void
 FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars)
 {
-    nsStringBuffer::FromData(chars)->Release();
+    nsStringBuffer* buf = nsStringBuffer::FromData(chars);
+    if (buf == sCachedBuffer) {
+        sCachedBuffer = nullptr;
+        // No need to clear sCachedString
+    }
+    buf->Release();
 }
 
 static const JSStringFinalizer sDOMStringFinalizer = { FinalizeDOMString };
 
 
 // convert a readable to a JSString, copying string data
 // static
 jsval
@@ -42,24 +55,32 @@ XPCStringConvert::ReadableToJSVal(JSCont
 
     uint32_t length = readable.Length();
 
     if (length == 0)
         return JS_GetEmptyStringValue(cx);
 
     nsStringBuffer *buf = nsStringBuffer::FromString(readable);
     if (buf) {
+        if (buf == sCachedBuffer &&
+            js::GetGCThingCompartment(sCachedString) == js::GetContextCompartment(cx)) {
+            // We're done.  Just return our existing string.
+            return JS::StringValue(sCachedString);
+        }
+
         // yay, we can share the string's buffer!
 
         str = JS_NewExternalString(cx,
                                    reinterpret_cast<jschar *>(buf->Data()),
                                    length, &sDOMStringFinalizer);
 
         if (str) {
             *sharedBuffer = buf;
+            sCachedString = str;
+            sCachedBuffer = buf;
         }
     } else {
         // blech, have to copy.
 
         jschar *chars = reinterpret_cast<jschar *>
                                         (JS_malloc(cx, (length + 1) *
                                                    sizeof(jschar)));
         if (!chars)
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -236,18 +236,26 @@ bool DeferredRelease(nsISupports *obj);
 bool Base64Encode(JSContext *cx, JS::Value val, JS::Value *out);
 bool Base64Decode(JSContext *cx, JS::Value val, JS::Value *out);
 
 /**
  * Convert an nsString to jsval, returning true on success.
  * Note, the ownership of the string buffer may be moved from str to rval.
  * If that happens, str will point to an empty string after this call.
  */
-bool StringToJsval(JSContext *cx, nsAString &str, JS::Value *rval);
 bool NonVoidStringToJsval(JSContext *cx, nsAString &str, JS::Value *rval);
+inline bool StringToJsval(JSContext *cx, nsAString &str, JS::Value *rval)
+{
+    // From the T_DOMSTRING case in XPCConvert::NativeData2JS.
+    if (str.IsVoid()) {
+        *rval = JSVAL_NULL;
+        return true;
+    }
+    return NonVoidStringToJsval(cx, str, rval);
+}
 
 nsIPrincipal *GetCompartmentPrincipal(JSCompartment *compartment);
 
 void DumpJSHeap(FILE* file);
 
 void SetLocationForGlobal(JSObject *global, const nsACString& location);
 void SetLocationForGlobal(JSObject *global, nsIURI *locationURI);
 
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1201,17 +1201,17 @@ nsresult PresShell::ClearPreferenceStyle
 }
 
 nsresult
 PresShell::CreatePreferenceStyleSheet()
 {
   NS_TIME_FUNCTION_MIN(1.0);
 
   NS_ASSERTION(!mPrefStyleSheet, "prefStyleSheet already exists");
-  mPrefStyleSheet = new nsCSSStyleSheet();
+  mPrefStyleSheet = new nsCSSStyleSheet(CORS_NONE);
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), "about:PreferenceStyleSheet", nullptr);
   if (NS_FAILED(rv)) {
     mPrefStyleSheet = nullptr;
     return rv;
   }
   NS_ASSERTION(uri, "null but no error");
   mPrefStyleSheet->SetURIs(uri, uri, uri);
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -836,18 +836,18 @@ const nsIFrame::ChildListID nsIFrame::kP
 const nsIFrame::ChildListID nsIFrame::kSelectPopupList;
 const nsIFrame::ChildListID nsIFrame::kNoReflowPrincipalList;
 #endif
 
 /* virtual */ nsMargin
 nsIFrame::GetUsedMargin() const
 {
   nsMargin margin(0, 0, 0, 0);
-  if ((mState & NS_FRAME_FIRST_REFLOW) &&
-      !(mState & NS_FRAME_IN_REFLOW) ||
+  if (((mState & NS_FRAME_FIRST_REFLOW) &&
+       !(mState & NS_FRAME_IN_REFLOW)) ||
       (mState & NS_FRAME_IS_SVG_TEXT))
     return margin;
 
   nsMargin *m = static_cast<nsMargin*>
                            (Properties().Get(UsedMarginProperty()));
   if (m) {
     margin = *m;
   } else {
@@ -859,18 +859,18 @@ nsIFrame::GetUsedMargin() const
   }
   return margin;
 }
 
 /* virtual */ nsMargin
 nsIFrame::GetUsedBorder() const
 {
   nsMargin border(0, 0, 0, 0);
-  if ((mState & NS_FRAME_FIRST_REFLOW) &&
-      !(mState & NS_FRAME_IN_REFLOW) ||
+  if (((mState & NS_FRAME_FIRST_REFLOW) &&
+       !(mState & NS_FRAME_IN_REFLOW)) ||
       (mState & NS_FRAME_IS_SVG_TEXT))
     return border;
 
   // Theme methods don't use const-ness.
   nsIFrame *mutable_this = const_cast<nsIFrame*>(this);
 
   const nsStyleDisplay *disp = GetStyleDisplay();
   if (mutable_this->IsThemed(disp)) {
@@ -895,18 +895,18 @@ nsIFrame::GetUsedBorder() const
   }
   return border;
 }
 
 /* virtual */ nsMargin
 nsIFrame::GetUsedPadding() const
 {
   nsMargin padding(0, 0, 0, 0);
-  if ((mState & NS_FRAME_FIRST_REFLOW) &&
-      !(mState & NS_FRAME_IN_REFLOW) ||
+  if (((mState & NS_FRAME_FIRST_REFLOW) &&
+       !(mState & NS_FRAME_IN_REFLOW)) ||
       (mState & NS_FRAME_IS_SVG_TEXT))
     return padding;
 
   // Theme methods don't use const-ness.
   nsIFrame *mutable_this = const_cast<nsIFrame*>(this);
 
   const nsStyleDisplay *disp = GetStyleDisplay();
   if (mutable_this->IsThemed(disp)) {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/input-percentage-padding-ref.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            .container {
+                width: 400px;
+                background: #ddd;
+            }
+            .text-input {
+                width: 200px; /* 50% */
+                padding: 40px; /* 10% */
+                background: #fff;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="container">
+            <input type="text" class="text-input" />
+        </div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/input-percentage-padding.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            .container {
+                width: 400px;
+                background: #ddd;
+            }
+            .text-input {
+                width: 50%; /* 200px */
+                padding: 10%; /* 40px */
+                background: #fff;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="container">
+            <input type="text" class="text-input" />
+        </div>
+    </body>
+</html>
--- a/layout/reftests/forms/reftest.list
+++ b/layout/reftests/forms/reftest.list
@@ -76,8 +76,10 @@ include input/reftest.list
 # meter element
 include meter/reftest.list
 
 # output element
 include output/reftest.list
 
 # progress element
 include progress/reftest.list
+
+== input-percentage-padding.html input-percentage-padding-ref.html
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -304,13 +304,14 @@ random-if(/^Windows\x20NT\x205\.1/.test(
 == userSpaceOnUse-and-pattern-01.svg userSpaceOnUse-and-pattern-01-ref.svg
 == viewBox-and-pattern-01.svg pass.svg
 == viewBox-and-pattern-02.svg pass.svg
 == viewBox-and-pattern-03.svg pass.svg
 == viewBox-invalid-01.svg pass.svg
 == viewBox-valid-01.svg pass.svg
 == viewBox-valid-02.xhtml pass.svg
 == viewport-percent-graphic-user-01.svg pass.svg
+== winding-01.svg pass.svg
 
 == svg-effects-area-unzoomed.xhtml svg-effects-area-unzoomed-ref.xhtml
 == svg-effects-area-zoomed-in.xhtml svg-effects-area-zoomed-in-ref.xhtml
 == svg-effects-area-zoomed-out.xhtml svg-effects-area-zoomed-out-ref.xhtml
 == href-attr-change-restyles.svg href-attr-change-restyles-ref.svg
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/winding-01.svg
@@ -0,0 +1,11 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
+
+  <title>Testcase for path with evenodd winding</title>
+  
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=786216 -->
+
+  <rect width="100%" height="100%" fill="lime"/>
+
+  <path fill-rule="evenodd" fill="red" d="M100,100 l 50,0 0,50 -50,0 0,-50 50,0 0,50 -50,0 0,-50z"/>
+
+</svg>
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -46,16 +46,17 @@
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsICSSLoaderObserver.h"
 #include "nsCSSParser.h"
 #include "mozilla/css/ImportRule.h"
 #include "nsThreadUtils.h"
 #include "nsGkAtoms.h"
 #include "nsDocShellCID.h"
 #include "nsIThreadInternal.h"
+#include "nsCrossSiteListenerProxy.h"
 
 #ifdef MOZ_XUL
 #include "nsXULPrototypeCache.h"
 #endif
 
 #include "nsIMediaList.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsIDOMCSSStyleSheet.h"
@@ -548,17 +549,17 @@ Loader::DropDocumentReference(void)
   // loads should short-circuit through the mDocument check in
   // LoadSheet and just end up in SheetComplete immediately
   if (mPendingDatas.IsInitialized()) {
     StartAlternateLoads();
   }
 }
 
 static PLDHashOperator
-CollectNonAlternates(URIAndPrincipalHashKey *aKey,
+CollectNonAlternates(URIPrincipalAndCORSModeHashKey *aKey,
                      SheetLoadData* &aData,
                      void* aClosure)
 {
   NS_PRECONDITION(aData, "Must have a data");
   NS_PRECONDITION(aClosure, "Must have an array");
 
   // Note that we don't want to affect what the selected style set is,
   // so use true for aHasAlternateRel.
@@ -1055,16 +1056,17 @@ Loader::CheckLoadAllowed(nsIPrincipal* a
  * sheets will have the title/media/enabled state of the sheet they
  * are clones off; make sure to call PrepareSheet() on the result of
  * CreateSheet().
  */
 nsresult
 Loader::CreateSheet(nsIURI* aURI,
                     nsIContent* aLinkingContent,
                     nsIPrincipal* aLoaderPrincipal,
+                    CORSMode aCORSMode,
                     bool aSyncLoad,
                     bool aHasAlternateRel,
                     const nsAString& aTitle,                       
                     StyleSheetState& aSheetState,
                     bool *aIsAlternate,
                     nsCSSStyleSheet** aSheet)
 {
   LOG(("css::Loader::CreateSheet"));
@@ -1101,17 +1103,17 @@ Loader::CreateSheet(nsIURI* aURI,
           LOG(("  From XUL cache: %p", sheet.get()));
         }
       }
     }
 #endif
 
     if (!sheet) {
       // Then our per-document complete sheets.
-      URIAndPrincipalHashKey key(aURI, aLoaderPrincipal);
+      URIPrincipalAndCORSModeHashKey key(aURI, aLoaderPrincipal, aCORSMode);
 
       mCompleteSheets.Get(&key, getter_AddRefs(sheet));
       LOG(("  From completed: %p", sheet.get()));
     }
 
     if (sheet) {
       // This sheet came from the XUL cache or our per-document hashtable; it
       // better be a complete sheet.
@@ -1125,17 +1127,17 @@ Loader::CreateSheet(nsIURI* aURI,
         sheet = nullptr;
       }
     }
 
     // Then loading sheets
     if (!sheet && !aSyncLoad) {
       aSheetState = eSheetLoading;
       SheetLoadData* loadData = nullptr;
-      URIAndPrincipalHashKey key(aURI, aLoaderPrincipal);
+      URIPrincipalAndCORSModeHashKey key(aURI, aLoaderPrincipal, aCORSMode);
       mLoadingDatas.Get(&key, &loadData);
       if (loadData) {
         sheet = loadData->mSheet;
         LOG(("  From loading: %p", sheet.get()));
 
 #ifdef DEBUG
         bool debugEqual;
         NS_ASSERTION((!aLoaderPrincipal && !loadData->mLoaderPrincipal) ||
@@ -1193,17 +1195,17 @@ Loader::CreateSheet(nsIURI* aURI,
       sheetURI = aLinkingContent->GetDocument()->GetDocumentURI();
       originalURI = nullptr;
     } else {
       baseURI = aURI;
       sheetURI = aURI;
       originalURI = aURI;
     }
 
-    nsRefPtr<nsCSSStyleSheet> sheet = new nsCSSStyleSheet();
+    nsRefPtr<nsCSSStyleSheet> sheet = new nsCSSStyleSheet(aCORSMode);
     sheet->SetURIs(sheetURI, originalURI, baseURI);
     sheet.forget(aSheet);
   }
 
   NS_ASSERTION(*aSheet, "We should have a sheet by now!");
   NS_ASSERTION(aSheetState != eSheetStateUnknown, "Have to set a state!");
   LOG(("  State: %s", gStateStrings[aSheetState]));
 
@@ -1445,17 +1447,19 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
     // SheetComplete has been called.
     return nsSyncLoadService::PushSyncStreamToListener(stream,
                                                        streamLoader,
                                                        channel);
   }
 
   SheetLoadData* existingData = nullptr;
 
-  URIAndPrincipalHashKey key(aLoadData->mURI, aLoadData->mLoaderPrincipal);
+  URIPrincipalAndCORSModeHashKey key(aLoadData->mURI,
+                                     aLoadData->mLoaderPrincipal,
+                                     aLoadData->mSheet->GetCORSMode());
   if (aSheetState == eSheetLoading) {
     mLoadingDatas.Get(&key, &existingData);
     NS_ASSERTION(existingData, "CreateSheet lied about the state");
   }
   else if (aSheetState == eSheetPending){
     mPendingDatas.Get(&key, &existingData);
     NS_ASSERTION(existingData, "CreateSheet lied about the state");
   }
@@ -1550,19 +1554,46 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
     }
   }
 
   // We don't have to hold on to the stream loader.  The ownership
   // model is: Necko owns the stream loader, which owns the load data,
   // which owns us
   nsCOMPtr<nsIUnicharStreamLoader> streamLoader;
   rv = NS_NewUnicharStreamLoader(getter_AddRefs(streamLoader), aLoadData);
+  if (NS_FAILED(rv)) {
+#ifdef DEBUG
+    mSyncCallback = false;
+#endif
+    LOG_ERROR(("  Failed to create stream loader"));
+    SheetComplete(aLoadData, rv);
+    return rv;
+  }
 
-  if (NS_SUCCEEDED(rv))
-    rv = channel->AsyncOpen(streamLoader, nullptr);
+  nsCOMPtr<nsIStreamListener> channelListener;
+  CORSMode ourCORSMode = aLoadData->mSheet->GetCORSMode();
+  if (ourCORSMode != CORS_NONE) {
+    bool withCredentials = (ourCORSMode == CORS_USE_CREDENTIALS);
+    LOG(("  Doing CORS-enabled load; credentials %d", withCredentials));
+    channelListener =
+      new nsCORSListenerProxy(streamLoader, aLoadData->mLoaderPrincipal,
+			      channel, withCredentials, &rv);
+    if (NS_FAILED(rv)) {
+#ifdef DEBUG
+      mSyncCallback = false;
+#endif
+      LOG_ERROR(("  Initial CORS check failed"));
+      SheetComplete(aLoadData, rv);
+      return rv;
+    }
+  } else {
+    channelListener = streamLoader;
+  }
+
+  rv = channel->AsyncOpen(channelListener, nullptr);
 
 #ifdef DEBUG
   mSyncCallback = false;
 #endif
 
   if (NS_FAILED(rv)) {
     LOG_ERROR(("  Failed to create stream loader"));
     SheetComplete(aLoadData, rv);
@@ -1691,18 +1722,19 @@ Loader::DoSheetComplete(SheetLoadData* a
 
   LOG(("Load completed, status: 0x%x", aStatus));
 
   // Twiddle the hashtables
   if (aLoadData->mURI) {
     LOG_URI("  Finished loading: '%s'", aLoadData->mURI);
     // Remove the data from the list of loading datas
     if (aLoadData->mIsLoading) {
-      URIAndPrincipalHashKey key(aLoadData->mURI,
-                                 aLoadData->mLoaderPrincipal);
+      URIPrincipalAndCORSModeHashKey key(aLoadData->mURI,
+                                         aLoadData->mLoaderPrincipal,
+                                         aLoadData->mSheet->GetCORSMode());
 #ifdef DEBUG
       SheetLoadData *loadingData;
       NS_ASSERTION(mLoadingDatas.Get(&key, &loadingData) &&
                    loadingData == aLoadData,
                    "Bad loading table");
 #endif
 
       mLoadingDatas.Remove(&key);
@@ -1761,18 +1793,19 @@ Loader::DoSheetComplete(SheetLoadData* a
         if (!cache->GetStyleSheet(aLoadData->mURI)) {
           LOG(("  Putting sheet in XUL prototype cache"));
           cache->PutStyleSheet(aLoadData->mSheet);
         }
       }
     }
     else {
 #endif
-      URIAndPrincipalHashKey key(aLoadData->mURI,
-                                 aLoadData->mLoaderPrincipal);
+      URIPrincipalAndCORSModeHashKey key(aLoadData->mURI,
+                                         aLoadData->mLoaderPrincipal,
+                                         aLoadData->mSheet->GetCORSMode());
       mCompleteSheets.Put(&key, aLoadData->mSheet);
 #ifdef MOZ_XUL
     }
 #endif
   }
 
   NS_RELEASE(aLoadData);  // this will release parents and siblings and all that
 }
@@ -1798,20 +1831,21 @@ Loader::LoadInlineStyle(nsIContent* aEle
   }
 
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
 
   nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
   NS_ASSERTION(owningElement, "Element is not a style linking element!");
 
   // Since we're not planning to load a URI, no need to hand a principal to the
-  // load data or to CreateSheet().
+  // load data or to CreateSheet().  Also, OK to use CORS_NONE for the CORS
+  // mode.
   StyleSheetState state;
   nsRefPtr<nsCSSStyleSheet> sheet;
-  nsresult rv = CreateSheet(nullptr, aElement, nullptr, false, false,
+  nsresult rv = CreateSheet(nullptr, aElement, nullptr, CORS_NONE, false, false,
                             aTitle, state, aIsAlternate, getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(state == eSheetNeedsParser,
                "Inline sheets should not be cached");
 
   LOG(("  Sheet is alternate: %d", *aIsAlternate));
 
   rv = PrepareSheet(sheet, aTitle, aMedia, nullptr, *aIsAlternate);
@@ -1841,16 +1875,17 @@ Loader::LoadInlineStyle(nsIContent* aEle
 }
 
 nsresult
 Loader::LoadStyleLink(nsIContent* aElement,
                       nsIURI* aURL,
                       const nsAString& aTitle,
                       const nsAString& aMedia,
                       bool aHasAlternateRel,
+                      CORSMode aCORSMode,
                       nsICSSLoaderObserver* aObserver,
                       bool* aIsAlternate)
 {
   LOG(("css::Loader::LoadStyleLink"));
   NS_PRECONDITION(aURL, "Must have URL to load");
   NS_ASSERTION(mParsingDatas.Length() == 0, "We're in the middle of a parse?");
 
   LOG_URI("  Link uri: '%s'", aURL);
@@ -1874,18 +1909,19 @@ Loader::LoadStyleLink(nsIContent* aEleme
   }
   nsresult rv = CheckLoadAllowed(principal, aURL, context);
   if (NS_FAILED(rv)) return rv;
 
   LOG(("  Passed load check"));
 
   StyleSheetState state;
   nsRefPtr<nsCSSStyleSheet> sheet;
-  rv = CreateSheet(aURL, aElement, principal, false, aHasAlternateRel,
-                   aTitle, state, aIsAlternate, getter_AddRefs(sheet));
+  rv = CreateSheet(aURL, aElement, principal, aCORSMode, false,
+                   aHasAlternateRel, aTitle, state, aIsAlternate,
+                   getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
 
   LOG(("  Sheet is alternate: %d", *aIsAlternate));
 
   rv = PrepareSheet(sheet, aTitle, aMedia, nullptr, *aIsAlternate);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = InsertSheetInDoc(sheet, aElement, mDocument);
@@ -1910,17 +1946,18 @@ Loader::LoadStyleLink(nsIContent* aEleme
                                           owningElement, *aIsAlternate,
                                           aObserver, principal);
   NS_ADDREF(data);
 
   // If we have to parse and it's an alternate non-inline, defer it
   if (aURL && state == eSheetNeedsParser && mLoadingDatas.Count() != 0 &&
       *aIsAlternate) {
     LOG(("  Deferring alternate sheet load"));
-    URIAndPrincipalHashKey key(data->mURI, data->mLoaderPrincipal);
+    URIPrincipalAndCORSModeHashKey key(data->mURI, data->mLoaderPrincipal,
+                                       data->mSheet->GetCORSMode());
     mPendingDatas.Put(&key, data);
 
     data->mMustNotify = true;
     return NS_OK;
   }
 
   // Load completion will free the data
   rv = LoadSheet(data, state);
@@ -2026,22 +2063,23 @@ Loader::LoadChildSheet(nsCSSStyleSheet* 
   } else {
     LOG(("  No parent load; must be CSSOM"));
     // No parent load data, so the sheet will need to be notified when
     // we finish, if it can be, if we do the load asynchronously.
     observer = aParentSheet;
   }
 
   // Now that we know it's safe to load this (passes security check and not a
-  // loop) do so
+  // loop) do so.
   nsRefPtr<nsCSSStyleSheet> sheet;
   bool isAlternate;
   StyleSheetState state;
   const nsSubstring& empty = EmptyString();
-  rv = CreateSheet(aURL, nullptr, principal,
+  // For now, use CORS_NONE for child sheets
+  rv = CreateSheet(aURL, nullptr, principal, CORS_NONE,
                    parentData ? parentData->mSyncLoad : false,
                    false, empty, state, &isAlternate, getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = PrepareSheet(sheet, empty, empty, aMedia, isAlternate);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = InsertChildSheet(sheet, aParentSheet, aParentRule);
@@ -2096,32 +2134,34 @@ Loader::LoadSheet(nsIURI* aURL,
                                       aOriginPrincipal, aCharset,
                                       aSheet, aObserver);
 }
 
 nsresult
 Loader::LoadSheet(nsIURI* aURL,
                   nsIPrincipal* aOriginPrincipal,
                   const nsCString& aCharset,
-                  nsICSSLoaderObserver* aObserver)
+                  nsICSSLoaderObserver* aObserver,
+                  CORSMode aCORSMode)
 {
   LOG(("css::Loader::LoadSheet(aURL, aObserver) api call"));
   return InternalLoadNonDocumentSheet(aURL, false, false,
                                       aOriginPrincipal, aCharset,
-                                      nullptr, aObserver);
+                                      nullptr, aObserver, aCORSMode);
 }
 
 nsresult
 Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
                                      bool aAllowUnsafeRules,
                                      bool aUseSystemPrincipal,
                                      nsIPrincipal* aOriginPrincipal,
                                      const nsCString& aCharset,
                                      nsCSSStyleSheet** aSheet,
-                                     nsICSSLoaderObserver* aObserver)
+                                     nsICSSLoaderObserver* aObserver,
+                                     CORSMode aCORSMode)
 {
   NS_PRECONDITION(aURL, "Must have a URI to load");
   NS_PRECONDITION(aSheet || aObserver, "Sheet and observer can't both be null");
   NS_PRECONDITION(!aUseSystemPrincipal || !aObserver,
                   "Shouldn't load system-principal sheets async");
   NS_ASSERTION(mParsingDatas.Length() == 0, "We're in the middle of a parse?");
 
   LOG_URI("  Non-document sheet uri: '%s'", aURL);
@@ -2141,18 +2181,18 @@ Loader::InternalLoadNonDocumentSheet(nsI
   }
 
   StyleSheetState state;
   bool isAlternate;
   nsRefPtr<nsCSSStyleSheet> sheet;
   bool syncLoad = (aObserver == nullptr);
   const nsSubstring& empty = EmptyString();
 
-  rv = CreateSheet(aURL, nullptr, aOriginPrincipal, syncLoad, false, empty,
-                   state, &isAlternate, getter_AddRefs(sheet));
+  rv = CreateSheet(aURL, nullptr, aOriginPrincipal, aCORSMode, syncLoad, false,
+                   empty, state, &isAlternate, getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = PrepareSheet(sheet, empty, empty, nullptr, isAlternate);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete"));
     if (aObserver || !mObservers.IsEmpty()) {
@@ -2254,17 +2294,17 @@ Loader::HandleLoadEvent(SheetLoadData* a
   }
 
   if (mDocument) {
     mDocument->UnblockOnload(true);
   }
 }
 
 static PLDHashOperator
-StopLoadingSheetCallback(URIAndPrincipalHashKey* aKey,
+StopLoadingSheetCallback(URIPrincipalAndCORSModeHashKey* aKey,
                          SheetLoadData*& aData,
                          void* aClosure)
 {
   NS_PRECONDITION(aData, "Must have a data!");
   NS_PRECONDITION(aClosure, "Must have a loader");
 
   aData->mIsLoading = false; // we will handle the removal right here
   aData->mIsCancelled = true;
@@ -2338,17 +2378,17 @@ Loader::AddObserver(nsICSSLoaderObserver
 
 void
 Loader::RemoveObserver(nsICSSLoaderObserver* aObserver)
 {
   mObservers.RemoveElement(aObserver);
 }
 
 static PLDHashOperator
-CollectLoadDatas(URIAndPrincipalHashKey *aKey,
+CollectLoadDatas(URIPrincipalAndCORSModeHashKey *aKey,
                  SheetLoadData* &aData,
                  void* aClosure)
 {
   static_cast<Loader::LoadDataArray*>(aClosure)->AppendElement(aData);
   return PL_DHASH_REMOVE;
 }
 
 void
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -14,84 +14,94 @@
 #include "nsCompatibility.h"
 #include "nsDataHashtable.h"
 #include "nsInterfaceHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsTArray.h"
 #include "nsTObserverArray.h"
 #include "nsURIHashKey.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/CORSMode.h"
 
 class nsIAtom;
 class nsICSSLoaderObserver;
 class nsCSSStyleSheet;
 class nsIContent;
 class nsIDocument;
 class nsCSSParser;
 class nsMediaList;
 class nsIStyleSheetLinkingElement;
 
 namespace mozilla {
 
-class URIAndPrincipalHashKey : public nsURIHashKey
+class URIPrincipalAndCORSModeHashKey : public nsURIHashKey
 {
 public:
-  typedef URIAndPrincipalHashKey* KeyType;
-  typedef const URIAndPrincipalHashKey* KeyTypePointer;
+  typedef URIPrincipalAndCORSModeHashKey* KeyType;
+  typedef const URIPrincipalAndCORSModeHashKey* KeyTypePointer;
 
-  URIAndPrincipalHashKey(const URIAndPrincipalHashKey* aKey)
-    : nsURIHashKey(aKey->mKey), mPrincipal(aKey->mPrincipal)
-  {
-    MOZ_COUNT_CTOR(URIAndPrincipalHashKey);
-  }
-  URIAndPrincipalHashKey(nsIURI* aURI, nsIPrincipal* aPrincipal)
-    : nsURIHashKey(aURI), mPrincipal(aPrincipal)
+  URIPrincipalAndCORSModeHashKey(const URIPrincipalAndCORSModeHashKey* aKey)
+    : nsURIHashKey(aKey->mKey), mPrincipal(aKey->mPrincipal),
+      mCORSMode(aKey->mCORSMode)
   {
-    MOZ_COUNT_CTOR(URIAndPrincipalHashKey);
+    MOZ_COUNT_CTOR(URIPrincipalAndCORSModeHashKey);
   }
-  URIAndPrincipalHashKey(const URIAndPrincipalHashKey& toCopy)
-    : nsURIHashKey(toCopy), mPrincipal(toCopy.mPrincipal)
+  URIPrincipalAndCORSModeHashKey(nsIURI* aURI, nsIPrincipal* aPrincipal,
+                                 CORSMode aCORSMode)
+    : nsURIHashKey(aURI), mPrincipal(aPrincipal), mCORSMode(aCORSMode)
   {
-    MOZ_COUNT_CTOR(URIAndPrincipalHashKey);
+    MOZ_COUNT_CTOR(URIPrincipalAndCORSModeHashKey);
   }
-  ~URIAndPrincipalHashKey()
+  URIPrincipalAndCORSModeHashKey(const URIPrincipalAndCORSModeHashKey& toCopy)
+    : nsURIHashKey(toCopy), mPrincipal(toCopy.mPrincipal),
+      mCORSMode(toCopy.mCORSMode)
   {
-    MOZ_COUNT_DTOR(URIAndPrincipalHashKey);
+    MOZ_COUNT_CTOR(URIPrincipalAndCORSModeHashKey);
+  }
+  ~URIPrincipalAndCORSModeHashKey()
+  {
+    MOZ_COUNT_DTOR(URIPrincipalAndCORSModeHashKey);
   }
 
-  URIAndPrincipalHashKey* GetKey() const {
-    return const_cast<URIAndPrincipalHashKey*>(this);
+  URIPrincipalAndCORSModeHashKey* GetKey() const {
+    return const_cast<URIPrincipalAndCORSModeHashKey*>(this);
   }
-  const URIAndPrincipalHashKey* GetKeyPointer() const { return this; }
+  const URIPrincipalAndCORSModeHashKey* GetKeyPointer() const { return this; }
 
-  bool KeyEquals(const URIAndPrincipalHashKey* aKey) const {
+  bool KeyEquals(const URIPrincipalAndCORSModeHashKey* aKey) const {
     if (!nsURIHashKey::KeyEquals(aKey->mKey)) {
       return false;
     }
 
     if (!mPrincipal != !aKey->mPrincipal) {
       // One or the other has a principal, but not both... not equal
       return false;
     }
 
+    if (mCORSMode != aKey->mCORSMode) {
+      // Different CORS modes; we don't match
+      return false;
+    }
+
     bool eq;
     return !mPrincipal ||
       (NS_SUCCEEDED(mPrincipal->Equals(aKey->mPrincipal, &eq)) && eq);
   }
 
-  static const URIAndPrincipalHashKey*
-  KeyToPointer(URIAndPrincipalHashKey* aKey) { return aKey; }
-  static PLDHashNumber HashKey(const URIAndPrincipalHashKey* aKey) {
+  static const URIPrincipalAndCORSModeHashKey*
+  KeyToPointer(URIPrincipalAndCORSModeHashKey* aKey) { return aKey; }
+  static PLDHashNumber HashKey(const URIPrincipalAndCORSModeHashKey* aKey) {
     return nsURIHashKey::HashKey(aKey->mKey);
   }
 
   enum { ALLOW_MEMMOVE = true };
 
 protected:
   nsCOMPtr<nsIPrincipal> mPrincipal;
+  CORSMode mCORSMode;
 };
 
 
 
 namespace css {
 
 class SheetLoadData;
 class ImportRule;
@@ -163,27 +173,29 @@ public:
    * into the stylesheet list of this CSSLoader's document.
    *
    * @param aElement the element linking to the the stylesheet.  May be null.
    * @param aURL the URL of the sheet.
    * @param aTitle the title of the sheet.
    * @param aMedia the media string for the sheet.
    * @param aHasAlternateRel whether the rel for this link included
    *        "alternate".
+   * @param aCORSMode the CORS mode for this load.
    * @param aObserver the observer to notify when the load completes.
    *                  May be null.
    * @param [out] aIsAlternate whether the stylesheet actually ended up beinga
    *        an alternate sheet.  Note that this need not match
    *        aHasAlternateRel.
    */
   nsresult LoadStyleLink(nsIContent* aElement,
                          nsIURI* aURL,
                          const nsAString& aTitle,
                          const nsAString& aMedia,
                          bool aHasAlternateRel,
+                         CORSMode aCORSMode,
                          nsICSSLoaderObserver* aObserver,
                          bool* aIsAlternate);
 
   /**
    * Load a child (@import-ed) style sheet.  In addition to loading the sheet,
    * this method will insert it into the child sheet list of aParentSheet.  If
    * there is no sheet currently being parsed and the child sheet is not
    * complete when this method returns, then when the child sheet becomes
@@ -269,17 +281,18 @@ public:
 
   /**
    * Same as above, to be used when the caller doesn't care about the
    * not-yet-loaded sheet.
    */
   nsresult LoadSheet(nsIURI* aURL,
                      nsIPrincipal* aOriginPrincipal,
                      const nsCString& aCharset,
-                     nsICSSLoaderObserver* aObserver);
+                     nsICSSLoaderObserver* aObserver,
+                     CORSMode aCORSMode = CORS_NONE);
 
   /**
    * Stop loading all sheets.  All nsICSSLoaderObservers involved will be
    * notified with NS_BINDING_ABORTED as the status, possibly synchronously.
    */
   nsresult Stop(void);
 
   /**
@@ -352,16 +365,17 @@ private:
 
   // For inline style, the aURI param is null, but the aLinkingContent
   // must be non-null then.  The loader principal must never be null
   // if aURI is not null.
   // *aIsAlternate is set based on aTitle and aHasAlternateRel.
   nsresult CreateSheet(nsIURI* aURI,
                        nsIContent* aLinkingContent,
                        nsIPrincipal* aLoaderPrincipal,
+                       CORSMode aCORSMode,
                        bool aSyncLoad,
                        bool aHasAlternateRel,
                        const nsAString& aTitle,
                        StyleSheetState& aSheetState,
                        bool *aIsAlternate,
                        nsCSSStyleSheet** aSheet);
 
   // Pass in either a media string or the nsMediaList from the
@@ -382,17 +396,18 @@ private:
                             ImportRule* aParentRule);
 
   nsresult InternalLoadNonDocumentSheet(nsIURI* aURL,
                                         bool aAllowUnsafeRules,
                                         bool aUseSystemPrincipal,
                                         nsIPrincipal* aOriginPrincipal,
                                         const nsCString& aCharset,
                                         nsCSSStyleSheet** aSheet,
-                                        nsICSSLoaderObserver* aObserver);
+                                        nsICSSLoaderObserver* aObserver,
+                                        CORSMode aCORSMode = CORS_NONE);
 
   // Post a load event for aObserver to be notified about aSheet.  The
   // notification will be sent with status NS_OK unless the load event is
   // canceled at some point (in which case it will be sent with
   // NS_BINDING_ABORTED).  aWasAlternate indicates the state when the load was
   // initiated, not the state at some later time.  aURI should be the URI the
   // sheet was loaded from (may be null for inline sheets).  aElement is the
   // owning element for this sheet.
@@ -425,21 +440,21 @@ private:
   void SheetComplete(SheetLoadData* aLoadData, nsresult aStatus);
 
   // The guts of SheetComplete.  This may be called recursively on parent datas
   // or datas that had glommed on to a single load.  The array is there so load
   // datas whose observers need to be notified can be added to it.
   void DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus,
                        LoadDataArray& aDatasToNotify);
 
-  nsRefPtrHashtable<URIAndPrincipalHashKey, nsCSSStyleSheet>
+  nsRefPtrHashtable<URIPrincipalAndCORSModeHashKey, nsCSSStyleSheet>
                     mCompleteSheets;
-  nsDataHashtable<URIAndPrincipalHashKey, SheetLoadData*>
+  nsDataHashtable<URIPrincipalAndCORSModeHashKey, SheetLoadData*>
                     mLoadingDatas; // weak refs
-  nsDataHashtable<URIAndPrincipalHashKey, SheetLoadData*>
+  nsDataHashtable<URIPrincipalAndCORSModeHashKey, SheetLoadData*>
                     mPendingDatas; // weak refs
 
   // We're not likely to have many levels of @import...  But likely to have
   // some.  Allocate some storage, what the hell.
   nsAutoTArray<SheetLoadData*, 8> mParsingDatas;
 
   // The array of posted stylesheet loaded events (SheetLoadDatas) we have.
   // Note that these are rare.
--- a/layout/style/nsCSSStyleSheet.cpp
+++ b/layout/style/nsCSSStyleSheet.cpp
@@ -34,17 +34,18 @@
 #include "nsContentUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "mozAutoDocUpdate.h"
 #include "mozilla/css/Declaration.h"
 #include "nsRuleNode.h"
 #include "nsMediaFeatures.h"
 #include "nsDOMClassInfoID.h"
 
-namespace css = mozilla::css;
+using namespace mozilla;
+
 
 // -------------------------------
 // Style Rule List for the DOM
 //
 class CSSRuleListImpl : public nsICSSRuleList
 {
 public:
   CSSRuleListImpl(nsCSSStyleSheet *aStyleSheet);
@@ -758,18 +759,20 @@ nsMediaList::Append(const nsAString& aNe
   return rv;
 }
 
 // -------------------------------
 // CSS Style Sheet Inner Data Container
 //
 
 
-nsCSSStyleSheetInner::nsCSSStyleSheetInner(nsCSSStyleSheet* aPrimarySheet)
+nsCSSStyleSheetInner::nsCSSStyleSheetInner(nsCSSStyleSheet* aPrimarySheet,
+                                           CORSMode aCORSMode)
   : mSheets(),
+    mCORSMode(aCORSMode),
     mComplete(false)
 #ifdef DEBUG
     , mPrincipalSet(false)
 #endif
 {
   MOZ_COUNT_CTOR(nsCSSStyleSheetInner);
   mSheets.AppendElement(aPrimarySheet);
 
@@ -879,16 +882,17 @@ nsCSSStyleSheet::SizeOfIncludingThis(nsM
 
 nsCSSStyleSheetInner::nsCSSStyleSheetInner(nsCSSStyleSheetInner& aCopy,
                                            nsCSSStyleSheet* aPrimarySheet)
   : mSheets(),
     mSheetURI(aCopy.mSheetURI),
     mOriginalSheetURI(aCopy.mOriginalSheetURI),
     mBaseURI(aCopy.mBaseURI),
     mPrincipal(aCopy.mPrincipal),
+    mCORSMode(aCopy.mCORSMode),
     mComplete(aCopy.mComplete)
 #ifdef DEBUG
     , mPrincipalSet(aCopy.mPrincipalSet)
 #endif
 {
   MOZ_COUNT_CTOR(nsCSSStyleSheetInner);
   AddSheet(aPrimarySheet);
   aCopy.mOrderedRules.EnumerateForwards(CloneRuleInto, &mOrderedRules);
@@ -1007,29 +1011,29 @@ nsCSSStyleSheetInner::SizeOfIncludingThi
 
   return n;
 }
 
 // -------------------------------
 // CSS Style Sheet
 //
 
-nsCSSStyleSheet::nsCSSStyleSheet()
+nsCSSStyleSheet::nsCSSStyleSheet(CORSMode aCORSMode)
   : mTitle(), 
     mParent(nullptr),
     mOwnerRule(nullptr),
     mRuleCollection(nullptr),
     mDocument(nullptr),
     mOwningNode(nullptr),
     mDisabled(false),
     mDirty(false),
     mRuleProcessors(nullptr)
 {
 
-  mInner = new nsCSSStyleSheetInner(this);
+  mInner = new nsCSSStyleSheetInner(this, aCORSMode);
 }
 
 nsCSSStyleSheet::nsCSSStyleSheet(const nsCSSStyleSheet& aCopy,
                                  nsCSSStyleSheet* aParentToUse,
                                  css::ImportRule* aOwnerRuleToUse,
                                  nsIDocument* aDocumentToUse,
                                  nsIDOMNode* aOwningNodeToUse)
   : mTitle(aCopy.mTitle),
@@ -1580,17 +1584,17 @@ void
 nsCSSStyleSheet::DidDirty()
 {
   NS_ABORT_IF_FALSE(!mInner->mComplete || mDirty,
                     "caller must have called WillDirty()");
   ClearRuleCascades();
 }
 
 nsresult
-nsCSSStyleSheet::SubjectSubsumesInnerPrincipal() const
+nsCSSStyleSheet::SubjectSubsumesInnerPrincipal()
 {
   // Get the security manager and do the subsumes check
   nsIScriptSecurityManager *securityManager =
     nsContentUtils::GetSecurityManager();
 
   nsCOMPtr<nsIPrincipal> subjectPrincipal;
   nsresult rv = securityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1603,17 +1607,36 @@ nsCSSStyleSheet::SubjectSubsumesInnerPri
   rv = subjectPrincipal->Subsumes(mInner->mPrincipal, &subsumes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (subsumes) {
     return NS_OK;
   }
   
   if (!nsContentUtils::IsCallerTrustedForWrite()) {
-    return NS_ERROR_DOM_SECURITY_ERR;
+    // Allow access only if CORS mode is not NONE
+    if (GetCORSMode() == CORS_NONE) {
+      return NS_ERROR_DOM_SECURITY_ERR;
+    }
+
+    // Now make sure we set the principal of our inner to the
+    // subjectPrincipal.  That means we need a unique inner, of
+    // course.  But we don't want to do that if we're not complete
+    // yet.  Luckily, all the callers of this method throw anyway if
+    // not complete, so we can just do that here too.
+    if (!mInner->mComplete) {
+      return NS_ERROR_DOM_INVALID_ACCESS_ERR;
+    }
+
+    rv = WillDirty();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    mInner->mPrincipal = subjectPrincipal;
+
+    DidDirty();
   }
 
   return NS_OK;
 }
 
 nsresult
 nsCSSStyleSheet::RegisterNamespaceRule(css::Rule* aRule)
 {
--- a/layout/style/nsCSSStyleSheet.h
+++ b/layout/style/nsCSSStyleSheet.h
@@ -15,16 +15,17 @@
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsIStyleSheet.h"
 #include "nsIDOMCSSStyleSheet.h"
 #include "nsICSSLoaderObserver.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsString.h"
+#include "mozilla/CORSMode.h"
 
 class nsXMLNameSpaceMap;
 class nsCSSRuleProcessor;
 class nsMediaList;
 class nsIPrincipal;
 class nsIURI;
 class nsMediaList;
 class nsMediaQueryResultCacheKey;
@@ -44,17 +45,18 @@ class ImportRule;
 // CSS Style Sheet Inner Data Container
 //
 
 class nsCSSStyleSheetInner {
 public:
   friend class nsCSSStyleSheet;
   friend class nsCSSRuleProcessor;
 private:
-  nsCSSStyleSheetInner(nsCSSStyleSheet* aPrimarySheet);
+  nsCSSStyleSheetInner(nsCSSStyleSheet* aPrimarySheet,
+                       mozilla::CORSMode aCORSMode);
   nsCSSStyleSheetInner(nsCSSStyleSheetInner& aCopy,
                        nsCSSStyleSheet* aPrimarySheet);
   ~nsCSSStyleSheetInner();
 
   nsCSSStyleSheetInner* CloneFor(nsCSSStyleSheet* aPrimarySheet);
   void AddSheet(nsCSSStyleSheet* aSheet);
   void RemoveSheet(nsCSSStyleSheet* aSheet);
 
@@ -73,16 +75,17 @@ private:
   nsCOMArray<mozilla::css::Rule> mOrderedRules;
   nsAutoPtr<nsXMLNameSpaceMap> mNameSpaceMap;
   // Linked list of child sheets.  This is al fundamentally broken, because
   // each of the child sheets has a unique parent... We can only hope (and
   // currently this is the case) that any time page JS can get ts hands on a
   // child sheet that means we've already ensured unique inners throughout its
   // parent chain and things are good.
   nsRefPtr<nsCSSStyleSheet> mFirstChild;
+  mozilla::CORSMode      mCORSMode;
   bool                   mComplete;
 
 #ifdef DEBUG
   bool                   mPrincipalSet;
 #endif
 };
 
 
@@ -100,17 +103,17 @@ struct ChildSheetListBuilder;
  { 0x84, 0x67, 0x80, 0x3f, 0xb3, 0x2a, 0xf2, 0x0a } }
 
 
 class nsCSSStyleSheet MOZ_FINAL : public nsIStyleSheet,
                                   public nsIDOMCSSStyleSheet,
                                   public nsICSSLoaderObserver
 {
 public:
-  nsCSSStyleSheet();
+  nsCSSStyleSheet(mozilla::CORSMode aCORSMode);
 
   NS_DECL_ISUPPORTS
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_CSS_STYLE_SHEET_IMPL_CID)
 
   // nsIStyleSheet interface
   virtual nsIURI* GetSheetURI() const;
   virtual nsIURI* GetBaseURI() const;
@@ -234,16 +237,19 @@ public:
   NS_DECL_NSIDOMCSSSTYLESHEET
 
   // Function used as a callback to rebuild our inner's child sheet
   // list after we clone a unique inner for ourselves.
   static bool RebuildChildList(mozilla::css::Rule* aRule, void* aBuilder);
 
   size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
+  // Get this style sheet's CORS mode
+  mozilla::CORSMode GetCORSMode() const { return mInner->mCORSMode; }
+
 private:
   nsCSSStyleSheet(const nsCSSStyleSheet& aCopy,
                   nsCSSStyleSheet* aParentToUse,
                   mozilla::css::ImportRule* aOwnerRuleToUse,
                   nsIDocument* aDocumentToUse,
                   nsIDOMNode* aOwningNodeToUse);
 
   nsCSSStyleSheet(const nsCSSStyleSheet& aCopy) MOZ_DELETE;
@@ -254,18 +260,19 @@ protected:
 
   void ClearRuleCascades();
 
   nsresult WillDirty();
   void     DidDirty();
 
   // Return success if the subject principal subsumes the principal of our
   // inner, error otherwise.  This will also succeed if the subject has
-  // UniversalXPConnect.
-  nsresult SubjectSubsumesInnerPrincipal() const;
+  // UniversalXPConnect or if access is allowed by CORS.  In the latter case,
+  // it will set the principal of the inner to the subject principal.
+  nsresult SubjectSubsumesInnerPrincipal();
 
   // Add the namespace mapping from this @namespace rule to our namespace map
   nsresult RegisterNamespaceRule(mozilla::css::Rule* aRule);
 
 protected:
   nsString              mTitle;
   nsRefPtr<nsMediaList> mMedia;
   nsRefPtr<nsCSSStyleSheet> mNext;
--- a/layout/style/test/Makefile.in
+++ b/layout/style/test/Makefile.in
@@ -181,16 +181,18 @@ MOCHITEST_FILES =	test_acid3_test46.html
 		visited-pref-iframe.html \
 		visited-lying-inner.html \
 		visited_image_loading.sjs \
 		visited_image_loading_frame.html \
 		visited_image_loading_frame_empty.html \
 		test_load_events_on_stylesheets.html \
 		test_bug721136.html \
 		test_bug732153.html \
+		test_bug732209.html \
+		bug732209-css.sjs \
 		$(NULL)
 
 ifdef MOZ_FLEXBOX
 MOCHITEST_FILES +=	\
 		test_flexbox_align_self_auto.html \
 		test_flexbox_flex_grow_and_shrink.html \
 		test_flexbox_flex_shorthand.html \
 		test_flexbox_layout.html \
new file mode 100644
--- /dev/null
+++ b/layout/style/test/bug732209-css.sjs
@@ -0,0 +1,19 @@
+function handleRequest(request, response)
+{
+   // First item will be the ID; other items are optional
+   var query = request.queryString.split(/&/);
+
+   response.setHeader("Content-Type", "text/css", false);
+
+   if (query.indexOf("cors-anonymous") != -1) {
+     response.setHeader("Access-Control-Allow-Origin", "*", false);
+   } else if (query.indexOf("cors-credentials") != -1 &&
+              request.hasHeader("Origin")) {
+     response.setHeader("Access-Control-Allow-Origin",
+                        request.getHeader("Origin"), false)
+     response.setHeader("Access-Control-Allow-Credentials", "true", false);
+   }
+
+   response.write("#" + query[0] + " { color: green !important }" + "\n" +
+                  "#" + query[0] + ".reverse { color: red !important }");
+}
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_bug732209.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=732209
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 732209</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+    #content span { color: red; }
+    #content span.reverse { color: green; }
+    #content { display: block !important; }
+    #content span::before { content: attr(id); }
+  </style>
+  <link rel="stylesheet" href="bug732209-css.sjs?one">
+  <link rel="stylesheet" href="bug732209-css.sjs?two" crossorigin>
+  <link rel="stylesheet" href="bug732209-css.sjs?three" crossorigin="use-credentials">
+  <link rel="stylesheet"
+        href="http://example.com/tests/layout/style/test/bug732209-css.sjs?four">
+  <link rel="stylesheet"
+        href="http://example.com/tests/layout/style/test/bug732209-css.sjs?five"
+        crossorigin>
+  <link rel="stylesheet"
+        href="http://example.com/tests/layout/style/test/bug732209-css.sjs?six"
+        crossorigin="use-credentials">
+  <link rel="stylesheet"
+        href="http://example.com/tests/layout/style/test/bug732209-css.sjs?seven&cors-anonymous">
+  <link rel="stylesheet" id="cross-origin-sheet"
+        href="http://example.com/tests/layout/style/test/bug732209-css.sjs?eight&cors-anonymous"
+        crossorigin>
+  <link rel="stylesheet"
+        href="http://example.com/tests/layout/style/test/bug732209-css.sjs?nine&cors-anonymous"
+        crossorigin="use-credentials">
+  <link rel="stylesheet"
+        href="http://example.com/tests/layout/style/test/bug732209-css.sjs?ten&cors-credentials">
+  <link rel="stylesheet"
+        href="http://example.com/tests/layout/style/test/bug732209-css.sjs?eleven&cors-credentials"
+        crossorigin>
+  <link rel="stylesheet"
+        href="http://example.com/tests/layout/style/test/bug732209-css.sjs?twelve&cors-credentials"
+        crossorigin="use-credentials">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=732209">Mozilla Bug 732209</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <span id="one"></span>
+  <span id="two"></span>
+  <span id="three"></span>
+  <span id="four"></span>
+  <span id="five" class="reverse"></span>
+  <span id="six" class="reverse"></span>
+  <span id="seven"></span>
+  <span id="eight"></span>
+  <span id="nine" class="reverse"></span>
+  <span id="ten"></span>
+  <span id="eleven"></span>
+  <span id="twelve"></span>
+</div>
+<pre id="test" style="color: red">
+<script type="application/javascript">
+
+/** Test for Bug 732209 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+  var spans = $("content").querySelectorAll("span");
+  for (var i = 0; i < spans.length; ++i) {
+    is(getComputedStyle(spans[i], "").color, "rgb(0, 128, 0)",
+       "Span " + spans[i].id + " should be green");
+  }
+
+  try {
+    var sheet = $("cross-origin-sheet").sheet;
+    dump('aaa');
+    is(sheet.cssRules.length, 2,
+       "Should be able to get length of list of rules");
+    is(sheet.cssRules[0].style.color, "green",
+       "Should be able to read individual rules");
+  } catch (e) {
+    ok(false,
+       "Should be allowed to access cross-origin sheet that opted in with CORS: " + e);
+  }
+
+  SimpleTest.finish();
+});
+
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/svg/base/src/nsSVGUtils.cpp
+++ b/layout/svg/base/src/nsSVGUtils.cpp
@@ -1889,16 +1889,22 @@ MaybeOptimizeOpacity(nsIFrame *aFrame, f
 }
 
 bool
 nsSVGUtils::SetupCairoFillPaint(nsIFrame *aFrame, gfxContext* aContext)
 {
   const nsStyleSVG* style = aFrame->GetStyleSVG();
   if (style->mFill.mType == eStyleSVGPaintType_None)
     return false;
+
+  if (style->mFillRule == NS_STYLE_FILL_RULE_EVENODD)
+    aContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
+  else
+    aContext->SetFillRule(gfxContext::FILL_RULE_WINDING);
+
   float opacity = MaybeOptimizeOpacity(aFrame, style->mFillOpacity);
   nsSVGPaintServerFrame *ps =
     nsSVGEffects::GetPaintServer(aFrame, &style->mFill, nsSVGEffects::FillProperty());
   if (ps && ps->SetupPaintServer(aContext, aFrame, &nsStyleSVG::mFill, opacity))
     return true;
 
   // On failure, use the fallback colour in case we have an
   // objectBoundingBox where the width or height of the object is zero.
--- a/media/libvpx/Makefile.in
+++ b/media/libvpx/Makefile.in
@@ -5,16 +5,20 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
+ifdef GNU_CC
+OS_CFLAGS := $(filter-out -pedantic,$(OS_CFLAGS))
+endif
+
 DEFINES += -DHAVE_CONFIG_H=vpx_config.h
 
 MODULE = vpx
 LIBRARY_NAME = vpx
 FORCE_STATIC_LIB= 1
 ifeq (WINNT,$(OS_TARGET))
 VISIBILITY_FLAGS =
 endif
--- a/mobile/android/chrome/content/aboutReader.html
+++ b/mobile/android/chrome/content/aboutReader.html
@@ -4,30 +4,37 @@
 <head>
   <title></title>
   <meta content="text/html; charset=UTF-8" http-equiv="content-type">
   <meta name="viewport" content="width=device-width; user-scalable=0" />
 
   <link rel="stylesheet" href="chrome://browser/skin/aboutReader.css" type="text/css"/>
 </head>
 
-<body onload="AboutReader.init();" onunload="AboutReader.uninit();">
-  <iframe id="frame" src="about:readercontent"></iframe>
+<body>
+  <div id="reader-header" class="header">
+    <div id="reader-domain" class="domain"></div>
+    <h1 id="reader-title"></h1>
+    <div id="reader-credits" class="credits"></div>
+  </div>
+
+  <div id="reader-content" class="content">
+  </div>
+
   <ul id="reader-toolbar" class="toolbar toolbar-hidden">
     <li><a id="share-button" class="button share-button" href="#"></a></li>
     <ul class="dropdown">
       <li><a class="dropdown-toggle button style-button" href="#"></a></li>
       <li class="dropdown-popup">
         <ul id="color-scheme-buttons" class="segmented-button"></ul>
         <hr></hr>
         <div id="font-size-control" class="step-control"></div>
         <hr></hr>
         <div id="margin-size-control" class="step-control"></div>
       </li>
     </ul>
     <li><a id="list-button" class="button list-button" href="#"></a></li>
     <li><a id="toggle-button" class="button toggle-button" href="#"></a></li>
   </ul>
 
-  <script type="application/javascript;version=1.8" src="chrome://browser/content/aboutReader.js"></script>
 </body>
 
 </html>
--- a/mobile/android/chrome/content/aboutReader.js
+++ b/mobile/android/chrome/content/aboutReader.js
@@ -12,109 +12,117 @@ XPCOMUtils.defineLazyGetter(window, "gCh
     .getInterface(Ci.nsIWebNavigation)
     .QueryInterface(Ci.nsIDocShellTreeItem)
     .rootTreeItem
     .QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Ci.nsIDOMWindow)
     .QueryInterface(Ci.nsIDOMChromeWindow));
 
 function dump(s) {
-  Services.console.logStringMessage("Reader: " + s);
+  Services.console.logStringMessage("AboutReader: " + s);
 }
 
 let gStrings = Services.strings.createBundle("chrome://browser/locale/aboutReader.properties");
 
-let AboutReader = {
+let AboutReader = function(doc, win) {
+  dump("Init()");
+
+  this._doc = doc;
+  this._win = win;
+
+  Services.obs.addObserver(this, "Reader:FaviconReturn", false);
+
+  this._article = null;
+
+  dump("Feching toolbar, header and content notes from about:reader");
+  this._headerElement = doc.getElementById("reader-header");
+  this._domainElement = doc.getElementById("reader-domain");
+  this._titleElement = doc.getElementById("reader-title");
+  this._creditsElement = doc.getElementById("reader-credits");
+  this._contentElement = doc.getElementById("reader-content");
+  this._toolbarElement = doc.getElementById("reader-toolbar");
+
+  this._toolbarEnabled = false;
+
+  this._scrollOffset = win.pageYOffset;
+
+  let body = doc.body;
+  body.addEventListener("touchstart", this, false);
+  body.addEventListener("click", this, false);
+
+  win.addEventListener("scroll", this, false);
+  win.addEventListener("popstate", this, false);
+  win.addEventListener("resize", this, false);
+
+  this._setupAllDropdowns();
+  this._setupButton("toggle-button", this._onReaderToggle.bind(this));
+  this._setupButton("list-button", this._onList.bind(this));
+  this._setupButton("share-button", this._onShare.bind(this));
+
+  let colorSchemeOptions = [
+    { name: gStrings.GetStringFromName("aboutReader.colorSchemeLight"),
+      value: "light"},
+    { name: gStrings.GetStringFromName("aboutReader.colorSchemeDark"),
+      value: "dark"}
+  ];
+
+  let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
+  this._setupSegmentedButton("color-scheme-buttons", colorSchemeOptions, colorScheme, this._setColorScheme.bind(this));
+  this._setColorScheme(colorScheme);
+
+  let fontTitle = gStrings.GetStringFromName("aboutReader.textTitle");
+  this._setupStepControl("font-size-control", fontTitle, this._onFontSizeChange.bind(this));
+  this._fontSize = 0;
+  this._setFontSize(Services.prefs.getIntPref("reader.font_size"));
+
+  let marginTitle = gStrings.GetStringFromName("aboutReader.marginTitle");
+  this._setupStepControl("margin-size-control", marginTitle, this._onMarginSizeChange.bind(this));
+  this._marginSize = 0;
+  this._setMarginSize(Services.prefs.getIntPref("reader.margin_size"));
+
+  dump("Decoding query arguments");
+  let queryArgs = this._decodeQueryString(win.location.href);
+
+  this._isReadingListItem = (queryArgs.readingList == "1");
+  this._updateToggleButton();
+
+  let url = queryArgs.url;
+  let tabId = queryArgs.tabId;
+  if (tabId) {
+    dump("Loading from tab with ID: " + tabId + ", URL: " + url);
+    this._loadFromTab(tabId, url);
+  } else {
+    dump("Fetching page with URL: " + url);
+    this._loadFromURL(url);
+  }
+}
+
+AboutReader.prototype = {
   _STEP_INCREMENT: 0,
   _STEP_DECREMENT: 1,
 
   _BLOCK_IMAGES_SELECTOR: ".content p > img:only-child, " +
                           ".content p > a:only-child > img:only-child, " +
                           ".content .wp-caption img, " +
                           ".content figure img",
 
-  init: function Reader_init() {
-    dump("Init()");
-
-    Services.obs.addObserver(this, "Reader:FaviconReturn", false);
-
-    this._article = null;
-
-    dump("Feching toolbar, header and content notes from about:reader");
-    this._frame = document.getElementById("frame");
-    this._headerElement = this._frame.contentDocument.getElementById("reader-header");
-    this._domainElement = this._frame.contentDocument.getElementById("reader-domain");
-    this._creditsElement = this._frame.contentDocument.getElementById("reader-credits");
-    this._contentElement = this._frame.contentDocument.getElementById("reader-content");
-    this._toolbarElement = document.getElementById("reader-toolbar");
-
-    this._toolbarEnabled = false;
-
-    this._frame.contentDocument.addEventListener("DOMSubtreeModified", this, false);
-    this._frame.contentDocument.addEventListener("MozScrolledAreaChanged", this, false);
-    this._frame.contentDocument.addEventListener("touchstart", this, false);
-    this._frame.contentDocument.addEventListener("click", this, false);
-    window.addEventListener("scroll", this, false);
-    window.addEventListener("popstate", this, false);
-    window.addEventListener("resize", this, false);
-
-    this._setupAllDropdowns();
-    this._setupButton("toggle-button", this._onReaderToggle.bind(this));
-    this._setupButton("list-button", this._onList.bind(this));
-    this._setupButton("share-button", this._onShare.bind(this));
-
-    let colorSchemeOptions = [
-      { name: gStrings.GetStringFromName("aboutReader.colorSchemeLight"),
-        value: "light"},
-      { name: gStrings.GetStringFromName("aboutReader.colorSchemeDark"),
-        value: "dark"}
-    ];
-
-    let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
-    this._setupSegmentedButton("color-scheme-buttons", colorSchemeOptions, colorScheme, this._setColorScheme.bind(this));
-    this._setColorScheme(colorScheme);
-
-    let fontTitle = gStrings.GetStringFromName("aboutReader.textTitle");
-    this._setupStepControl("font-size-control", fontTitle, this._onFontSizeChange.bind(this));
-    this._fontSize = 0;
-    this._setFontSize(Services.prefs.getIntPref("reader.font_size"));
-
-    let marginTitle = gStrings.GetStringFromName("aboutReader.marginTitle");
-    this._setupStepControl("margin-size-control", marginTitle, this._onMarginSizeChange.bind(this));
-    this._marginSize = 0;
-    this._setMarginSize(Services.prefs.getIntPref("reader.margin_size"));
-
-    dump("Decoding query arguments");
-    let queryArgs = this._decodeQueryString(window.location.href);
-
-    this._isReadingListItem = (queryArgs.readingList == "1");
-    this._updateToggleButton();
-
-    let url = queryArgs.url;
-    let tabId = queryArgs.tabId;
-    if (tabId) {
-      dump("Loading from tab with ID: " + tabId + ", URL: " + url);
-      this._loadFromTab(tabId, url);
-    } else {
-      dump("Fetching page with URL: " + url);
-      this._loadFromURL(url);
-    }
-  },
-
   observe: function(aMessage, aTopic, aData) {
     switch(aTopic) {
       case "Reader:FaviconReturn": {
         let info = JSON.parse(aData);
         this._loadFavicon(info.url, info.faviconUrl);
         break;
       }
     }
   },
 
   handleEvent: function Reader_handleEvent(aEvent) {
+    if (!aEvent.isTrusted)
+      return;
+
     switch (aEvent.type) {
       case "touchstart":
         this._scrolled = false;
         break;
       case "click":
         if (!this._scrolled)
           this._toggleToolbarVisibility();
         break;
@@ -126,44 +134,38 @@ let AboutReader = {
         break;
       case "popstate":
         if (!aEvent.state)
           this._closeAllDropdowns();
         break;
       case "resize":
         this._updateImageMargins();
         break;
-      case "DOMSubtreeModified":
-      case "MozScrolledAreaChanged":
-        let newHeight = this._frame.contentDocument.body.offsetHeight + "px";
-        if (this._frame.style.height != newHeight) {
-          this._frame.style.height = newHeight;
-        }
-        break;
     }
   },
 
   uninit: function Reader_uninit() {
     dump("Uninit()");
 
-    Services.obs.removeObserver(this, "Reader:FaviconReturn");
+    Services.obs.removeObserver(this, "Reader:FaviconReturn", false);
 
-    this._frame.contentDocument.removeEventListener("touchstart", this, false);
-    this._frame.contentDocument.removeEventListener("click", this, false);
-    this._frame.contentDocument.removeEventListener("DOMSubtreeModified", this, false);
-    this._frame.contentDocument.removeEventListener("MozScrolledAreaChanged", this, false);
-    window.removeEventListener("scroll", this, false);
-    window.removeEventListener("popstate", this, false);
-    window.removeEventListener("resize", this, false);
+    let body = this._doc.body;
+    body.removeEventListener("touchstart", this, false);
+    body.removeEventListener("click", this, false);
+
+    let win = this._win;
+    win.removeEventListener("scroll", this, false);
+    win.removeEventListener("popstate", this, false);
+    win.removeEventListener("resize", this, false);
 
     this._hideContent();
   },
 
   _updateToggleButton: function Reader_updateToggleButton() {
-    let classes = document.getElementById("toggle-button").classList;
+    let classes = this._doc.getElementById("toggle-button").classList;
 
     if (this._isReadingListItem) {
       classes.add("on");
     } else {
       classes.remove("on");
     }
   },
 
@@ -231,20 +233,21 @@ let AboutReader = {
     else
       this._setMarginSize(this._marginSize - 5);
   },
 
   _setMarginSize: function Reader_setMarginSize(newMarginSize) {
     if (this._marginSize === newMarginSize)
       return;
 
+    let doc = this._doc;
+
     this._marginSize = Math.max(5, Math.min(25, newMarginSize));
-    let bodyStyle = this._frame.contentDocument.body.style;
-    bodyStyle.marginLeft = this._marginSize + "%";
-    bodyStyle.marginRight = this._marginSize + "%";
+    doc.body.style.marginLeft = this._marginSize + "%";
+    doc.body.style.marginRight = this._marginSize + "%";
 
     this._updateImageMargins();
 
     Services.prefs.setIntPref("reader.margin_size", this._marginSize);
   },
 
   _onFontSizeChange: function Reader_onFontSizeChange(operation) {
     if (operation == this._STEP_INCREMENT)
@@ -252,53 +255,50 @@ let AboutReader = {
     else
       this._setFontSize(this._fontSize - 1);
   },
 
   _setFontSize: function Reader_setFontSize(newFontSize) {
     if (this._fontSize === newFontSize)
       return;
 
-    let bodyClasses = this._frame.contentDocument.body.classList;
+    let bodyClasses = this._doc.body.classList;
 
     if (this._fontSize > 0)
       bodyClasses.remove("font-size" + this._fontSize);
 
     this._fontSize = Math.max(1, Math.min(7, newFontSize));
     bodyClasses.add("font-size" + this._fontSize);
 
     Services.prefs.setIntPref("reader.font_size", this._fontSize);
   },
 
   _setColorScheme: function Reader_setColorScheme(newColorScheme) {
     if (this._colorScheme === newColorScheme)
       return;
 
-    let bodyClasses = document.body.classList;
-    let frameClasses = this._frame.contentDocument.body.classList;
+    let bodyClasses = this._doc.body.classList;
 
-    if (this._colorScheme) {
+    if (this._colorScheme)
       bodyClasses.remove(this._colorScheme);
-      frameClasses.remove(this._colorScheme);
-    }
 
     this._colorScheme = newColorScheme;
     bodyClasses.add(this._colorScheme);
-    frameClasses.add(this._colorScheme);
 
     Services.prefs.setCharPref("reader.color_scheme", this._colorScheme);
   },
 
   _getToolbarVisibility: function Reader_getToolbarVisibility() {
     return !this._toolbarElement.classList.contains("toolbar-hidden");
   },
 
   _setToolbarVisibility: function Reader_setToolbarVisibility(visible) {
-    if (history.state)
-      history.back();
+    let win = this._win;
+    if (win.history.state)
+      win.history.back();
 
     if (!this._toolbarEnabled)
       return;
 
     if (this._getToolbarVisibility() === visible)
       return;
 
     this._toolbarElement.classList.toggle("toolbar-hidden");
@@ -348,25 +348,27 @@ let AboutReader = {
       }
     });
   },
 
   _loadFavicon: function Reader_loadFavicon(url, faviconUrl) {
     if (this._article.url !== url)
       return;
 
-    let link = document.createElement('link');
+    let doc = this._doc;
+
+    let link = doc.createElement('link');
     link.rel = 'shortcut icon';
     link.href = faviconUrl;
 
-    document.getElementsByTagName('head')[0].appendChild(link);
+    doc.getElementsByTagName('head')[0].appendChild(link);
   },
 
   _updateImageMargins: function Reader_updateImageMargins() {
-    let windowWidth = window.innerWidth;
+    let windowWidth = this._win.innerWidth;
     let contentWidth = this._contentElement.offsetWidth;
     let maxWidthStyle = windowWidth + "px !important";
 
     let setImageMargins = function(img) {
       if (!img._originalWidth)
         img._originalWidth = img.offsetWidth;
 
       let imgWidth = img._originalWidth;
@@ -385,17 +387,17 @@ let AboutReader = {
       let cssText = "max-width: " + maxWidthStyle + ";" +
                     "width: " + widthStyle + ";" +
                     "margin-left: " + imageStyle + ";" +
                     "margin-right: " + imageStyle + ";";
 
       img.style.cssText = cssText;
     }
 
-    let imgs = document.querySelectorAll(this._BLOCK_IMAGES_SELECTOR);
+    let imgs = this._doc.querySelectorAll(this._BLOCK_IMAGES_SELECTOR);
     for (let i = imgs.length; --i >= 0;) {
       let img = imgs[i];
 
       if (img.width > 0) {
         setImageMargins(img);
       } else {
         img.onload = function() {
           setImageMargins(img);
@@ -404,29 +406,29 @@ let AboutReader = {
     }
   },
 
   _showError: function Reader_showError(error) {
     this._headerElement.style.display = "none";
     this._contentElement.innerHTML = error;
     this._contentElement.style.display = "block";
 
-    document.title = error;
+    this._doc.title = error;
   },
 
   _showContent: function Reader_showContent(article) {
     this._article = article;
 
     let domain = Services.io.newURI(article.url, null, null).host;
     this._domainElement.innerHTML = domain;
 
     this._creditsElement.innerHTML = article.byline;
 
-    this._frame.contentDocument.getElementById("reader-title").innerHTML = article.title;
-    document.title = article.title;
+    this._titleElement.innerHTML = article.title;
+    this._doc.title = article.title;
 
     this._headerElement.style.display = "block";
 
     this._contentElement.innerHTML = article.content;
     this._updateImageMargins();
 
     this._contentElement.style.display = "block";
 
@@ -458,55 +460,66 @@ let AboutReader = {
         result[name] = decodeURIComponent(value);
       }
     }
 
     return result;
   },
 
   _setupStepControl: function Reader_setupStepControl(id, name, callback) {
-    let stepControl = document.getElementById(id);
+    let doc = this._doc;
+    let stepControl = doc.getElementById(id);
 
-    let title = document.createElement("h1");
+    let title = this._doc.createElement("h1");
     title.innerHTML = name;
     stepControl.appendChild(title);
 
-    let plusButton = document.createElement("div");
+    let plusButton = doc.createElement("div");
     plusButton.className = "button plus-button";
     stepControl.appendChild(plusButton);
 
-    let minusButton = document.createElement("div");
+    let minusButton = doc.createElement("div");
     minusButton.className = "button minus-button";
     stepControl.appendChild(minusButton);
 
     plusButton.addEventListener("click", function(aEvent) {
+      if (!aEvent.isTrusted)
+        return;
+
       aEvent.stopPropagation();
       callback(this._STEP_INCREMENT);
     }.bind(this), true);
 
     minusButton.addEventListener("click", function(aEvent) {
+      if (!aEvent.isTrusted)
+        return;
+
       aEvent.stopPropagation();
       callback(this._STEP_DECREMENT);
     }.bind(this), true);
   },
 
   _setupSegmentedButton: function Reader_setupSegmentedButton(id, options, initialValue, callback) {
-    let segmentedButton = document.getElementById(id);
+    let doc = this._doc;
+    let segmentedButton = doc.getElementById(id);
 
     for (let i = 0; i < options.length; i++) {
       let option = options[i];
 
-      let item = document.createElement("li");
-      let link = document.createElement("a");
+      let item = doc.createElement("li");
+      let link = doc.createElement("a");
       link.innerHTML = option.name;
       item.appendChild(link);
 
       segmentedButton.appendChild(item);
 
       link.addEventListener("click", function(aEvent) {
+        if (!aEvent.isTrusted)
+          return;
+
         aEvent.stopPropagation();
 
         let items = segmentedButton.children;
         for (let j = items.length - 1; j >= 0; j--) {
           items[j].classList.remove("selected");
         }
 
         item.classList.add("selected");
@@ -514,78 +527,109 @@ let AboutReader = {
       }.bind(this), true);
 
       if (option.value === initialValue)
         item.classList.add("selected");
     }
   },
 
   _setupButton: function Reader_setupButton(id, callback) {
-    let button = document.getElementById(id);
+    let button = this._doc.getElementById(id);
 
     button.addEventListener("click", function(aEvent) {
+      if (!aEvent.isTrusted)
+        return;
+
       aEvent.stopPropagation();
       callback();
     }, true);
   },
 
   _setupAllDropdowns: function Reader_setupAllDropdowns() {
-    let dropdowns = document.getElementsByClassName("dropdown");
+    let doc = this._doc;
+    let win = this._win;
+
+    let dropdowns = doc.getElementsByClassName("dropdown");
 
     for (let i = dropdowns.length - 1; i >= 0; i--) {
       let dropdown = dropdowns[i];
 
       let dropdownToggle = dropdown.getElementsByClassName("dropdown-toggle")[0];
       let dropdownPopup = dropdown.getElementsByClassName("dropdown-popup")[0];
 
       if (!dropdownToggle || !dropdownPopup)
         continue;
 
-      let dropdownArrow = document.createElement("div");
+      let dropdownArrow = doc.createElement("div");
       dropdownArrow.className = "dropdown-arrow";
       dropdownPopup.appendChild(dropdownArrow);
 
       let updatePopupPosition = function() {
           let popupWidth = dropdownPopup.offsetWidth + 30;
           let arrowWidth = dropdownArrow.offsetWidth;
           let toggleWidth = dropdownToggle.offsetWidth;
           let toggleLeft = dropdownToggle.offsetLeft;
 
           let popupShift = (toggleWidth - popupWidth) / 2;
-          let popupLeft = Math.max(0, Math.min(window.innerWidth - popupWidth, toggleLeft + popupShift));
+          let popupLeft = Math.max(0, Math.min(win.innerWidth - popupWidth, toggleLeft + popupShift));
           dropdownPopup.style.left = popupLeft + "px";
 
           let arrowShift = (toggleWidth - arrowWidth) / 2;
           let arrowLeft = toggleLeft - popupLeft + arrowShift;
           dropdownArrow.style.left = arrowLeft + "px";
-      }
+      };
 
-      window.addEventListener("resize", function(aEvent) {
+      win.addEventListener("resize", function(aEvent) {
+        if (!aEvent.isTrusted)
+          return;
+
         updatePopupPosition();
       }, true);
 
       dropdownToggle.addEventListener("click", function(aEvent) {
+        if (!aEvent.isTrusted)
+          return;
+
         aEvent.stopPropagation();
 
         let dropdownClasses = dropdown.classList;
 
         if (dropdownClasses.contains("open")) {
-          history.back();
+          win.history.back();
         } else {
           updatePopupPosition();
           if (!this._closeAllDropdowns())
-            history.pushState({ dropdown: 1 }, document.title);
+            this._pushDropdownState();
 
           dropdownClasses.add("open");
         }
       }.bind(this), true);
     }
   },
 
+  _pushDropdownState: function Reader_pushDropdownState() {
+    // FIXME: We're getting a NS_ERROR_UNEXPECTED error when we try
+    // to do win.history.pushState() here (see bug 682296). This is
+    // a workaround that allows us to push history state on the target
+    // content document.
+
+    let doc = this._doc;
+    let body = doc.body;
+
+    if (this._pushStateScript)
+      body.removeChild(this._pushStateScript);
+
+    this._pushStateScript = doc.createElement('script');
+    this._pushStateScript.type = "text/javascript";
+    this._pushStateScript.innerHTML = 'history.pushState({ dropdown: 1 }, document.title);';
+
+    body.appendChild(this._pushStateScript);
+  },
+
   _closeAllDropdowns : function Reader_closeAllDropdowns() {
-    let dropdowns = document.querySelectorAll(".dropdown.open");
+    let dropdowns = this._doc.querySelectorAll(".dropdown.open");
     for (let i = dropdowns.length - 1; i >= 0; i--) {
       dropdowns[i].classList.remove("open");
     }
 
     return (dropdowns.length > 0)
   }
-}
+};
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -31,16 +31,17 @@ XPCOMUtils.defineLazyGetter(this, "NetUt
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
 // Lazily-loaded browser scripts:
 [
   ["HelperApps", "chrome://browser/content/HelperApps.js"],
   ["SelectHelper", "chrome://browser/content/SelectHelper.js"],
+  ["AboutReader", "chrome://browser/content/aboutReader.js"],
   ["WebAppRT", "chrome://browser/content/WebAppRT.js"],
 ].forEach(function (aScript) {
   let [name, script] = aScript;
   XPCOMUtils.defineLazyGetter(window, name, function() {
     let sandbox = {};
     Services.scriptloader.loadSubScript(script, sandbox);
     return sandbox[name];
   });
@@ -2678,16 +2679,24 @@ Tab.prototype = {
         // pages have any privilege themselves.
         if (/^about:/.test(target.documentURI)) {
           this.browser.addEventListener("click", ErrorPageEventHandler, false);
           this.browser.addEventListener("pagehide", function listener() {
             this.browser.removeEventListener("click", ErrorPageEventHandler, false);
             this.browser.removeEventListener("pagehide", listener, true);
           }.bind(this), true);
         }
+
+        if (/^about:reader/.test(target.documentURI)) {
+          let aboutReader = new AboutReader(this.browser.contentDocument, this.browser.contentWindow);
+          this.browser.addEventListener("pagehide", function listener() {
+            aboutReader.uninit();
+            this.browser.removeEventListener("pagehide", listener, true);
+          }.bind(this), true);
+        }
         break;
       }
 
       case "DOMLinkAdded": {
         let target = aEvent.originalTarget;
         if (!target.href || target.disabled)
           return;
 
--- a/mobile/android/chrome/jar.mn
+++ b/mobile/android/chrome/jar.mn
@@ -1,27 +1,26 @@
 #filter substitution
 # 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/.
 
 
 chrome.jar:
-% content browser %content/ contentaccessible=yes
+% content browser %content/
 
 * content/about.xhtml                  (content/about.xhtml)
   content/config.xhtml                 (content/config.xhtml)
   content/aboutAddons.xhtml            (content/aboutAddons.xhtml)
   content/aboutAddons.js               (content/aboutAddons.js)
   content/aboutCertError.xhtml         (content/aboutCertError.xhtml)
   content/aboutDownloads.xhtml         (content/aboutDownloads.xhtml)
   content/aboutDownloads.js            (content/aboutDownloads.js)
   content/aboutFeedback.xhtml          (content/aboutFeedback.xhtml)
   content/aboutReader.html             (content/aboutReader.html)
-  content/aboutReaderContent.html      (content/aboutReaderContent.html)
   content/aboutReader.js               (content/aboutReader.js)
   content/Readability.js               (content/Readability.js)
   content/JSDOMParser.js               (content/JSDOMParser.js)
   content/readerWorker.js              (content/readerWorker.js)
   content/aboutHome.xhtml              (content/aboutHome.xhtml)
 * content/aboutRights.xhtml            (content/aboutRights.xhtml)
 * content/aboutApps.xhtml              (content/aboutApps.xhtml)
   content/aboutApps.js                 (content/aboutApps.js)
--- a/mobile/android/components/AboutRedirector.js
+++ b/mobile/android/components/AboutRedirector.js
@@ -56,21 +56,16 @@ let modules = {
     privileged: true
   },
   downloads: {
     uri: "chrome://browser/content/aboutDownloads.xhtml",
     privileged: true
   },
   reader: {
     uri: "chrome://browser/content/aboutReader.html",
-    privileged: true,
-    hide: true
-  },
-  readercontent: {
-    uri: "chrome://browser/content/aboutReaderContent.html",
     privileged: false,
     hide: true
   },
   feedback: {
     uri: "chrome://browser/content/aboutFeedback.xhtml",
     privileged: true
   }
 }
--- a/mobile/android/components/MobileComponents.manifest
+++ b/mobile/android/components/MobileComponents.manifest
@@ -5,17 +5,16 @@ contract @mozilla.org/network/protocol/a
 contract @mozilla.org/network/protocol/about;1?what=firefox {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=empty {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=rights {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=certerror {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=home {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=apps {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=downloads {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=reader {322ba47e-7047-4f71-aebf-cb7d69325cd9}
-contract @mozilla.org/network/protocol/about;1?what=readercontent {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=feedback {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 #ifdef MOZ_SAFE_BROWSING
 contract @mozilla.org/network/protocol/about;1?what=blocked {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 #endif
 
 # DirectoryProvider.js
 component {ef0f7a87-c1ee-45a8-8d67-26f586e46a4b} DirectoryProvider.js
 contract @mozilla.org/browser/directory-provider;1 {ef0f7a87-c1ee-45a8-8d67-26f586e46a4b}
--- a/mobile/android/locales/en-US/chrome/aboutFeedback.dtd
+++ b/mobile/android/locales/en-US/chrome/aboutFeedback.dtd
@@ -1,49 +1,70 @@
 <!-- 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/. -->
 
+<!-- LOCALIZATION NOTE: The text in some of these strings is supposed to be
+     fun and playful. Please feel free to adjust the tone as works best in
+     your language and/or locale. More detailed notes below. -->
+
 <!ENTITY pageTitle                 "&brandShortName; Feedback">
 
 <!ENTITY intro.header              "Have a minute?">
 <!ENTITY intro.message             "Tell us what you think about &brandShortName; for Android so far.">
 <!ENTITY intro.happyLink           "I love it">
 <!ENTITY intro.sadLink             "I ran into some problems">
 <!ENTITY intro.ideaLink            "I have an idea">
 
 <!-- LOCALIZATION NOTE (support.pre): Include a trailing space as needed. -->
 <!-- LOCALIZATION NOTE (support.link): Avoid leading/trailing spaces, this text is a link. -->
 <!-- LOCALIZATION NOTE (support.post): Include a starting space as needed. -->
 <!ENTITY support.pre               "If you need help or have a problem with &brandShortName;, please visit ">
 <!ENTITY support.link              "&brandShortName; Support">
 <!ENTITY support.post              ".">
 
 <!ENTITY happy.header              "That's great to hear!">
+
+<!-- LOCALIZATION NOTE (happy.message): "share the love" — This feels purposely exaggerated in English,
+     but essentially it means that we want you to let others know how much you love Firefox. -->
 <!ENTITY happy.message             "Want to share the love by giving us a 5 star rating on Google Play?">
+
+<!-- LOCALIZATION NOTE (happy.finePrint): "feels great" — Another exaggeration where we're trying to
+     get people to rate us by playfully telling them there's a benefit in it for them as well. -->
 <!ENTITY happy.finePrint           "It takes less than a minute and feels great.">
+
 <!ENTITY happy.ratingLink          "Yes, go to Google Play">
 <!ENTITY happy.maybeLater          "Maybe Later">
 <!ENTITY happy.noThanks            "No thanks">
 
 <!ENTITY sad.message               "We’re sorry that you had some problems with &brandShortName;. Please tell us what happened so that we can fix it.">
 <!ENTITY sad.placeholder           "Enter your feedback here">
 <!ENTITY sad.lastSite              "Last visited site (optional)">
+
 <!-- LOCALIZATION NOTE (sad.urlPlaceholder): Placeholder text that appears in "Last visited site" input box when there is no text. -->
 <!ENTITY sad.urlPlaceholder        "http://">
 <!ENTITY sad.thanksHeader          "Thanks for letting us know.">
 
-<!-- LOCALIZATION NOTE (sad.thanksMessageTop, sad.thanksMessageBottom): These two
-     strings will appear as separate paragraphs but make up one message. -->
+<!-- LOCALIZATION NOTE (sad.thanksMessageTop): "real people" — We're stating that an actual human will look at the feedback
+     and that it doesn't just go to some automated system that looks for keywords, or something like that. -->
 <!ENTITY sad.thanksMessageTop      "We’re always working to make &brandShortName; better. Rest assured that real people will look at your feedback and do their very best to resolve your issue.">
+
+<!-- LOCALIZATION NOTE (sad.thanksMessageBottom): We're suggesting that there will be consequences for the people working
+     on Firefox if they don't resolve the user's problem, like "or if they don't fix it, we'll fire them." If this doesn't
+     work in your language, you can change it to something like "no matter what" or just remove it entirely. -->
 <!ENTITY sad.thanksMessageBottom   "Or else.">
 
+<!-- LOCALIZATION NOTE (idea.message): In English, "please share your thoughts" could mean that we're asking the user to
+     tell us any thoughts or ideas they have about anything, so we're jokingly telling them not to use the space below
+     to tell us anything they're thinking about. -->
 <!ENTITY idea.message              "We love hearing your ideas! Please share your thoughts below. (Just the ones about &brandShortName;, please.)">
 <!ENTITY idea.placeholder          "Enter your idea here">
 <!ENTITY idea.thanksHeader         "Thanks!">
 
-<!-- LOCALIZATION NOTE (idea.thanksMessageTop, idea.thanksMessageBottom): These two
-     strings will appear as separate paragraphs but make up one message. -->
 <!ENTITY idea.thanksMessageTop     "We appreciate you taking the time to share your thoughts. We’re always working to make &brandShortName; better and contributions like yours can lead to great things.">
+
+<!-- LOCALIZATION NOTE (idea.thanksMessageBottom): "high five" — This is a celebratory or congratulatory gesture.
+     It could also be a handshake, a pat on the back, a thumbs up or something similar. The idea is that it's
+     something physical, which is why they can't see it.-->
 <!ENTITY idea.thanksMessageBottom  "You can't see it, but we're giving you a high five right now.">
 
 <!ENTITY feedback.privacy          "For your privacy, please don't include any personally indentifiable information in your feedback.">
 <!ENTITY feedback.send             "Send Feedback">
--- a/mobile/android/themes/core/aboutReader.css
+++ b/mobile/android/themes/core/aboutReader.css
@@ -1,47 +1,343 @@
 /* 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/. */
 
-body {
-  font-family: "OpenSansRegular","Droid Sans",sans-serif;
+%filter substitution
+%include defines.inc
+
+html {
+  -moz-text-size-adjust: none;
 }
 
-#frame {
-  border: 0;
-  width: 100%;
+body {
+  font-family: "OpenSansRegular","Droid Sans",sans-serif;
+  margin-top: 20px;
+  margin-bottom: 20px;
 }
 
 .light {
   background-color: #ffffff;
+  color: #222222;
 }
 
 .dark {
   background-color: #000000;
+  color: #eeeeee;
+}
+
+.header {
+  text-align: left;
+  display: none;
+}
+
+.header > .domain {
+  margin-top: 10px;
+  padding-bottom: 10px;
+  border-bottom: 2px solid; 
+}
+
+.header > h1 {
+  font-family: "OpenSansLight","Droid Sans",sans-serif;
+  font-weight: normal;
+  line-height: 1.1em;
+  width: 100%;
+  margin: 0px;
+  margin-top: 32px;
+  margin-bottom: 16px;
+  padding: 0px;
+}
+
+.header > .credits {
+  padding: 0px;
+  margin: 0px;
+  margin-bottom: 32px;
+}
+
+.light > .header > .domain {
+  color: #ee7600;
+  border-bottom-color: #d0d0d0; 
+}
+
+.light > .header > h1 {
+  color: #222222;
+}
+
+.light > .header > .credits {
+  color: #898989;
+}
+
+.dark > .header > .domain {
+  color: #ff9400;
+  border-bottom-color: #777777; 
+}
+
+.dark > .header > h1 {
+  color: #eeeeee;
+}
+
+.dark > .header > .credits {
+  color: #aaaaaa;
+}
+
+.font-size1 > .header > h1 {
+  font-size: 23px;
+}
+
+.font-size2 > .header > h1 {
+  font-size: 25px;
+}
+
+.font-size3 > .header > h1 {
+  font-size: 27px;
+}
+
+.font-size4 > .header > h1 {
+  font-size: 29px;
+}
+
+.font-size5 > .header > h1 {
+  font-size: 31px;
+}
+
+.font-size6 > .header > h1 {
+  font-size: 33px;
+}
+
+.font-size7 > .header > h1 {
+  font-size: 35px;
+}
+
+/* This covers caption, domain, and credits
+   texts in the reader UI */
+.font-size1 > .content .wp-caption-text,
+.font-size1 > .content figcaption,
+.font-size1 > .header > .domain,
+.font-size1 > .header > .credits {
+  font-size: 6px;
+}
+
+.font-size2 > .content .wp-caption-text,
+.font-size2 > .content figcaption,
+.font-size2 > .header > .domain,
+.font-size2 > .header > .credits {
+  font-size: 8px;
+}
+
+.font-size3 > .content .wp-caption-text,
+.font-size3 > .content figcaption,
+.font-size3 > .header > .domain,
+.font-size3 > .header > .credits {
+  font-size: 11px;
+}
+
+.font-size4 > .content .wp-caption-text,
+.font-size4 > .content figcaption,
+.font-size4 > .header > .domain,
+.font-size4 > .header > .credits {
+  font-size: 13px;
+}
+
+.font-size5 > .content .wp-caption-text,
+.font-size5 > .content figcaption,
+.font-size5 > .header > .domain,
+.font-size5 > .header > .credits {
+  font-size: 15px;
+}
+
+.font-size6 > .content .wp-caption-text,
+.font-size6 > .content figcaption,
+.font-size6 > .header > .domain,
+.font-size6 > .header > .credits {
+  font-size: 17px;
+}
+
+.font-size7 > .content .wp-caption-text,
+.font-size7 > .content figcaption,
+.font-size7 > .header > .domain,
+.font-size7 > .header > .credits {
+  font-size: 19px;
+}
+
+.content {
+  display: none;
+}
+
+.content a {
+  text-decoration: underline !important;
+  font-weight: normal;
+}
+
+.light > .content a,
+.light > .content a:visited,
+.light > .content a:hover,
+.light > .content a:active {
+  color: #ee6700 !important;
+}
+
+.dark > .content a,
+.dark > .content a:visited,
+.dark > .content a:hover,
+.dark > .content a:active {
+  color: #ff9400 !important;
+}
+
+.content * {
+  max-width: 100% !important;
+  height: auto !important;
+}
+
+.content p {
+  line-height: 1.4em !important;
+  margin: 0px !important;
+  margin-bottom: 20px !important;
+}
+
+/* Covers all images showing edge-to-edge using a 
+   an optional caption text */
+.content .wp-caption,
+.content figure {
+  display: block !important;
+  width: 100% !important;
+  margin: 0px !important;
+  margin-bottom: 32px !important;
+}
+
+/* Images marked to be shown edge-to-edge with an
+   optional captio ntext */
+.content p > img:only-child,
+.content p > a:only-child > img:only-child,
+.content .wp-caption img,
+.content figure img {
+  max-width: none !important;
+  height: auto !important;
+  display: block !important;
+  margin-top: 0px !important;
+  margin-bottom: 32px !important;
+}
+
+/* If image is place inside one of these blocks
+   there's no need to add margin at the bottom */
+.content .wp-caption img,
+.content figure img {
+  margin-bottom: 0px !important;
+}
+
+/* Image caption text */
+.content .caption,
+.content .wp-caption-text,
+.content figcaption {
+  margin: 0px !important;
+  padding-top: 4px !important;
+}
+
+.light > .content .caption,
+.light > .content .wp-caption-text,
+.light > .content figcaption {
+  color: #898989;
+}
+
+.dark > .content .caption,
+.dark > .content .wp-caption-text,
+.dark > .content figcaption {
+  color: #aaaaaa;
+}
+
+/* Ensure all pre-formatted code inside the reader content
+   are properly wrapped inside content width */
+.content code,
+.content pre {
+  white-space: pre-wrap !important;
+  margin-bottom: 20px !important;
+}
+
+.content blockquote {
+  margin: 0px !important;
+  margin-bottom: 20px !important;
+  padding: 0px !important;
+  padding-left: 16px !important;
+  border: 0px !important;
+  border-left: 2px solid !important;
+}
+
+.light > .content blockquote {
+  color: #898989 !important;
+  border-left-color: #d0d0d0 !important;
+}
+
+.dark > .content blockquote {
+  color: #aaaaaa !important;
+  border-left-color: #777777 !important;
+}
+
+.content ul,
+.content ol {
+  margin: 0px !important;
+  margin-bottom: 20px !important;
+  padding: 0px !important;
+  line-height: 1.5em;
+}
+
+.content ul {
+  padding-left: 30px !important;
+  list-style: disk !important;
+}
+
+.content ol {
+  padding-left: 35px !important;
+  list-style: decimal !important;
+}
+
+.font-size1 > .content {
+  font-size: 10px !important;
+}
+
+.font-size2 > .content {
+  font-size: 12px !important;
+}
+
+.font-size3 > .content {
+  font-size: 14px !important;
+}
+
+.font-size4 > .content {
+  font-size: 16px !important;
+}
+
+.font-size5 > .content {
+  font-size: 18px !important;
+}
+
+.font-size6 > .content {
+  font-size: 20px !important;
+}
+
+.font-size7 > .content {
+  font-size: 22px !important;
 }
 
 .toolbar {
   font-family: "Droid Sans",helvetica,arial,clean,sans-serif;
-  -moz-transition-property: visibility, opacity;
+  -moz-transition-property: visibility opacity;
   -moz-transition-duration: 0.7s;
   visibility: visible;
   opacity: 1.0;
   position: fixed;
   width: 100%;
   bottom: 0px;
   left: 0px;
   margin: 0;
   padding: 0;
   list-style: none;
   background-repeat: repeat;
 }
 
 .toolbar-hidden {
-  -moz-transition-property: visibility, opacity;
+  -moz-transition-property: visibility opacity;
   -moz-transition-duration: 0.7s;
   visibility: hidden;
   opacity: 0.0;
 }
 
 .toolbar > * {
   float: right;
   width: 25%;
--- a/mobile/android/themes/core/content.css
+++ b/mobile/android/themes/core/content.css
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 %filter substitution
 %include defines.inc
 
 @namespace url("http://www.w3.org/1999/xhtml");
 @namespace xul url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
-@-moz-document url(about:readercontent) {
+@-moz-document url-prefix(about:reader) {
   @font-face {
     font-family: 'OpenSansRegular';
     src: url('chrome://browser/skin/fonts/opensans-regular.ttf') format('truetype');
     font-weight: normal;
     font-style: normal;
   }
 
   @font-face {
--- a/mobile/android/themes/core/jar.mn
+++ b/mobile/android/themes/core/jar.mn
@@ -8,17 +8,16 @@ chrome.jar:
 % skin browser classic/1.0 %skin/
   skin/aboutPage.css                        (aboutPage.css)
   skin/about.css                            (about.css)
   skin/aboutAddons.css                      (aboutAddons.css)
   skin/aboutApps.css                        (aboutApps.css)
 * skin/aboutDownloads.css                   (aboutDownloads.css)
   skin/aboutFeedback.css                    (aboutFeedback.css)
   skin/aboutReader.css                      (aboutReader.css)
-  skin/aboutReaderContent.css               (aboutReaderContent.css)
 * skin/browser.css                          (browser.css)
 * skin/content.css                          (content.css)
   skin/config.css                           (config.css)
   skin/touchcontrols.css                    (touchcontrols.css)
   skin/netError.css                         (netError.css)
 % override chrome://global/skin/about.css chrome://browser/skin/about.css
 % override chrome://global/skin/media/videocontrols.css chrome://browser/skin/touchcontrols.css
 % override chrome://global/skin/netError.css chrome://browser/skin/netError.css
--- a/netwerk/base/src/nsBufferedStreams.cpp
+++ b/netwerk/base/src/nsBufferedStreams.cpp
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 #include "nsAlgorithm.h"
 #include "nsBufferedStreams.h"
 #include "nsStreamUtils.h"
 #include "nsCRT.h"
 #include "nsNetCID.h"
 #include "nsIClassInfoImpl.h"
 #include "mozilla/ipc/InputStreamUtils.h"
@@ -811,9 +811,9 @@ nsBufferedOutputStream::GetUnbufferedStr
             return rv;
     }
 
     *aStream = mStream;
     NS_IF_ADDREF(*aStream);
     return NS_OK;
 }
 
-////////////////////////////////////////////////////////////////////////////////
\ No newline at end of file
+////////////////////////////////////////////////////////////////////////////////
--- a/netwerk/base/src/nsFileStreams.cpp
+++ b/netwerk/base/src/nsFileStreams.cpp
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 #if defined(XP_UNIX) || defined(XP_BEOS)
 #include <unistd.h>
 #elif defined(XP_WIN)
 #include <windows.h>
 #elif defined(XP_OS2)
 #define INCL_DOSERRORS
 #include <os2.h>
--- a/netwerk/base/src/nsMIMEInputStream.cpp
+++ b/netwerk/base/src/nsMIMEInputStream.cpp
@@ -3,17 +3,17 @@
  * 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/. */
 
 /**
  * The MIME stream separates headers and a datastream. It also allows
  * automatic creation of the content-length header.
  */
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 #include "nsCOMPtr.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIMultiplexInputStream.h"
 #include "nsIMIMEInputStream.h"
 #include "nsISeekableStream.h"
 #include "nsIStringStream.h"
 #include "nsString.h"
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -140,22 +140,21 @@ private:
         // the queue that wants to call DoCallback.  No need to wait for
         // it, just run the callback now.
         DoCallback();
     }
 
     void DoCallback()
     {
         // Generate proxy info from the PAC string if appropriate
-        if (NS_SUCCEEDED(mStatus) && !mProxyInfo && !mPACString.IsEmpty())
+        if (NS_SUCCEEDED(mStatus) && !mProxyInfo && !mPACString.IsEmpty()) {
             mPPS->ProcessPACString(mPACString, mResolveFlags,
                                    getter_AddRefs(mProxyInfo));
 
-        // Now apply proxy filters
-        if (NS_SUCCEEDED(mStatus)) {
+            // Now apply proxy filters
             nsProtocolInfo info;
             mStatus = mPPS->GetProtocolInfo(mURI, &info);
             if (NS_SUCCEEDED(mStatus))
                 mPPS->ApplyFilters(mURI, info, mProxyInfo);
             else
                 mProxyInfo = nullptr;
         }
 
--- a/netwerk/ipc/NeckoMessageUtils.h
+++ b/netwerk/ipc/NeckoMessageUtils.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_net_NeckoMessageUtils_h
 #define mozilla_net_NeckoMessageUtils_h
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsStringGlue.h"
 #include "prio.h"
 #include "mozilla/Util.h" // for DebugOnly
 
 namespace IPC {
 
 // nsIPermissionManager utilities
 
--- a/netwerk/protocol/http/PHttpChannelParams.h
+++ b/netwerk/protocol/http/PHttpChannelParams.h
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_net_PHttpChannelParams_h
 #define mozilla_net_PHttpChannelParams_h
 
 #define ALLOW_LATE_NSHTTP_H_INCLUDE 1
 #include "base/basictypes.h"
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsHttp.h"
 #include "nsHttpHeaderArray.h"
 #include "nsHttpResponseHead.h"
 
 #include "nsIClassInfo.h"
 #include "nsNetUtil.h"
 
 namespace mozilla {
--- a/netwerk/test/unit/test_protocolproxyservice.js
+++ b/netwerk/test/unit/test_protocolproxyservice.js
@@ -117,16 +117,33 @@ BasicFilter.prototype = {
     throw Components.results.NS_ERROR_NO_INTERFACE;
   },
   applyFilter: function(pps, uri, pi) {
     return pps.newProxyInfo("http", "localhost", 8080, 0, 10,
            pps.newProxyInfo("direct", "", -1, 0, 0, null));
   }
 };
 
+function resolveCallback() { }
+resolveCallback.prototype = {
+  nextFunction: null,
+
+  QueryInterface : function (iid) {
+    const interfaces = [Components.interfaces.nsIProtocolProxyCallback,
+                        Components.interfaces..nsISupports];
+    if (!interfaces.some( function(v) { return iid.equals(v) } ))
+      throw Components.results.NS_ERROR_NO_INTERFACE;
+    return this;
+  },
+
+  onProxyAvailable : function (req, uri, pi, status) {
+    this.nextFunction(pi);
+  }
+};
+
 function run_filter_test() {
   var uri = ios.newURI("http://www.mozilla.org/", null, null);
 
   // Verify initial state
 
   var pi = pps.resolve(uri, 0);
   do_check_eq(pi, null);
 
@@ -178,16 +195,39 @@ function run_filter_test2() {
 
   // Remove filter and verify that we return to the initial state
 
   pps.unregisterFilter(filter1);
   pi = pps.resolve(uri, 0);
   do_check_eq(pi, null);
 }
 
+var filter_3_1;
+
+function run_filter_test3() {
+  var uri = ios.newURI("http://www.mozilla.org/", null, null);
+
+  // Push a filter and verify the results asynchronously
+
+  filter_3_1 = new TestFilter("http", "foo", 8080, 0, 10);
+  pps.registerFilter(filter_3_1, 20);
+
+  var cb = new resolveCallback();
+  cb.nextFunction = filter_test3_1;
+  var req = pps.asyncResolve(uri, 0, cb);
+  do_test_pending();
+}
+
+function filter_test3_1(pi) {
+  check_proxy(pi, "http", "foo", 8080, 0, 10, false);
+  pps.unregisterFilter(filter_3_1);
+  run_test_continued_3();
+  do_test_finished();
+}
+
 function run_pref_test() {
   var uri = ios.newURI("http://www.mozilla.org/", null, null);
 
   var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                         .getService(Components.interfaces.nsIPrefBranch);
 
   // Verify 'direct' setting
 
@@ -431,14 +471,18 @@ function run_test() {
   run_filter_test2();
   run_pref_test();
   run_pac_test();
   // additional tests may be added to run_test_continued
 }
 
 function run_test_continued() {
   run_pac_cancel_test();
-  // additional tests may be added to run_test_continued_2
+  // additional tests may be added to run_test_continued_3
 }
 
 function run_test_continued_2() {
+  run_filter_test3();
+}
+
+function run_test_continued_3() {
   run_proxy_host_filters_test();
 }
--- a/parser/html/nsHtml5SpeculativeLoad.cpp
+++ b/parser/html/nsHtml5SpeculativeLoad.cpp
@@ -30,17 +30,17 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5T
     case eSpeculativeLoadImage:
       aExecutor->PreloadImage(mUrl, mCrossOrigin);
       break;
     case eSpeculativeLoadScript:
       aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSource,
 			       mCrossOrigin);
       break;
     case eSpeculativeLoadStyle:
-      aExecutor->PreloadStyle(mUrl, mCharset);
+      aExecutor->PreloadStyle(mUrl, mCharset, mCrossOrigin);
       break;
     case eSpeculativeLoadManifest:  
       aExecutor->ProcessOfflineManifest(mUrl);
       break;
     case eSpeculativeLoadSetDocumentCharset: {
         nsCAutoString narrowName;
         CopyUTF16toUTF8(mCharset, narrowName);
         NS_ASSERTION(mTypeOrCharsetSource.Length() == 1,
--- a/parser/html/nsHtml5SpeculativeLoad.h
+++ b/parser/html/nsHtml5SpeculativeLoad.h
@@ -50,22 +50,24 @@ class nsHtml5SpeculativeLoad {
                       "Trying to reinitialize a speculative load!");
       mOpCode = eSpeculativeLoadScript;
       mUrl.Assign(aUrl);
       mCharset.Assign(aCharset);
       mTypeOrCharsetSource.Assign(aType);
       mCrossOrigin.Assign(aCrossOrigin);
     }
     
-    inline void InitStyle(const nsAString& aUrl, const nsAString& aCharset) {
+    inline void InitStyle(const nsAString& aUrl, const nsAString& aCharset,
+			  const nsAString& aCrossOrigin) {
       NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
                       "Trying to reinitialize a speculative load!");
       mOpCode = eSpeculativeLoadStyle;
       mUrl.Assign(aUrl);
       mCharset.Assign(aCharset);
+      mCrossOrigin.Assign(aCrossOrigin);
     }
 
     /**
      * "Speculative" manifest loads aren't truly speculative--if a manifest
      * gets loaded, we are committed to it. There can never be a <script>
      * before the manifest, so the situation of having to undo a manifest due
      * to document.write() never arises. The reason why a parser
      * thread-discovered manifest gets loaded via the speculative load queue
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -100,18 +100,22 @@ nsHtml5TreeBuilder::createElement(int32_
         } else if (nsHtml5Atoms::link == aName) {
           nsString* rel = aAttributes->getValue(nsHtml5AttributeName::ATTR_REL);
           // Not splitting on space here is bogus but the old parser didn't even
           // do a case-insensitive check.
           if (rel && rel->LowerCaseEqualsASCII("stylesheet")) {
             nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
             if (url) {
               nsString* charset = aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
-              mSpeculativeLoadQueue.AppendElement()->InitStyle(*url,
-                                                    (charset) ? *charset : EmptyString());
+              nsString* crossOrigin =
+                aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
+              mSpeculativeLoadQueue.AppendElement()->
+                InitStyle(*url,
+                          (charset) ? *charset : EmptyString(),
+                          (crossOrigin) ? *crossOrigin : NullString());
             }
           }
         } else if (nsHtml5Atoms::video == aName) {
           nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER);
           if (url) {
             mSpeculativeLoadQueue.AppendElement()->InitImage(*url, NullString());
           }
         } else if (nsHtml5Atoms::style == aName) {
@@ -157,17 +161,21 @@ nsHtml5TreeBuilder::createElement(int32_
           }
         } else if (nsHtml5Atoms::style == aName) {
           nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
           NS_ASSERTION(treeOp, "Tree op allocation failed.");
           treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber());
 
           nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
           if (url) {
-            mSpeculativeLoadQueue.AppendElement()->InitStyle(*url, EmptyString());
+            nsString* crossOrigin =
+              aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
+            mSpeculativeLoadQueue.AppendElement()->
+              InitStyle(*url, EmptyString(),
+                        (crossOrigin) ? *crossOrigin : NullString());
           }
         }        
         break;
     }
   } else if (aNamespace != kNameSpaceID_MathML) {
     // No speculative loader--just line numbers and defer/async check
     if (nsHtml5Atoms::style == aName) {
       nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -1055,23 +1055,24 @@ nsHtml5TreeOpExecutor::PreloadScript(con
   if (!uri) {
     return;
   }
   mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType, aCrossOrigin);
 }
 
 void
 nsHtml5TreeOpExecutor::PreloadStyle(const nsAString& aURL,
-                                    const nsAString& aCharset)
+                                    const nsAString& aCharset,
+                                    const nsAString& aCrossOrigin)
 {
   nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
   if (!uri) {
     return;
   }
-  mDocument->PreloadStyle(uri, aCharset);
+  mDocument->PreloadStyle(uri, aCharset, aCrossOrigin);
 }
 
 void
 nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
                                     const nsAString& aCrossOrigin)
 {
   nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
   if (!uri) {
--- a/parser/html/nsHtml5TreeOpExecutor.h
+++ b/parser/html/nsHtml5TreeOpExecutor.h
@@ -390,17 +390,18 @@ class nsHtml5TreeOpExecutor : public nsC
 
     nsIURI* GetViewSourceBaseURI();
 
     void PreloadScript(const nsAString& aURL,
                        const nsAString& aCharset,
                        const nsAString& aType,
                        const nsAString& aCrossOrigin);
 
-    void PreloadStyle(const nsAString& aURL, const nsAString& aCharset);
+    void PreloadStyle(const nsAString& aURL, const nsAString& aCharset,
+		      const nsAString& aCrossOrigin);
 
     void PreloadImage(const nsAString& aURL, const nsAString& aCrossOrigin);
 
     void SetSpeculationBase(const nsAString& aURL);
 
     static void InitializeStatics();
 
   private:
--- a/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
+++ b/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
@@ -314,16 +314,17 @@ certErrorTrust_CaInvalid=The certificate
 certErrorTrust_Issuer=The certificate is not trusted because the issuer certificate is not trusted.
 certErrorTrust_SignatureAlgorithmDisabled=The certificate is not trusted because it was signed using a signature algorithm that was disabled because that algorithm is not secure.
 certErrorTrust_ExpiredIssuer=The certificate is not trusted because the issuer certificate has expired.
 certErrorTrust_Untrusted=The certificate does not come from a trusted source.
 
 certErrorMismatch=The certificate is not valid for the name %S.
 # LOCALIZATION NOTE (certErrorMismatchSingle2): Do not translate <a id="cert_domain_link" title="%1$S">%1$S</a>
 certErrorMismatchSingle2=The certificate is only valid for <a id="cert_domain_link" title="%1$S">%1$S</a>
+certErrorMismatchSinglePlain=The certificate is only valid for %S
 certErrorMismatchMultiple=The certificate is only valid for the following names:
 certErrorMismatchNoNames=The certificate is not valid for any server names.
 
 # LOCALIZATION NOTE (certErrorExpiredNow): Do not translate %1$S (date+time of expired certificate) or %2$S (current date+time)
 certErrorExpiredNow=The certificate expired on %1$S. The current time is %2$S.
 # LOCALIZATION NOTE (certErrorNotYetValidNow): Do not translate %1$S (date+time certificate will become valid) or %2$S (current date+time)
 certErrorNotYetValidNow=The certificate will not be valid until %1$S. The current time is %2$S.
 
--- a/security/manager/ssl/src/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/src/SSLServerCertVerification.cpp
@@ -103,16 +103,17 @@
 #include "nsRecentBadCerts.h"
 #include "nsNSSIOLayer.h"
 
 #include "mozilla/Assertions.h"
 #include "nsIThreadPool.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsComponentManagerUtils.h"
 #include "nsServiceManagerUtils.h"
+#include "nsIConsoleService.h"
 #include "PSMRunnable.h"
 
 #include "ssl.h"
 #include "secerr.h"
 #include "secport.h"
 #include "sslerr.h"
 
 #ifdef PR_LOGGING
@@ -176,16 +177,37 @@ void StopSSLServerCertVerificationThread
   if (gCertVerificationThreadPool) {
     gCertVerificationThreadPool->Shutdown();
     NS_RELEASE(gCertVerificationThreadPool);
   }
 }
 
 namespace {
 
+void
+LogInvalidCertError(TransportSecurityInfo *socketInfo, 
+                    const nsACString &host, 
+                    const nsACString &hostWithPort,
+                    PRInt32 port,
+                    PRErrorCode errorCode,
+                    ::mozilla::psm::SSLErrorMessageType errorMessageType,
+                    nsIX509Cert* ix509)
+{
+  nsString message;
+  socketInfo->GetErrorLogMessage(errorCode, errorMessageType, message);
+  
+  if (!message.IsEmpty()) {
+    nsCOMPtr<nsIConsoleService> console;
+    console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+    if (console) {
+      console->LogStringMessage(message.get());
+    }
+  }
+}
+
 // Dispatched to the STS thread to notify the infoObject of the verification
 // result.
 //
 // This will cause the PR_Poll in the STS thread to return, so things work
 // correctly even if the STS thread is blocked polling (only) on the file
 // descriptor that is waiting for this result.
 class SSLServerCertVerificationResult : public nsRunnable
 {
@@ -223,17 +245,17 @@ class CertErrorRunnable : public SyncRun
       mErrorCodeMismatch(errorCodeMismatch),
       mErrorCodeExpired(errorCodeExpired)
   {
   }
 
   virtual void RunOnTargetThread();
   nsRefPtr<SSLServerCertVerificationResult> mResult; // out
 private:
-  SSLServerCertVerificationResult* CheckCertOverrides();
+  SSLServerCertVerificationResult *CheckCertOverrides();
   
   const void * const mFdForLogging; // may become an invalid pointer; do not dereference
   const nsCOMPtr<nsIX509Cert> mCert;
   const nsRefPtr<TransportSecurityInfo> mInfoObject;
   const PRErrorCode mDefaultErrorCodeToReport;
   const uint32_t mCollectedErrors;
   const PRErrorCode mErrorCodeTrust;
   const PRErrorCode mErrorCodeMismatch;
@@ -350,19 +372,31 @@ CertErrorRunnable::CheckCertOverrides()
                                       mInfoObject->SSLStatus());
   }
 
   // pick the error code to report by priority
   PRErrorCode errorCodeToReport = mErrorCodeTrust    ? mErrorCodeTrust
                                 : mErrorCodeMismatch ? mErrorCodeMismatch
                                 : mErrorCodeExpired  ? mErrorCodeExpired
                                 : mDefaultErrorCodeToReport;
+                                
+  SSLServerCertVerificationResult *result = 
+    new SSLServerCertVerificationResult(mInfoObject, 
+                                        errorCodeToReport,
+                                        OverridableCertErrorMessage);
 
-  return new SSLServerCertVerificationResult(mInfoObject, errorCodeToReport,
-                                             OverridableCertErrorMessage);
+  LogInvalidCertError(mInfoObject,
+                      nsDependentCString(mInfoObject->GetHostName()),
+                      hostWithPortString,
+                      port,
+                      result->mErrorCode,
+                      result->mErrorMessageType,
+                      mCert);
+
+  return result;
 }
 
 void 
 CertErrorRunnable::RunOnTargetThread()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mResult = CheckCertOverrides();
--- a/security/manager/ssl/src/TransportSecurityInfo.cpp
+++ b/security/manager/ssl/src/TransportSecurityInfo.cpp
@@ -240,62 +240,92 @@ TransportSecurityInfo::GetErrorMessage(P
 
   if (!NS_IsMainThread()) {
     NS_ERROR("nsNSSSocketInfo::GetErrorMessage called off the main thread");
     return NS_ERROR_NOT_SAME_THREAD;
   }
 
   MutexAutoLock lock(mMutex);
 
-  nsresult rv = formatErrorMessage(lock);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (mErrorMessageCached.IsEmpty()) {
+    nsresult rv = formatErrorMessage(lock, 
+                                     mErrorCode, mErrorMessageType,
+                                     true, true, mErrorMessageCached);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   *aText = ToNewUnicode(mErrorMessageCached);
   return *aText != nullptr ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
+void
+TransportSecurityInfo::GetErrorLogMessage(PRErrorCode errorCode,
+                                          SSLErrorMessageType errorMessageType,
+                                          nsString &result)
+{
+  if (!NS_IsMainThread()) {
+    NS_ERROR("nsNSSSocketInfo::GetErrorLogMessage called off the main thread");
+    return;
+  }
+
+  MutexAutoLock lock(mMutex);
+  (void) formatErrorMessage(lock, errorCode, errorMessageType,
+                            false, false, result);
+}
+
 static nsresult
 formatPlainErrorMessage(nsXPIDLCString const & host, int32_t port,
-                        PRErrorCode err, nsString &returnedMessage);
+                        PRErrorCode err, 
+                        bool suppressPort443,
+                        nsString &returnedMessage);
 
 static nsresult
 formatOverridableCertErrorMessage(nsISSLStatus & sslStatus,
                                   PRErrorCode errorCodeToReport, 
                                   const nsXPIDLCString & host, int32_t port,
+                                  bool suppressPort443,
+                                  bool wantsHtml,
                                   nsString & returnedMessage);
 
 // XXX: uses nsNSSComponent string bundles off the main thread when called by
-//      nsNSSSocketInfo::Write(). When we remove the error message from the
-//      serialization of nsNSSSocketInfo (bug 697781) we can inline
-//      formatErrorMessage into GetErrorMessage().
+//      nsNSSSocketInfo::Write().
 nsresult
-TransportSecurityInfo::formatErrorMessage(MutexAutoLock const & proofOfLock)
+TransportSecurityInfo::formatErrorMessage(MutexAutoLock const & proofOfLock, 
+                                          PRErrorCode errorCode,
+                                          SSLErrorMessageType errorMessageType,
+                                          bool wantsHtml, bool suppressPort443, 
+                                          nsString &result)
 {
-  if (mErrorCode == 0 || !mErrorMessageCached.IsEmpty()) {
+  if (errorCode == 0) {
+    result.Truncate();
     return NS_OK;
   }
 
   nsresult rv;
   NS_ConvertASCIItoUTF16 hostNameU(mHostName);
-  NS_ASSERTION(mErrorMessageType != OverridableCertErrorMessage || 
+  NS_ASSERTION(errorMessageType != OverridableCertErrorMessage || 
                 (mSSLStatus && mSSLStatus->mServerCert &&
                  mSSLStatus->mHaveCertErrorBits),
-                "GetErrorMessage called for cert error without cert");
-  if (mErrorMessageType == OverridableCertErrorMessage && 
+                "GetErrorLogMessage called for cert error without cert");
+  if (errorMessageType == OverridableCertErrorMessage && 
       mSSLStatus && mSSLStatus->mServerCert) {
-    rv = formatOverridableCertErrorMessage(*mSSLStatus, mErrorCode,
+    rv = formatOverridableCertErrorMessage(*mSSLStatus, errorCode,
                                            mHostName, mPort,
-                                           mErrorMessageCached);
+                                           suppressPort443,
+                                           wantsHtml,
+                                           result);
   } else {
-    rv = formatPlainErrorMessage(mHostName, mPort, mErrorCode,
-                                 mErrorMessageCached);
+    rv = formatPlainErrorMessage(mHostName, mPort, 
+                                 errorCode,
+                                 suppressPort443,
+                                 result);
   }
 
   if (NS_FAILED(rv)) {
-    mErrorMessageCached.Truncate();
+    result.Truncate();
   }
 
   return rv;
 }
 
 /* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
 NS_IMETHODIMP
 TransportSecurityInfo::GetInterface(const nsIID & uuid, void * *result)
@@ -367,17 +397,19 @@ TransportSecurityInfo::Write(nsIObjectOu
   // This mask value has been chosen as mSecurityState could
   // never be assigned such value.
   uint32_t version = 3;
   stream->Write32(version | 0xFFFF0000);
   stream->Write32(mSecurityState);
   stream->WriteWStringZ(mShortDesc.get());
 
   // XXX: uses nsNSSComponent string bundles off the main thread
-  nsresult rv = formatErrorMessage(lock); 
+  nsresult rv = formatErrorMessage(lock, 
+                                   mErrorCode, mErrorMessageType,
+                                   true, true, mErrorMessageCached);
   NS_ENSURE_SUCCESS(rv, rv);
   stream->WriteWStringZ(mErrorMessageCached.get());
 
   stream->WriteCompoundObject(NS_ISUPPORTS_CAST(nsISSLStatus*, status),
                               NS_GET_IID(nsISupports), true);
 
   stream->Write32((uint32_t)mSubRequestsHighSecurity);
   stream->Write32((uint32_t)mSubRequestsLowSecurity);
@@ -580,17 +612,19 @@ TransportSecurityInfo::SetSSLStatus(nsSS
 
 /* Formats an error message for non-certificate-related SSL errors
  * and non-overridable certificate errors (both are of type
  * PlainErrormMessage). Use formatOverridableCertErrorMessage
  * for overridable cert errors.
  */
 static nsresult
 formatPlainErrorMessage(const nsXPIDLCString &host, int32_t port,
-                        PRErrorCode err, nsString &returnedMessage)
+                        PRErrorCode err, 
+                        bool suppressPort443,
+                        nsString &returnedMessage)
 {
   const PRUnichar *params[1];
   nsresult rv;
 
   nsCOMPtr<nsINSSComponent> component = do_GetService(kNSSComponentCID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (host.Length())
@@ -600,17 +634,17 @@ formatPlainErrorMessage(const nsXPIDLCSt
     // For now, hide port when it's 443 and we're reporting the error.
     // In the future a better mechanism should be used
     // to make a decision about showing the port number, possibly by requiring
     // the context object to implement a specific interface.
     // The motivation is that Mozilla browser would like to hide the port number
     // in error pages in the common case.
 
     hostWithPort.AssignASCII(host);
-    if (port != 443) {
+    if (!suppressPort443 || port != 443) {
       hostWithPort.AppendLiteral(":");
       hostWithPort.AppendInt(port);
     }
     params[0] = hostWithPort.get();
 
     nsString formattedString;
     rv = component->PIPBundleFormatStringFromName("SSLConnectionErrorPrefix", 
                                                   params, 1, 
@@ -775,16 +809,17 @@ GetSubjectAltNames(CERTCertificate *nssC
   PORT_FreeArena(san_arena, false);
   return true;
 }
 
 static void
 AppendErrorTextMismatch(const nsString &host,
                         nsIX509Cert* ix509,
                         nsINSSComponent *component,
+                        bool wantsHtml,
                         nsString &returnedMessage)
 {
   const PRUnichar *params[1];
   nsresult rv;
 
   CERTCertificate *nssCert = NULL;
   CERTCertificateCleaner nssCertCleaner(nssCert);
 
@@ -837,19 +872,25 @@ AppendErrorTextMismatch(const nsString &
       returnedMessage.Append(NS_LITERAL_STRING("\n  "));
       returnedMessage.Append(allNames);
       returnedMessage.Append(NS_LITERAL_STRING("  \n"));
     }
   }
   else if (nameCount == 1) {
     const PRUnichar *params[1];
     params[0] = allNames.get();
+    
+    const char *stringID;
+    if (wantsHtml)
+      stringID = "certErrorMismatchSingle2";
+    else
+      stringID = "certErrorMismatchSinglePlain";
 
     nsString formattedString;
-    rv = component->PIPBundleFormatStringFromName("certErrorMismatchSingle2", 
+    rv = component->PIPBundleFormatStringFromName(stringID, 
                                                   params, 1, 
                                                   formattedString);
     if (NS_SUCCEEDED(rv)) {
       returnedMessage.Append(formattedString);
       returnedMessage.Append(NS_LITERAL_STRING("\n"));
     }
   }
   else { // nameCount == 0
@@ -973,32 +1014,34 @@ AppendErrorTextCode(PRErrorCode errorCod
 /* Formats an error message for overridable certificate errors (of type
  * OverridableCertErrorMessage). Use formatPlainErrorMessage to format
  * non-overridable cert errors and non-cert-related errors.
  */
 static nsresult
 formatOverridableCertErrorMessage(nsISSLStatus & sslStatus,
                                   PRErrorCode errorCodeToReport, 
                                   const nsXPIDLCString & host, int32_t port,
+                                  bool suppressPort443,
+                                  bool wantsHtml,
                                   nsString & returnedMessage)
 {
   const PRUnichar *params[1];
   nsresult rv;
   nsAutoString hostWithPort;
   nsAutoString hostWithoutPort;
 
   // For now, hide port when it's 443 and we're reporting the error.
   // In the future a better mechanism should be used
   // to make a decision about showing the port number, possibly by requiring
   // the context object to implement a specific interface.
   // The motivation is that Mozilla browser would like to hide the port number
   // in error pages in the common case.
   
   hostWithoutPort.AppendASCII(host);
-  if (port == 443) {
+  if (suppressPort443 && port == 443) {
     params[0] = hostWithoutPort.get();
   } else {
     hostWithPort.AppendASCII(host);
     hostWithPort.Append(':');
     hostWithPort.AppendInt(port);
     params[0] = hostWithPort.get();
   }
 
@@ -1023,17 +1066,17 @@ formatOverridableCertErrorMessage(nsISSL
     AppendErrorTextUntrusted(errorCodeToReport, hostWithoutPort, ix509, 
                              component, returnedMessage);
   }
 
   bool isDomainMismatch;
   rv = sslStatus.GetIsDomainMismatch(&isDomainMismatch);
   NS_ENSURE_SUCCESS(rv, rv);
   if (isDomainMismatch) {
-    AppendErrorTextMismatch(hostWithoutPort, ix509, component, returnedMessage);
+    AppendErrorTextMismatch(hostWithoutPort, ix509, component, wantsHtml, returnedMessage);
   }
 
   bool isNotValidAtThisTime;
   rv = sslStatus.GetIsNotValidAtThisTime(&isNotValidAtThisTime);
   NS_ENSURE_SUCCESS(rv, rv);
   if (isNotValidAtThisTime) {
     AppendErrorTextTime(ix509, component, returnedMessage);
   }
--- a/security/manager/ssl/src/TransportSecurityInfo.h
+++ b/security/manager/ssl/src/TransportSecurityInfo.h
@@ -54,16 +54,21 @@ public:
   nsresult GetHostName(char **aHostName);
   nsresult SetHostName(const char *aHostName);
 
   int32_t GetPort() const { return mPort; }
   nsresult GetPort(int32_t *aPort);
   nsresult SetPort(int32_t aPort);
 
   PRErrorCode GetErrorCode() const;
+  
+  void GetErrorLogMessage(PRErrorCode errorCode,
+                          ::mozilla::psm::SSLErrorMessageType errorMessageType,
+                          nsString &result);
+  
   void SetCanceled(PRErrorCode errorCode,
                    ::mozilla::psm::SSLErrorMessageType errorMessageType);
   
   /* Set SSL Status values */
   nsresult SetSSLStatus(nsSSLStatus *aSSLStatus);
   nsSSLStatus* SSLStatus() { return mSSLStatus; }
   void SetStatusErrorBits(nsIX509Cert & cert, uint32_t collected_errors);
 
@@ -86,17 +91,21 @@ private:
   int32_t mSubRequestsLowSecurity;
   int32_t mSubRequestsBrokenSecurity;
   int32_t mSubRequestsNoSecurity;
   nsString mShortDesc;
 
   PRErrorCode mErrorCode;
   ::mozilla::psm::SSLErrorMessageType mErrorMessageType;
   nsString mErrorMessageCached;
-  nsresult formatErrorMessage(::mozilla::MutexAutoLock const & proofOfLock);
+  nsresult formatErrorMessage(::mozilla::MutexAutoLock const & proofOfLock, 
+                              PRErrorCode errorCode,
+                              ::mozilla::psm::SSLErrorMessageType errorMessageType,
+                              bool wantsHtml, bool suppressPort443, 
+                              nsString &result);
 
   int32_t mPort;
   nsXPIDLCString mHostName;
   PRErrorCode mIsCertIssuerBlacklisted;
 
   /* SSL Status */
   nsRefPtr<nsSSLStatus> mSSLStatus;
 
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -18,16 +18,17 @@
 #include "SSLServerCertVerification.h"
 #include "nsNSSCertHelper.h"
 #include "nsNSSCleaner.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsISecureBrowserUI.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsCharSeparatedTokenizer.h"
+#include "nsIConsoleService.h"
 #include "PSMRunnable.h"
 
 #include "ssl.h"
 #include "secerr.h"
 #include "sslerr.h"
 #include "secder.h"
 #include "keyhi.h"
 
@@ -480,17 +481,19 @@ void nsSSLIOLayerHelpers::Cleanup()
 
   if (mutex) {
     delete mutex;
     mutex = nullptr;
   }
 }
 
 static void
-nsHandleSSLError(nsNSSSocketInfo *socketInfo, PRErrorCode err)
+nsHandleSSLError(nsNSSSocketInfo *socketInfo, 
+                 ::mozilla::psm::SSLErrorMessageType errtype, 
+                 PRErrorCode err)
 {
   if (!NS_IsMainThread()) {
     NS_ERROR("nsHandleSSLError called off the main thread");
     return;
   }
 
   // SetCanceled is only called by the main thread or the socket transport
   // thread. Whenever this function is called on the main thread, the SSL
@@ -524,18 +527,29 @@ nsHandleSSLError(nsNSSSocketInfo *socket
       nsCString hostWithPortString = hostName;
       hostWithPortString.AppendLiteral(":");
       hostWithPortString.AppendInt(port);
     
       bool suppressMessage = false; // obsolete, ignored
       rv = sel->NotifySSLError(csi, err, hostWithPortString, &suppressMessage);
     }
   }
-
+  
+  // We must cancel first, which sets the error code.
   socketInfo->SetCanceled(err, PlainErrorMessage);
+  nsXPIDLString errorString;
+  socketInfo->GetErrorLogMessage(err, errtype, errorString);
+  
+  if (!errorString.IsEmpty()) {
+    nsCOMPtr<nsIConsoleService> console;
+    console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+    if (console) {
+      console->LogStringMessage(errorString.get());
+    }
+  }
 }
 
 namespace {
 
 enum Operation { reading, writing, not_reading_or_writing };
 
 int32_t checkHandshake(int32_t bytesTransfered, bool wasReading,
                        PRFileDesc* ssl_layer_fd,
@@ -801,27 +815,32 @@ isTLSIntoleranceError(int32_t err, bool 
   }
   
   return false;
 }
 
 class SSLErrorRunnable : public SyncRunnableBase
 {
  public:
-  SSLErrorRunnable(nsNSSSocketInfo * infoObject, PRErrorCode errorCode)
-    : mInfoObject(infoObject), mErrorCode(errorCode)
+  SSLErrorRunnable(nsNSSSocketInfo * infoObject, 
+                   ::mozilla::psm::SSLErrorMessageType errtype, 
+                   PRErrorCode errorCode)
+    : mInfoObject(infoObject)
+    , mErrType(errtype)
+    , mErrorCode(errorCode)
   {
   }
 
   virtual void RunOnTargetThread()
   {
-    nsHandleSSLError(mInfoObject, mErrorCode);
+    nsHandleSSLError(mInfoObject, mErrType, mErrorCode);
   }
   
   nsRefPtr<nsNSSSocketInfo> mInfoObject;
+  ::mozilla::psm::SSLErrorMessageType mErrType;
   const PRErrorCode mErrorCode;
 };
 
 namespace {
 
 int32_t checkHandshake(int32_t bytesTransfered, bool wasReading,
                        PRFileDesc* ssl_layer_fd,
                        nsNSSSocketInfo *socketInfo)
@@ -885,16 +904,17 @@ int32_t checkHandshake(int32_t bytesTran
     // do the synchronous dispatch to the main thread unnecessarily after we've
     // already handled a certificate error. (SSLErrorRunnable calls
     // nsHandleSSLError, which has logic to avoid replacing the error message,
     // so without the !socketInfo->GetErrorCode(), it would just be an
     // expensive no-op.)
     if (!wantRetry && (IS_SSL_ERROR(err) || IS_SEC_ERROR(err)) &&
         !socketInfo->GetErrorCode()) {
       nsRefPtr<SyncRunnableBase> runnable = new SSLErrorRunnable(socketInfo,
+                                                                 PlainErrorMessage,
                                                                  err);
       (void) runnable->DispatchToMainThreadAndWait();
     }
   }
   else if (wasReading && 0 == bytesTransfered) // zero bytes on reading, socket closed
   {
     if (handleHandshakeResultNow)
     {
--- a/testing/marionette/client/marionette/tests/unit/test_findelement.py
+++ b/testing/marionette/client/marionette/tests/unit/test_findelement.py
@@ -111,16 +111,19 @@ class TestElements(MarionetteTestCase):
         self.assertEqual(el, found_el)
         found_el = self.marionette.find_elements("xpath", "id('mozLink')")[0]
         self.assertEqual(HTMLElement, type(found_el))
         self.assertEqual(el, found_el)
 
     def test_not_found(self):
         test_html = self.marionette.absolute_url("test.html")
         self.marionette.navigate(test_html)
+        self.marionette.set_search_timeout(1000)
+        self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "I'm not on the page")
+        self.marionette.set_search_timeout(0)
         self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "I'm not on the page")
 
     def test_timeout(self):
         test_html = self.marionette.absolute_url("test.html")
         self.marionette.navigate(test_html)
         self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "newDiv")
         self.assertTrue(True, self.marionette.set_search_timeout(4000))
         self.marionette.navigate(test_html)
@@ -172,17 +175,19 @@ class TestElementsChrome(MarionetteTestC
 
     def test_xpath(self):
         el = self.marionette.execute_script("return window.document.getElementById('testBox');")
         found_el = self.marionette.find_element("xpath", "id('testBox')")
         self.assertEqual(HTMLElement, type(found_el));
         self.assertEqual(el, found_el)
 
     def test_not_found(self):
+        self.marionette.set_search_timeout(1000)
         self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "I'm not on the page")
-
+        self.marionette.set_search_timeout(0)
+        self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "I'm not on the page")
 
     def test_timeout(self):
         self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "myid")
         self.assertTrue(True, self.marionette.set_search_timeout(4000))
         self.marionette.execute_script("window.setTimeout(function() {var b = window.document.createElement('button'); b.id = 'myid'; document.getElementById('things').appendChild(b);}, 1000)")
         self.assertEqual(HTMLElement, type(self.marionette.find_element("id", "myid")))
         self.marionette.execute_script("window.document.getElementById('things').removeChild(window.document.getElementById('myid'));")
--- a/testing/marionette/marionette-actors.js
+++ b/testing/marionette/marionette-actors.js
@@ -976,18 +976,19 @@ MarionetteDriverActor.prototype = {
    * @param object aRequest
    *        'using' member indicates which search method to use
    *        'value' member is the value the client is looking for
    */
   findElement: function MDA_findElement(aRequest) {
     if (this.context == "chrome") {
       let id;
       try {
-        let notify = this.sendResponse.bind(this);
-        id = this.curBrowser.elementManager.find(this.getCurrentWindow(),aRequest, notify, false);
+        let on_success = this.sendResponse.bind(this);
+        let on_error = this.sendError.bind(this);
+        id = this.curBrowser.elementManager.find(this.getCurrentWindow(),aRequest, on_success, on_error, false);
       }
       catch (e) {
         this.sendError(e.message, e.code, e.stack);
         return;
       }
     }
     else {
       this.sendAsync("findElementContent", {value: aRequest.value, using: aRequest.using, element: aRequest.element});
@@ -1000,18 +1001,19 @@ MarionetteDriverActor.prototype = {
    * @param object aRequest
    *        'using' member indicates which search method to use
    *        'value' member is the value the client is looking for
    */
   findElements: function MDA_findElements(aRequest) {
     if (this.context == "chrome") {
       let id;
       try {
-        let notify = this.sendResponse.bind(this);
-        id = this.curBrowser.elementManager.find(this.getCurrentWindow(), aRequest, notify, true);
+        let on_success = this.sendResponse.bind(this);
+        let on_error = this.sendError.bind(this);
+        id = this.curBrowser.elementManager.find(this.getCurrentWindow(), aRequest, on_success, on_error, true);
       }
       catch (e) {
         this.sendError(e.message, e.code, e.stack);
         return;
       }
     }
     else {
       this.sendAsync("findElementsContent", {value: aRequest.value, using: aRequest.using, element: aRequest.element});
--- a/testing/marionette/marionette-elements.js
+++ b/testing/marionette/marionette-elements.js
@@ -230,52 +230,54 @@ ElementManager.prototype = {
    * @param object values
    *        The 'using' member of values will tell us which search
    *        method to use. The 'value' member tells us the value we
    *        are looking for.
    *        If this object has an 'element' member, this will be used
    *        as the start node instead of the document root
    *        If this object has a 'time' member, this number will be
    *        used to see if we have hit the search timelimit.
-   * @param function notify
-   *        The notification callback used when we are returning
+   * @param function on_success
+   *        The notification callback used when we are returning successfully.
+   * @param function on_error
+            The callback to invoke when an error occurs.
    * @param boolean all
    *        If true, all found elements will be returned.
    *        If false, only the first element will be returned.
    *
    * @return nsIDOMElement or list of nsIDOMElements
-   *        Returns the element(s) by calling the notify function.
+   *        Returns the element(s) by calling the on_success function.
    */
-  find: function EM_find(win, values, notify, all) {
+  find: function EM_find(win, values, on_success, on_error, all) {
     let startTime = values.time ? values.time : new Date().getTime();
     let startNode = (values.element != undefined) ? this.getKnownElement(values.element, win) : win.document;
     if (this.elementStrategies.indexOf(values.using) < 0) {
       throw new ElementException("No such strategy.", 17, null);
     }
     let found = all ? this.findElements(values.using, values.value, win.document, startNode) : this.findElement(values.using, values.value, win.document, startNode);
     if (found) {
       let type = Object.prototype.toString.call(found);
       if ((type == '[object Array]') || (type == '[object HTMLCollection]')) {
         let ids = []
         for (let i = 0 ; i < found.length ; i++) {
           ids.push(this.addToKnownElements(found[i]));
         }
-        notify(ids);
+        on_success(ids);
       }
       else {
         let id = this.addToKnownElements(found);
-        notify(id);
+        on_success(id);
       }
       return;
     } else {
       if (this.searchTimeout == 0 || new Date().getTime() - startTime > this.searchTimeout) {
-        throw new ElementException("Unable to locate element: " + values.value, 7, null);
+        on_error("Unable to locate element: " + values.value, 7, null);
       } else {
         values.time = startTime;
-        this.timer.initWithCallback(this.find.bind(this, win, values, notify, all), 100, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+        this.timer.initWithCallback(this.find.bind(this, win, values, on_success, on_error, all), 100, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
       }
     }
   },
 
   /**
    * Find a value by XPATH
    * 
    * @param nsIDOMElement root
--- a/testing/marionette/marionette-listener.js
+++ b/testing/marionette/marionette-listener.js
@@ -557,34 +557,34 @@ function refresh(msg) {
   let listen = function() { removeEventListener("DOMContentLoaded", arguments.callee, false); sendOk() } ;
   addEventListener("DOMContentLoaded", listen, false);
 }
 
 /**
  * Find an element in the document using requested search strategy 
  */
 function findElementContent(msg) {
-  let id;
   try {
-    let notify = function(id) { sendResponse({value:id});};
-    id = elementManager.find(curWindow, msg.json, notify, false);
+    let on_success = function(id) { sendResponse({value:id}); };
+    let on_error = sendError;
+    elementManager.find(curWindow, msg.json, on_success, on_error, false);
   }
   catch (e) {
     sendError(e.message, e.code, e.stack);
   }
 }
 
 /**
  * Find elements in the document using requested search strategy 
  */
 function findElementsContent(msg) {
-  let id;
   try {
-    let notify = function(id) { sendResponse({value:id});};
-    id = elementManager.find(curWindow, msg.json, notify, true);
+    let on_success = function(id) { sendResponse({value:id}); };
+    let on_error = sendError;
+    elementManager.find(curWindow, msg.json, on_success, on_error, true);
   }
   catch (e) {
     sendError(e.message, e.code, e.stack);
   }
 }
 
 /**
  * Send click event to element
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -142,16 +142,18 @@
  "dom/imptests/webapps/DOMCore/tests/approved/test_Range-insertNode.html": "bug 775227",
  "dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html": "bug 775227",
  "dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html": "bug 775227",
  "dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html": "bug 775227",
  "dom/imptests/webapps/WebStorage/tests/submissions/Infraware/test_storage_local_key.html": "bug 775227",
  "dom/indexedDB/ipc/test_ipc.html": "bug 783513",
  "dom/indexedDB/test/test_third_party.html": "TIMED_OUT",
  "dom/indexedDB/test/test_event_propagation.html": "TIMED_OUT, bug 780855",
+ "dom/indexedDB/test/test_app_isolation_inproc.html": "TIMED_OUT",
+ "dom/indexedDB/test/test_app_isolation_oop.html": "TIMED_OUT",
  "dom/network/tests/test_network_basics.html": "",
  "dom/settings/tests/test_settings_events.html": "",
  "dom/settings/tests/test_settings_basics.html": "",
  "dom/contacts/tests/test_contacts_blobs.html": "",
  "dom/contacts/tests/test_contacts_basics.html": "",
  "dom/contacts/tests/test_contacts_events.html": "",
  "dom/sms/tests/test_sms_basics.html": "",
  "dom/tests/mochitest/ajax/jquery/test_jQuery.html": "bug 775227",
--- a/toolkit/components/osfile/osfile_shared_allthreads.jsm
+++ b/toolkit/components/osfile/osfile_shared_allthreads.jsm
@@ -26,16 +26,30 @@
      // Import components after having initialized |exports.OS|, to ensure
      // that everybody uses the same definition of |OS|.
      if (typeof Components != "undefined") {
        Components.utils.import("resource://gre/modules/ctypes.jsm");
        Components.classes["@mozilla.org/net/osfileconstantsservice;1"].
          getService(Components.interfaces.nsIOSFileConstantsService).init();
      }
 
+     // Define a lazy getter for a property
+     let defineLazyGetter = function(object, name, getter) {
+       Object.defineProperty(object, name, {
+         configurable: true,
+         get: function lazy() {
+           delete this[name];
+           let value = getter.call(this);
+           Object.defineProperty(object, name, {
+             value: value
+           });
+           return value;
+         }
+       });
+     };
 
      let LOG;
      if (typeof console != "undefined" && console.log) {
        LOG = console.log.bind(console, "OS");
      } else {
        LOG = function() {
          let text = "OS";
          for (let i = 0; i < arguments.length; ++i) {
@@ -793,18 +807,21 @@
      };
      exports.OS.Shared.declareFFI = declareFFI;
 
 
      /**
       * Libxul-based utilities, shared by all back-ends.
       */
 
-     let libxul = ctypes.open(OS.Constants.Path.libxul);
-     exports.OS.Shared.libxul = libxul;
+     // Lazy getter for libxul
+     defineLazyGetter(exports.OS.Shared, "libxul",
+       function init_libxul() {
+         return ctypes.open(OS.Constants.Path.libxul);
+       });
 
      exports.OS.Shared.Utils = {};
 
      let Strings = exports.OS.Shared.Utils.Strings = {};
 
      // A bogus array type used to perform pointer arithmetics
      let gOffsetByType;
 
@@ -856,54 +873,66 @@
       * (can be jschar* or a jschar[]).
       * @return {string} The same string, as a JavaScript String.
       */
      Strings.importWString = function importWString(wstring) {
        return wstring.readString();
      };
 
 
-     let NS_Free = libxul.declare("osfile_ns_free", ctypes.default_abi,
-       /*return*/ Types.void_t.implementation,
-       /*ptr*/ Types.voidptr_t.implementation);
-
-     let wstrdup = declareFFI(libxul, "osfile_wstrdup", ctypes.default_abi,
-       /*return*/ Types.out_wstring.releaseWith(NS_Free),
-       /*ptr*/ Types.wstring);
-
+     let Pointers = {};
+     defineLazyGetter(Pointers, "NS_Free",
+       function init_NS_Free() {
+         return exports.OS.Shared.libxul.declare("osfile_ns_free",
+           ctypes.default_abi,
+          /*return*/ Types.void_t.implementation,
+          /*ptr*/ Types.voidptr_t.implementation);
+       });
 
-      /**
-        * Export a string as a wide string (e.g. a |jschar.ptr|).
-        *
-        * @param {string} string A JavaScript String.
-        * @return {CData} The C representation of that string, as a |jschar*|.
-        * This value will be automatically garbage-collected once it is
-        * not referenced anymore.
-        */
-      Strings.exportWString = function exportWString(string) {
-        return wstrdup(string);
-      };
+     /**
+      * Export a string as a wide string (e.g. a |jschar.ptr|).
+      *
+      * @param {string} string A JavaScript String.
+      * @return {CData} The C representation of that string, as a |jschar*|.
+      * This value will be automatically garbage-collected once it is
+      * not referenced anymore.
+      */
+     defineLazyGetter(Strings, "exportWString",
+       function init_exportWString() {
+         return declareFFI(exports.OS.Shared.libxul,
+           "osfile_wstrdup",
+           ctypes.default_abi,
+           /*return*/ Types.out_wstring.releaseWith(Pointers.NS_Free),
+           /*ptr*/ Types.wstring);
+       });
 
 // Encodings
 
-     Strings.encodeAll = declareFFI(libxul, "osfile_EncodeAll",
-        ctypes.default_abi,
-         /*return*/     Types.void_t.out_ptr.releaseWith(NS_Free),
-         /*encoding*/   Types.cstring,
-         /*source*/     Types.wstring,
-         /*bytes*/      Types.uint32_t.out_ptr);
+     defineLazyGetter(Strings, "encodeAll",
+       function init_encodeAll() {
+         return declareFFI(exports.OS.Shared.libxul,
+           "osfile_EncodeAll",
+           ctypes.default_abi,
+           /*return*/     Types.void_t.out_ptr.releaseWith(Pointers.NS_Free),
+           /*encoding*/   Types.cstring,
+           /*source*/     Types.wstring,
+           /*bytes*/      Types.uint32_t.out_ptr);
+       });
 
-     let _decodeAll = declareFFI(libxul, "osfile_DecodeAll",
-        ctypes.default_abi,
-         /*return*/     Types.out_wstring.releaseWith(NS_Free),
-         /*encoding*/   Types.cstring,
-         /*source*/     Types.void_t.in_ptr,
-         /*bytes*/      Types.uint32_t);
-
-     Strings.decodeAll = function decodeAll(encoding, source, bytes) {
-       let decoded = _decodeAll(encoding, source, bytes);
-       if (!decoded) {
-         return null;
-       }
-       return Strings.importWString(decoded);
-     };
+     defineLazyGetter(Strings, "decodeAll",
+       function init_decodeAll() {
+         let _decodeAll = declareFFI(exports.OS.Shared.libxul, "osfile_DecodeAll",
+           ctypes.default_abi,
+            /*return*/     Types.out_wstring.releaseWith(Pointers.NS_Free),
+            /*encoding*/   Types.cstring,
+            /*source*/     Types.void_t.in_ptr,
+            /*bytes*/      Types.uint32_t);
+         return function decodeAll(encoding, source, bytes) {
+           let decoded = _decodeAll(encoding, source, bytes);
+           if (!decoded) {
+             return null;
+           }
+           return Strings.importWString(decoded);
+          };
+        }
+     );
    })(this);
 }
--- a/toolkit/components/osfile/osfile_unix_front.jsm
+++ b/toolkit/components/osfile/osfile_unix_front.jsm
@@ -137,17 +137,17 @@
       * file.  If |OS.File.POS_CURRENT|, |pos| is relative to the
       * current position in the file. If |OS.File.POS_END|, |pos| is
       * relative to the end of the file.
       *
       * @return The new position in the file.
       */
      File.prototype.setPosition = function setPosition(pos, whence) {
        if (whence === undefined) {
-         whence = Const.SEEK_START;
+         whence = Const.SEEK_SET;
        }
        return throw_on_negative("setPosition",
          UnixFile.lseek(this.fd, pos, whence)
        );
      };
 
      /**
       * Fetch the information on the file.
--- a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js
+++ b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js
@@ -486,16 +486,22 @@ function test_position() {
   let file = OS.File.open(src_file_name);
   is(file.getPosition(), 0, "test_position: Initial position is 0");
 
   let size = 0 + file.stat().size; // Hack: We can remove this 0 + once 776259 has landed
 
   file.setPosition(ARBITRARY_POSITION, OS.File.POS_START);
   is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position from start");
 
+  file.setPosition(0, OS.File.POS_START);
+  is(file.getPosition(), 0, "test_position: Setting position from start back to 0");
+
+  file.setPosition(ARBITRARY_POSITION);
+  is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position without argument");
+
   file.setPosition(-ARBITRARY_POSITION, OS.File.POS_END);
   is(file.getPosition(), size - ARBITRARY_POSITION, "test_position: Setting position from end");
 
   file.setPosition(ARBITRARY_POSITION, OS.File.POS_CURRENT);
   is(file.getPosition(), size, "test_position: Setting position from current");
 
   file.close();
   ok(true, "test_position: Complete");
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -395,19 +395,18 @@
   },
   "SYSTEM_FONT_FALLBACK_FIRST": {
     "kind": "exponential",
     "high": "40000",
     "n_buckets": 20,
     "description": "System font fallback, first call (ms)"
   },
   "SYSTEM_FONT_FALLBACK_SCRIPT": {
-    "kind": "linear",
-    "high": "110",
-    "n_buckets": 111,
+    "kind": "enumerated",
+    "n_values": 110,
     "description": "System font fallback script"
   },
   "GRADIENT_DURATION": {
     "kind": "exponential",
     "high":"50000000",
     "n_buckets":20,
     "description": "Gradient generation time (us)"
   },
@@ -530,19 +529,18 @@
   },
   "HTTP_REQUEST_PER_PAGE": {
     "kind": "exponential",
     "high": "1000",
     "n_buckets": 50,
     "description": "HTTP: Requests per page (count)"
   },
   "HTTP_REQUEST_PER_PAGE_FROM_CACHE": {
-    "kind": "linear",
-    "high": "101",
-    "n_buckets": 102,
+    "kind": "enumerated",
+    "n_values": 101,
     "description": "HTTP: Requests serviced from cache (%)"
   },
   "HTTP_REQUEST_PER_CONN": {
     "kind": "exponential",
     "high": "1000",
     "n_buckets": 50,
     "description": "HTTP: requests per connection"
   },
@@ -1820,37 +1818,35 @@
   },
   "PLACES_FRECENCY_CALC_TIME_MS": {
     "kind": "exponential",
     "high": "100",
     "n_buckets": 10,
     "description": "PLACES: Time to calculate frecency of a page (ms)"
   },
   "UPDATER_STATUS_CODES": {
-    "kind": "linear",
-    "high": "50",
-    "n_buckets": 51,
+    "kind": "enumerated",
+    "n_values": 50,
     "description": "Updater: the status of the latest update performed"
   },
   "UPDATER_UPDATES_ENABLED": {
     "kind": "boolean",
     "description": "Updater: Whether or not updates are enabled"
   },
   "UPDATER_UPDATES_AUTOMATIC": {
     "kind": "boolean",
     "description": "Updater: Whether or not updates are automatic"
   },
   "UPDATER_SERVICE_ENABLED": {
     "kind": "boolean",
     "description": "Updater: Whether or not the MozillaMaintenance service is enabled"
   },
   "UPDATER_SERVICE_ERRORS": {
-    "kind": "linear",
-    "high": "30",
-    "n_buckets": 31,
+    "kind": "enumerated",
+    "n_values": 30,
     "description": "Updater: The number of MozillaMaintenance service errors that have occurred"
   },
   "UPDATER_SERVICE_INSTALLED": {
     "kind": "boolean",
     "description": "Updater: Whether or not the MozillaMaintenance service is installed"
   },
   "UPDATER_SERVICE_MANUALLY_UNINSTALLED": {
     "kind": "boolean",
@@ -2135,19 +2131,18 @@
     "n_values": 3,
     "description": "Whether the user is in safe mode (No, Yes, Forced)"
   },
   "NEWTAB_PAGE_ENABLED": {
     "kind": "boolean",
     "description": "New tab page is enabled."
   },
   "NEWTAB_PAGE_PINNED_SITES_COUNT": {
-    "kind": "exponential",
-    "high": "9",
-    "n_buckets": 10,
+    "kind": "enumerated",
+    "n_values": 9,
     "description": "Number of pinned sites on the new tab page."
   },
   "NEWTAB_PAGE_BLOCKED_SITES_COUNT": {
     "kind": "exponential",
     "high": "100",
     "n_buckets": 10,
     "description": "Number of sites blocked from the new tab page."
   },
--- a/toolkit/components/telemetry/Makefile.in
+++ b/toolkit/components/telemetry/Makefile.in
@@ -60,16 +60,26 @@ endif
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 histograms_file := $(srcdir)/Histograms.json
 histogram_enum_file := TelemetryHistogramEnums.h
 histogram_data_file := TelemetryHistogramData.inc
 
-$(histogram_enum_file): $(histograms_file) $(srcdir)/gen-histogram-enum.py
+enum_python_deps := \
+  $(srcdir)/gen-histogram-enum.py \
+  $(srcdir)/histogram_tools.py \
+  $(NULL)
+
+data_python_deps := \
+  $(srcdir)/gen-histogram-data.py \
+  $(srcdir)/histogram_tools.py \
+  $(NULL)
+
+$(histogram_enum_file): $(histograms_file) $(enum_python_deps)
 	$(PYTHON) $(srcdir)/gen-histogram-enum.py $< > $@
-$(histogram_data_file): $(histograms_file) $(srcdir)/gen-histogram-data.py
+$(histogram_data_file): $(histograms_file) $(data_python_deps)
 	$(PYTHON) $(srcdir)/gen-histogram-data.py $< > $@
 
 Telemetry.$(OBJ_SUFFIX): $(histogram_data_file)
 
 GARBAGE += $(histogram_data_file) $(histogram_enum_file)
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -267,16 +267,30 @@ GetHistogramByEnumId(Telemetry::ID id, H
     return NS_OK;
   }
 
   const TelemetryHistogram &p = gHistograms[id];
   nsresult rv = HistogramGet(p.id, p.min, p.max, p.bucketCount, p.histogramType, &h);
   if (NS_FAILED(rv))
     return rv;
 
+#ifdef DEBUG
+  // Check that the C++ Histogram code computes the same ranges as the
+  // Python histogram code.
+  const struct bounds &b = gBucketLowerBoundIndex[id];
+  if (b.length != 0) {
+    MOZ_ASSERT(size_t(b.length) == h->bucket_count(),
+               "C++/Python bucket # mismatch");
+    for (int i = 0; i < b.length; ++i) {
+      MOZ_ASSERT(gBucketLowerBounds[b.offset + i] == h->ranges(i),
+                 "C++/Python bucket mismatch");
+    }
+  }
+#endif
+
   *ret = knownHistograms[id] = h;
   return NS_OK;
 }
 
 bool
 FillRanges(JSContext *cx, JSObject *array, Histogram *h)
 {
   for (size_t i = 0; i < h->bucket_count(); i++) {
--- a/toolkit/components/telemetry/gen-histogram-data.py
+++ b/toolkit/components/telemetry/gen-histogram-data.py
@@ -4,141 +4,139 @@
 
 # Write out histogram information for C++.  The histograms are defined
 # in a file provided as a command-line argument.
 
 from __future__ import with_statement
 
 import sys
 import histogram_tools
+import itertools
 
 banner = """/* This file is auto-generated, see gen-histogram-data.py.  */
 """
 
-# Write out the gHistograms array.  Try and ensure the user didn't
-# provide bogus keys in the histogram definition.
+# Write out the gHistograms array.
 
-def check_keys(name, definition, allowed_keys):
-    for key in definition.iterkeys():
-        if key not in allowed_keys:
-            raise KeyError, '%s not permitted for %s' % (key, name)
-
-def print_array_entry(name, low, high, n_buckets, kind, definition):
-    cpp_guard = definition.get('cpp_guard')
+def print_array_entry(histogram):
+    cpp_guard = histogram.cpp_guard()
     if cpp_guard:
         print "#if defined(%s)" % cpp_guard
-    print "  { \"%s\", %s, %s, %s, nsITelemetry::HISTOGRAM_%s, \"%s\" }," \
-        % (name, low, high, n_buckets, kind, definition['description'])
+    print "  { \"%s\", %s, %s, %s, %s, \"%s\" }," \
+        % (histogram.name(), histogram.low(), histogram.high(),
+           histogram.n_buckets(), histogram.nsITelemetry_kind(),
+           histogram.description())
     if cpp_guard:
         print "#endif"
 
-def process_boolean(name, definition):
-    print_array_entry(name, 0, 1, 2, 'BOOLEAN', definition)
-
-def process_flag(name, definition):
-    print_array_entry(name, 0, 1, 2, 'FLAG', definition)
-
-def process_enumerated_values(name, definition):
-    n_values = definition['n_values']
-    print_array_entry(name, 1, n_values, "%s+1" % n_values, 'LINEAR',
-                      definition)
-
-def process_general_histogram(name, definition):
-    low = definition.get('low', 1)
-    high = definition['high']
-    n_buckets = definition['n_buckets']
-    print_array_entry(name, low, high, n_buckets,
-                      definition['kind'].upper(), definition)
-
-always_allowed_keys = ['kind', 'description', 'cpp_guard']
-
 def write_histogram_table(histograms):
-    general_keys = ['low', 'high', 'n_buckets'] + always_allowed_keys
-
-    table = {
-        'boolean' : (process_boolean, always_allowed_keys),
-        'flag' : (process_flag, always_allowed_keys),
-        'enumerated' : (process_enumerated_values, ['n_values'] + always_allowed_keys),
-        'linear' : (process_general_histogram, general_keys),
-        'exponential' : (process_general_histogram, general_keys),
-        }
-
     print "const TelemetryHistogram gHistograms[] = {"
-    for (name, definition) in histograms:
-        kind = definition['kind']
-        if kind in table:
-            (processor, allowed_keys) = table[kind]
-            check_keys(name, definition, allowed_keys)
-            processor(name, definition)
-        else:
-            print "Don't know how to handle a histogram of kind ", kind
-            sys.exit(1)
+    for histogram in histograms:
+        print_array_entry(histogram)
     print "};"
 
 # Write out static asserts for histogram data.  We'd prefer to perform
 # these checks in this script itself, but since several histograms
 # (generally enumerated histograms) use compile-time constants for
 # their upper bounds, we have to let the compiler do the checking.
 
 def static_assert(expression, message):
     print "MOZ_STATIC_ASSERT(%s, \"%s\");" % (expression, message)
 
-def static_asserts_for_boolean(name, definition):
+def static_asserts_for_boolean(histogram):
     pass
 
-def static_asserts_for_flag(name, definition):
+def static_asserts_for_flag(histogram):
     pass
 
-def static_asserts_for_enumerated(name, definition):
-    n_values = definition['n_values']
-    static_assert("%s > 2" % n_values, "Not enough values for %s" % name)
+def static_asserts_for_enumerated(histogram):
+    n_values = histogram.high()
+    static_assert("%s > 2" % n_values,
+                  "Not enough values for %s" % histogram.name())
 
-def shared_static_asserts(name, definition):
-    low = definition.get('low', 1)
-    high = definition['high']
-    n_buckets = definition['n_buckets']
+def shared_static_asserts(histogram):
+    name = histogram.name()
+    low = histogram.low()
+    high = histogram.high()
+    n_buckets = histogram.n_buckets()
     static_assert("%s < %s" % (low, high), "low >= high for %s" % name)
     static_assert("%s > 2" % n_buckets, "Not enough values for %s" % name)
     static_assert("%s >= 1" % low, "Incorrect low value for %s" % name)
 
-def static_asserts_for_linear(name, definition):
-    shared_static_asserts(name, definition)
+def static_asserts_for_linear(histogram):
+    shared_static_asserts(histogram)
 
-def static_asserts_for_exponential(name, definition):
-    shared_static_asserts(name, definition)
+def static_asserts_for_exponential(histogram):
+    shared_static_asserts(histogram)
 
 def write_histogram_static_asserts(histograms):
     print """
 // Perform the checks at the beginning of HistogramGet at
 // compile time, so that incorrect histogram definitions
 // give compile-time errors, not runtime errors."""
 
     table = {
         'boolean' : static_asserts_for_boolean,
         'flag' : static_asserts_for_flag,
         'enumerated' : static_asserts_for_enumerated,
         'linear' : static_asserts_for_linear,
         'exponential' : static_asserts_for_exponential,
         }
 
-    for (name, definition) in histograms:
-        kind = definition['kind']
-        if kind in table:
-            cpp_guard = definition.get('cpp_guard')
-            if cpp_guard:
-                print "#if defined(%s)" % cpp_guard
-            table[kind](name, definition)
-            if cpp_guard:
-                print "#endif"
+    for histogram in histograms:
+        histogram_tools.table_dispatch(histogram.kind(), table,
+                                       lambda f: f(histogram))
+
+def write_debug_histogram_ranges(histograms):
+    ranges_lengths = []
+
+    # Collect all the range information from individual histograms.
+    # Write that information out as well.
+    print "#ifdef DEBUG"
+    print "const int gBucketLowerBounds[] = {"
+    for histogram in histograms:
+        ranges = []
+        try:
+            ranges = histogram.ranges()
+        except histogram_tools.DefinitionException:
+            pass
+        ranges_lengths.append(len(ranges))
+        # Note that we do not test cpp_guard here.  We do this so we
+        # will have complete information about all the histograms in
+        # this array.  Just having information about the ranges of
+        # histograms is not platform-specific; if there are histograms
+        # that have platform-specific constants in their definitions,
+        # those histograms will fail in the .ranges() call above and
+        # we'll have a zero-length array to deal with here.
+        if len(ranges) > 0:
+            print ','.join(map(str, ranges)), ','
         else:
-            print "Don't know how to handle a histogram of kind", kind
-            sys.exit(1)
+            print '/* Skipping %s */' % histogram.name()
+    print "};"
+
+    # Write the offsets into gBucketLowerBounds.
+    print "struct bounds { int offset; int length; };"
+    print "const struct bounds gBucketLowerBoundIndex[] = {"
+    offset = 0
+    for (histogram, range_length) in itertools.izip(histograms, ranges_lengths):
+        cpp_guard = histogram.cpp_guard()
+        # We do test cpp_guard here, so that histogram IDs are valid
+        # indexes into this array.
+        if cpp_guard:
+            print "#if defined(%s)" % cpp_guard
+        print "{ %d, %d }," % (offset, range_length)
+        if cpp_guard:
+            print "#endif"
+        offset += range_length
+    print "};"
+    print "#endif"
 
 def main(argv):
     filename = argv[0]
 
     histograms = list(histogram_tools.from_file(filename))
 
     print banner
     write_histogram_table(histograms)
     write_histogram_static_asserts(histograms)
+    write_debug_histogram_ranges(histograms)
 
 main(sys.argv[1:])
--- a/toolkit/components/telemetry/gen-histogram-enum.py
+++ b/toolkit/components/telemetry/gen-histogram-enum.py
@@ -14,19 +14,19 @@ import histogram_tools
 banner = """/* This file is auto-generated, see gen-histogram-enum.py.  */
 """
 
 def main(argv):
     filename = argv[0]
 
     print banner
     print "enum ID {"
-    for (name, definition) in histogram_tools.from_file(filename):
-        cpp_guard = definition.get('cpp_guard')
+    for histogram in histogram_tools.from_file(filename):
+        cpp_guard = histogram.cpp_guard()
         if cpp_guard:
             print "#if defined(%s)" % cpp_guard
-        print "  %s," % (name,)
+        print "  %s," % histogram.name()
         if cpp_guard:
             print "#endif"
     print "  HistogramCount"
     print "};"
 
 main(sys.argv[1:])
--- a/toolkit/components/telemetry/histogram_tools.py
+++ b/toolkit/components/telemetry/histogram_tools.py
@@ -1,15 +1,205 @@
 # 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/.
 
 from __future__ import with_statement
 
+import math
 import simplejson as json
 
+def table_dispatch(kind, table, body):
+    """Call body with table[kind] if it exists.  Raise an error otherwise."""
+    if kind in table:
+        return body(table[kind])
+    else:
+        raise BaseException, "don't know how to handle a histogram of kind %s" % kind
+
+class DefinitionException(BaseException):
+    pass
+
+def check_numeric_limits(dmin, dmax, n_buckets):
+    if type(dmin) != int:
+        raise DefinitionException, "minimum is not a number"
+    if type(dmax) != int:
+        raise DefinitionException, "maximum is not a number"
+    if type(n_buckets) != int:
+        raise DefinitionException, "number of buckets is not a number"
+
+def linear_buckets(dmin, dmax, n_buckets):
+    check_numeric_limits(dmin, dmax, n_buckets)
+    if n_buckets == 2:
+        return [0, 1, 2]
+    ret_array = [0] * n_buckets
+    dmin = float(dmin)
+    dmax = float(dmax)
+    for i in range(1, n_buckets):
+        linear_range = (dmin * (n_buckets - 1 - i) + dmax * (i - 1)) / (n_buckets - 2)
+        ret_array[i] = int(linear_range + 0.5)
+    return ret_array
+
+def exponential_buckets(dmin, dmax, n_buckets):
+    check_numeric_limits(dmin, dmax, n_buckets)
+    log_max = math.log(dmax);
+    bucket_index = 2;
+    ret_array = [0] * n_buckets
+    current = dmin
+    ret_array[1] = current
+    for bucket_index in range(2, n_buckets):
+        log_current = math.log(current)
+        log_ratio = (log_max - log_current) / (n_buckets - bucket_index)
+        log_next = log_current + log_ratio
+        next_value = int(math.floor(math.exp(log_next) + 0.5))
+        if next_value > current:
+            current = next_value
+        else:
+            current = current + 1
+        ret_array[bucket_index] = current
+    return ret_array
+
+always_allowed_keys = ['kind', 'description', 'cpp_guard']
+
+class Histogram:
+    """A class for representing a histogram definition."""
+
+    def __init__(self, name, definition):
+        """Initialize a histogram named name with the given definition.
+definition is a dict-like object that must contain at least the keys:
+
+ - 'kind': The kind of histogram.  Must be one of 'boolean', 'flag',
+   'enumerated', 'linear', or 'exponential'.
+ - 'description': A textual description of the histogram.
+
+The key 'cpp_guard' is optional; if present, it denotes a preprocessor
+symbol that should guard C/C++ definitions associated with the histogram."""
+        self.verify_attributes(name, definition)
+        self._name = name
+        self._description = definition['description']
+        self._kind = definition['kind']
+        self._cpp_guard = definition.get('cpp_guard')
+        self.compute_bucket_parameters(definition)
+        table = { 'boolean': 'BOOLEAN',
+                  'flag': 'FLAG',
+                  'enumerated': 'LINEAR',
+                  'linear': 'LINEAR',
+                  'exponential': 'EXPONENTIAL' }
+        table_dispatch(self.kind(), table,
+                       lambda k: self._set_nsITelemetry_kind(k))
+
+    def name(self):
+        """Return the name of the histogram."""
+        return self._name
+
+    def description(self):
+        """Return the description of the histogram."""
+        return self._description
+
+    def kind(self):
+        """Return the kind of the histogram.
+Will be one of 'boolean', 'flag', 'enumerated', 'linear', or 'exponential'."""
+        return self._kind
+
+    def nsITelemetry_kind(self):
+        """Return the nsITelemetry constant corresponding to the kind of
+the histogram."""
+        return self._nsITelemetry_kind
+
+    def _set_nsITelemetry_kind(self, kind):
+        self._nsITelemetry_kind = "nsITelemetry::HISTOGRAM_%s" % kind
+
+    def low(self):
+        """Return the lower bound of the histogram.  May be a string."""
+        return self._low
+
+    def high(self):
+        """Return the high bound of the histogram.  May be a string."""
+        return self._high
+
+    def n_buckets(self):
+        """Return the number of buckets in the histogram.  May be a string."""
+        return self._n_buckets
+
+    def cpp_guard(self):
+        """Return the preprocessor symbol that should guard C/C++ definitions
+associated with the histogram.  Returns None if no guarding is necessary."""
+        return self._cpp_guard
+
+    def ranges(self):
+        """Return an array of lower bounds for each bucket in the histogram."""
+        table = { 'boolean': linear_buckets,
+                  'flag': linear_buckets,
+                  'enumerated': linear_buckets,
+                  'linear': linear_buckets,
+                  'exponential': exponential_buckets }
+        return table_dispatch(self.kind(), table,
+                              lambda p: p(self.low(), self.high(), self.n_buckets()))
+
+    def compute_bucket_parameters(self, definition):
+        table = {
+            'boolean': Histogram.boolean_flag_bucket_parameters,
+            'flag': Histogram.boolean_flag_bucket_parameters,
+            'enumerated': Histogram.enumerated_bucket_parameters,
+            'linear': Histogram.linear_bucket_parameters,
+            'exponential': Histogram.exponential_bucket_parameters
+            }
+        table_dispatch(self.kind(), table,
+                       lambda p: self.set_bucket_parameters(*p(definition)))
+
+    def verify_attributes(self, name, definition):
+        global always_allowed_keys
+        general_keys = always_allowed_keys + ['low', 'high', 'n_buckets']
+
+        table = {
+            'boolean': always_allowed_keys,
+            'flag': always_allowed_keys,
+            'enumerated': always_allowed_keys + ['n_values'],
+            'linear': general_keys,
+            'exponential': general_keys
+            }
+        table_dispatch(definition['kind'], table,
+                       lambda allowed_keys: Histogram.check_keys(name, definition, allowed_keys))
+
+    @staticmethod
+    def check_keys(name, definition, allowed_keys):
+        for key in definition.iterkeys():
+            if key not in allowed_keys:
+                raise KeyError, '%s not permitted for %s' % (key, name)
+
+    def set_bucket_parameters(self, low, high, n_buckets):
+        def try_to_coerce_to_number(v):
+            try:
+                return eval(v, {})
+            except:
+                return v
+        self._low = try_to_coerce_to_number(low)
+        self._high = try_to_coerce_to_number(high)
+        self._n_buckets = try_to_coerce_to_number(n_buckets)
+
+    @staticmethod
+    def boolean_flag_bucket_parameters(definition):
+        return (0, 1, 2)
+
+    @staticmethod
+    def linear_bucket_parameters(definition):
+        return (definition.get('low', 1),
+                definition['high'],
+                definition['n_buckets'])
+
+    @staticmethod
+    def enumerated_bucket_parameters(definition):
+        n_values = definition['n_values']
+        return (1, n_values, "%s+1" % n_values)
+
+    @staticmethod
+    def exponential_bucket_parameters(definition):
+        return (definition.get('low', 1),
+                definition['high'],
+                definition['n_buckets'])
+
 def from_file(filename):
-    """Return an iterator that provides (name, definition) tuples of
-histograms defined in filename.
+    """Return an iterator that provides a sequence of Histograms for
+the histograms defined in filename.
     """
     with open(filename, 'r') as f:
         histograms = json.load(f, object_pairs_hook=json.OrderedDict)
-        return histograms.iteritems()
+        for (name, definition) in histograms.iteritems():
+            yield Histogram(name, definition)
--- a/widget/gtk2/nsWindow.cpp
+++ b/widget/gtk2/nsWindow.cpp
@@ -2106,17 +2106,16 @@ nsWindow::OnExposeEvent(cairo_t *cr)
         g_free(rects);
 #else
         cairo_rectangle_list_destroy(rects);
 #endif
         return TRUE;
     }
     // If this widget uses OMTC...
     if (GetLayerManager()->AsShadowForwarder() && GetLayerManager()->AsShadowForwarder()->HasShadowManager()) {
-        nsEventStatus status;
 #if defined(MOZ_WIDGET_GTK2)
         nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface());
 #else
         nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface(cr));
 #endif
         nsBaseWidget::AutoLayerManagerSetup
           setupLayerManager(this, ctx, mozilla::layers::BUFFER_NONE);
 
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsGUIEventIPC_h__
 #define nsGUIEventIPC_h__
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 #include "nsDOMTouchEvent.h"
 #include "nsGUIEvent.h"
 
 namespace IPC
 {
 
 template<>
 struct ParamTraits<nsEvent>
--- a/xpcom/io/nsStringStream.cpp
+++ b/xpcom/io/nsStringStream.cpp
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Based on original code from nsIStringStream.cpp
  */
 
-#include "IPC/IPCMessageUtils.h"
+#include "ipc/IPCMessageUtils.h"
 
 #include "nsStringStream.h"
 #include "nsStreamUtils.h"
 #include "nsReadableUtils.h"
 #include "nsISeekableStream.h"
 #include "nsISupportsPrimitives.h"
 #include "nsCRT.h"
 #include "prerror.h"