Merge m-c to birch.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 17 May 2013 12:45:19 -0400
changeset 143730 86e3e253c6b630ffdca34f3ff0b1f1ec20a6967c
parent 143729 27c73f18702b81968564f01b9f0b00667f17485b (current diff)
parent 143727 37b8fa6c1c92d8b5644afb43eacdd4da080377e4 (diff)
child 143731 459bf64f256952275fafbaedded8814846aed3a7
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to birch.
browser/metro/theme/images/closetab-tab.png
browser/metro/theme/images/closetab-tabselected.png
browser/metro/theme/images/tab-selection-left.png
browser/metro/theme/images/tab-selection-right.png
dom/media/nsIDOMRTCPeerConnection.idl
dom/media/tests/crashtests/837421.html
dom/webidl/RTCIceServer.webidl
--- a/accessible/public/ia2/moz.build
+++ b/accessible/public/ia2/moz.build
@@ -29,11 +29,18 @@ midl_interfaces = [
 # is ported over.
 midl_enums = [
     'AccessibleEventId',
     'AccessibleRole',
     'AccessibleStates',
     'IA2CommonTypes',
 ]
 
-EXPORTS += [x + '.h' for x in midl_enums]
-EXPORTS += [x + '.h' for x in midl_interfaces]
-EXPORTS += [x + '_i.c' for x in midl_interfaces]
+headers = ['%s.h' % x for x in midl_enums]
+interfaces_h = ['%s.h' % x for x in midl_interfaces]
+interfaces_c = ['%s_i.c' % x for x in midl_interfaces]
+
+# The underscore throws off sorting and EXPORTS expects sorted lists.
+interfaces_c.sort()
+
+EXPORTS += headers
+EXPORTS += interfaces_h
+EXPORTS += interfaces_c
--- a/accessible/src/atk/AccessibleWrap.cpp
+++ b/accessible/src/atk/AccessibleWrap.cpp
@@ -946,22 +946,16 @@ GetAccessibleWrap(AtkObject* aAtkObj)
 }
 
 nsresult
 AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
 {
   nsresult rv = Accessible::HandleAccEvent(aEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return FirePlatformEvent(aEvent);
-}
-
-nsresult
-AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
-{
     Accessible* accessible = aEvent->GetAccessible();
     NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
 
     uint32_t type = aEvent->GetEventType();
 
     AtkObject* atkObj = AccessibleWrap::GetAtkObject(accessible);
 
     // We don't create ATK objects for nsIAccessible plain text leaves,
--- a/accessible/src/atk/AccessibleWrap.h
+++ b/accessible/src/atk/AccessibleWrap.h
@@ -70,17 +70,16 @@ public:
 
   static const char * ReturnString(nsAString &aString) {
     static nsCString returnedString;
     returnedString = NS_ConvertUTF16toUTF8(aString);
     return returnedString.get();
   }
 
 protected:
-  virtual nsresult FirePlatformEvent(AccEvent* aEvent);
 
   nsresult FireAtkStateChangeEvent(AccEvent* aEvent, AtkObject *aObject);
   nsresult FireAtkTextChangedEvent(AccEvent* aEvent, AtkObject *aObject);
   nsresult FireAtkShowHideEvent(AccEvent* aEvent, AtkObject *aObject,
                                 bool aIsAdded);
 
   AtkObject *mAtkObject;
 
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -876,26 +876,16 @@ protected:
    */
   uint32_t GetActionRule();
 
   /**
    * Return group info.
    */
   AccGroupInfo* GetGroupInfo();
 
-  /**
-   * Fires platform accessible event. It's notification method only. It does
-   * change nothing on Gecko side. Don't use it until you're sure what you do
-   * (see example in XUL tree accessible), use nsEventShell::FireEvent()
-   * instead. MUST be overridden in wrap classes.
-   *
-   * @param aEvent  the accessible event to fire.
-   */
-  virtual nsresult FirePlatformEvent(AccEvent* aEvent) = 0;
-
   // Data Members
   nsRefPtr<Accessible> mParent;
   nsTArray<nsRefPtr<Accessible> > mChildren;
   int32_t mIndexInParent;
 
   static const uint8_t kChildrenFlagsBits = 2;
   static const uint8_t kStateFlagsBits = 5;
   static const uint8_t kTypeBits = 6;
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -1009,42 +1009,34 @@ HyperTextAccessible::GetTextBeforeOffset
     return NS_ERROR_INVALID_ARG;
 
   switch (aBoundaryType) {
     case BOUNDARY_CHAR:
       GetCharAt(offset, eGetBefore, aText, aStartOffset, aEndOffset);
       return NS_OK;
 
     case BOUNDARY_WORD_START: {
-      if (offset == 0) { // no word before 0 offset
-        *aStartOffset = *aEndOffset = 0;
-        return NS_OK;
+      // If the offset is a word start (except text length offset) then move
+      // backward to find a start offset (end offset is the given offset).
+      // Otherwise move backward twice to find both start and end offsets.
+      if (offset == CharacterCount()) {
+        *aEndOffset = FindWordBoundary(offset, eDirPrevious, eStartWord);
+        *aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eStartWord);
+      } else {
+        *aStartOffset = FindWordBoundary(offset, eDirPrevious, eStartWord);
+        *aEndOffset = FindWordBoundary(*aStartOffset, eDirNext, eStartWord);
+        if (*aEndOffset != offset) {
+          *aEndOffset = *aStartOffset;
+          *aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eStartWord);
+        }
       }
-
-      // If the offset is a word start then move backward to find start offset
-      // (end offset is the given offset). Otherwise move backward twice to find
-      // both start and end offsets.
-      int32_t midOffset = FindWordBoundary(offset, eDirPrevious, eStartWord);
-      *aEndOffset = FindWordBoundary(midOffset, eDirNext, eStartWord);
-      if (*aEndOffset == offset) {
-        *aStartOffset = midOffset;
-        return GetText(*aStartOffset, *aEndOffset, aText);
-      }
-
-      *aStartOffset = FindWordBoundary(midOffset, eDirPrevious, eStartWord);
-      *aEndOffset = midOffset;
       return GetText(*aStartOffset, *aEndOffset, aText);
     }
 
     case BOUNDARY_WORD_END: {
-      if (offset == 0) { // no word before 0 offset
-        *aStartOffset = *aEndOffset = 0;
-        return NS_OK;
-      }
-
       // Move word backward twice to find start and end offsets.
       *aEndOffset = FindWordBoundary(offset, eDirPrevious, eEndWord);
       *aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eEndWord);
       return GetText(*aStartOffset, *aEndOffset, aText);
     }
 
     case BOUNDARY_LINE_START:
     case BOUNDARY_LINE_END:
--- a/accessible/src/mac/AccessibleWrap.h
+++ b/accessible/src/mac/AccessibleWrap.h
@@ -68,18 +68,16 @@ public: // construction, destruction
    * Returns this accessible's all children, adhering to "flat" accessibles by 
    * not returning their children.
    */
   void GetUnignoredChildren(nsTArray<Accessible*>* aChildrenArray);
   Accessible* GetUnignoredParent() const;
 
 protected:
 
-  virtual nsresult FirePlatformEvent(AccEvent* aEvent);
-
   /**
    * Return true if the parent doesn't have children to expose to AT.
    */
   bool AncestorIsFlat();
 
   /**
    * Get the native object. Create it if needed.
    */
--- a/accessible/src/mac/AccessibleWrap.mm
+++ b/accessible/src/mac/AccessibleWrap.mm
@@ -134,26 +134,16 @@ AccessibleWrap::Shutdown ()
 nsresult
 AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   nsresult rv = Accessible::HandleAccEvent(aEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return FirePlatformEvent(aEvent);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-nsresult
-AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
   uint32_t eventType = aEvent->GetEventType();
 
   // ignore everything but focus-changed, value-changed, caret and selection
   // events for now.
   if (eventType != nsIAccessibleEvent::EVENT_FOCUS &&
       eventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
       eventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
       eventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED)
--- a/accessible/src/other/AccessibleWrap.h
+++ b/accessible/src/other/AccessibleWrap.h
@@ -16,20 +16,14 @@
 namespace mozilla {
 namespace a11y {
 
 class AccessibleWrap : public Accessible
 {
 public: // construction, destruction
   AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~AccessibleWrap();
-
-  protected:
-    virtual nsresult FirePlatformEvent(AccEvent* aEvent)
-    {
-      return NS_OK;
-    }
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/src/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/AccessibleWrap.cpp
@@ -1500,25 +1500,16 @@ AccessibleWrap::GetNativeInterface(void 
 // Accessible
 
 nsresult
 AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
 {
   nsresult rv = Accessible::HandleAccEvent(aEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return FirePlatformEvent(aEvent);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// AccessibleWrap
-
-nsresult
-AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
-{
   // Don't fire native MSAA events or mess with the system caret
   // when running in metro mode. This confuses input focus tracking
   // in metro's UIA implementation.
   if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
     return NS_OK;
   }
 
   uint32_t eventType = aEvent->GetEventType();
@@ -1578,16 +1569,19 @@ AccessibleWrap::FirePlatformEvent(AccEve
       accessible->Role() == roles::COMBOBOX_OPTION) {
       ::NotifyWinEvent(EVENT_OBJECT_FOCUS, hWnd, OBJID_CLIENT, childID);
     }
   }
 
   return NS_OK;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// AccessibleWrap
+
 //------- Helper methods ---------
 
 int32_t
 AccessibleWrap::GetChildIDFor(Accessible* aAccessible)
 {
   // A child ID of the window is required, when we use NotifyWinEvent,
   // so that the 3rd party application can call back and get the IAccessible
   // the event occurred on.
--- a/accessible/src/windows/msaa/AccessibleWrap.h
+++ b/accessible/src/windows/msaa/AccessibleWrap.h
@@ -238,17 +238,16 @@ public: // construction, destruction
    */
   Accessible* GetXPAccessibleFor(const VARIANT& aVarChild);
 
   NS_IMETHOD GetNativeInterface(void **aOutAccessible);
 
   static IDispatch *NativeAccessible(nsIAccessible *aXPAccessible);
 
 protected:
-  virtual nsresult FirePlatformEvent(AccEvent* aEvent);
 
   /**
    * Creates ITypeInfo for LIBID_Accessibility if it's needed and returns it.
    */
   static ITypeInfo* GetTI(LCID lcid);
 
   static ITypeInfo* gTypeInfo;
 
--- a/accessible/tests/mochitest/text.js
+++ b/accessible/tests/mochitest/text.js
@@ -100,58 +100,42 @@ function testCharAtOffset(aIDs, aOffset,
     testTextHelper(IDs[i], aOffset, BOUNDARY_CHAR,
                    aChar, aStartOffset, aEndOffset,
                    kOk, kOk, kOk,
                    acc.getTextAtOffset, "getTextAtOffset ");
   }
 }
 
 /**
- * Test getTextAtOffset function over different elements
+ * Test getTextAtOffset function over different elements.
+ *
+ * @param aIDs            [in] ID or array of IDs
+ * @param aBoundaryType   [in] boundary type for text to be retrieved
+ * @param aTestList       [in] array of sets:
+ *                              offset1 and offset2 defining the offset range
+ *                              the text in the range
+ *                              start offset of the text in the range
+ *                              end offset of the text in the range
+ *
+ * or
  *
  * @param aOffset         [in] the offset to get the text at
  * @param aBoundaryType   [in] Boundary type for text to be retrieved
  * @param aText           [in] expected return text for getTextAtOffset
  * @param aStartOffset    [in] expected return start offset for getTextAtOffset
  * @param aEndOffset      [in] expected return end offset for getTextAtOffset
  * @param ...             [in] list of ids or list of tuples made of:
  *                              element identifier
  *                              kTodo or kOk for returned text
  *                              kTodo or kOk for returned start offset
  *                              kTodo or kOk for returned offset result
  */
-function testTextAtOffset(aOffset, aBoundaryType, aText,
-                          aStartOffset, aEndOffset)
+function testTextAtOffset()
 {
-  // List of IDs.
-  if (arguments[5] instanceof Array) {
-    var ids = arguments[5];
-    for (var i = 0; i < ids.length; i++) {
-      var acc = getAccessible(ids[i], nsIAccessibleText);
-      testTextHelper(ids[i], aOffset, aBoundaryType,
-                     aText, aStartOffset, aEndOffset,
-                     kOk, kOk, kOk,
-                     acc.getTextAtOffset, "getTextAtOffset ");
-    }
-
-    return;
-  }
-
-  for (var i = 5; i < arguments.length; i = i + 4) {
-    var ID = arguments[i];
-    var acc = getAccessible(ID, nsIAccessibleText);
-    var toDoFlag1 = arguments[i + 1];
-    var toDoFlag2 = arguments[i + 2];
-    var toDoFlag3 = arguments[i + 3];
-
-    testTextHelper(ID, aOffset, aBoundaryType,
-                   aText, aStartOffset, aEndOffset,
-                   toDoFlag1, toDoFlag2, toDoFlag3,
-                   acc.getTextAtOffset, "getTextAtOffset ");
-  }
+  testTextSuperHelper("getTextAtOffset", arguments);
 }
 
 /**
  * Test getTextAfterOffset for BOUNDARY_CHAR over different elements.
  *
  * @param aIDs          [in] the accessible identifier or array of accessible
  *                        identifiers
  * @param aOffset       [in] the offset to get a character after it
@@ -169,57 +153,41 @@ function testCharAfterOffset(aIDs, aOffs
                    kOk, kOk, kOk,
                    acc.getTextAfterOffset, "getTextAfterOffset ");
   }
 }
 
 /**
  * Test getTextAfterOffset function over different elements
  *
+ * @param aIDs            [in] ID or array of IDs
+ * @param aBoundaryType   [in] boundary type for text to be retrieved
+ * @param aTestList       [in] array of sets:
+ *                              offset1 and offset2 defining the offset range
+ *                              the text in the range
+ *                              start offset of the text in the range
+ *                              end offset of the text in the range
+ *
+ * or
+ *
  * @param aOffset         [in] the offset to get the text after
  * @param aBoundaryType   [in] Boundary type for text to be retrieved
  * @param aText           [in] expected return text for getTextAfterOffset
  * @param aStartOffset    [in] expected return start offset for getTextAfterOffset
  * @param aEndOffset      [in] expected return end offset for getTextAfterOffset
  * @param ...             [in] list of ids or list of tuples made of:
  *                              element identifier
  *                              kTodo or kOk for returned text
  *                              kTodo or kOk for returned start offset
  *                              kTodo or kOk for returned offset result
  */
 function testTextAfterOffset(aOffset, aBoundaryType,
                              aText, aStartOffset, aEndOffset)
 {
-  // List of IDs.
-  if (arguments[5] instanceof Array) {
-    var ids = arguments[5];
-    for (var i = 0; i < ids.length; i++) {
-      var acc = getAccessible(ids[i], nsIAccessibleText);
-      testTextHelper(ids[i], aOffset, aBoundaryType,
-                     aText, aStartOffset, aEndOffset,
-                     kOk, kOk, kOk,
-                     acc.getTextAfterOffset, "getTextAfterOffset ");
-    }
-
-    return;
-  }
-
-  // List of tuples.
-  for (var i = 5; i < arguments.length; i = i + 4) {
-    var ID = arguments[i];
-    var acc = getAccessible(ID, nsIAccessibleText);
-    var toDoFlag1 = arguments[i + 1];
-    var toDoFlag2 = arguments[i + 2];
-    var toDoFlag3 = arguments[i + 3];
-
-    testTextHelper(ID, aOffset, aBoundaryType,
-                   aText, aStartOffset, aEndOffset,
-                   toDoFlag1, toDoFlag2, toDoFlag3, 
-                   acc.getTextAfterOffset, "getTextAfterOffset ");
-  }
+  testTextSuperHelper("getTextAfterOffset", arguments);
 }
 
 /**
  * Test getTextBeforeOffset for BOUNDARY_CHAR over different elements.
  *
  * @param aIDs          [in] the accessible identifier or array of accessible
  *                        identifiers
  * @param aOffset       [in] the offset to get a character before it
@@ -237,56 +205,41 @@ function testCharBeforeOffset(aIDs, aOff
                    kOk, kOk, kOk,
                    acc.getTextBeforeOffset, "getTextBeforeOffset ");
   }
 }
 
 /**
  * Test getTextBeforeOffset function over different elements
  *
+ * @param aIDs            [in] ID or array of IDs
+ * @param aBoundaryType   [in] boundary type for text to be retrieved
+ * @param aTestList       [in] array of sets:
+ *                              offset1 and offset2 defining the offset range
+ *                              the text in the range
+ *                              start offset of the text in the range
+ *                              end offset of the text in the range
+ *
+ * or
+ *
  * @param aOffset         [in] the offset to get the text before
  * @param aBoundaryType   [in] Boundary type for text to be retrieved
  * @param aText           [in] expected return text for getTextBeforeOffset
  * @param aStartOffset    [in] expected return start offset for getTextBeforeOffset
  * @param aEndOffset      [in] expected return end offset for getTextBeforeOffset
  * @param ...             [in] list of ids or list of tuples made of:
  *                              element identifier
  *                              kTodo or kOk for returned text
  *                              kTodo or kOk for returned start offset
  *                              kTodo or kOk for returned offset result
  */
 function testTextBeforeOffset(aOffset, aBoundaryType,
                               aText, aStartOffset, aEndOffset)
 {
-  // List of IDs.
-  if (arguments[5] instanceof Array) {
-    var ids = arguments[5];
-    for (var i = 0; i < ids.length; i++) {
-      var acc = getAccessible(ids[i], nsIAccessibleText);
-      testTextHelper(ids[i], aOffset, aBoundaryType,
-                     aText, aStartOffset, aEndOffset,
-                     kOk, kOk, kOk,
-                     acc.getTextBeforeOffset, "getTextBeforeOffset ");
-    }
-
-    return;
-  }
-
-  for (var i = 5; i < arguments.length; i = i + 4) {
-    var ID = arguments[i];
-    var acc = getAccessible(ID, nsIAccessibleText);
-    var toDoFlag1 = arguments[i + 1];
-    var toDoFlag2 = arguments[i + 2];
-    var toDoFlag3 = arguments[i + 3];
-
-    testTextHelper(ID, aOffset, aBoundaryType,
-                   aText, aStartOffset, aEndOffset,
-                   toDoFlag1, toDoFlag2, toDoFlag3,
-                   acc.getTextBeforeOffset, "getTextBeforeOffset ");
-  }
+  testTextSuperHelper("getTextBeforeOffset", arguments);
 }
 
 /**
  * Test word count for an element.
  *
  * @param aElement   [in] element identifier
  * @param aCount     [in] Expected word count
  * @param aToDoFlag  [in] kTodo or kOk for returned text
@@ -497,16 +450,88 @@ function testTextGetSelection(aID, aStar
      aSelectionIndex + "'");
   is(endObj.value, aEndOffset, text + ": wrong end offset for index '" +
      aSelectionIndex + "'");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Private
 
+function testTextSuperHelper(aFuncName, aArgs)
+{
+  // List of tests.
+  if (aArgs[2] instanceof Array) {
+    var ids = (aArgs[0] instanceof Array) ? aArgs[0] : [ aArgs[0] ];
+    var boundaryType = aArgs[1];
+    var list = aArgs[2];
+    for (var i = 0; i < list.length; i++) {
+      var offset1 = list[i][0], offset2 = list[i][1];
+      var text = list[i][2], startOffset = list[i][3], endOffset = list[i][4];
+      var failureList = list[i][5];
+      for (var offset = offset1; offset <= offset2; offset++) {
+        for (var idIdx = 0; idIdx < ids.length; idIdx++) {
+          var id = ids[idIdx];
+
+          var flagOk1 = kOk, flagOk2 = kOk, flagOk3 = kOk;
+          if (failureList) {
+            for (var fIdx = 0; fIdx < failureList.length; fIdx++) {
+              if (offset == failureList[fIdx][0] && id == failureList[fIdx][1]) {
+                flagOk1 = failureList[fIdx][2];
+                flagOk2 = failureList[fIdx][3];
+                flagOk3 = failureList[fIdx][4];
+                break;
+              }
+            }
+          }
+
+          var acc = getAccessible(id, nsIAccessibleText);
+          testTextHelper(id, offset, boundaryType,
+                         text, startOffset, endOffset,
+                         flagOk1, flagOk2, flagOk3,
+                         acc[aFuncName], aFuncName + " ");
+        }
+      }
+    }
+    return;
+  }
+
+  // Test at single offset. List of IDs.
+  var offset = aArgs[0];
+  var boundaryType = aArgs[1];
+  var text = aArgs[2];
+  var startOffset = aArgs[3];
+  var endOffset = aArgs[4];
+  if (aArgs[5] instanceof Array) {
+    var ids = aArgs[5];
+    for (var i = 0; i < ids.length; i++) {
+      var acc = getAccessible(ids[i], nsIAccessibleText);
+      testTextHelper(ids[i], offset, boundaryType,
+                     text, startOffset, endOffset,
+                     kOk, kOk, kOk,
+                     acc[aFuncName], aFuncName + " ");
+    }
+
+    return;
+  }
+
+  // Each ID is tested separately.
+  for (var i = 5; i < aArgs.length; i = i + 4) {
+    var ID = aArgs[i];
+    var acc = getAccessible(ID, nsIAccessibleText);
+    var toDoFlag1 = aArgs[i + 1];
+    var toDoFlag2 = aArgs[i + 2];
+    var toDoFlag3 = aArgs[i + 3];
+
+    testTextHelper(ID, offset, boundaryType,
+                   text, startOffset, endOffset,
+                   toDoFlag1, toDoFlag2, toDoFlag3,
+                   acc[aFuncName], aFuncName + " ");
+  }
+}
+
 function testTextHelper(aID, aOffset, aBoundaryType,
                         aText, aStartOffset, aEndOffset,
                         aToDoFlag1, aToDoFlag2, aToDoFlag3,
                         aTextFunc, aTextFuncName)
 {
   var exceptionFlag = aToDoFlag1 == undefined ||
                       aToDoFlag2 == undefined ||
                       aToDoFlag3 == undefined;
--- a/accessible/tests/mochitest/text/Makefile.in
+++ b/accessible/tests/mochitest/text/Makefile.in
@@ -17,12 +17,13 @@ MOCHITEST_A11Y_FILES = \
 		test_doc.html \
 		test_hypertext.html \
 		test_label.xul \
 		test_multiline.html \
 		test_passwords.html \
 		test_selection.html \
 		test_singleline.html \
 		test_whitespaces.html \
+		test_wordboundary.html \
 		test_words.html \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/accessible/tests/mochitest/text/test_multiline.html
+++ b/accessible/tests/mochitest/text/test_multiline.html
@@ -168,17 +168,17 @@
 
       // BOUNDARY_WORD_START
       testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0, IDs);
       testTextBeforeOffset(7, BOUNDARY_WORD_START, "", 0, 0, IDs);
       testTextBeforeOffset(8, BOUNDARY_WORD_START, "", 0, 0, IDs);
       testTextBeforeOffset(9, BOUNDARY_WORD_START, "oneword\n\n", 0, 9, IDs);
       testTextBeforeOffset(13, BOUNDARY_WORD_START, "two ", 9, 13, IDs);
       testTextBeforeOffset(18, BOUNDARY_WORD_START, "two ", 9, 13, IDs);
-      testTextBeforeOffset(19, BOUNDARY_WORD_START, "words\n", 13, 19, IDs);
+      testTextBeforeOffset(19, BOUNDARY_WORD_START, "two ", 9, 13, IDs);
 
       // BOUNDARY_WORD_END
       testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0, IDs);
       testTextBeforeOffset(7, BOUNDARY_WORD_END, "", 0, 0, IDs);
       testTextBeforeOffset(8, BOUNDARY_WORD_END, "oneword", 0, 7,
                            "div", kOk, kOk, kOk,
                            "divbr", kTodo, kOk, kTodo,
                            "editable", kOk, kOk, kOk,
--- a/accessible/tests/mochitest/text/test_singleline.html
+++ b/accessible/tests/mochitest/text/test_singleline.html
@@ -142,17 +142,21 @@
       testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0, IDs);
       testTextBeforeOffset(5, BOUNDARY_WORD_START, "", 0, 0, IDs);
       testTextBeforeOffset(6, BOUNDARY_WORD_START, "hello ", 0, 6, IDs);
       testTextBeforeOffset(7, BOUNDARY_WORD_START, "hello ", 0, 6, IDs);
       testTextBeforeOffset(8, BOUNDARY_WORD_START, "hello ", 0, 6, IDs);
       testTextBeforeOffset(9, BOUNDARY_WORD_START, "my ", 6, 9, IDs);
       testTextBeforeOffset(10, BOUNDARY_WORD_START, "my ", 6, 9, IDs);
       testTextBeforeOffset(14, BOUNDARY_WORD_START, "my ", 6, 9, IDs);
-      testTextBeforeOffset(15, BOUNDARY_WORD_START, "friend", 9, 15, IDs);
+      testTextBeforeOffset(15, BOUNDARY_WORD_START, "my ", 6, 9,
+                           "input", kOk, kOk, kOk,
+                           "div", kOk, kOk, kOk,
+                           "editable", kOk, kOk, kOk,
+                           "textarea", kTodo, kTodo, kTodo);
 
       // BOUNDARY_WORD_END
       testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0, IDs);
       testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0, IDs);
       testTextBeforeOffset(5, BOUNDARY_WORD_END, "", 0, 0, IDs);
       testTextBeforeOffset(6, BOUNDARY_WORD_END, "hello", 0, 5, IDs);
       testTextBeforeOffset(7, BOUNDARY_WORD_END, "hello", 0, 5, IDs);
       testTextBeforeOffset(8, BOUNDARY_WORD_END, "hello", 0, 5, IDs);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/text/test_wordboundary.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Word boundary text tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../text.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      // "hello"
+      var ids = [ "i1", "d1", "e1" ];
+      testTextBeforeOffset(ids, BOUNDARY_WORD_START,
+                           [ [ 0, 5, "", 0, 0 ] ]);
+      testTextBeforeOffset(ids, BOUNDARY_WORD_END,
+                           [ [ 0, 5, "", 0, 0 ] ]);
+
+      testTextAtOffset(ids, BOUNDARY_WORD_START,
+                       [ [ 0, 5, "hello", 0, 5 ] ]);
+      testTextAtOffset(ids, BOUNDARY_WORD_END,
+                       [ [ 0, 5, "hello", 0, 5 ] ]);
+
+      testTextAfterOffset(ids, BOUNDARY_WORD_START,
+                          [ [ 0, 5, "", 5, 5 ] ]);
+      testTextAfterOffset(ids, BOUNDARY_WORD_END,
+                          [ [ 0, 5, "", 5, 5 ] ]);
+
+      // "hello "
+      var ids = [ "i2", "d2", "e2" ];
+      testTextBeforeOffset(ids, BOUNDARY_WORD_START,
+                           [ [ 0, 6, "", 0, 0 ] ]);
+      testTextBeforeOffset(ids, BOUNDARY_WORD_END,
+                           [ [ 0, 5, "", 0, 0 ],
+                             [ 6, 6, "hello", 0, 5,
+                               [ [6, "e2", kTodo, kOk, kTodo ] ]
+                             ]
+                           ]);
+
+      testTextAtOffset(ids, BOUNDARY_WORD_START,
+                       [ [ 0, 6, "hello ", 0, 6 ] ]);
+      testTextAtOffset(ids, BOUNDARY_WORD_END,
+                       [ [ 0, 4, "hello", 0, 5 ],
+                         [ 5, 6, " ", 5, 6,
+                           [ [ 5, "e2", kTodo, kTodo, kOk ],
+                             [ 6, "e2", kTodo, kTodo, kOk ] ]
+                         ]
+                       ]);
+
+      testTextAfterOffset(ids, BOUNDARY_WORD_START,
+                          [ [ 0, 6, "", 6, 6 ] ]);
+      testTextAfterOffset(ids, BOUNDARY_WORD_END,
+                          [ [ 0, 5, " ", 5, 6,
+                              [ [ 5, "e2", kTodo, kTodo, kOk ] ]
+                            ],
+                            [ 6, 6, "", 6, 6 ]
+                          ]);
+
+      // "hello all"
+      ids = [ "i6", "d6", "e6" ];
+      testTextAtOffset(ids, BOUNDARY_WORD_START,
+                       [ [ 0, 5, "hello ", 0, 6 ],
+                         [ 6, 9, "all", 6, 9 ] ]);
+      testTextAtOffset(ids, BOUNDARY_WORD_END,
+                       [ [ 0, 4, "hello", 0, 5 ],
+                         [ 5, 9, " all", 5, 9 ] ]);
+
+      // "hello my friend"
+      ids = [ "i7", "d7", "e7" ];
+      testTextAtOffset(ids, BOUNDARY_WORD_START,
+                       [ [ 0, 5, "hello ", 0, 6 ],
+                         [ 6, 8, "my ", 6, 9 ],
+                         [ 9, 15, "friend", 9, 15] ]);
+      testTextAtOffset(ids, BOUNDARY_WORD_END,
+                       [ [ 0, 4, "hello", 0, 5 ],
+                         [ 5, 7, " my", 5, 8 ],
+                         [ 8, 15, " friend", 8, 15] ]);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <input id="i1" value="hello"/>
+  <div id="d1">hello</div>
+  <div id="e1" contenteditable="true">hello</div>
+
+  <input id="i2" value="hello "/>
+  <pre><div id="d2">hello </div></pre>
+  <div id="e2" contenteditable="true">hello </div>
+
+  <input id="i6" value="hello all"/>
+  <div id="d6">hello all</div>
+  <div id="e6" contenteditable="true">hello all</div>
+
+  <input id="i7" value="hello my friend"/>
+  <div id="d7">hello my friend</div>
+  <div id="e7" contenteditable="true">hello my friend</div>
+
+</body>
+</html>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1225,16 +1225,19 @@ pref("social.directories", "https://addo
 pref("social.remote-install.enabled", true);
 
 pref("social.sidebar.open", true);
 pref("social.sidebar.unload_timeout_ms", 10000);
 pref("social.toast-notifications.enabled", true);
 
 pref("dom.identity.enabled", false);
 
+// Turn on the CSP 1.0 parser for Content Security Policy headers
+pref("security.csp.speccompliant", true);
+
 // Block insecure active content on https pages
 pref("security.mixed_content.block_active_content", true);
 
 
 // Override the Gecko-default value of false for Firefox.
 pref("plain_text.wrap_long_lines", true);
 
 #ifndef RELEASE_BUILD
--- a/browser/base/content/test/browser_gestureSupport.js
+++ b/browser/base/content/test/browser_gestureSupport.js
@@ -157,18 +157,20 @@ function test_TestEventListeners()
   e("MozRotateGesture", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0);
   
   // Tap and presstap gesture events
   test_clicks("MozTapGesture", 1);
   test_clicks("MozTapGesture", 2);
   test_clicks("MozTapGesture", 3);
   test_clicks("MozPressTapGesture", 1);
 
-  // simple delivery test for edgeui gesture
-  e("MozEdgeUIGesture", 0, 0, 0);
+  // simple delivery test for edgeui gestures
+  e("MozEdgeUIStarted", 0, 0, 0);
+  e("MozEdgeUICanceled", 0, 0, 0);
+  e("MozEdgeUICompleted", 0, 0, 0);
 
   // event.shiftKey
   let modifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK;
   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
 
   // event.metaKey
   modifier = Components.interfaces.nsIDOMEvent.META_MASK;
   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -142,17 +142,17 @@ var gPrivacyPane = {
   },
 
   /**
    * Obtain the tracking preference value and reflect it in the UI.
    */
   getTrackingPrefs: function PPP_getTrackingPrefs()
   {
     // XXX avoid using bindings that might not be attached, see bug 859982
-    let dntValue = Services.prefs.getBoolPref("privacy.donottrackheader.value"),
+    let dntValue = Services.prefs.getIntPref("privacy.donottrackheader.value"),
         dntEnabled = Services.prefs.getBoolPref("privacy.donottrackheader.enabled");
 
     // if DNT is enbaled, select the value from the selected radio
     // button, otherwise choose the "no preference" radio button
     if (dntEnabled)
       return dntValue;
 
     return document.getElementById("dntnopref").value;
--- a/browser/devtools/netmonitor/test/browser_net_simple-request-data.js
+++ b/browser/devtools/netmonitor/test/browser_net_simple-request-data.js
@@ -81,18 +81,20 @@ function test() {
       verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS);
     });
 
     aMonitor.panelWin.once("NetMonitor:NetworkEventUpdated:RequestHeaders", () => {
       let requestItem = RequestsMenu.getItemAtIndex(0);
 
       ok(requestItem.attachment.requestHeaders,
         "There should be a requestHeaders attachment available.");
-      is(requestItem.attachment.requestHeaders.headers.length, 7,
+      ok(requestItem.attachment.requestHeaders.headers.length >= 6,
         "The requestHeaders attachment has an incorrect |headers| property.");
+      // Can't test for an exact total number of headers, because it seems to
+      // vary across pgo/non-pgo builds.
       isnot(requestItem.attachment.requestHeaders.headersSize, 0,
         "The requestHeaders attachment has an incorrect |headersSize| property.");
       // Can't test for the exact request headers size because the value may
       // vary across platforms ("User-Agent" header differs).
 
       verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS);
     });
 
--- a/browser/devtools/netmonitor/test/browser_net_simple-request-details.js
+++ b/browser/devtools/netmonitor/test/browser_net_simple-request-details.js
@@ -58,18 +58,21 @@ function test() {
         "GET", "The method summary value is incorrect.");
       is(tabpanel.querySelector("#headers-summary-status-circle").getAttribute("code"),
         "200", "The status summary code is incorrect.");
       is(tabpanel.querySelector("#headers-summary-status-value").getAttribute("value"),
         "200 Och Aye", "The status summary value is incorrect.");
 
       is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
         "There should be 2 header scopes displayed in this tabpanel.");
-      is(tabpanel.querySelectorAll(".variable-or-property").length, 13,
-        "There should be 13 header values displayed in this tabpanel.");
+      ok(tabpanel.querySelectorAll(".variable-or-property").length >= 12,
+        "There should be at least 12 header values displayed in this tabpanel.");
+      // Can't test for an exact total number of headers, because it seems to
+      // vary across pgo/non-pgo builds.
+
       is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
         "The empty notice should not be displayed in this tabpanel.");
 
       let responseScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
       let requestScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
 
       is(responseScope.querySelector(".name").getAttribute("value"),
         L10N.getStr("responseHeaders") + " (" +
@@ -103,20 +106,28 @@ function test() {
       is(requestScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
         "Host", "The first request header name was incorrect.");
       is(requestScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
         "\"example.com\"", "The first request header value was incorrect.");
       is(requestScope.querySelectorAll(".variables-view-variable .name")[5].getAttribute("value"),
         "Connection", "The penultimate request header name was incorrect.");
       is(requestScope.querySelectorAll(".variables-view-variable .value")[5].getAttribute("value"),
         "\"keep-alive\"", "The penultimate request header value was incorrect.");
-      is(requestScope.querySelectorAll(".variables-view-variable .name")[6].getAttribute("value"),
-        "Cache-Control", "The last request header name was incorrect.");
-      is(requestScope.querySelectorAll(".variables-view-variable .value")[6].getAttribute("value"),
-        "\"max-age=0\"", "The last request header value was incorrect.");
+
+      let lastReqHeaderName = requestScope.querySelectorAll(".variables-view-variable .name")[6];
+      let lastReqHeaderValue = requestScope.querySelectorAll(".variables-view-variable .value")[6];
+      if (lastReqHeaderName && lastReqHeaderValue) {
+        is(lastReqHeaderName.getAttribute("value"),
+          "Cache-Control", "The last request header name was incorrect.");
+        is(lastReqHeaderValue.getAttribute("value"),
+          "\"max-age=0\"", "The last request header value was incorrect.");
+      } else {
+        info("The number of request headers was 6 instead of 7. Technically, " +
+             "not a failure in this particular test, but needs investigation.");
+      }
     }
 
     function testCookiesTab() {
       EventUtils.sendMouseEvent({ type: "mousedown" },
         document.querySelectorAll("#details-pane tab")[1]);
 
       let tab = document.querySelectorAll("#details-pane tab")[1];
       let tabpanel = document.querySelectorAll("#details-pane tabpanel")[1];
--- a/browser/metro/base/content/BrowserTouchHandler.js
+++ b/browser/metro/base/content/BrowserTouchHandler.js
@@ -41,17 +41,17 @@ const BrowserTouchHandler = {
     if (ContextMenuUI.showContextMenu(contextInfo)) {
       let event = document.createEvent("Events");
       event.initEvent("CancelTouchSequence", true, false);
       document.dispatchEvent(event);
     } else {
       // Send the MozEdgeUIGesture to input.js to
       // toggle the context ui.
       let event = document.createEvent("Events");
-      event.initEvent("MozEdgeUIGesture", true, false);
+      event.initEvent("MozEdgeUICompleted", true, false);
       window.dispatchEvent(event);
     }
   },
 
   /*
    * Called when Content wants to initiate selection management
    * due to a tap in a form input.
    */
--- a/browser/metro/base/content/ContentAreaObserver.js
+++ b/browser/metro/base/content/ContentAreaObserver.js
@@ -285,18 +285,17 @@ var ContentAreaObserver = {
                        "content-height", "content-width",
                        "viewable-height", "viewable-width"]) {
       let index = stylesheet.insertRule("." + style + " {}", stylesheet.cssRules.length);
       this.styles[style] = stylesheet.cssRules[index].style;
     }
   },
 
   _getContentHeightForWindow: function (windowHeight) {
-    let contextUIHeight = BrowserUI.isTabsOnly ? Elements.toolbar.getBoundingClientRect().bottom : 0;
-    return windowHeight - contextUIHeight;
+    return windowHeight;
   },
 
   _getViewableHeightForContent: function (contentHeight) {
     let keyboardHeight = MetroUtils.keyboardHeight;
     return contentHeight - keyboardHeight;
   },
 
   _debugDumpDims: function _debugDumpDims() {
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -91,17 +91,16 @@ var BrowserUI = {
     messageManager.addMessageListener("Content:StateChange", this);
 
     // listening escape to dismiss dialog on VK_ESCAPE
     window.addEventListener("keypress", this, true);
 
     window.addEventListener("MozPrecisePointer", this, true);
     window.addEventListener("MozImprecisePointer", this, true);
 
-    Services.prefs.addObserver("browser.tabs.tabsOnly", this, false);
     Services.prefs.addObserver("browser.cache.disk_cache_ssl", this, false);
     Services.obs.addObserver(this, "metro_viewstate_changed", false);
 
     // Init core UI modules
     ContextUI.init();
     StartUI.init();
     PanelUI.init();
     FlyoutPanelsUI.init();
@@ -138,17 +137,16 @@ var BrowserUI = {
 
       // Login Manager and Form History initialization
       Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
       Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
 
       messageManager.addMessageListener("Browser:MozApplicationManifest", OfflineApps);
 
       try {
-        BrowserUI._updateTabsOnly();
         Downloads.init();
         DialogUI.init();
         FormHelperUI.init();
         FindHelperUI.init();
         PdfJs.init();
 #ifdef MOZ_SERVICES_SYNC
         Sync.init();
 #endif
@@ -397,33 +395,28 @@ var BrowserUI = {
 
   closeTab: function closeTab(aTab) {
     // If no tab is passed in, assume the current tab
     let tab = aTab || Browser.selectedTab;
     Browser.closeTab(tab);
   },
 
   animateClosingTab: function animateClosingTab(tabToClose) {
-    if (this.isTabsOnly) {
-      Browser.closeTab(tabToClose, { forceClose: true } );
-    } else {
-      // Trigger closing animation
-      tabToClose.chromeTab.setAttribute("closing", "true");
+    tabToClose.chromeTab.setAttribute("closing", "true");
 
-      let wasCollapsed = !ContextUI.isExpanded;
-      if (wasCollapsed) {
-        ContextUI.displayTabs();
-      }
+    let wasCollapsed = !ContextUI.isExpanded;
+    if (wasCollapsed) {
+      ContextUI.displayTabs();
+    }
 
-      this.setOnTabAnimationEnd(function() {
-	Browser.closeTab(tabToClose, { forceClose: true } );
+    this.setOnTabAnimationEnd(function() {
+	    Browser.closeTab(tabToClose, { forceClose: true } );
         if (wasCollapsed)
           ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
-      });
-    }
+    });
   },
 
   /**
     * Re-open a closed tab.
     * @param aIndex
     *        The index of the tab (via nsSessionStore.getClosedTabData)
     * @returns a reference to the reopened tab.
     */
@@ -520,42 +513,20 @@ var BrowserUI = {
   },
 
   // If the user types in the address bar, cancel pending
   // navbar autohide if set.
   navEditKeyPress: function navEditKeyPress() {
     ContextUI.cancelDismiss();
   },
 
-
-  /*********************************
-   * Conventional tabs
-   */
-
-  // Tabsonly displays the url bar with conventional tabs. Also
-  // the tray does not auto hide.
-  get isTabsOnly() {
-    return Services.prefs.getBoolPref("browser.tabs.tabsOnly");
-  },
-
-  _updateTabsOnly: function _updateTabsOnly() {
-    if (this.isTabsOnly) {
-      Elements.windowState.setAttribute("tabsonly", "true");
-    } else {
-      Elements.windowState.removeAttribute("tabsonly");
-    }
-  },
-
   observe: function BrowserUI_observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "nsPref:changed":
         switch (aData) {
-          case "browser.tabs.tabsOnly":
-            this._updateTabsOnly();
-            break;
           case "browser.cache.disk_cache_ssl":
             this._sslDiskCacheEnabled = Services.prefs.getBoolPref(aData);
             break;
         }
         break;
       case "metro_viewstate_changed":
         this._adjustDOMforViewState();
         let autocomplete = document.getElementById("start-autocomplete");
@@ -1114,17 +1085,19 @@ var ContextUI = {
   /*******************************************
    * init
    */
 
   init: function init() {
     Elements.browsers.addEventListener("mousedown", this, true);
     Elements.browsers.addEventListener("touchstart", this, true);
     Elements.browsers.addEventListener("AlertActive", this, true);
-    window.addEventListener("MozEdgeUIGesture", this, true);
+    window.addEventListener("MozEdgeUIStarted", this, true);
+    window.addEventListener("MozEdgeUICanceled", this, true);
+    window.addEventListener("MozEdgeUICompleted", this, true);
     window.addEventListener("keypress", this, true);
     window.addEventListener("KeyboardChanged", this, false);
 
     Elements.tray.addEventListener("transitionend", this, true);
 
     Appbar.init();
   },
 
@@ -1279,18 +1252,17 @@ var ContextUI = {
     }
 
     if (!setSilently)
       this._fire(aFlag ? "MozContextUIShow" : "MozContextUIDismiss");
   },
 
   // tab tray state
   _setIsExpanded: function _setIsExpanded(aFlag, setSilently) {
-    // if the tray can't be expanded because we're in
-    // tabsonly mode, don't expand it.
+    // if the tray can't be expanded, don't expand it.
     if (!this.isExpandable || this.isExpanded == aFlag)
       return;
 
     if (aFlag)
       Elements.tray.setAttribute("expanded", "true");
     else
       Elements.tray.removeAttribute("expanded");
 
@@ -1308,29 +1280,57 @@ var ContextUI = {
       this._hidingId = 0;
     }
   },
 
   /*******************************************
    * Events
    */
 
-  _onEdgeUIEvent: function _onEdgeUIEvent(aEvent) {
+  _onEdgeUIStarted: function(aEvent) {
+    this._hasEdgeSwipeStarted = true;
+    this._clearDelayedTimeout();
+
+    if (StartUI.hide()) {
+      this.dismiss();
+      return;
+    }
+    this.toggle();
+  },
+
+  _onEdgeUICanceled: function(aEvent) {
+    this._hasEdgeSwipeStarted = false;
+    StartUI.hide();
+    this.dismiss();
+  },
+
+  _onEdgeUICompleted: function(aEvent) {
+    if (this._hasEdgeSwipeStarted) {
+      this._hasEdgeSwipeStarted = false;
+      return;
+    }
+
     this._clearDelayedTimeout();
     if (StartUI.hide()) {
       this.dismiss();
       return;
     }
     this.toggle();
   },
 
   handleEvent: function handleEvent(aEvent) {
     switch (aEvent.type) {
-      case "MozEdgeUIGesture":
-        this._onEdgeUIEvent(aEvent);
+      case "MozEdgeUIStarted":
+        this._onEdgeUIStarted(aEvent);
+        break;
+      case "MozEdgeUICanceled":
+        this._onEdgeUICanceled(aEvent);
+        break;
+      case "MozEdgeUICompleted":
+        this._onEdgeUICompleted(aEvent);
         break;
       case "mousedown":
         if (aEvent.button == 0 && this.isVisible)
           this.dismiss();
         break;
       case "touchstart":
       // ContextUI can hide the notification bar. Workaround until bug 845348 is fixed.
       case "AlertActive":
@@ -1466,17 +1466,17 @@ var StartUI = {
       case "autocompletestart":
         this.filter();
         break;
       case "autocompleteend":
         this.unfilter();
         break;
       case "contextmenu":
         let event = document.createEvent("Events");
-        event.initEvent("MozEdgeUIGesture", true, false);
+        event.initEvent("MozEdgeUICompleted", true, false);
         window.dispatchEvent(event);
         break;
     }
   }
 };
 
 var SyncPanelUI = {
   init: function() {
--- a/browser/metro/base/content/browser.js
+++ b/browser/metro/base/content/browser.js
@@ -93,22 +93,22 @@ var Browser = {
         aScrollX.value = scroll.x;
         aScrollY.value = scroll.y;
       }
     };
 
     ContentAreaObserver.init();
 
     function fullscreenHandler() {
-      if (!window.fullScreen)
-        Elements.toolbar.setAttribute("fullscreen", "true");
+      if (Browser.selectedBrowser.contentWindow.document.mozFullScreenElement)
+        Elements.stack.setAttribute("fullscreen", "true");
       else
-        Elements.toolbar.removeAttribute("fullscreen");
+        Elements.stack.removeAttribute("fullscreen");
     }
-    window.addEventListener("fullscreen", fullscreenHandler, false);
+    window.addEventListener("mozfullscreenchange", fullscreenHandler, true);
 
     BrowserUI.init();
 
     window.controllers.appendController(this);
     window.controllers.appendController(BrowserUI);
 
     let os = Services.obs;
     os.addObserver(SessionHistoryObserver, "browser:purge-session-history", false);
--- a/browser/metro/base/content/browser.xul
+++ b/browser/metro/base/content/browser.xul
@@ -362,21 +362,26 @@
         <toolbarbutton id="delete-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('delete')"/>
         <toolbarbutton id="restore-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('restore')"/>
         <toolbarbutton id="pin-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('pin')"/>
         <toolbarbutton id="unpin-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('unpin')"/>
         <toolbarbutton id="clear-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('clear')"/>
       </toolbar>
     </appbar>
 
-  <!-- Selection overlay - this should be below any content that can have selectable text -->
-  <!-- onclick addresses dom bug 835175, str in bug 832957 -->
-  <box onclick="false" class="selection-overlay-hidden" id="selection-overlay"/>
+    <!-- Selection overlay - this should be below any content that can have selectable text -->
+    <!-- onclick addresses dom bug 835175, str in bug 832957 -->
+    <box onclick="false" class="selection-overlay-hidden" id="selection-overlay"/>
 
-  <flyoutpanel id="about-flyoutpanel" headertext="&aboutHeader.title;">
+    <html:div id="overlay-back" class="overlay-button"
+              observes="cmd_back" onclick="CommandUpdater.doCommand('cmd_back');"></html:div>
+    <html:div id="overlay-plus" class="overlay-button"
+              observes="cmd_back" onclick="CommandUpdater.doCommand('cmd_newTab');"></html:div>
+
+    <flyoutpanel id="about-flyoutpanel" headertext="&aboutHeader.title;">
         <label id="about-product-label" value="&aboutHeader.product.label;"/>
         <label value="&aboutHeader.company.label;"/>
 #expand <label id="about-version-label">__MOZ_APP_VERSION__</label>
         <label id="about-policy-label"
                onclick="if (event.button == 0) { Browser.onAboutPolicyClick(); }"
                class="text-link" value="&aboutHeader.policy.label;"/>
     </flyoutpanel>
 
@@ -420,17 +425,16 @@
           <menulist id="prefs-homepage-options">
             <menupopup id="prefs-homepage-popup" position="after_end">
               <menuitem id="prefs-homepage-default" label="&optionsHeader.homepage.startPage.button;" value="false"/>
               <menuitem id="prefs-homepage-session" label="&optionsHeader.homepage.sessionRestore.button;" value="true"/>
             </menupopup>
           </menulist>
         </setting>
       </settings>
-      <setting pref="browser.tabs.tabsOnly" title="&optionsHeader.tabs.title;" type="bool"/>
       <settings id="prefs-charencoding" label="&optionsHeader.char.title;">
         <setting pref="browser.menu.showCharacterEncoding" title="&optionsHeader.char.options.label;" type="bool"/>
       </settings>
       <settings id="prefs-privdata" label="&clearPrivateData.title;">
         <description>&clearPrivateData.label;</description>
 
         <checkbox id="prefs-privdata-history" itemName="history" label="&clearPrivateData.history;" checked="true" />
 
@@ -676,14 +680,9 @@
       <image id="alerts-image"/>
       <vbox flex="1">
         <label id="alerts-title" value=""/>
         <description id="alerts-text" flex="1"/>
       </vbox>
     </hbox>
   </stack>
 
-  <html:div id="overlay-back" class="overlay-button"
-            observes="cmd_back" onclick="CommandUpdater.doCommand('cmd_back');"></html:div>
-  <html:div id="overlay-plus" class="overlay-button"
-            observes="cmd_back" onclick="CommandUpdater.doCommand('cmd_newTab');"></html:div>
-
 </window>
--- a/browser/metro/base/content/input.js
+++ b/browser/metro/base/content/input.js
@@ -180,17 +180,17 @@ var TouchModule = {
     this._targetScrollInterface = null;
   },
 
   _onContextMenu: function _onContextMenu(aEvent) {
     // Special case when running on the desktop, fire off
     // a edge ui event when we get the contextmenu event.
     if (this._treatMouseAsTouch) {
       let event = document.createEvent("Events");
-      event.initEvent("MozEdgeUIGesture", true, false);
+      event.initEvent("MozEdgeUICompleted", true, false);
       window.dispatchEvent(event);
       return;
     }
 
     // bug 598965 - chrome UI should stop to be pannable once the
     // context menu has appeared.
     if (ContextMenuUI.popupState) {
       this.cancelPending();
--- a/browser/metro/base/tests/mochitest/browser_context_ui.js
+++ b/browser/metro/base/tests/mochitest/browser_context_ui.js
@@ -83,11 +83,11 @@ gTests.push({
     is(edit.selectionEnd, edit.value.length, "Location field is selected");
 
     Browser.closeTab(tab, { forceClose: true });
   }
 });
 
 function doEdgeUIGesture() {
   let event = document.createEvent("Events");
-  event.initEvent("MozEdgeUIGesture", true, false);
+  event.initEvent("MozEdgeUICompleted", true, false);
   window.dispatchEvent(event);
 }
--- a/browser/metro/base/tests/mochitest/head.js
+++ b/browser/metro/base/tests/mochitest/head.js
@@ -183,17 +183,17 @@ function showNavBar()
     return promise;
   }
 }
 
 function fireAppBarDisplayEvent()
 {
   let promise = waitForEvent(Elements.tray, "transitionend");
   let event = document.createEvent("Events");
-  event.initEvent("MozEdgeUIGesture", true, false);
+  event.initEvent("MozEdgeUICompleted", true, false);
   gWindow.dispatchEvent(event);
   purgeEventQueue();
   return promise;
 }
 
 /*=============================================================================
   Asynchronous test helpers
 =============================================================================*/
@@ -730,9 +730,9 @@ function stubMethod(aObj, aMethod) {
     func.callCount++;
   }
   func.callCount = 0;
   func.restore = function() {
     return (aObj[aMethod] = origFunc);
   };
   aObj[aMethod] = func;
   return func;
-}
\ No newline at end of file
+}
--- a/browser/metro/locales/en-US/chrome/preferences.dtd
+++ b/browser/metro/locales/en-US/chrome/preferences.dtd
@@ -9,17 +9,16 @@
 <!ENTITY aboutHeader.policy.label                                "Read the &brandShortName; privacy policy online">
 
 <!-- ## Options Flyout Panel ## -->
 <!ENTITY optionsHeader.title                                     "Options">
 <!ENTITY optionsHeader.startup.title                             "Startup">
 <!ENTITY optionsHeader.homepage.title                            "When &brandShortName; starts, show">
 <!ENTITY optionsHeader.homepage.startPage.button                 "start page">
 <!ENTITY optionsHeader.homepage.sessionRestore.button            "tabs from last time">
-<!ENTITY optionsHeader.tabs.title                                "Always Show Tabs">
 <!ENTITY optionsHeader.char.title                                "Character Encoding">
 <!ENTITY optionsHeader.char.autodetect.label                     "Auto-detect">
 <!ENTITY optionsHeader.char.options.label                        "Show encoding options on the App Bar">
 
 <!ENTITY clearPrivateData.title                                  "Clear Private Data">
 <!ENTITY clearPrivateData.label                                  "Clear your browsing history, passwords, cookies, and form data on this device">
 <!ENTITY clearPrivateData.button                                 "Clear">
 <!ENTITY clearPrivateData.done                                   "Done!">
--- a/browser/metro/profile/metro.js
+++ b/browser/metro/profile/metro.js
@@ -46,22 +46,20 @@ pref("mousewheel.enable_pixel_scrolling"
 //
 pref("toolkit.browser.cacheRatioWidth", 2000);
 pref("toolkit.browser.cacheRatioHeight", 3000);
 
 // How long before a content view (a handle to a remote scrollable object)
 // expires.
 pref("toolkit.browser.contentViewExpire", 3000);
 
+
 pref("toolkit.defaultChromeURI", "chrome://browser/content/browser.xul");
 pref("browser.chromeURL", "chrome://browser/content/");
 
-// When true, always show the tab strip and use desktop-style tabs (no thumbnails)
-pref("browser.tabs.tabsOnly", false);
-
 pref("browser.tabs.remote", false);
 
 // Telemetry
 pref("toolkit.telemetry.enabled", true);
 pref("toolkit.telemetry.prompted", 2);
 
 pref("toolkit.screen.lock", false);
 
--- a/browser/metro/theme/browser.css
+++ b/browser/metro/theme/browser.css
@@ -43,19 +43,17 @@
 /* Sliding Toolbar/Tab Tray ------------------------------------------------- */
 
 #tray {
   transition: transform @metro_animation_duration@ @metro_animation_easing@;
   transform: translateY(-@tabs_height@);
   width: 100%;
 }
 
-/* in non-tabsonly mode the navigation bar and tab tray float over content. In
-   tabsonly mode they are always visible and offset content. */
-#tray:not([tabsonly]) {
+#tray {
   position: fixed;
 }
 
 #tray[visible][expanded]:not([viewstate="snapped"]) {
   transform: none;
 }
 
 /* Tabs --------------------------------------------------------------------- */
@@ -139,26 +137,26 @@
   }
 
   100% {
     opacity: 0;
     transform: scale(0, 0);
   }
 }
 
-#tray:not([tabsonly]) .documenttab-container {
+.documenttab-container {
   animation: open-documenttab 0.4s ease-out;
 }
 
-#tray:not([tabsonly]) documenttab[closing] > .documenttab-container {
+documenttab[closing] > .documenttab-container {
   animation: close-documenttab 0.4s ease-out;
   animation-fill-mode: forwards;
 }
 
-#tray:not([tabsonly]) .documenttab-favicon {
+.documenttab-favicon {
   visibility: collapse;
 }
 
 .documenttab-thumbnail {
   margin: @metro_spacing_normal@ @metro_spacing_snormal@;
   background: white none center top no-repeat;
   background-size: cover;
   width: @thumbnail_width@;
@@ -198,97 +196,16 @@ documenttab[selected] .documenttab-selec
   border-color: transparent !important;
   list-style-image: url("chrome://browser/skin/images/closetab-default.png");
 }
 
 .documenttab-close > .button-box > .button-text {
   display: none;
 }
 
-#tray[tabsonly] {
-  transform: none !important;
-}
-
-#tray[tabsonly] #tabs {
-  -moz-padding-start: @metro_spacing_small@;
-}
-
-#tray[tabsonly] #tabs-controls {
-  -moz-box-align: center;
-  -moz-box-orient: horizontal;
-  -moz-box-pack: end;
-  margin: 0;
-}
-
-#tray[tabsonly] #tabs-controls toolbarbutton {
-  margin-top: 0;
-  margin-bottom: 0;
-}
-
-#tray[tabsonly] documenttab {
-  height: @toolbar_height@;
-  margin: 0 -@tab_compression@;
-}
-
-#tray[tabsonly] documenttab:first-child {
-  -moz-margin-start: 0;
-}
-
-#tray[tabsonly] documenttab:last-child {
-  -moz-margin-end: 0;
-}
-
-#tray[tabsonly] .documenttab-thumbnail,
-#tray[tabsonly] .documenttab-selection,
-#tray[tabsonly] .documenttab-crop {
-  visibility: collapse;
-}
-
-#tray[tabsonly] .documenttab-container {
-  display: -moz-box;
-  -moz-box-orient: horizontal;
-  -moz-box-align: center;
-  padding: 0 @tab_spacing@;
-}
-
-#tray[tabsonly] .documenttab-favicon {
-  -moz-margin-start: @metro_spacing_normal@;
-  -moz-margin-end: @metro_spacing_snormal@;
-}
-
-#tray[tabsonly] .documenttab-title {
-  padding: 0;
-  margin: 0;
-  height: auto;
-  background: 0 none;
-  opacity: 1;
-  box-shadow: none;
-  width: @tab_inner_width@;
-}
-
-#tray[tabsonly] .documenttab-close {
-  list-style-image: url("chrome://browser/skin/images/closetab-tab.png");
-  position: relative;
-  padding: 0 !important;
-  z-index: 1;
-}
-
-#tray[tabsonly] documenttab[selected=true] {
-  background-color: @panel_light_color@;
-  background-image: url("chrome://browser/skin/images/tab-selection-left.png"),
-                    url("chrome://browser/skin/images/tab-selection-right.png"),
-                    @panel_light_background@;
-  background-position: left top, right top, center center;
-  background-repeat: no-repeat, no-repeat, repeat;
-}
-
-#tray[tabsonly] documenttab[selected=true] .documenttab-close {
-  list-style-image: url("chrome://browser/skin/images/closetab-tabselected.png");
-}
-
 #page,
 .selection-overlay {
   -moz-stack-sizing: ignore;
 }
 
 .selection-overlay {
   pointer-events: none;  
 }
@@ -296,20 +213,16 @@ documenttab[selected] .documenttab-selec
 .selection-overlay:-moz-focusring {
   outline: 0 !important;
 }
 
 .selection-overlay-hidden {
   display: none;
 }
 
-#tray[tabsonly] documenttab[selected=true] .documenttab-title {
-  color: #000;
-}
-
 #tabs-controls {
   margin-top: @metro_spacing_small@;
   -moz-box-align: start;
   -moz-box-orient: vertical;
   padding: 0 @metro_spacing_small@;
 }
 
 #tabs-controls toolbarbutton {
@@ -963,44 +876,55 @@ setting[type="radio"] > vbox {
 }
 
 #overlay-plus:-moz-locale-dir(ltr),
 #overlay-back:-moz-locale-dir(rtl) {
   right: -70px;
   background-position: left 6px center;
 }
 
+#stack[fullscreen] > .overlay-button,
+#appbar[visible] ~ .overlay-button,
 .overlay-button[disabled] {
   box-shadow: none;
+  visibility: collapse;
 }
 
+#stack[fullscreen] > #overlay-back:-moz-locale-dir(ltr),
+#stack[fullscreen] > #overlay-plus:-moz-locale-dir(rtl),
+#appbar[visible] ~ #overlay-back:-moz-locale-dir(ltr),
+#appbar[visible] ~ #overlay-plus:-moz-locale-dir(rtl),
 #overlay-back[disabled]:-moz-locale-dir(ltr),
 #overlay-plus[disabled]:-moz-locale-dir(rtl) {
   transform: translateX(-60px);
 }
 
+#stack[fullscreen] > #overlay-plus:-moz-locale-dir(ltr),
+#stack[fullscreen] > #overlay-back:-moz-locale-dir(rtl),
+#appbar[visible] ~ #overlay-plus:-moz-locale-dir(ltr),
+#appbar[visible] ~ #overlay-back:-moz-locale-dir(rtl),
 #overlay-plus[disabled]:-moz-locale-dir(ltr),
 #overlay-back[disabled]:-moz-locale-dir(rtl) {
   transform: translateX(60px);
 }
 
-.overlay-button:not([disabled]):hover {
+.overlay-button:hover {
   background-color: hsla(210,30%,10%,.4);
   background-size: 90px;
   border-color: hsla(0,0%,100%,.9);
 }
 
-#overlay-back:not([disabled]):-moz-locale-dir(ltr):hover,
-#overlay-plus:not([disabled]):-moz-locale-dir(rtl):hover {
+#overlay-back:-moz-locale-dir(ltr):hover,
+#overlay-plus:-moz-locale-dir(rtl):hover {
   background-position: right 12px center;
   transform: translateX(40px) scale(1.2);
 }
 
-#overlay-plus:not([disabled]):-moz-locale-dir(ltr):hover,
-#overlay-back:not([disabled]):-moz-locale-dir(rtl):hover {
+#overlay-plus:-moz-locale-dir(ltr):hover,
+#overlay-back:-moz-locale-dir(rtl):hover {
   background-position: left 12px center;
   transform: translateX(-40px) scale(1.2);
 }
 
 /* helperapp (save-as) popup ----------------------------------------------- */
 #helperapp-target {
   font-size: @font_small@ !important;
 }
--- a/browser/metro/theme/defines.inc
+++ b/browser/metro/theme/defines.inc
@@ -18,105 +18,67 @@
 %define urlbar_edit_height 36px
 
 %define toolbar_vertical_spacing 5px
 %define toolbar_horizontal_spacing 20px
 %define toolbar_height 68px
 %define tabs_height 178px
 
 %define progress_height 5px
-%define progress_start_color #0095dd
-%define progress_end_color #97cbff
 
 %define metro_orange #FF8000
 
-%define label_height 30px
-
 %define thumbnail_width 232px
 %define thumbnail_height 148px
 
 %define tile_border_color #dbdcde
 %define tile_width 200px
 
-%define tab_inner_width 180px
-%define tab_spacing 45px;
-%define tab_compression 40px;
-
 %define scroller_thickness 4px
 %define scroller_minimum 8px
 
-%define metro_spacing_xxsmall 2px
 %define metro_spacing_xsmall 3px
 %define metro_spacing_small 5px
 %define metro_spacing_snormal 10px
 %define metro_spacing_normal 15px
 %define metro_spacing_xnormal 20px
 %define metro_spacing_xxnormal 25px
 %define metro_spacing_xxxnormal 30px
 %define metro_spacing_large 40px
-%define metro_spacing_xlarge 45px
 
 %define metro_border_thin 1px
 %define metro_border_thick 2px
 %define metro_border_xthick 4px
 
 %define metro_font_snormal 14px
 %define metro_font_normal 15px
 %define metro_font_large 25px
 %define metro_font_xlarge 45px
 
-%define font_xlarge 32px
-%define font_xnormal 17px
 %define font_normal 16px
 %define font_snormal 15px
 %define font_small 12px
 %define font_xsmall 11px
-%define font_tiny 9px
-%define font_xtiny 8px
-%define font_xxtiny 7px
 
 %define touch_row 47px
-%define touch_button_xlarge 48px
-%define touch_button_large 43px
 %define touch_button_small 37px
 %define touch_action_minwidth 133px
-%define touch_normal 43px
-%define touch_small 36px
 
-%define margin_context_popup 21px
 %define margin_large 16px
-%define margin_xxxnormal 11px
 %define margin_xnormal 7px
 %define margin_normal 5px
-%define margin_snormal 4px
-%define margin_small 3px
-%define margin_tiny 1px
-%define margin_xtiny 1px
 
-%define padding_xlarge 21px
-%define padding_large 16px
-%define padding_xxxnormal 11px
 %define padding_xxnormal 8px
 %define padding_xnormal 7px
 %define padding_normal 5px
-%define padding_snormal 4px
-%define padding_small 3px
-%define padding_xsmall 1px
-%define padding_tiny 1px
 
-%define border_width_xxlarge 4px
-%define border_width_xlarge 3px
 %define border_width_large 2px
 %define border_width_small 1px
 %define border_width_tiny 1px
 
 %define border_radius_normal 5px
-%define border_radius_small 4px
-%define border_radius_xsmall 2px
 %define border_radius_tiny 1px
 
-%define shadow_width_xlarge 7px
-%define shadow_width_large 4px
 %define shadow_width_small 1px
 
 % easing function and duration for animations match winJS showPanel method
 %define metro_animation_duration 550ms
 %define metro_animation_easing cubic-bezier(0.1, 0.9, 0.2, 1)
deleted file mode 100644
index 5561a1814c9b3c367ed6837658bd3319455f6136..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index bd35a2e2536da22c0b12ea2e9e0eef53021eb9ca..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index fc959e21a5a29d0d1a9d2e602be7a96da8282656..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 0a2c78129f02bc995759b1808d33a5f27526d77b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/metro/theme/jar.mn
+++ b/browser/metro/theme/jar.mn
@@ -23,23 +23,19 @@ chrome.jar:
 
   skin/images/panel-light.png               (images/panel-light.png)
   skin/images/panel-dark.png                (images/panel-dark.png)
   skin/images/back.png                      (images/back.png)
   skin/images/forward.png                   (images/forward.png)
   skin/images/reload.png                    (images/reload.png)
   skin/images/newtab-default.png            (images/newtab-default.png)
   skin/images/closetab-default.png          (images/closetab-default.png)
-  skin/images/closetab-tab.png              (images/closetab-tab.png)
-  skin/images/closetab-tabselected.png      (images/closetab-tabselected.png)
   skin/images/tab-arrows.png                (images/tab-arrows.png)
   skin/images/tab-crop.png                  (images/tab-crop.png)
   skin/images/tab-overlay.png               (images/tab-overlay.png)
-  skin/images/tab-selection-left.png        (images/tab-selection-left.png)
-  skin/images/tab-selection-right.png       (images/tab-selection-right.png)
   skin/images/identity-icons-generic.png    (images/identity-icons-generic.png)
   skin/images/identity-icons-https-ev.png   (images/identity-icons-https-ev.png)
   skin/images/identity-icons-https-mixed.png  (images/identity-icons-https-mixed.png)
   skin/images/identity-icons-https.png      (images/identity-icons-https.png)
   skin/images/infobar-close.png             (images/infobar-close.png)
   skin/images/infobar-geolocation.png       (images/infobar-geolocation.png)
   skin/images/infobar-key.png               (images/infobar-key.png)
   skin/images/infobar-popup.png             (images/infobar-popup.png)
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -100,17 +100,17 @@ class RemoteAutomation(Automation):
                 # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at org.mozilla.gecko.GeckoApp$21.run(GeckoApp.java:1833)
                 # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at android.os.Handler.handleCallback(Handler.java:587)
                 # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at android.os.Handler.dispatchMessage(Handler.java:92)
                 # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at android.os.Looper.loop(Looper.java:123)
                 # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at org.mozilla.gecko.util.GeckoBackgroundThread.run(GeckoBackgroundThread.java:31)
                 #
                 #   -> java.lang.NullPointerException at org.mozilla.gecko.GeckoApp$21.run(GeckoApp.java:1833)
                 found_exception = True
-                logre = re.compile(r".*\):\s(.*)")
+                logre = re.compile(r".*\): \t?(.*)")
                 m = logre.search(logcat[i+1])
                 if m and m.group(1):
                     top_frame = m.group(1)
                 m = logre.search(logcat[i+2])
                 if m and m.group(1):
                     top_frame = top_frame + m.group(1)
                 print "PROCESS-CRASH | java-exception | %s" % top_frame
                 break
--- a/build/unix/mozconfig.linux
+++ b/build/unix/mozconfig.linux
@@ -1,4 +1,4 @@
 . "$topsrcdir/build/mozconfig.common"
 
-CC=/tools/gcc-4.5-0moz3/bin/gcc
-CXX=/tools/gcc-4.5-0moz3/bin/g++
+CC="/tools/gcc-4.7.2-0moz1/bin/gcc"
+CXX="/tools/gcc-4.7.2-0moz1/bin/g++"
--- a/content/base/public/nsIContentSecurityPolicy.idl
+++ b/content/base/public/nsIContentSecurityPolicy.idl
@@ -8,17 +8,17 @@ interface nsIURI;
 interface nsIHttpChannel;
 interface nsIDocShell;
 
 /**
  * nsIContentSecurityPolicy
  * Describes an XPCOM component used to model an enforce CSPs.
  */
 
-[scriptable, uuid(91E1F257-914C-4D4F-902C-F67F772839AB)]
+[scriptable, uuid(230b126d-afc3-4588-9794-3e135594d626)]
 interface nsIContentSecurityPolicy : nsISupports
 {
 
   /**
    * Set to true when the CSP has been read in and parsed and is ready to
    * enforce.  This is a barrier for the nsDocument so it doesn't load any
    * sub-content until either it knows that a CSP is ready or will not be used.
    */
@@ -58,16 +58,31 @@ interface nsIContentSecurityPolicy : nsI
    *     well.
    * @return
    *     Whether or not the effects of the eval call should be allowed
    *     (block the call if false).
    */
   boolean getAllowsEval(out boolean shouldReportViolation);
 
   /**
+   * Whether this policy allows in-page styles.
+   * This includes <style> tags with text content and style="" attributes in
+   * HTML elements.
+   * @param shouldReportViolation
+   *     Whether or not the use of eval should be reported.
+   *     This function always returns "true" for report-only policies, but when
+   *     the report-only policy is violated, shouldReportViolation is true as
+   *     well.
+   * @return
+   *     Whether or not the effects of the eval call should be allowed
+   *     (block the call if false).
+   */
+  boolean getAllowsInlineStyle(out boolean shouldReportViolation);
+
+  /**
    * Log policy violation on the Error Console and send a report if a report-uri
    * is present in the policy
    *
    * @param violationType
    *     one of the VIOLATION_TYPE_* constants, e.g. inline-script or eval
    * @param sourceFile
    *     name of the source file containing the violation (if available)
    * @param contentSample
@@ -77,16 +92,17 @@ interface nsIContentSecurityPolicy : nsI
    */
   void logViolationDetails(in unsigned short violationType,
                            in AString sourceFile,
                            in AString scriptSample,
                            in int32_t lineNum);
 
   const unsigned short VIOLATION_TYPE_INLINE_SCRIPT = 1;
   const unsigned short VIOLATION_TYPE_EVAL = 2;
+  const unsigned short VIOLATION_TYPE_INLINE_STYLE = 3;
 
   /**
    * Manually triggers violation report sending given a URI and reason.
    * The URI may be null, in which case "self" is sent.
    * @param blockedURI
    *     the URI that violated the policy
    * @param violatedDirective
    *     the directive that was violated.
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -176,16 +176,19 @@ this.CSPRep = function CSPRep(aSpecCompl
   this._allowInlineScripts = false;
 
   // don't auto-populate _directives, so it is easier to find bugs
   this._directives = {};
 
   // Is this a 1.0 spec compliant CSPRep ?
   // Default to false if not specified.
   this._specCompliant = (aSpecCompliant !== undefined) ? aSpecCompliant : false;
+
+  // Only CSP 1.0 spec compliant policies block inline styles by default.
+  this._allowInlineStyles = !aSpecCompliant;
 }
 
 // Source directives for our original CSP implementation.
 // These can be removed when the original implementation is deprecated.
 CSPRep.SRC_DIRECTIVES_OLD = {
   DEFAULT_SRC:      "default-src",
   SCRIPT_SRC:       "script-src",
   STYLE_SRC:        "style-src",
@@ -712,17 +715,18 @@ CSPRep.prototype = {
       return false;
     }
     for (var i in this._directives) {
       if (!that._directives[i] || !this._directives[i].equals(that._directives[i])) {
         return false;
       }
     }
     return (this.allowsInlineScripts === that.allowsInlineScripts)
-        && (this.allowsEvalInScripts === that.allowsEvalInScripts);
+        && (this.allowsEvalInScripts === that.allowsEvalInScripts)
+        && (this.allowsInlineStyles === that.allowsInlineStyles);
   },
 
   /**
    * Generates canonical string representation of the policy.
    */
   toString:
   function csp_toString() {
     var dirs = [];
@@ -807,16 +811,19 @@ CSPRep.prototype = {
     }
 
     newRep._allowEval =          this.allowsEvalInScripts
                            && aCSPRep.allowsEvalInScripts;
 
     newRep._allowInlineScripts = this.allowsInlineScripts
                            && aCSPRep.allowsInlineScripts;
 
+    newRep._allowInlineStyles = this.allowsInlineStyles
+                           && aCSPRep.allowsInlineStyles;
+
     newRep._innerWindowID = this._innerWindowID ?
                               this._innerWindowID : aCSPRep._innerWindowID;
 
     return newRep;
   },
 
   /**
    * Copies default source list to each unspecified directive.
@@ -868,16 +875,24 @@ CSPRep.prototype = {
    * Returns true if inline scripts are enabled through the "inline"
    * keyword.
    */
   get allowsInlineScripts () {
     return this._allowInlineScripts;
   },
 
   /**
+   * Returns true if inline styles are enabled through the "inline-style"
+   * keyword.
+   */
+  get allowsInlineStyles () {
+    return this._allowInlineStyles;
+  },
+
+  /**
    * Sends a warning message to the error console and web developer console.
    * @param aMsg
    *        The message to send
    * @param aSource (optional)
    *        The URL of the file in which the error occurred
    * @param aScriptLine (optional)
    *        The line in the source file which the error occurred
    * @param aLineNum (optional)
--- a/content/base/src/contentSecurityPolicy.js
+++ b/content/base/src/contentSecurityPolicy.js
@@ -35,16 +35,17 @@ function ContentSecurityPolicy() {
   CSPdebug("CSP CREATED");
   this._isInitialized = false;
   this._reportOnlyMode = false;
 
   this._policy = CSPRep.fromString("default-src *");
 
   // default options "wide open" since this policy will be intersected soon
   this._policy._allowInlineScripts = true;
+  this._policy._allowInlineStyles = true;
   this._policy._allowEval = true;
 
   this._request = "";
   this._requestOrigin = "";
   this._requestPrincipal = "";
   this._referrer = "";
   this._docRequest = null;
   CSPdebug("CSP POLICY INITED TO 'default-src *'");
@@ -139,16 +140,24 @@ ContentSecurityPolicy.prototype = {
   getAllowsEval: function(shouldReportViolation) {
     // report it?
     shouldReportViolation.value = !this._policy.allowsEvalInScripts;
 
     // allow it to execute?
     return this._reportOnlyMode || this._policy.allowsEvalInScripts;
   },
 
+  getAllowsInlineStyle: function(shouldReportViolation) {
+    // report it?
+    shouldReportViolation.value = !this._policy.allowsInlineStyles;
+
+    // allow it to execute?
+    return this._reportOnlyMode || this._policy.allowsInlineStyles;
+  },
+
   /**
    * Log policy violation on the Error Console and send a report if a report-uri
    * is present in the policy
    *
    * @param aViolationType
    *     one of the VIOLATION_TYPE_* constants, e.g. inline-script or eval
    * @param aSourceFile
    *     name of the source file containing the violation (if available)
@@ -158,16 +167,22 @@ ContentSecurityPolicy.prototype = {
    *     source line number of the violation (if available)
    */
   logViolationDetails:
   function(aViolationType, aSourceFile, aScriptSample, aLineNum) {
     // allowsInlineScript and allowsEval both return true when report-only mode
     // is enabled, resulting in a call to this function. Therefore we need to
     // check that the policy was in fact violated before logging any violations
     switch (aViolationType) {
+    case Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_STYLE:
+      if (!this._policy.allowsInlineStyles)
+        this._asyncReportViolation('self',null,'inline style base restriction',
+                                   'violated base restriction: Inline Stylesheets will not apply',
+                                   aSourceFile, aScriptSample, aLineNum);
+      break;
     case Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT:
       if (!this._policy.allowsInlineScripts)
         this._asyncReportViolation('self',null,'inline script base restriction',
                                    'violated base restriction: Inline Scripts will not execute',
                                    aSourceFile, aScriptSample, aLineNum);
       break;
     case Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_EVAL:
       if (!this._policy.allowsEvalInScripts)
--- a/content/base/src/nsDOMDataChannel.cpp
+++ b/content/base/src/nsDOMDataChannel.cpp
@@ -17,17 +17,16 @@ extern PRLogModuleInfo* GetDataChannelLo
 #undef LOG
 #define LOG(args) PR_LOG(GetDataChannelLog(), PR_LOG_DEBUG, args)
 
 
 #include "nsDOMDataChannel.h"
 #include "nsIDOMFile.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsIDOMDataChannel.h"
-#include "nsIDOMRTCPeerConnection.h"
 #include "nsIDOMMessageEvent.h"
 #include "nsDOMClassInfo.h"
 #include "nsDOMEventTargetHelper.h"
 
 #include "js/Value.h"
 
 #include "nsError.h"
 #include "nsAutoPtr.h"
@@ -109,21 +108,16 @@ private:
   enum
   {
     DC_BINARY_TYPE_ARRAYBUFFER,
     DC_BINARY_TYPE_BLOB,
   } mBinaryType;
 };
 
 DOMCI_DATA(DataChannel, nsDOMDataChannel)
-// A bit of a hack for RTCPeerConnection, since it doesn't have a .cpp file of
-// its own.  Note that it's not castable to anything in particular other than
-// nsIDOMRTCPeerConnection, so we can just use nsIDOMRTCPeerConnection as the
-// "class".
-DOMCI_DATA(RTCPeerConnection, nsIDOMRTCPeerConnection)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataChannel,
                                                   nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDataChannel,
                                                 nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -162,20 +156,16 @@ nsDOMDataChannel::Init(nsPIDOMWindow* aD
   } else {
     BindToOwner(aDOMWindow);
   }
 
   // Attempt to kill "ghost" DataChannel (if one can happen): but usually too early for check to fail
   rv = CheckInnerWindowCorrectness();
   NS_ENSURE_SUCCESS(rv,rv);
 
-  // See bug 696085
-  // We don't need to observe for window destroyed or frozen; but PeerConnection needs
-  // to not allow itself to be bfcached (and get destroyed on navigation).
-
   rv = nsContentUtils::GetUTFOrigin(principal,mOrigin);
   LOG(("%s: origin = %s\n",__FUNCTION__,NS_LossyConvertUTF16toASCII(mOrigin).get()));
   return rv;
 }
 
 NS_IMPL_EVENT_HANDLER(nsDOMDataChannel, open)
 NS_IMPL_EVENT_HANDLER(nsDOMDataChannel, error)
 NS_IMPL_EVENT_HANDLER(nsDOMDataChannel, close)
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1732,17 +1732,19 @@ GK_ATOM(onMozSwipeGesture, "onMozSwipeGe
 GK_ATOM(onMozMagnifyGestureStart, "onMozMagnifyGestureStart")
 GK_ATOM(onMozMagnifyGestureUpdate, "onMozMagnifyGestureUpdate")
 GK_ATOM(onMozMagnifyGesture, "onMozMagnifyGesture")
 GK_ATOM(onMozRotateGestureStart, "onMozRotateGestureStart")
 GK_ATOM(onMozRotateGestureUpdate, "onMozRotateGestureUpdate")
 GK_ATOM(onMozRotateGesture, "onMozRotateGesture")
 GK_ATOM(onMozTapGesture, "onMozTapGesture")
 GK_ATOM(onMozPressTapGesture, "onMozPressTapGesture")
-GK_ATOM(onMozEdgeUIGesture, "onMozEdgeUIGesture")
+GK_ATOM(onMozEdgeUIStarted, "onMozEdgeUIStarted")
+GK_ATOM(onMozEdgeUICanceled, "onMozEdgeUICanceled")
+GK_ATOM(onMozEdgeUICompleted, "onMozEdgeUICompleted")
 
 // orientation support
 GK_ATOM(ondevicemotion, "ondevicemotion")
 GK_ATOM(ondeviceorientation, "ondeviceorientation")
 GK_ATOM(ondeviceproximity, "ondeviceproximity")
 GK_ATOM(onmozorientationchange, "onmozorientationchange")
 GK_ATOM(onuserproximity, "onuserproximity")
 
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -2392,17 +2392,17 @@ nsINode::WrapObject(JSContext *aCx, JS::
       !nsContentUtils::IsCallerChrome()) {
     Throw<true>(aCx, NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   JS::Rooted<JSObject*> obj(aCx, WrapNode(aCx, aScope));
   if (obj && ChromeOnlyAccess() &&
       !nsContentUtils::IsSystemPrincipal(NodePrincipal()) &&
-      xpc::AllowXBLScope(js::GetContextCompartment(aCx)))
+      xpc::AllowXBLScope(js::GetObjectCompartment(obj)))
   {
     // Create a new wrapper and cache it.
     JSAutoCompartment ac(aCx, obj);
     JSObject* wrapper = xpc::WrapperFactory::WrapSOWObject(aCx, obj);
     if (!wrapper) {
       ClearWrapper();
       return nullptr;
     }
--- a/content/base/src/nsStyleLinkElement.cpp
+++ b/content/base/src/nsStyleLinkElement.cpp
@@ -21,16 +21,17 @@
 #include "nsIDOMNode.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsNetUtil.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsUnicharInputStream.h"
 #include "nsContentUtils.h"
+#include "nsStyleUtil.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsStyleLinkElement::nsStyleLinkElement()
   : mDontLoadStyle(false)
   , mUpdatesEnabled(true)
   , mLineNumber(1)
@@ -361,16 +362,21 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
   }
 
   bool doneLoading = false;
   nsresult rv = NS_OK;
   if (isInline) {
     nsAutoString text;
     nsContentUtils::GetNodeTextContent(thisContent, false, text);
 
+    if (!nsStyleUtil::CSPAllowsInlineStyle(thisContent->NodePrincipal(),
+                                           doc->GetDocumentURI(),
+                                           mLineNumber, text, &rv))
+      return rv;
+
     // Parse the style sheet.
     rv = doc->CSSLoader()->
       LoadInlineStyle(thisContent, text, mLineNumber, title, media,
                       scopeElement, aObserver, &doneLoading, &isAlternate);
   }
   else {
     // XXXbz clone the URI here to work around content policies modifying URIs.
     nsCOMPtr<nsIURI> clonedURI;
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -15,16 +15,17 @@
 #include "nsServiceManagerUtils.h"
 #include "nsIDocument.h"
 #include "mozilla/css/StyleRule.h"
 #include "nsCSSParser.h"
 #include "mozilla/css/Loader.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsXULElement.h"
 #include "nsContentUtils.h"
+#include "nsStyleUtil.h"
 
 namespace css = mozilla::css;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsIAtom*
@@ -230,16 +231,21 @@ nsStyledElementNotElementCSSInlineStyle:
 
 void
 nsStyledElementNotElementCSSInlineStyle::ParseStyleAttribute(const nsAString& aValue,
                                                              nsAttrValue& aResult,
                                                              bool aForceInDataDoc)
 {
   nsIDocument* doc = OwnerDoc();
 
+  if (!nsStyleUtil::CSPAllowsInlineStyle(NodePrincipal(),
+                                         doc->GetDocumentURI(), 0, aValue,
+                                         nullptr))
+    return;
+
   if (aForceInDataDoc ||
       !doc->IsLoadedAsData() ||
       doc->IsStaticDocument()) {
     bool isCSS = true; // assume CSS until proven otherwise
 
     if (!IsInNativeAnonymousSubtree()) {  // native anonymous content
                                           // always assumes CSS
       nsAutoString styleType;
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -334,16 +334,17 @@ MOCHITEST_FILES_B = \
 		test_copypaste.html \
 		test_bug503481.html \
 		file_bug503481.sjs \
 		test_bug503481b.html \
 		file_bug503481b_inner.html \
 		test_viewport_scroll.html \
 		test_CSP.html \
 		file_CSP.sjs \
+		file_CSP.css \
 		file_CSP_main.html \
 		file_CSP_main.html^headers^ \
 		file_CSP_main_spec_compliant.html \
 		file_CSP_main_spec_compliant.html^headers^ \
 		file_CSP_main.js \
 		file_CSP_main_spec_compliant.js \
 		test_CSP_frameancestors.html \
 		file_CSP_frameancestors.sjs \
@@ -363,16 +364,23 @@ MOCHITEST_FILES_B = \
 		file_CSP_evalscript_main.html \
 		file_CSP_evalscript_main.html^headers^ \
 		file_CSP_evalscript_main.js \
 		file_CSP_evalscript_main_allowed.js \
 		file_CSP_evalscript_main_spec_compliant.html \
 	 	file_CSP_evalscript_main_spec_compliant.html^headers^ \
 		file_CSP_evalscript_main_spec_compliant_allowed.html \
 		file_CSP_evalscript_main_spec_compliant_allowed.html^headers^ \
+		test_CSP_inlinestyle.html \
+		file_CSP_inlinestyle_main.html \
+		file_CSP_inlinestyle_main.html^headers^ \
+		file_CSP_inlinestyle_main_spec_compliant.html \
+		file_CSP_inlinestyle_main_spec_compliant.html^headers^ \
+		file_CSP_inlinestyle_main_spec_compliant_allowed.html \
+		file_CSP_inlinestyle_main_spec_compliant_allowed.html^headers^ \
 		file_csp_bug768029.html \
 		file_csp_bug768029.sjs \
 		file_csp_bug773891.html \
 		file_csp_bug773891.sjs \
 		test_bug540854.html \
 		bug540854.sjs \
 		test_bug548463.html \
 		test_bug545644.html \
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP.css
@@ -0,0 +1,20 @@
+/*
+ * Moved this CSS from an inline stylesheet to an external file when we added
+ * inline-style blocking in bug 763879.
+ * This test may hang if the load for this .css file is blocked due to a
+ * malfunction of CSP, but should pass if the style_good test passes.
+ */
+
+/* CSS font embedding tests */
+@font-face {
+  font-family: "arbitrary_good";
+  src: url('file_CSP.sjs?testid=font_good&type=application/octet-stream');
+}
+@font-face {
+  font-family: "arbitrary_bad";
+  src: url('http://example.org/tests/content/base/test/file_CSP.sjs?testid=font_bad&type=application/octet-stream');
+}
+
+.div_arbitrary_good { font-family: "arbitrary_good"; }
+.div_arbitrary_bad { font-family: "arbitrary_bad"; }
+
--- a/content/base/test/file_CSP.sjs
+++ b/content/base/test/file_CSP.sjs
@@ -16,12 +16,11 @@ function handleRequest(request, response
 
   if ("type" in query) {
     response.setHeader("Content-Type", unescape(query['type']), false);
   } else {
     response.setHeader("Content-Type", "text/html", false);
   }
 
   if ("content" in query) {
-    response.setHeader("Content-Type", "text/html", false);
     response.write(unescape(query['content']));
   }
 }
--- a/content/base/test/file_CSP_inlinescript_main.html
+++ b/content/base/test/file_CSP_inlinescript_main.html
@@ -1,8 +1,13 @@
+<!--
+-- The original CSP implementation predates the CSP 1.0 spec and didn't
+-- block inline styles, so when the prefixed X-Content-Security-Policy header is used,
+-- as it is for this file, inline styles should be allowed.
+-->
 <html>
   <head>
     <title>CSP inline script tests</title>
   </head>
   <body onload="window.parent.scriptRan(false, 'eventattr', 'event attribute in body tag fired')">
 
     <script type="text/javascript">
       window.parent.scriptRan(false, "textnode", "text node in a script tag executed.");
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP_inlinestyle_main.html
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<html>
+  <head>
+    <title>CSP inline script tests</title>
+    <!-- content= "div#linkstylediv { color: #0f0; }" -->
+    <link rel="stylesheet" type="text/css"
+          href='file_CSP.sjs?type=text/css&content=div%23linkstylediv%20%7B%20color%3A%20%230f0%3B%20%7D' />
+  </head>
+  <body>
+
+    <style type="text/css">
+      div#inlinestylediv {
+        color: #00ff00;
+      }
+    </style>
+
+    <div id='linkstylediv'>Link tag (external) stylesheet test (should be green)</div>
+    <div id='attrstylediv' style="color: #00ff00;">Attribute stylesheet test (should be green)</div>
+    <div id='inlinestylediv'>Inline stylesheet test (should be green)</div>
+
+	    <!-- tests for SMIL stuff - animations -->
+    <svg xmlns="http://www.w3.org/2000/svg"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         width="100%"
+         height="100px">
+
+      <!-- Animates XML attribute, which is mapped into style. -->
+      <text id="xmlTest" x="0" y="15">
+         This should be green since the animation should be allowed by CSP.
+
+        <animate attributeName="fill" attributeType="XML"
+                  values="lime;green;lime" dur="2s"
+                  repeatCount="indefinite" />
+      </text>
+
+      <!-- Animates override value for CSS property. -->
+      <text id="cssOverrideTest" x="0" y="35">
+         This should be green since the animation should be allowed by CSP.
+
+        <animate attributeName="fill" attributeType="CSS"
+                  values="lime;green;lime" dur="2s"
+                  repeatCount="indefinite" />
+      </text>
+
+      <!-- Animates override value for CSS property targeted via ID. -->
+      <text id="cssOverrideTestById" x="0" y="55">
+         This should be green since the animation should be allowed by CSP.
+      </text>
+      <animate xlink:href="#cssOverrideTestById"
+               attributeName="fill"
+               values="lime;green;lime"
+               dur="2s" repeatCount="indefinite" />
+
+      <!-- Sets value for CSS property targeted via ID. -->
+      <text id="cssSetTestById" x="0" y="75">
+         This should be green since the &lt;set&gt; should be allowed by CSP.
+      </text>
+      <set xlink:href="#cssSetTestById"
+               attributeName="fill"
+               to="lime" />
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP_inlinestyle_main.html^headers^
@@ -0,0 +1,2 @@
+X-Content-Security-Policy: default-src 'self'
+Cache-Control: no-cache
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP_inlinestyle_main_spec_compliant.html
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<html>
+  <head>
+    <title>CSP inline script tests</title>
+    <!-- content= "div#linkstylediv { color: #0f0; }" -->
+    <link rel="stylesheet" type="text/css"
+          href='file_CSP.sjs?type=text/css&content=div%23linkstylediv%20%7B%20color%3A%20%230f0%3B%20%7D' />
+    <!-- content= "div#modifycsstextdiv { color: #0f0; }" -->
+    <link rel="stylesheet" type="text/css"
+          href='file_CSP.sjs?type=text/css&content=div%23modifycsstextdiv%20%7B%20color%3A%20%23f00%3B%20%7D' />
+    <script>
+      function cssTest() {
+        var elem = document.getElementById('csstextstylediv');
+        elem.style.cssText = "color: #00FF00;";
+        getComputedStyle(elem, null).color;
+
+        document.styleSheets[1].cssRules[0].style.cssText = "color: #00FF00;";
+        elem = document.getElementById('modifycsstextdiv');
+        getComputedStyle(elem, null).color;
+      }
+    </script>
+  </head>
+  <body onload='cssTest()'>
+
+    <style type="text/css">
+      div#inlinestylediv {
+        color: #FF0000;
+      }
+    </style>
+
+    <div id='linkstylediv'>Link tag (external) stylesheet test (should be green)</div>
+    <div id='inlinestylediv'>Inline stylesheet test (should be black)</div>
+    <div id='attrstylediv' style="color: #FF0000;">Attribute stylesheet test (should be black)</div>
+    <div id='csstextstylediv'>cssText test (should be black)</div>
+    <div id='modifycsstextdiv'> modify rule from style sheet via cssText(should be green) </div>
+
+    <!-- tests for SMIL stuff - animations -->
+    <svg xmlns="http://www.w3.org/2000/svg"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         width="100%"
+         height="100px">
+
+      <!-- Animates XML attribute, which is mapped into style. -->
+      <text id="xmlTest" x="0" y="15">
+         This shouldn't be red since the animation should be blocked by CSP.
+
+        <animate attributeName="fill" attributeType="XML"
+                  values="red;orange;red" dur="2s"
+                  repeatCount="indefinite" />
+      </text>
+
+      <!-- Animates override value for CSS property. -->
+      <text id="cssOverrideTest" x="0" y="35">
+         This shouldn't be red since the animation should be blocked by CSP.
+
+        <animate attributeName="fill" attributeType="CSS"
+                  values="red;orange;red" dur="2s"
+                  repeatCount="indefinite" />
+      </text>
+
+      <!-- Animates override value for CSS property targeted via ID. -->
+      <text id="cssOverrideTestById" x="0" y="55">
+         This shouldn't be red since the animation should be blocked by CSP.
+      </text>
+      <animate xlink:href="#cssOverrideTestById"
+               attributeName="fill"
+               values="red;orange;red"
+               dur="2s" repeatCount="indefinite" />
+
+      <!-- Sets value for CSS property targeted via ID. -->
+      <text id="cssSetTestById" x="0" y="75">
+         This shouldn't be red since the &lt;set&gt; should be blocked by CSP.
+      </text>
+      <set xlink:href="#cssSetTestById"
+               attributeName="fill"
+               to="red" />
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP_inlinestyle_main_spec_compliant.html^headers^
@@ -0,0 +1,2 @@
+Content-Security-Policy: default-src 'self' ; script-src 'self' 'unsafe-inline'
+Cache-Control: no-cache
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP_inlinestyle_main_spec_compliant_allowed.html
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<html>
+  <head>
+    <title>CSP inline script tests</title>
+    <!-- content= "div#linkstylediv { color: #0f0; }" -->
+    <link rel="stylesheet" type="text/css"
+          href='file_CSP.sjs?type=text/css&content=div%23linkstylediv%20%7B%20color%3A%20%230f0%3B%20%7D' />
+    <!-- content= "div#modifycsstextdiv { color: #f00; }" -->
+    <link rel="stylesheet" type="text/css"
+          href='file_CSP.sjs?type=text/css&content=div%23modifycsstextdiv%20%7B%20color%3A%20%23f00%3B%20%7D' />
+    <script>
+      function cssTest() {
+        // CSSStyleDeclaration.cssText
+        var elem = document.getElementById('csstextstylediv');
+        elem.style.cssText = "color: #00FF00;";
+
+        // If I call getComputedStyle as below, this test passes as the parent page
+        // correctly detects that the text is colored green - if I remove this, getComputedStyle
+        // thinks the text is black when called by the parent page.
+        getComputedStyle(elem, null).color;
+
+        document.styleSheets[1].cssRules[0].style.cssText = "color: #00FF00;";
+        elem = document.getElementById('modifycsstextdiv');
+        getComputedStyle(elem, null).color;
+      }
+    </script>
+  </head>
+  <body onload='cssTest()'>
+
+    <style type="text/css">
+      div#inlinestylediv {
+        color: #00FF00;
+      }
+    </style>
+
+    <div id='linkstylediv'>Link tag (external) stylesheet test (should be green)</div>
+    <div id='inlinestylediv'>Inline stylesheet test (should be green)</div>
+    <div id='attrstylediv' style="color: #00FF00;">Attribute stylesheet test (should be green)</div>
+    <div id='csstextstylediv'>style.cssText test (should be green)</div>
+    <div id='modifycsstextdiv'> modify rule from style sheet via cssText(should be green) </div>
+
+    <!-- tests for SMIL stuff - animations -->
+    <svg xmlns="http://www.w3.org/2000/svg"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         width="100%"
+         height="100px">
+
+      <!-- Animates XML attribute, which is mapped into style. -->
+      <text id="xmlTest" x="0" y="15">
+         This should be green since the animation should be allowed by CSP.
+
+        <animate attributeName="fill" attributeType="XML"
+                  values="lime;green;lime" dur="2s"
+                  repeatCount="indefinite" />
+      </text>
+
+      <!-- Animates override value for CSS property. -->
+      <text id="cssOverrideTest" x="0" y="35">
+         This should be green since the animation should be allowed by CSP.
+
+        <animate attributeName="fill" attributeType="CSS"
+                  values="lime;green;lime" dur="2s"
+                  repeatCount="indefinite" />
+      </text>
+
+      <!-- Animates override value for CSS property targeted via ID. -->
+      <text id="cssOverrideTestById" x="0" y="55">
+         This should be green since the animation should be allowed by CSP.
+      </text>
+      <animate xlink:href="#cssOverrideTestById"
+               attributeName="fill"
+               values="lime;green;lime"
+               dur="2s" repeatCount="indefinite" />
+
+      <!-- Sets value for CSS property targeted via ID. -->
+      <text id="cssSetTestById" x="0" y="75">
+         This should be green since the &lt;set&gt; should be allowed by CSP.
+      </text>
+      <set xlink:href="#cssSetTestById"
+               attributeName="fill"
+               to="lime" />
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP_inlinestyle_main_spec_compliant_allowed.html^headers^
@@ -0,0 +1,2 @@
+Content-Security-Policy: default-src 'self' ; script-src 'self' 'unsafe-inline' ; style-src 'self' 'unsafe-inline'
+Cache-Control: no-cache
--- a/content/base/test/file_CSP_main.html
+++ b/content/base/test/file_CSP_main.html
@@ -1,30 +1,20 @@
 <html>
   <head>
     <link rel='stylesheet' type='text/css'
           href='http://example.org/tests/content/base/test/file_CSP.sjs?testid=style_bad&type=text/css' />
     <link rel='stylesheet' type='text/css'
           href='file_CSP.sjs?testid=style_good&type=text/css' />
 
+    <!-- Used to embed inline styles here for testing fonts, but can't do that -->
+    <!-- due to bug 763879 (block inline styles). Moved these to an external, CSS -->
+    <!-- file (file_CSP.css).  -->
+    <link rel='stylesheet' type='text/css' href='file_CSP.css' />
 
-    <style>
-      /* CSS font embedding tests */
-      @font-face {
-        font-family: "arbitrary_good";
-        src: url('file_CSP.sjs?testid=font_good&type=application/octet-stream');
-      }
-      @font-face {
-        font-family: "arbitrary_bad";
-        src: url('http://example.org/tests/content/base/test/file_CSP.sjs?testid=font_bad&type=application/octet-stream');
-      }
-
-      .div_arbitrary_good { font-family: "arbitrary_good"; }
-      .div_arbitrary_bad { font-family: "arbitrary_bad"; }
-    </style>
   </head>
   <body>
     <!-- these should be stopped by CSP.  :) -->
     <img src="http://example.org/tests/content/base/test/file_CSP.sjs?testid=img_bad&type=img/png"> </img>
     <audio src="http://example.org/tests/content/base/test/file_CSP.sjs?testid=media_bad&type=audio/vorbis"></audio>
     <script src='http://example.org/tests/content/base/test/file_CSP.sjs?testid=script_bad&type=text/javascript'></script>
     <iframe src='http://example.org/tests/content/base/test/file_CSP.sjs?testid=frame_bad&content=FAIL'></iframe>
     <object width="10" height="10">
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_CSP_inlinestyle.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Content Security Policy inline stylesheets stuff</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<iframe style="width:100%;height:300px;" id='cspframe'></iframe>
+<iframe style="width:100%;height:300px;" id='cspframe2'></iframe>
+<iframe style="width:100%;height:300px;" id='cspframe3'></iframe>
+<script class="testbody" type="text/javascript">
+
+var path = "/tests/content/base/test/";
+
+
+//////////////////////////////////////////////////////////////////////
+// set up and go
+SimpleTest.waitForExplicitFinish();
+
+var done = 0;
+
+// Our original CSP implementation does not block inline styles.
+function checkStyles(evt) {
+  var cspframe = document.getElementById('cspframe');
+  var color;
+
+  // black means the style wasn't applied.  green colors are used for styles
+  //expected to be applied.  A color is red if a style is erroneously applied
+  color = window.getComputedStyle(cspframe.contentDocument.getElementById('linkstylediv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'External Stylesheet (original CSP implementation) (' + color + ')');
+  color = window.getComputedStyle(cspframe.contentDocument.getElementById('inlinestylediv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'Inline Style TAG (original CSP implementation) (' + color + ')');
+  color = window.getComputedStyle(cspframe.contentDocument.getElementById('attrstylediv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'Style Attribute (original CSP implementation) (' + color + ')');
+  // SMIL tests
+  color = window.getComputedStyle(cspframe.contentDocument.getElementById('xmlTest',null))['fill'];
+  ok('rgb(0, 255, 0)' === color, 'XML Attribute styling (SMIL) (' + color + ')');
+  color = window.getComputedStyle(cspframe.contentDocument.getElementById('cssOverrideTest',null))['fill'];
+  ok('rgb(0, 255, 0)' === color, 'CSS Override styling (SMIL) (' + color + ')');
+  color = window.getComputedStyle(cspframe.contentDocument.getElementById('cssOverrideTestById',null))['fill'];
+  ok('rgb(0, 255, 0)' === color, 'CSS Override styling via ID lookup (SMIL) (' + color + ')');
+  color = window.getComputedStyle(cspframe.contentDocument.getElementById('cssSetTestById',null))['fill'];
+  ok('rgb(0, 255, 0)' === color, 'CSS Set Element styling via ID lookup (SMIL) (' + color + ')');
+  checkIfDone();
+}
+
+// When a CSP 1.0 compliant policy is specified we should block inline
+// styles applied by <style> element, style attribute, and SMIL <animate> and <set> tags
+// (when it's not explicitly allowed.)
+function checkStylesSpecCompliant(evt) {
+  var cspframe = document.getElementById('cspframe2');
+  var color;
+
+  // black means the style wasn't applied.  green colors are used for styles
+  //expected to be applied.  A color is red if a style is erroneously applied
+  color = window.getComputedStyle(cspframe2.contentDocument.getElementById('linkstylediv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'External Stylesheet (CSP 1.0 spec compliant) (' + color + ')');
+  color = window.getComputedStyle(cspframe2.contentDocument.getElementById('inlinestylediv'),null)['color'];
+  ok('rgb(0, 0, 0)' === color, 'Inline Style TAG (CSP 1.0 spec compliant) (' + color + ')');
+  color = window.getComputedStyle(cspframe2.contentDocument.getElementById('attrstylediv'),null)['color'];
+  ok('rgb(0, 0, 0)' === color, 'Style Attribute (CSP 1.0 spec compliant) (' + color + ')');
+  color = window.getComputedStyle(cspframe2.contentDocument.getElementById('csstextstylediv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'cssText (CSP 1.0 spec compliant) (' + color + ')');
+  // SMIL tests
+  color = window.getComputedStyle(cspframe2.contentDocument.getElementById('xmlTest',null))['fill'];
+  ok('rgb(0, 0, 0)' === color, 'XML Attribute styling (SMIL) (' + color + ')');
+  color = window.getComputedStyle(cspframe2.contentDocument.getElementById('cssOverrideTest',null))['fill'];
+  ok('rgb(0, 0, 0)' === color, 'CSS Override styling (SMIL) (' + color + ')');
+  color = window.getComputedStyle(cspframe2.contentDocument.getElementById('cssOverrideTestById',null))['fill'];
+  ok('rgb(0, 0, 0)' === color, 'CSS Override styling via ID lookup (SMIL) (' + color + ')');
+  color = window.getComputedStyle(cspframe2.contentDocument.getElementById('cssSetTestById',null))['fill'];
+  ok('rgb(0, 0, 0)' === color, 'CSS Set Element styling via ID lookup (SMIL) (' + color + ')');
+
+  color = window.getComputedStyle(cspframe2.contentDocument.getElementById('modifycsstextdiv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'Modify loaded style sheet via cssText (' + color + ')');
+
+  checkIfDone();
+}
+
+// When a CSP 1.0 compliant policy is specified we should allow inline
+// styles when it is explicitly allowed.
+function checkStylesSpecCompliantAllowed(evt) {
+  var cspframe = document.getElementById('cspframe3');
+  var color;
+
+  // black means the style wasn't applied.  green colors are used for styles
+  // expected to be applied.  A color is red if a style is erroneously applied
+  color = window.getComputedStyle(cspframe3.contentDocument.getElementById('linkstylediv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'External Stylesheet (CSP 1.0 spec compliant, allowed) (' + color + ')');
+  color = window.getComputedStyle(cspframe3.contentDocument.getElementById('inlinestylediv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'Inline Style TAG (CSP 1.0 spec compliant, allowed) (' + color + ')');
+  color = window.getComputedStyle(cspframe3.contentDocument.getElementById('attrstylediv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'Style Attribute (CSP 1.0 spec compliant, allowed) (' + color + ')');
+
+  // Note that the below test will fail if "script-src: 'unsafe-inline'" breaks,
+  // since it relies on executing script to set .cssText
+  color = window.getComputedStyle(cspframe3.contentDocument.getElementById('csstextstylediv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'style.cssText (CSP 1.0 spec compliant, allowed) (' + color + ')');
+  // SMIL tests
+  color = window.getComputedStyle(cspframe3.contentDocument.getElementById('xmlTest',null))['fill'];
+  ok('rgb(0, 255, 0)' === color, 'XML Attribute styling (SMIL) (' + color + ')');
+  color = window.getComputedStyle(cspframe3.contentDocument.getElementById('cssOverrideTest',null))['fill'];
+  ok('rgb(0, 255, 0)' === color, 'CSS Override styling (SMIL) (' + color + ')');
+  color = window.getComputedStyle(cspframe3.contentDocument.getElementById('cssOverrideTestById',null))['fill'];
+  ok('rgb(0, 255, 0)' === color, 'CSS Override styling via ID lookup (SMIL) (' + color + ')');
+  color = window.getComputedStyle(cspframe3.contentDocument.getElementById('cssSetTestById',null))['fill'];
+  ok('rgb(0, 255, 0)' === color, 'CSS Set Element styling via ID lookup (SMIL) (' + color + ')');
+
+  color = window.getComputedStyle(cspframe3.contentDocument.getElementById('modifycsstextdiv'),null)['color'];
+  ok('rgb(0, 255, 0)' === color, 'Modify loaded style sheet via cssText (' + color + ')');
+
+  checkIfDone();
+}
+
+function checkIfDone() {
+  done++;
+  if (done == 3)
+    SimpleTest.finish();
+}
+
+SpecialPowers.pushPrefEnv(
+  {'set':[["security.csp.speccompliant", true]]},
+  function() {
+    // save this for last so that our listeners are registered.
+    // ... this loads the testbed of good and bad requests.
+    document.getElementById('cspframe').src = 'file_CSP_inlinestyle_main.html';
+    document.getElementById('cspframe').addEventListener('load', checkStyles, false);
+    document.getElementById('cspframe2').src = 'file_CSP_inlinestyle_main_spec_compliant.html';
+    document.getElementById('cspframe2').addEventListener('load', checkStylesSpecCompliant, false);
+    document.getElementById('cspframe3').src = 'file_CSP_inlinestyle_main_spec_compliant_allowed.html';
+    document.getElementById('cspframe3').addEventListener('load', checkStylesSpecCompliantAllowed, false);
+  }
+);
+</script>
+</pre>
+</body>
+</html>
--- a/content/events/public/nsEventNameList.h
+++ b/content/events/public/nsEventNameList.h
@@ -821,18 +821,26 @@ NON_IDL_EVENT(MozRotateGesture,
 NON_IDL_EVENT(MozTapGesture,
               NS_SIMPLE_GESTURE_TAP,
               EventNameType_None,
               NS_SIMPLE_GESTURE_EVENT)
 NON_IDL_EVENT(MozPressTapGesture,
               NS_SIMPLE_GESTURE_PRESSTAP,
               EventNameType_None,
               NS_SIMPLE_GESTURE_EVENT)
-NON_IDL_EVENT(MozEdgeUIGesture,
-              NS_SIMPLE_GESTURE_EDGEUI,
+NON_IDL_EVENT(MozEdgeUIStarted,
+              NS_SIMPLE_GESTURE_EDGE_STARTED,
+              EventNameType_None,
+              NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozEdgeUICanceled,
+              NS_SIMPLE_GESTURE_EDGE_CANCELED,
+              EventNameType_None,
+              NS_SIMPLE_GESTURE_EVENT)
+NON_IDL_EVENT(MozEdgeUICompleted,
+              NS_SIMPLE_GESTURE_EDGE_COMPLETED,
               EventNameType_None,
               NS_SIMPLE_GESTURE_EVENT)
 
 NON_IDL_EVENT(transitionend,
               NS_TRANSITION_END,
               EventNameType_None,
               NS_TRANSITION_EVENT)
 NON_IDL_EVENT(animationstart,
@@ -848,16 +856,21 @@ NON_IDL_EVENT(animationiteration,
               EventNameType_None,
               NS_ANIMATION_EVENT)
 
 NON_IDL_EVENT(audioprocess,
               NS_AUDIO_PROCESS,
               EventNameType_None,
               NS_EVENT)
 
+NON_IDL_EVENT(complete,
+              NS_AUDIO_COMPLETE,
+              EventNameType_None,
+              NS_EVENT)
+
 #ifdef DEFINED_FORWARDED_EVENT
 #undef DEFINED_FORWARDED_EVENT
 #undef FORWARDED_EVENT
 #endif /* DEFINED_FORWARDED_EVENT */
 
 #ifdef DEFINED_WINDOW_EVENT
 #undef DEFINED_WINDOW_EVENT
 #undef WINDOW_EVENT
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -29,26 +29,39 @@
 #include "mozilla/Preferences.h"
 #include "nsJSUtils.h"
 #include "DictionaryHelpers.h"
 #include "nsLayoutUtils.h"
 #include "nsIScrollableFrame.h"
 #include "nsDOMClassInfoID.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsPIWindowRoot.h"
+#include "nsGlobalWindow.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static char *sPopupAllowedEvents;
 
 
 nsDOMEvent::nsDOMEvent(mozilla::dom::EventTarget* aOwner,
                        nsPresContext* aPresContext, nsEvent* aEvent)
 {
+  ConstructorInit(aOwner, aPresContext, aEvent);
+}
+
+nsDOMEvent::nsDOMEvent(nsPIDOMWindow* aParent)
+{
+  ConstructorInit(static_cast<nsGlobalWindow *>(aParent), nullptr, nullptr);
+  SetIsDOMBinding();
+}
+
+void nsDOMEvent::ConstructorInit(mozilla::dom::EventTarget* aOwner,
+                                 nsPresContext* aPresContext, nsEvent* aEvent)
+{
   SetOwner(aOwner);
 
   mPrivateDataDuplicated = false;
 
   if (aEvent) {
     mEvent = aEvent;
     mEventIsInternal = false;
   }
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -33,17 +33,21 @@ class nsDOMEventBase : public nsIDOMEven
 
 class nsDOMEvent : public nsDOMEventBase,
                    public nsIJSNativeInitializer,
                    public nsWrapperCache
 {
 protected:
   nsDOMEvent(mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext,
              nsEvent* aEvent);
+  nsDOMEvent(nsPIDOMWindow* aWindow);
   virtual ~nsDOMEvent();
+private:
+  void ConstructorInit(mozilla::dom::EventTarget* aOwner,
+                       nsPresContext* aPresContext, nsEvent* aEvent);
 public:
   void GetParentObject(nsIScriptGlobalObject** aParentObject)
   {
     if (mOwner) {
       CallQueryInterface(mOwner, aParentObject);
     } else {
       *aParentObject = nullptr;
     }
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -948,16 +948,25 @@ MediaStreamGraphImpl::RunThread()
   nsTArray<MessageBlock> messageQueue;
   {
     MonitorAutoLock lock(mMonitor);
     messageQueue.SwapElements(mMessageQueue);
   }
   NS_ASSERTION(!messageQueue.IsEmpty(),
                "Shouldn't have started a graph with empty message queue!");
 
+  uint32_t ticksProcessed = 0;
+  if (!mRealtime) {
+    NS_ASSERTION(!mNonRealtimeIsRunning,
+                 "We should not be running in non-realtime mode already");
+    NS_ASSERTION(mNonRealtimeTicksToProcess,
+                 "We should have a non-zero number of ticks to process");
+    mNonRealtimeIsRunning = true;
+  }
+
   for (;;) {
     // Update mCurrentTime to the min of the playing audio times, or using the
     // wall-clock time change if no audio is playing.
     UpdateCurrentTime();
 
     // Calculate independent action times for each batch of messages (each
     // batch corresponding to an event loop task). This isolates the performance
     // of different scripts to some extent.
@@ -1027,16 +1036,28 @@ MediaStreamGraphImpl::RunThread()
       if (is) {
         UpdateBufferSufficiencyState(is);
       }
       GraphTime end;
       if (!stream->mBlocked.GetAt(mCurrentTime, &end) || end < GRAPH_TIME_MAX) {
         allBlockedForever = false;
       }
     }
+    if (!mRealtime) {
+      ticksProcessed += TimeToTicksRoundDown(IdealAudioRate(), mStateComputedTime - prevComputedTime);
+      // Terminate processing if we've produce enough non-realtime ticks.
+      if (ticksProcessed >= mNonRealtimeTicksToProcess) {
+        // Wait indefinitely when we've processed enough non-realtime ticks.
+        // We'll be woken up when the graph shuts down.
+        MonitorAutoLock lock(mMonitor);
+        PrepareUpdatesToMainThreadState();
+        mWaitState = WAITSTATE_WAITING_INDEFINITELY;
+        mMonitor.Wait(PR_INTERVAL_NO_TIMEOUT);
+      }
+    }
     if (ensureNextIteration || !allBlockedForever || audioStreamsActive > 0) {
       EnsureNextIteration();
     }
 
     // Send updates to the main thread and wait for the next control loop
     // iteration.
     {
       MonitorAutoLock lock(mMonitor);
@@ -1077,16 +1098,20 @@ MediaStreamGraphImpl::RunThread()
                                (TimeStamp::Now() - now).ToSeconds()));
         }
       }
       mWaitState = WAITSTATE_RUNNING;
       mNeedAnotherIteration = false;
       messageQueue.SwapElements(mMessageQueue);
     }
   }
+
+  if (!mRealtime) {
+    mNonRealtimeIsRunning = false;
+  }
 }
 
 void
 MediaStreamGraphImpl::ApplyStreamUpdate(StreamUpdate* aUpdate)
 {
   mMonitor.AssertCurrentThreadOwns();
 
   MediaStream* stream = aUpdate->mStream;
@@ -1358,24 +1383,33 @@ MediaStreamGraphImpl::AppendMessage(Cont
     // because that will never be processed again, so just RunDuringShutdown
     // this message.
     // This should only happen during forced shutdown.
     aMessage->RunDuringShutdown();
     delete aMessage;
     if (IsEmpty()) {
       if (gGraph == this) {
         gGraph = nullptr;
-        delete this;
       }
+      delete this;
+    } else if (!mRealtime) {
+      // Make sure to mark the graph as not doing non-realtime processing,
+      // because otherwise AppendMessage will try to ensure that the graph
+      // is running, and we will never manage to release our resources.
+      mNonRealtimeProcessing = false;
     }
     return;
   }
 
   mCurrentTaskMessageQueue.AppendElement(aMessage);
-  EnsureRunInStableState();
+  // Do not start running the non-realtime graph unless processing has
+  // explicitly started.
+  if (mRealtime || mNonRealtimeProcessing) {
+    EnsureRunInStableState();
+  }
 }
 
 void
 MediaStream::Init()
 {
   MediaStreamGraphImpl* graph = GraphImpl();
   mBlocked.SetAtAndAfter(graph->mCurrentTime, true);
   mExplicitBlockerCount.SetAtAndAfter(graph->mCurrentTime, true);
@@ -1953,22 +1987,25 @@ static const int32_t INITIAL_CURRENT_TIM
 MediaStreamGraphImpl::MediaStreamGraphImpl(bool aRealtime)
   : mCurrentTime(INITIAL_CURRENT_TIME)
   , mStateComputedTime(INITIAL_CURRENT_TIME)
   , mProcessingGraphUpdateIndex(0)
   , mPortCount(0)
   , mMonitor("MediaStreamGraphImpl")
   , mLifecycleState(LIFECYCLE_THREAD_NOT_STARTED)
   , mWaitState(WAITSTATE_RUNNING)
+  , mNonRealtimeTicksToProcess(0)
   , mNeedAnotherIteration(false)
   , mForceShutDown(false)
   , mPostedRunInStableStateEvent(false)
+  , mNonRealtimeIsRunning(false)
   , mDetectedNotRunning(false)
   , mPostedRunInStableState(false)
   , mRealtime(aRealtime)
+  , mNonRealtimeProcessing(false)
 {
 #ifdef PR_LOGGING
   if (!gMediaStreamGraphLog) {
     gMediaStreamGraphLog = PR_NewLogModule("MediaStreamGraph");
   }
 #endif
 
   mCurrentTimeStamp = mInitialTimeStamp = TimeStamp::Now();
@@ -2023,17 +2060,16 @@ MediaStreamGraph::CreateNonRealtimeInsta
 void
 MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
 {
   NS_ASSERTION(NS_IsMainThread(), "Main thread only");
   MOZ_ASSERT(aGraph != gGraph, "Should not destroy the global graph here");
 
   MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(aGraph);
   graph->ForceShutDown();
-  delete graph;
 }
 
 SourceMediaStream*
 MediaStreamGraph::CreateSourceStream(DOMMediaStream* aWrapper)
 {
   SourceMediaStream* stream = new SourceMediaStream(aWrapper);
   NS_ADDREF(stream);
   MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this);
@@ -2066,9 +2102,24 @@ MediaStreamGraph::CreateAudioNodeStream(
     stream->SetChannelMixingParametersImpl(aEngine->NodeMainThread()->ChannelCount(),
                                            aEngine->NodeMainThread()->ChannelCountModeValue(),
                                            aEngine->NodeMainThread()->ChannelInterpretationValue());
   }
   graph->AppendMessage(new CreateMessage(stream));
   return stream;
 }
 
+void
+MediaStreamGraph::StartNonRealtimeProcessing(uint32_t aTicksToProcess)
+{
+  NS_ASSERTION(NS_IsMainThread(), "main thread only");
+
+  MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this);
+  NS_ASSERTION(!graph->mRealtime, "non-realtime only");
+
+  if (graph->mNonRealtimeProcessing)
+    return;
+  graph->mNonRealtimeTicksToProcess = aTicksToProcess;
+  graph->mNonRealtimeProcessing = true;
+  graph->EnsureRunInStableState();
 }
+
+}
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -934,16 +934,20 @@ public:
   AudioNodeStream* CreateAudioNodeStream(AudioNodeEngine* aEngine,
                                          AudioNodeStreamKind aKind);
   /**
    * Returns the number of graph updates sent. This can be used to track
    * whether a given update has been processed by the graph thread and reflected
    * in main-thread stream state.
    */
   int64_t GetCurrentGraphUpdateIndex() { return mGraphUpdatesSent; }
+  /**
+   * Start processing non-realtime for a specific number of ticks.
+   */
+  void StartNonRealtimeProcessing(uint32_t aTicksToProcess);
 
   /**
    * Media graph thread only.
    * Dispatches a runnable that will run on the main thread after all
    * main-thread stream state has been next updated.
    * Should only be called during MediaStreamListener callbacks.
    */
   void DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed<nsIRunnable> aRunnable)
--- a/content/media/MediaStreamGraphImpl.h
+++ b/content/media/MediaStreamGraphImpl.h
@@ -476,28 +476,39 @@ public:
     // RunThread() is paused indefinitely waiting for something to change
     WAITSTATE_WAITING_INDEFINITELY,
     // Something has signaled RunThread() to wake up immediately,
     // but it hasn't done so yet
     WAITSTATE_WAKING_UP
   };
   WaitState mWaitState;
   /**
+   * How many non-realtime ticks the graph should process.
+   */
+  uint32_t mNonRealtimeTicksToProcess;
+  /**
    * True when another iteration of the control loop is required.
    */
   bool mNeedAnotherIteration;
   /**
    * True when we need to do a forced shutdown during application shutdown.
    */
   bool mForceShutDown;
   /**
    * True when we have posted an event to the main thread to run
    * RunInStableState() and the event hasn't run yet.
    */
   bool mPostedRunInStableStateEvent;
+  /**
+   * True when the non-realtime graph thread is processing, as a result of
+   * a request from the main thread.  When processing is finished, we post
+   * a message to the main thread in order to set mNonRealtimeProcessing
+   * back to false.
+   */
+  bool mNonRealtimeIsRunning;
 
   // Main thread only
 
   /**
    * Messages posted by the current event loop task. These are forwarded to
    * the media graph thread during RunInStableState. We can't forward them
    * immediately because we want all messages between stable states to be
    * processed as an atomic batch.
@@ -514,13 +525,18 @@ public:
    * RunInStableState at the next stable state.
    */
   bool mPostedRunInStableState;
   /**
    * True when processing real-time audio/video.  False when processing non-realtime
    * audio.
    */
   bool mRealtime;
+  /**
+   * True when a non-realtime MediaStreamGraph has started to process input.  This
+   * value is only accessed on the main thread.
+   */
+  bool mNonRealtimeProcessing;
 };
 
 }
 
 #endif /* MEDIASTREAMGRAPHIMPL_H_ */
--- a/content/media/webaudio/AudioBufferSourceNode.cpp
+++ b/content/media/webaudio/AudioBufferSourceNode.cpp
@@ -548,25 +548,26 @@ AudioBufferSourceNode::SendOffsetAndDura
   // Don't set parameter unnecessarily
   if (offsetTicks > 0) {
     aStream->SetInt32Parameter(OFFSET, offsetTicks);
   }
   aStream->SetInt32Parameter(DURATION, NS_lround(endOffset*rate) - offsetTicks);
 }
 
 void
-AudioBufferSourceNode::Stop(double aWhen, ErrorResult& aRv)
+AudioBufferSourceNode::Stop(double aWhen, ErrorResult& aRv, bool aShuttingDown)
 {
   if (!mStartCalled) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
-  if (!mBuffer) {
+  if (!mBuffer || aShuttingDown) {
     // We don't have a buffer, so the stream is never marked as finished.
+    // This can also happen if the AudioContext is being shut down.
     // Therefore we need to drop our playing ref right now.
     mPlayingRef.Drop(this);
   }
 
   AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get());
   if (!ns || !Context()) {
     // We've already stopped and had our stream shut down
     return;
--- a/content/media/webaudio/AudioBufferSourceNode.h
+++ b/content/media/webaudio/AudioBufferSourceNode.h
@@ -51,17 +51,17 @@ public:
   }
   void NoteGrainOn(double aWhen, double aOffset,
                    double aDuration, ErrorResult& aRv)
   {
     Optional<double> duration;
     duration.Construct(aDuration);
     Start(aWhen, aOffset, duration, aRv);
   }
-  void Stop(double aWhen, ErrorResult& aRv);
+  void Stop(double aWhen, ErrorResult& aRv, bool aShuttingDown = false);
   void NoteOff(double aWhen, ErrorResult& aRv)
   {
     Stop(aWhen, aRv);
   }
 
   AudioBuffer* GetBuffer(JSContext* aCx) const
   {
     return mBuffer;
--- a/content/media/webaudio/AudioContext.cpp
+++ b/content/media/webaudio/AudioContext.cpp
@@ -3,16 +3,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 "AudioContext.h"
 #include "nsContentUtils.h"
 #include "nsPIDOMWindow.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/dom/AudioContextBinding.h"
+#include "mozilla/dom/OfflineAudioContextBinding.h"
 #include "MediaStreamGraph.h"
 #include "mozilla/dom/AnalyserNode.h"
 #include "AudioDestinationNode.h"
 #include "AudioBufferSourceNode.h"
 #include "AudioBuffer.h"
 #include "GainNode.h"
 #include "DelayNode.h"
 #include "PannerNode.h"
@@ -39,18 +41,25 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED_2(Aud
 
 NS_IMPL_ADDREF_INHERITED(AudioContext, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(AudioContext, nsDOMEventTargetHelper)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioContext)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 static uint8_t gWebAudioOutputKey;
 
-AudioContext::AudioContext(nsPIDOMWindow* aWindow)
-  : mDestination(new AudioDestinationNode(this, MediaStreamGraph::GetInstance()))
+AudioContext::AudioContext(nsPIDOMWindow* aWindow,
+                           bool aIsOffline,
+                           uint32_t aNumberOfChannels,
+                           uint32_t aLength,
+                           float aSampleRate)
+  : mDestination(new AudioDestinationNode(this, aIsOffline,
+                                          aNumberOfChannels,
+                                          aLength, aSampleRate))
+  , mIsOffline(aIsOffline)
 {
   // Actually play audio
   mDestination->Stream()->AddAudioOutput(&gWebAudioOutputKey);
   nsDOMEventTargetHelper::BindToOwner(aWindow);
   SetIsDOMBinding();
 
   mPannerNodes.Init();
   mAudioBufferSourceNodes.Init();
@@ -59,29 +68,61 @@ AudioContext::AudioContext(nsPIDOMWindow
 
 AudioContext::~AudioContext()
 {
 }
 
 JSObject*
 AudioContext::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
-  return AudioContextBinding::Wrap(aCx, aScope, this);
+  if (mIsOffline) {
+    return OfflineAudioContextBinding::Wrap(aCx, aScope, this);
+  } else {
+    return AudioContextBinding::Wrap(aCx, aScope, this);
+  }
 }
 
 /* static */ already_AddRefed<AudioContext>
 AudioContext::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
   if (!window) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
-  nsRefPtr<AudioContext> object = new AudioContext(window);
+  nsRefPtr<AudioContext> object = new AudioContext(window, false);
+  window->AddAudioContext(object);
+  return object.forget();
+}
+
+/* static */ already_AddRefed<AudioContext>
+AudioContext::Constructor(const GlobalObject& aGlobal,
+                          uint32_t aNumberOfChannels,
+                          uint32_t aLength,
+                          float aSampleRate,
+                          ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
+  if (!window) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  if (aSampleRate != IdealAudioRate()) {
+    // TODO: Add support for running OfflineAudioContext at other sampling rates
+    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    return nullptr;
+  }
+
+  nsRefPtr<AudioContext> object = new AudioContext(window,
+                                                   true,
+                                                   aNumberOfChannels,
+                                                   aLength,
+                                                   aSampleRate);
   window->AddAudioContext(object);
   return object.forget();
 }
 
 already_AddRefed<AudioBufferSourceNode>
 AudioContext::CreateBufferSource()
 {
   nsRefPtr<AudioBufferSourceNode> bufferNode =
@@ -383,25 +424,30 @@ AudioContext::Shutdown()
   // We first gather an array of the nodes and then call Stop on each one,
   // since Stop may delete the object and therefore trigger a re-entrant
   // hashtable call to remove the pointer from the hashtable, which is
   // not safe.
   nsTArray<AudioBufferSourceNode*> sourceNodes;
   GetHashtableElements(mAudioBufferSourceNodes, sourceNodes);
   for (uint32_t i = 0; i < sourceNodes.Length(); ++i) {
     ErrorResult rv;
-    sourceNodes[i]->Stop(0.0, rv);
+    sourceNodes[i]->Stop(0.0, rv, true);
   }
   // Stop all script processor nodes, to make sure that they release
   // their self-references.
   nsTArray<ScriptProcessorNode*> spNodes;
   GetHashtableElements(mScriptProcessorNodes, spNodes);
   for (uint32_t i = 0; i < spNodes.Length(); ++i) {
     spNodes[i]->Stop();
   }
+
+  // For offline contexts, we can destroy the MediaStreamGraph at this point.
+  if (mIsOffline) {
+    mDestination->DestroyGraph();
+  }
 }
 
 void
 AudioContext::Suspend()
 {
   MediaStream* ds = DestinationStream();
   if (ds) {
     ds->ChangeExplicitBlockerCount(1);
@@ -429,10 +475,18 @@ AudioContext::GetJSContext() const
   }
   nsIScriptContext* scriptContext = scriptGlobal->GetContext();
   if (!scriptContext) {
     return nullptr;
   }
   return scriptContext->GetNativeContext();
 }
 
+void
+AudioContext::StartRendering()
+{
+  MOZ_ASSERT(mIsOffline, "This should only be called on OfflineAudioContext");
+
+  mDestination->StartRendering();
+}
+
 }
 }
--- a/content/media/webaudio/AudioContext.h
+++ b/content/media/webaudio/AudioContext.h
@@ -45,24 +45,29 @@ class AudioDestinationNode;
 class AudioListener;
 class BiquadFilterNode;
 class ChannelMergerNode;
 class ChannelSplitterNode;
 class DelayNode;
 class DynamicsCompressorNode;
 class GainNode;
 class GlobalObject;
+class OfflineRenderSuccessCallback;
 class PannerNode;
 class ScriptProcessorNode;
 class WaveShaperNode;
 
 class AudioContext MOZ_FINAL : public nsDOMEventTargetHelper,
                                public EnableWebAudioCheck
 {
-  explicit AudioContext(nsPIDOMWindow* aParentWindow);
+  AudioContext(nsPIDOMWindow* aParentWindow,
+               bool aIsOffline,
+               uint32_t aNumberOfChannels = 0,
+               uint32_t aLength = 0,
+               float aSampleRate = 0.0f);
   ~AudioContext();
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioContext,
                                            nsDOMEventTargetHelper)
 
   nsPIDOMWindow* GetParentObject() const
@@ -72,19 +77,32 @@ public:
 
   void Shutdown();
   void Suspend();
   void Resume();
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
+  using nsDOMEventTargetHelper::DispatchTrustedEvent;
+
+  // Constructor for regular AudioContext
   static already_AddRefed<AudioContext>
   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
 
+  // Constructor for offline AudioContext
+  static already_AddRefed<AudioContext>
+  Constructor(const GlobalObject& aGlobal,
+              uint32_t aNumberOfChannels,
+              uint32_t aLength,
+              float aSampleRate,
+              ErrorResult& aRv);
+
+  // AudioContext methods
+
   AudioDestinationNode* Destination() const
   {
     return mDestination;
   }
 
   float SampleRate() const
   {
     return float(IdealAudioRate());
@@ -159,17 +177,22 @@ public:
 
   already_AddRefed<BiquadFilterNode>
   CreateBiquadFilter();
 
   void DecodeAudioData(const ArrayBuffer& aBuffer,
                        DecodeSuccessCallback& aSuccessCallback,
                        const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback);
 
+  // OfflineAudioContext methods
+  void StartRendering();
+  IMPL_EVENT_HANDLER(complete)
+
   uint32_t GetRate() const { return IdealAudioRate(); }
+  bool IsOffline() const { return mIsOffline; }
 
   MediaStreamGraph* Graph() const;
   MediaStream* DestinationStream() const;
   void UnregisterAudioBufferSourceNode(AudioBufferSourceNode* aNode);
   void UnregisterPannerNode(PannerNode* aNode);
   void UnregisterScriptProcessorNode(ScriptProcessorNode* aNode);
   void UpdatePannerSource();
 
@@ -188,15 +211,16 @@ private:
   // Two hashsets containing all the PannerNodes and AudioBufferSourceNodes,
   // to compute the doppler shift, and also to stop AudioBufferSourceNodes.
   // These are all weak pointers.
   nsTHashtable<nsPtrHashKey<PannerNode> > mPannerNodes;
   nsTHashtable<nsPtrHashKey<AudioBufferSourceNode> > mAudioBufferSourceNodes;
   // Hashset containing all ScriptProcessorNodes in order to stop them.
   // These are all weak pointers.
   nsTHashtable<nsPtrHashKey<ScriptProcessorNode> > mScriptProcessorNodes;
+  bool mIsOffline;
 };
 
 }
 }
 
 #endif
 
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -4,32 +4,215 @@
  * 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 "AudioDestinationNode.h"
 #include "mozilla/dom/AudioDestinationNodeBinding.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include "MediaStreamGraph.h"
+#include "OfflineAudioCompletionEvent.h"
 
 namespace mozilla {
 namespace dom {
 
+class OfflineDestinationNodeEngine : public AudioNodeEngine
+{
+public:
+  typedef AutoFallibleTArray<nsAutoArrayPtr<float>, 2> InputChannels;
+
+  OfflineDestinationNodeEngine(AudioDestinationNode* aNode,
+                               uint32_t aNumberOfChannels,
+                               uint32_t aLength,
+                               float aSampleRate)
+    : AudioNodeEngine(aNode)
+    , mWriteIndex(0)
+    , mLength(aLength)
+    , mSampleRate(aSampleRate)
+  {
+    // These allocations might fail if content provides a huge number of
+    // channels or size, but it's OK since we'll deal with the failure
+    // gracefully.
+    if (mInputChannels.SetLength(aNumberOfChannels)) {
+      static const fallible_t fallible = fallible_t();
+      for (uint32_t i = 0; i < aNumberOfChannels; ++i) {
+        mInputChannels[i] = new(fallible) float[aLength];
+        if (!mInputChannels[i]) {
+          mInputChannels.Clear();
+          break;
+        }
+      }
+    }
+  }
+
+  virtual void ProduceAudioBlock(AudioNodeStream* aStream,
+                                 const AudioChunk& aInput,
+                                 AudioChunk* aOutput,
+                                 bool* aFinished) MOZ_OVERRIDE
+  {
+    // Do this just for the sake of political correctness; this output
+    // will not go anywhere.
+    *aOutput = aInput;
+
+    // Handle the case of allocation failure in the input buffer
+    if (mInputChannels.IsEmpty()) {
+      return;
+    }
+
+    // Record our input buffer
+    MOZ_ASSERT(mWriteIndex < mLength, "How did this happen?");
+    const uint32_t duration = std::min(WEBAUDIO_BLOCK_SIZE, mLength - mWriteIndex);
+    for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
+      if (aInput.IsNull()) {
+        PodZero(mInputChannels[i] + mWriteIndex, duration);
+      } else {
+        const float* inputBuffer = static_cast<const float*>(aInput.mChannelData[i]);
+        if (duration == WEBAUDIO_BLOCK_SIZE) {
+          // Use the optimized version of the copy with scale operation
+          AudioBlockCopyChannelWithScale(inputBuffer, aInput.mVolume,
+                                         mInputChannels[i] + mWriteIndex);
+        } else {
+          if (aInput.mVolume == 1.0f) {
+            PodCopy(mInputChannels[i] + mWriteIndex, inputBuffer, duration);
+          } else {
+            for (uint32_t j = 0; j < duration; ++j) {
+              mInputChannels[i][mWriteIndex + j] = aInput.mVolume * inputBuffer[j];
+            }
+          }
+        }
+      }
+    }
+    mWriteIndex += duration;
+
+    if (mWriteIndex == mLength) {
+      SendBufferToMainThread(aStream);
+      *aFinished = true;
+    }
+  }
+
+  void SendBufferToMainThread(AudioNodeStream* aStream)
+  {
+    class Command : public nsRunnable
+    {
+    public:
+      Command(AudioNodeStream* aStream,
+              InputChannels& aInputChannels,
+              uint32_t aLength,
+              float aSampleRate)
+        : mStream(aStream)
+        , mLength(aLength)
+        , mSampleRate(aSampleRate)
+      {
+        mInputChannels.SwapElements(aInputChannels);
+      }
+
+      NS_IMETHODIMP Run()
+      {
+        // If it's not safe to run scripts right now, schedule this to run later
+        if (!nsContentUtils::IsSafeToRunScript()) {
+          nsContentUtils::AddScriptRunner(this);
+          return NS_OK;
+        }
+
+        nsRefPtr<AudioContext> context;
+        {
+          MutexAutoLock lock(mStream->Engine()->NodeMutex());
+          AudioNode* node = mStream->Engine()->Node();
+          if (node) {
+            context = node->Context();
+          }
+        }
+        if (!context) {
+          return NS_OK;
+        }
+
+        AutoPushJSContext cx(context->GetJSContext());
+        if (cx) {
+          JSAutoRequest ar(cx);
+
+          // Create the input buffer
+          nsRefPtr<AudioBuffer> renderedBuffer = new AudioBuffer(context,
+                                                                 mLength,
+                                                                 mSampleRate);
+          if (!renderedBuffer->InitializeBuffers(mInputChannels.Length(), cx)) {
+            return NS_OK;
+          }
+          for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
+            renderedBuffer->SetRawChannelContents(cx, i, mInputChannels[i]);
+          }
+
+          nsRefPtr<OfflineAudioCompletionEvent> event =
+              new OfflineAudioCompletionEvent(context, nullptr, nullptr);
+          event->InitEvent(renderedBuffer);
+          context->DispatchTrustedEvent(event);
+        }
+
+        return NS_OK;
+      }
+    private:
+      nsRefPtr<AudioNodeStream> mStream;
+      InputChannels mInputChannels;
+      uint32_t mLength;
+      float mSampleRate;
+    };
+
+    // Empty out the source array to make sure we don't attempt to collect
+    // more input data in the future.
+    NS_DispatchToMainThread(new Command(aStream, mInputChannels, mLength, mSampleRate));
+  }
+
+private:
+  // The input to the destination node is recorded in the mInputChannels buffer.
+  // When this buffer fills up with mLength frames, the buffered input is sent
+  // to the main thread in order to dispatch OfflineAudioCompletionEvent.
+  InputChannels mInputChannels;
+  // An index representing the next offset in mInputChannels to be written to.
+  uint32_t mWriteIndex;
+  // How many frames the OfflineAudioContext intends to produce.
+  uint32_t mLength;
+  float mSampleRate;
+};
+
 NS_IMPL_ISUPPORTS_INHERITED0(AudioDestinationNode, AudioNode)
 
-AudioDestinationNode::AudioDestinationNode(AudioContext* aContext, MediaStreamGraph* aGraph)
+AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
+                                           bool aIsOffline,
+                                           uint32_t aNumberOfChannels,
+                                           uint32_t aLength,
+                                           float aSampleRate)
   : AudioNode(aContext,
-              2,
+              aIsOffline ? aNumberOfChannels : 2,
               ChannelCountMode::Explicit,
               ChannelInterpretation::Speakers)
+  , mFramesToProduce(aLength)
 {
-  mStream = aGraph->CreateAudioNodeStream(new AudioNodeEngine(this),
-                                          MediaStreamGraph::EXTERNAL_STREAM);
+  MediaStreamGraph* graph = aIsOffline ?
+                            MediaStreamGraph::CreateNonRealtimeInstance() :
+                            MediaStreamGraph::GetInstance();
+  AudioNodeEngine* engine = aIsOffline ?
+                            new OfflineDestinationNodeEngine(this, aNumberOfChannels,
+                                                             aLength, aSampleRate) :
+                            new AudioNodeEngine(this);
+  mStream = graph->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM);
+}
+
+void
+AudioDestinationNode::DestroyGraph()
+{
+  MOZ_ASSERT(Context() && Context()->IsOffline(),
+             "Should only be called on a valid OfflineAudioContext");
+  MediaStreamGraph::DestroyNonRealtimeInstance(mStream->Graph());
 }
 
 JSObject*
 AudioDestinationNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return AudioDestinationNodeBinding::Wrap(aCx, aScope, this);
 }
 
+void
+AudioDestinationNode::StartRendering()
+{
+  mStream->Graph()->StartNonRealtimeProcessing(mFramesToProduce);
+}
+
 }
 }
--- a/content/media/webaudio/AudioDestinationNode.h
+++ b/content/media/webaudio/AudioDestinationNode.h
@@ -12,27 +12,39 @@
 namespace mozilla {
 namespace dom {
 
 class AudioContext;
 
 class AudioDestinationNode : public AudioNode
 {
 public:
-  AudioDestinationNode(AudioContext* aContext, MediaStreamGraph* aGraph);
+  // This node type knows what MediaStreamGraph to use based on
+  // whether it's in offline mode.
+  AudioDestinationNode(AudioContext* aContext,
+                       bool aIsOffline,
+                       uint32_t aNumberOfChannels = 0,
+                       uint32_t aLength = 0,
+                       float aSampleRate = 0.0f);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   virtual uint16_t NumberOfOutputs() const MOZ_FINAL MOZ_OVERRIDE
   {
     return 0;
   }
 
+  void StartRendering();
+
+  void DestroyGraph();
+
+private:
+  uint32_t mFramesToProduce;
 };
 
 }
 }
 
 #endif
 
--- a/content/media/webaudio/Makefile.in
+++ b/content/media/webaudio/Makefile.in
@@ -28,16 +28,17 @@ CPPSRCS := \
   BiquadFilterNode.cpp \
   ChannelMergerNode.cpp \
   ChannelSplitterNode.cpp \
   DelayNode.cpp \
   DynamicsCompressorNode.cpp \
   EnableWebAudioCheck.cpp \
   GainNode.cpp \
   MediaBufferDecoder.cpp \
+  OfflineAudioCompletionEvent.cpp \
   PannerNode.cpp \
   ScriptProcessorNode.cpp \
   ThreeDPoint.cpp \
   WaveShaperNode.cpp \
   WebAudioUtils.cpp \
   $(NULL)
 
 FORCE_STATIC_LIB := 1
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/OfflineAudioCompletionEvent.cpp
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "OfflineAudioCompletionEvent.h"
+#include "mozilla/dom/OfflineAudioCompletionEventBinding.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(OfflineAudioCompletionEvent, nsDOMEvent,
+                                     mRenderedBuffer)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(OfflineAudioCompletionEvent)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
+
+NS_IMPL_ADDREF_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent)
+NS_IMPL_RELEASE_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent)
+
+OfflineAudioCompletionEvent::OfflineAudioCompletionEvent(AudioContext* aOwner,
+                                                         nsPresContext* aPresContext,
+                                                         nsEvent* aEvent)
+  : nsDOMEvent(aOwner, aPresContext, aEvent)
+{
+  SetIsDOMBinding();
+}
+
+JSObject*
+OfflineAudioCompletionEvent::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return OfflineAudioCompletionEventBinding::Wrap(aCx, aScope, this);
+}
+
+}
+}
+
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/OfflineAudioCompletionEvent.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef OfflineAudioCompletionEvent_h_
+#define OfflineAudioCompletionEvent_h_
+
+#include "nsDOMEvent.h"
+#include "AudioBuffer.h"
+#include "AudioContext.h"
+
+namespace mozilla {
+namespace dom {
+
+class OfflineAudioCompletionEvent : public nsDOMEvent,
+                                    public EnableWebAudioCheck
+{
+public:
+  OfflineAudioCompletionEvent(AudioContext* aOwner,
+                              nsPresContext *aPresContext,
+                              nsEvent *aEvent);
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_FORWARD_TO_NSDOMEVENT
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent)
+
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  void InitEvent(AudioBuffer* aRenderedBuffer)
+  {
+    InitEvent(NS_LITERAL_STRING("complete"), false, false);
+    mRenderedBuffer = aRenderedBuffer;
+  }
+
+  AudioBuffer* RenderedBuffer() const
+  {
+    return mRenderedBuffer;
+  }
+
+private:
+  nsRefPtr<AudioBuffer> mRenderedBuffer;
+};
+
+}
+}
+
+#endif
+
--- a/content/media/webaudio/moz.build
+++ b/content/media/webaudio/moz.build
@@ -29,13 +29,14 @@ EXPORTS.mozilla.dom += [
     'AudioProcessingEvent.h',
     'BiquadFilterNode.h',
     'ChannelMergerNode.h',
     'ChannelSplitterNode.h',
     'DelayNode.h',
     'DynamicsCompressorNode.h',
     'EnableWebAudioCheck.h',
     'GainNode.h',
+    'OfflineAudioCompletionEvent.h',
     'PannerNode.h',
     'ScriptProcessorNode.h',
     'WaveShaperNode.h',
 ]
 
--- a/content/media/webaudio/test/Makefile.in
+++ b/content/media/webaudio/test/Makefile.in
@@ -53,16 +53,17 @@ MOCHITEST_FILES := \
   test_delayNodeWithGain.html \
   test_delayNodeWithGainAlternate.html \
   test_dynamicsCompressorNode.html \
   test_gainNode.html \
   test_gainNodeInLoop.html \
   test_mediaDecoding.html \
   test_mixingRules.html \
   test_nodeToParamConnection.html \
+  test_OfflineAudioContext.html \
   test_pannerNode.html \
   test_scriptProcessorNode.html \
   test_scriptProcessorNodeChannelCount.html \
   test_singleSourceDest.html \
   test_waveShaper.html \
   test_waveShaperNoCurve.html \
   test_waveShaperZeroLengthCurve.html \
   ting.ogg \
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_OfflineAudioContext.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test OfflineAudioContext</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="webaudio.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+  SpecialPowers.setBoolPref("media.webaudio.enabled", true);
+  var ctx = new OfflineAudioContext(2, 100, (new AudioContext()).sampleRate);
+  ok(ctx instanceof EventTarget, "OfflineAudioContexts must be EventTargets");
+
+  var buf = ctx.createBuffer(2, 100, ctx.sampleRate);
+  for (var i = 0; i < 2; ++i) {
+    for (var j = 0; j < 100; ++j) {
+      buf.getChannelData(i)[j] = Math.sin(2 * Math.PI * 200 * j / ctx.sampleRate);
+    }
+  }
+
+  var src = ctx.createBufferSource();
+  src.buffer = buf;
+  src.start(0);
+  src.connect(ctx.destination);
+  ctx.startRendering();
+  ctx.addEventListener("complete", function(e) {
+    ok(e instanceof OfflineAudioCompletionEvent, "Correct event received");
+    is(e.renderedBuffer.numberOfChannels, 2, "Correct expected number of buffers");
+    compareBuffers(e.renderedBuffer.getChannelData(0), buf.getChannelData(0));
+    compareBuffers(e.renderedBuffer.getChannelData(1), buf.getChannelData(1));
+
+    SpecialPowers.clearUserPref("media.webaudio.enabled");
+    SimpleTest.finish();
+  }, false);
+});
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/media/webaudio/test/webaudio.js
+++ b/content/media/webaudio/test/webaudio.js
@@ -26,18 +26,21 @@ function expectTypeError(func) {
 function fuzzyCompare(a, b) {
   return Math.abs(a - b) < 9e-3;
 }
 
 function compareBuffers(buf1, buf2,
                         /*optional*/ offset,
                         /*optional*/ length,
                         /*optional*/ sourceOffset,
-                        /*optional*/ destOffset) {
-  is(buf1.length, buf2.length, "Buffers must have the same length");
+                        /*optional*/ destOffset,
+                        /*optional*/ skipLengthCheck) {
+  if (!skipLengthCheck) {
+    is(buf1.length, buf2.length, "Buffers must have the same length");
+  }
   if (length == undefined) {
     length = buf1.length - (offset || 0);
   }
   sourceOffset = sourceOffset || 0;
   destOffset = destOffset || 0;
   var difference = 0;
   var maxDifference = 0;
   var firstBadIndex = -1;
@@ -95,53 +98,94 @@ function runTest()
   SimpleTest.waitForExplicitFinish();
   addLoadEvent(function() {
     SpecialPowers.setBoolPref("media.webaudio.enabled", true);
 
     if (!gTest.numberOfChannels) {
       gTest.numberOfChannels = 2; // default
     }
 
-    var context = new AudioContext();
-    if (!gTest.createExpectedBuffers) {
-      // Assume that the output is silence
-      var expectedBuffers = getEmptyBuffer(context, gTest.length);
-    } else {
-      var expectedBuffers = gTest.createExpectedBuffers(context);
-    }
-    if (!(expectedBuffers instanceof Array)) {
-      expectedBuffers = [expectedBuffers];
-    }
-    var expectedFrames = 0;
-    for (var i = 0; i < expectedBuffers.length; ++i) {
-      is(expectedBuffers[i].numberOfChannels, gTest.numberOfChannels,
-         "Correct number of channels for expected buffer " + i);
-      expectedFrames += expectedBuffers[i].length;
-    }
-    is(expectedFrames, gTest.length, "Correct number of expected frames");
+    var testLength;
 
-    if (gTest.createGraphAsync) {
-      gTest.createGraphAsync(context, function(nodeToInspect) {
-        testOutput(nodeToInspect);
-      });
-    } else {
-      testOutput(gTest.createGraph(context));
+    function runTestOnContext(context, callback, testOutput) {
+      if (!gTest.createExpectedBuffers) {
+        // Assume that the output is silence
+        var expectedBuffers = getEmptyBuffer(context, gTest.length);
+      } else {
+        var expectedBuffers = gTest.createExpectedBuffers(context);
+      }
+      if (!(expectedBuffers instanceof Array)) {
+        expectedBuffers = [expectedBuffers];
+      }
+      var expectedFrames = 0;
+      for (var i = 0; i < expectedBuffers.length; ++i) {
+        is(expectedBuffers[i].numberOfChannels, gTest.numberOfChannels,
+           "Correct number of channels for expected buffer " + i);
+        expectedFrames += expectedBuffers[i].length;
+      }
+      is(expectedFrames, gTest.length, "Correct number of expected frames");
+
+      if (gTest.createGraphAsync) {
+        gTest.createGraphAsync(context, function(nodeToInspect) {
+          testOutput(nodeToInspect, expectedBuffers, callback);
+        });
+      } else {
+        testOutput(gTest.createGraph(context), expectedBuffers, callback);
+      }
     }
 
-    function testOutput(nodeToInspect) {
-      var sp = context.createScriptProcessor(expectedBuffers[0].length, gTest.numberOfChannels);
-      nodeToInspect.connect(sp);
-      sp.connect(context.destination);
-      sp.onaudioprocess = function(e) {
-        var expectedBuffer = expectedBuffers.shift();
-        is(e.inputBuffer.numberOfChannels, expectedBuffer.numberOfChannels,
-           "Correct number of input buffer channels");
-        for (var i = 0; i < e.inputBuffer.numberOfChannels; ++i) {
-          compareBuffers(e.inputBuffer.getChannelData(i), expectedBuffer.getChannelData(i));
-        }
-        if (expectedBuffers.length == 0) {
-          sp.onaudioprocess = null;
-          done();
-        }
-      };
+    function testOnNormalContext(callback) {
+      function testOutput(nodeToInspect, expectedBuffers, callback) {
+        testLength = 0;
+        var sp = context.createScriptProcessor(expectedBuffers[0].length, gTest.numberOfChannels);
+        nodeToInspect.connect(sp);
+        sp.connect(context.destination);
+        sp.onaudioprocess = function(e) {
+          var expectedBuffer = expectedBuffers.shift();
+          testLength += expectedBuffer.length;
+          is(e.inputBuffer.numberOfChannels, expectedBuffer.numberOfChannels,
+             "Correct number of input buffer channels");
+          for (var i = 0; i < e.inputBuffer.numberOfChannels; ++i) {
+            compareBuffers(e.inputBuffer.getChannelData(i), expectedBuffer.getChannelData(i));
+          }
+          if (expectedBuffers.length == 0) {
+            sp.onaudioprocess = null;
+            callback();
+          }
+        };
+      }
+      var context = new AudioContext();
+      runTestOnContext(context, callback, testOutput);
     }
+
+    function testOnOfflineContext(callback) {
+      function testOutput(nodeToInspect, expectedBuffers, callback) {
+        nodeToInspect.connect(context.destination);
+        context.oncomplete = function(e) {
+          var samplesSeen = 0;
+          while (expectedBuffers.length) {
+            var expectedBuffer = expectedBuffers.shift();
+            is(e.renderedBuffer.numberOfChannels, expectedBuffer.numberOfChannels,
+               "Correct number of input buffer channels");
+            for (var i = 0; i < e.renderedBuffer.numberOfChannels; ++i) {
+              compareBuffers(e.renderedBuffer.getChannelData(i),
+                             expectedBuffer.getChannelData(i),
+                             undefined,
+                             expectedBuffer.length,
+                             samplesSeen,
+                             undefined,
+                             true);
+            }
+            samplesSeen += expectedBuffer.length;
+          }
+          callback();
+        };
+        context.startRendering();
+      }
+      var context = new OfflineAudioContext(gTest.numberOfChannels, testLength, 48000);
+      runTestOnContext(context, callback, testOutput);
+    }
+
+    testOnNormalContext(function() {
+      testOnOfflineContext(done);
+    });
   });
 }
--- a/content/smil/nsSMILCSSValueType.cpp
+++ b/content/smil/nsSMILCSSValueType.cpp
@@ -10,16 +10,17 @@
 #include "nsStyleAnimation.h"
 #include "nsSMILParserUtils.h"
 #include "nsSMILValue.h"
 #include "nsCSSValue.h"
 #include "nsColor.h"
 #include "nsPresContext.h"
 #include "mozilla/dom/Element.h"
 #include "nsDebug.h"
+#include "nsStyleUtil.h"
 
 using namespace mozilla::dom;
 
 /*static*/ nsSMILCSSValueType nsSMILCSSValueType::sSingleton;
 
 struct ValueWrapper {
   ValueWrapper(nsCSSProperty aPropID, const nsStyleAnimation::Value& aValue) :
     mPropID(aPropID), mCSSValue(aValue) {}
@@ -386,16 +387,23 @@ nsSMILCSSValueType::ValueFromString(nsCS
 {
   NS_ABORT_IF_FALSE(aValue.IsNull(), "Outparam should be null-typed");
   nsPresContext* presContext = GetPresContextForElement(aTargetElement);
   if (!presContext) {
     NS_WARNING("Not parsing animation value; unable to get PresContext");
     return;
   }
 
+  nsIDocument* doc = aTargetElement->GetCurrentDoc();
+  if (doc && !nsStyleUtil::CSPAllowsInlineStyle(doc->NodePrincipal(),
+                                                doc->GetDocumentURI(),
+                                                0, aString, nullptr)) {
+    return;
+  }
+
   nsStyleAnimation::Value parsedValue;
   if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
                             aString, parsedValue, aIsContextSensitive)) {
     sSingleton.Init(aValue);
     aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue);
   }
 }
 
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2300,16 +2300,19 @@ nsXULPrototypeElement::SetAttrAt(uint32_
     else if (mAttributes[aPos].mName.Equals(nsGkAtoms::style)) {
         mHasStyleAttribute = true;
         // Parse the element's 'style' attribute
         nsRefPtr<css::StyleRule> rule;
 
         nsCSSParser parser;
 
         // XXX Get correct Base URI (need GetBaseURI on *prototype* element)
+        // TODO: If we implement Content Security Policy for chrome documents
+        // as has been discussed, the CSP should be checked here to see if
+        // inline styles are allowed to be applied.
         parser.ParseStyleAttribute(aValue, aDocumentURI, aDocumentURI,
                                    // This is basically duplicating what
                                    // nsINode::NodePrincipal() does
                                    mNodeInfo->NodeInfoManager()->
                                      DocumentPrincipal(),
                                    getter_AddRefs(rule));
         if (rule) {
             mAttributes[aPos].mValue.SetTo(rule, &aValue);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -331,17 +331,16 @@ using mozilla::dom::workers::ResolveWork
 #include "mozilla/Likely.h"
 
 #ifdef MOZ_TIME_MANAGER
 #include "TimeManager.h"
 #endif
 
 #ifdef MOZ_WEBRTC
 #include "nsIDOMDataChannel.h"
-#include "nsIDOMRTCPeerConnection.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
@@ -910,18 +909,16 @@ static nsDOMClassInfoData sClassInfoData
 #ifdef MOZ_TIME_MANAGER
   NS_DEFINE_CLASSINFO_DATA(MozTimeManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
 #ifdef MOZ_WEBRTC
   NS_DEFINE_CLASSINFO_DATA(DataChannel, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(RTCPeerConnection, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 };
 
 #define NS_DEFINE_CONTRACT_CTOR(_class, _contract_id)                           \
   static nsresult                                                               \
   _class##Ctor(nsISupports** aInstancePtrResult)                                \
   {                                                                             \
     nsresult rv = NS_OK;                                                        \
@@ -2298,20 +2295,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_END
 #endif
 
 #ifdef MOZ_WEBRTC
   DOM_CLASSINFO_MAP_BEGIN(DataChannel, nsIDOMDataChannel)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataChannel)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(RTCPeerConnection, nsIDOMRTCPeerConnection)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMRTCPeerConnection)
-  DOM_CLASSINFO_MAP_END
 #endif
 
   MOZ_STATIC_ASSERT(MOZ_ARRAY_LENGTH(sClassInfoData) == eDOMClassInfoIDCount,
                     "The number of items in sClassInfoData doesn't match the "
                     "number of nsIDOMClassInfo ID's, this is bad! Fix it!");
 
 #ifdef DEBUG
   for (size_t i = 0; i < eDOMClassInfoIDCount; i++) {
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -237,10 +237,9 @@ DOMCI_CLASS(LockedFile)
 DOMCI_CLASS(CSSFontFeatureValuesRule)
 
 #ifdef MOZ_TIME_MANAGER
 DOMCI_CLASS(MozTimeManager)
 #endif
 
 #ifdef MOZ_WEBRTC
 DOMCI_CLASS(DataChannel)
-DOMCI_CLASS(RTCPeerConnection)
 #endif
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1215,18 +1215,22 @@ nsDOMWindowUtils::SendSimpleGestureEvent
   else if (aType.EqualsLiteral("MozRotateGestureUpdate"))
     msg = NS_SIMPLE_GESTURE_ROTATE_UPDATE;
   else if (aType.EqualsLiteral("MozRotateGesture"))
     msg = NS_SIMPLE_GESTURE_ROTATE;
   else if (aType.EqualsLiteral("MozTapGesture"))
     msg = NS_SIMPLE_GESTURE_TAP;
   else if (aType.EqualsLiteral("MozPressTapGesture"))
     msg = NS_SIMPLE_GESTURE_PRESSTAP;
-  else if (aType.EqualsLiteral("MozEdgeUIGesture"))
-    msg = NS_SIMPLE_GESTURE_EDGEUI;
+  else if (aType.EqualsLiteral("MozEdgeUIStarted"))
+    msg = NS_SIMPLE_GESTURE_EDGE_STARTED;
+  else if (aType.EqualsLiteral("MozEdgeUICanceled"))
+    msg = NS_SIMPLE_GESTURE_EDGE_CANCELED;
+  else if (aType.EqualsLiteral("MozEdgeUICompleted"))
+    msg = NS_SIMPLE_GESTURE_EDGE_COMPLETED;
   else
     return NS_ERROR_FAILURE;
  
   nsSimpleGestureEvent event(true, msg, widget, aDirection, aDelta);
   event.modifiers = GetWidgetModifiers(aModifiers);
   event.clickCount = aClickCount;
   event.time = PR_IntervalNow();
 
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -670,16 +670,27 @@ DOMInterfaces = {
 'NotifyPaintEvent': {
     'nativeType': 'nsDOMNotifyPaintEvent',
 },
 
 'NotifyAudioAvailableEvent': {
     'nativeType': 'nsDOMNotifyAudioAvailableEvent',
 },
 
+'OfflineAudioCompletionEvent': {
+    'resultNotAddRefed': [ 'renderedBuffer' ],
+},
+
+'OfflineAudioContext': {
+    'nativeType': 'mozilla::dom::AudioContext',
+    'implicitJSContext': [ 'createBuffer' ],
+    'nativeOwnership': 'refcounted',
+    'resultNotAddRefed': [ 'destination', 'listener' ],
+},
+
 'PaintRequest': {
     'nativeType': 'nsPaintRequest',
 },
 
 'PaintRequestList': {
     'nativeType': 'nsPaintRequestList',
     'headerFile': 'nsPaintRequest.h',
     'resultNotAddRefed': [ 'item' ]
@@ -1537,16 +1548,17 @@ addExternalIface('ActivityOptions', nati
                  headerFile='nsIDOMActivityOptions.h')
 addExternalIface('Counter')
 addExternalIface('CSSRule')
 addExternalIface('DeviceAcceleration', headerFile='nsIDOMDeviceMotionEvent.h', notflattened=True)
 addExternalIface('DeviceRotationRate', headerFile='nsIDOMDeviceMotionEvent.h', notflattened=True)
 addExternalIface('DOMError')
 addExternalIface('CSSRuleList')
 addExternalIface('DOMStringList')
+addExternalIface('RTCDataChannel', nativeType='nsIDOMDataChannel')
 addExternalIface('File')
 addExternalIface('FileCallback', nativeType='nsIFileCallback',
                  headerFile='nsIDOMHTMLCanvasElement.h')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('IDBOpenDBRequest', nativeType='nsIIDBOpenDBRequest')
 addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
 addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
 addExternalIface('LockedFile')
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -8306,17 +8306,18 @@ class CGNativeMember(ClassMethod):
                                    pre=("%s%s<" % (warning, holder)),
                                    post=">")
             else:
                 result = CGWrapper(result, post="*")
             if iface.isExternal():
                 # The holder is an nsRefPtr.  If we're nullable and end up null,
                 # the holder will be null anyway, so it's safe to just always
                 # return it here.
-                returnCode = "return ${holderName}.forget();"
+                returnCode = ("(void)${declName}; // avoid warning. May end up not being read\n"
+                              "return ${holderName}.forget();")
             elif iface.isCallback():
                 # The decl is an OwningNonNull or nsRefPtr, depending
                 # on whether we're nullable.
                 returnCode = "return ${declName}.forget();"
             elif type.nullable():
                 # Decl is a raw pointer
                 returnCode = ("NS_IF_ADDREF(${declName});\n"
                               "return dont_AddRef(${declName});")
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -315,17 +315,18 @@ class IDLUnresolvedIdentifier(IDLObject)
 
         assert len(name) > 0
 
         if name[:2] == "__" and not allowDoubleUnderscore:
             raise WebIDLError("Identifiers beginning with __ are reserved",
                               [location])
         if name[0] == '_' and not allowDoubleUnderscore:
             name = name[1:]
-        if name in ["constructor", "iterator", "toString", "toJSON"] and not allowForbidden:
+        # TODO: Bug 872377, Restore "toJSON" to below list.
+        if name in ["constructor", "iterator", "toString"] and not allowForbidden:
             raise WebIDLError("Cannot use reserved identifier '%s'" % (name),
                               [location])
 
         self.name = name
 
     def __str__(self):
         return self.QName()
 
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -13,21 +13,21 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
 if CONFIG['MOZ_B2G_BT']:
     MODULE = 'dom'
     XPIDL_MODULE = 'dom_bluetooth'
     XPIDL_SOURCES += [
-        'nsIDOMNavigatorBluetooth.idl',
-        'nsIDOMBluetoothManager.idl',
         'nsIDOMBluetoothAdapter.idl',
         'nsIDOMBluetoothDevice.idl',
-        'nsIDOMBluetoothDeviceEvent.idl'
+        'nsIDOMBluetoothDeviceEvent.idl',
+        'nsIDOMBluetoothManager.idl',
+        'nsIDOMNavigatorBluetooth.idl',
     ]
 
 EXPORTS.mozilla.dom.bluetooth.ipc += [
     'BluetoothMessageUtils.h',
 ]
 
 EXPORTS.mozilla.dom.bluetooth += [
     'BluetoothCommon.h',
--- a/dom/interfaces/events/moz.build
+++ b/dom/interfaces/events/moz.build
@@ -42,18 +42,18 @@ XPIDL_SOURCES += [
     'nsIDOMPaintRequestList.idl',
     'nsIDOMPopStateEvent.idl',
     'nsIDOMPopupBlockedEvent.idl',
     'nsIDOMProgressEvent.idl',
     'nsIDOMScrollAreaEvent.idl',
     'nsIDOMSimpleGestureEvent.idl',
     'nsIDOMSmartCardEvent.idl',
     'nsIDOMStyleRuleChangeEvent.idl',
+    'nsIDOMStyleSheetApplicableStateChangeEvent.idl',
     'nsIDOMStyleSheetChangeEvent.idl',
-    'nsIDOMStyleSheetApplicableStateChangeEvent.idl',
     'nsIDOMTouchEvent.idl',
     'nsIDOMTransitionEvent.idl',
     'nsIDOMUIEvent.idl',
     'nsIDOMUserProximityEvent.idl',
     'nsIDOMWheelEvent.idl',
 ]
 
 XPIDL_MODULE = 'dom_events'
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -8,62 +8,58 @@ const {classes: Cc, interfaces: Ci, util
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const PC_CONTRACT = "@mozilla.org/dom/peerconnection;1";
 const PC_ICE_CONTRACT = "@mozilla.org/dom/rtcicecandidate;1";
 const PC_SESSION_CONTRACT = "@mozilla.org/dom/rtcsessiondescription;1";
 const PC_MANAGER_CONTRACT = "@mozilla.org/dom/peerconnectionmanager;1";
+const PC_ICEEVENT_CONTRACT = "@mozilla.org/dom/rtcpeerconnectioniceevent;1";
+const MSEVENT_CONTRACT = "@mozilla.org/dom/mediastreamevent;1";
+const DCEVENT_CONTRACT = "@mozilla.org/dom/datachannelevent;1";
 
-const PC_CID = Components.ID("{7cb2b368-b1ce-4560-acac-8e0dbda7d3d0}");
-const PC_ICE_CID = Components.ID("{8c5dbd70-2c8e-4ecb-a5ad-2fc919099f01}");
-const PC_SESSION_CID = Components.ID("{5f21ffd9-b73f-4ba0-a685-56b4667aaf1c}");
+const PC_CID = Components.ID("{9878b414-afaa-4176-a887-1e02b3b047c2}");
+const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
+const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
 const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
+const PC_ICEEVENT_CID = Components.ID("{b9cd25a7-9859-4f9e-8f84-ef5181ff36c0}");
+const MSEVENT_CID = Components.ID("{a722a8a9-2290-4e99-a5ed-07b504292d08}");
+const DCEVENT_CID = Components.ID("{d5ed7fbf-01a8-4b18-af6c-861cf2aac920}");
 
 // Global list of PeerConnection objects, so they can be cleaned up when
 // a page is torn down. (Maps inner window ID to an array of PC objects).
 function GlobalPCList() {
   this._list = [];
   this._networkdown = false; // XXX Need to query current state somehow
   Services.obs.addObserver(this, "inner-window-destroyed", true);
   Services.obs.addObserver(this, "profile-change-net-teardown", true);
   Services.obs.addObserver(this, "network:offline-about-to-go-offline", true);
   Services.obs.addObserver(this, "network:offline-status-changed", true);
 }
 GlobalPCList.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference,
                                          Ci.IPeerConnectionManager]),
-
   classID: PC_MANAGER_CID,
-  classInfo: XPCOMUtils.generateCI({classID: PC_MANAGER_CID,
-                                    contractID: PC_MANAGER_CONTRACT,
-                                    classDescription: "PeerConnectionManager",
-                                    interfaces: [
-                                      Ci.nsIObserver,
-                                      Ci.nsISupportsWeakReference,
-                                      Ci.IPeerConnectionManager
-                                    ]}),
-
   _xpcom_factory: {
     createInstance: function(outer, iid) {
       if (outer) {
         throw Cr.NS_ERROR_NO_AGGREGATION;
       }
       return _globalPCList.QueryInterface(iid);
     }
   },
 
   addPC: function(pc) {
     let winID = pc._winID;
     if (this._list[winID]) {
-      this._list[winID].push(Components.utils.getWeakReference(pc));
+      this._list[winID].push(Cu.getWeakReference(pc));
     } else {
-      this._list[winID] = [Components.utils.getWeakReference(pc)];
+      this._list[winID] = [Cu.getWeakReference(pc)];
     }
     this.removeNullRefs(winID);
   },
 
   removeNullRefs: function(winID) {
     if (this._list === undefined || this._list[winID] === undefined) {
       return;
     }
@@ -118,92 +114,126 @@ GlobalPCList.prototype = {
       } else if (data == "online") {
         this._networkdown = false;
       }
     }
   },
 };
 let _globalPCList = new GlobalPCList();
 
-function IceCandidate(candidate) {
-  this.candidate = candidate;
-  this.sdpMid = null;
-  this.sdpMLineIndex = null;
+function RTCIceCandidate() {
+  this.candidate = this.sdpMid = this.sdpMLineIndex = null;
 }
-IceCandidate.prototype = {
+RTCIceCandidate.prototype = {
+  classDescription: "mozRTCIceCandidate",
   classID: PC_ICE_CID,
+  contractID: PC_ICE_CONTRACT,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer]),
 
-  classInfo: XPCOMUtils.generateCI({classID: PC_ICE_CID,
-                                    contractID: PC_ICE_CONTRACT,
-                                    classDescription: "IceCandidate",
-                                    interfaces: [
-                                      Ci.nsIDOMRTCIceCandidate
-                                    ],
-                                    flags: Ci.nsIClassInfo.DOM_OBJECT}),
+  init: function(win) { this._win = win; },
+
+  __init: function(dict) {
+    this.candidate = dict.candidate;
+    this.sdpMid = dict.sdpMid;
+    this.sdpMLineIndex = ("sdpMLineIndex" in dict)? dict.sdpMLineIndex+1 : null;
+  }
+};
 
-  QueryInterface: XPCOMUtils.generateQI([
-    Ci.nsIDOMRTCIceCandidate, Ci.nsIDOMGlobalObjectConstructor
-  ]),
+function RTCSessionDescription() {
+  this.type = this.sdp = null;
+}
+RTCSessionDescription.prototype = {
+  classDescription: "mozRTCSessionDescription",
+  classID: PC_SESSION_CID,
+  contractID: PC_SESSION_CONTRACT,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer]),
 
-  constructor: function(win, candidateInitDict) {
-    if (this._win) {
-      throw new Components.Exception("Constructor already called");
-    }
-    this._win = win;
-    if (candidateInitDict !== undefined) {
-      this.candidate = candidateInitDict.candidate || null;
-      this.sdpMid = candidateInitDict.sdpMid || null;
-      this.sdpMLineIndex = candidateInitDict.sdpMLineIndex === null ?
-            null : candidateInitDict.sdpMLineIndex + 1;
-    } else {
-      this.candidate = this.sdpMid = this.sdpMLineIndex = null;
-    }
+  init: function(win) { this._win = win; },
+
+  __init: function(dict) {
+    this.type = dict.type;
+    this.sdp  = dict.sdp;
+  },
+
+  // Bug 863402 serializer support workaround
+  toJSON: function() {
+    return { type: this.type, sdp: this.sdp,
+             __exposedProps__: { type: "rw", sdp: "rw" } };
   }
 };
 
-function SessionDescription(type, sdp) {
-  this.type = type;
-  this.sdp = sdp;
+function MediaStreamEvent() {
+  this.type = this._stream = null;
 }
-SessionDescription.prototype = {
-  classID: PC_SESSION_CID,
-
-  classInfo: XPCOMUtils.generateCI({classID: PC_SESSION_CID,
-                                    contractID: PC_SESSION_CONTRACT,
-                                    classDescription: "SessionDescription",
-                                    interfaces: [
-                                      Ci.nsIDOMRTCSessionDescription
-                                    ],
-                                    flags: Ci.nsIClassInfo.DOM_OBJECT}),
+MediaStreamEvent.prototype = {
+  classDescription: "MediaStreamEvent",
+  classID: MSEVENT_CID,
+  contractID: MSEVENT_CONTRACT,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer]),
 
-  QueryInterface: XPCOMUtils.generateQI([
-    Ci.nsIDOMRTCSessionDescription, Ci.nsIDOMGlobalObjectConstructor
-  ]),
+  init: function(win) { this._win = win; },
 
-  constructor: function(win, descriptionInitDict) {
-    if (this._win) {
-      throw new Components.Exception("Constructor already called");
-    }
-    this._win = win;
-    if (descriptionInitDict !== undefined) {
-      this.type = descriptionInitDict.type || null;
-      this.sdp = descriptionInitDict.sdp || null;
-    } else {
-      this.type = this.sdp = null;
-    }
+  __init: function(type, dict) {
+    this.type = type;
+    this.__DOM_IMPL__.initEvent(type, dict.bubbles || false,
+                                dict.cancelable || false);
+    this._stream = dict.stream;
   },
 
-  toString: function() {
-    return JSON.stringify({
-      type: this.type, sdp: this.sdp
-    });
-  }
+  get stream() { return this._stream; }
 };
 
-function PeerConnection() {
+function RTCDataChannelEvent() {
+  this.type = this._channel = null;
+}
+RTCDataChannelEvent.prototype = {
+  classDescription: "RTCDataChannelEvent",
+  classID: DCEVENT_CID,
+  contractID: DCEVENT_CONTRACT,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer]),
+
+  init: function(win) { this._win = win; },
+
+  __init: function(type, dict) {
+    this.type = type;
+    this.__DOM_IMPL__.initEvent(type, dict.bubbles || false,
+                                dict.cancelable || false);
+    this._channel = dict.channel;
+  },
+
+  get channel() { return this._channel; }
+};
+
+function RTCPeerConnectionIceEvent() {
+  this.type = this._candidate = null;
+}
+RTCPeerConnectionIceEvent.prototype = {
+  classDescription: "RTCPeerConnectionIceEvent",
+  classID: PC_ICEEVENT_CID,
+  contractID: PC_ICEEVENT_CONTRACT,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer]),
+
+  init: function(win) { this._win = win; },
+
+  __init: function(type, dict) {
+    this.type = type;
+    this.__DOM_IMPL__.initEvent(type, dict.bubbles || false,
+                                dict.cancelable || false);
+    this._candidate = dict.candidate;
+  },
+
+  get candidate() { return this._candidate; }
+};
+
+function RTCPeerConnection() {
   this._queue = [];
 
   this._pc = null;
   this._observer = null;
   this._closed = false;
 
   this._onCreateOfferSuccess = null;
   this._onCreateOfferFailure = null;
@@ -219,82 +249,75 @@ function PeerConnection() {
    * there are no pending operations though, we will execute it immediately.
    * In PeerConnectionObserver, whenever we are notified that an operation
    * has finished, we will check the queue for the next operation and execute
    * if neccesary. The _pending flag indicates whether an operation is currently
    * in progress.
    */
   this._pending = false;
 
-  // Public attributes.
-  this.onaddstream = null;
-  this.onopen = null;
-  this.onremovestream = null;
-  this.onicecandidate = null;
-  this.onstatechange = null;
-  this.ongatheringchange = null;
-  this.onicechange = null;
-
-  // Data channel.
-  this.ondatachannel = null;
-  this.onconnection = null;
-  this.onclosedconnection = null;
-}
-PeerConnection.prototype = {
-  classID: PC_CID,
+  // States
+  this._iceGatheringState = this._iceConnectionState = "new";
 
-  classInfo: Cu.getDOMClassInfo("RTCPeerConnection"),
-
-  QueryInterface: XPCOMUtils.generateQI([
-    Ci.nsIDOMRTCPeerConnection,
-    Ci.nsIDOMGlobalObjectConstructor,
-    Ci.nsISupportsWeakReference
-  ]),
+  // Deprecated callbacks
+  this._ongatheringchange = null;
+  this._onicechange = null;
+}
+RTCPeerConnection.prototype = {
+  classDescription: "mozRTCPeerConnection",
+  classID: PC_CID,
+  contractID: PC_CONTRACT,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer,
+                                         Ci.nsISupportsWeakReference]),
+  init: function(win) { this._win = win; },
 
-  // Constructor is an explicit function, because of nsIDOMGlobalObjectConstructor.
-  constructor: function(win, rtcConfig) {
-    if (!Services.prefs.getBoolPref("media.peerconnection.enabled")) {
-      throw new Components.Exception("PeerConnection not enabled (did you set the pref?)");
-    }
-    if (this._win) {
-      throw new Components.Exception("RTCPeerConnection constructor already called");
-    }
-    if (!rtcConfig ||
+  __init: function(rtcConfig) {
+    if (!rtcConfig.iceServers ||
         !Services.prefs.getBoolPref("media.peerconnection.use_document_iceservers")) {
       rtcConfig = {iceServers:
         JSON.parse(Services.prefs.getCharPref("media.peerconnection.default_iceservers"))};
     }
     this._mustValidateRTCConfiguration(rtcConfig,
         "RTCPeerConnection constructor passed invalid RTCConfiguration");
     if (_globalPCList._networkdown) {
       throw new Components.Exception("Can't create RTCPeerConnections when the network is down");
     }
 
+    this.makeGetterSetterEH("onaddstream");
+    this.makeGetterSetterEH("onicecandidate");
+    this.makeGetterSetterEH("onnegotiationneeded");
+    this.makeGetterSetterEH("onsignalingstatechange");
+    this.makeGetterSetterEH("onremovestream");
+    this.makeGetterSetterEH("ondatachannel");
+    this.makeGetterSetterEH("onconnection");
+    this.makeGetterSetterEH("onclosedconnection");
+    this.makeGetterSetterEH("oniceconnectionstatechange");
+
     this._pc = Cc["@mozilla.org/peerconnection;1"].
              createInstance(Ci.IPeerConnection);
     this._observer = new PeerConnectionObserver(this);
 
     // Nothing starts until ICE gathering completes.
     this._queueOrRun({
       func: this._getPC().initialize,
-      args: [this._observer, win, rtcConfig, Services.tm.currentThread],
+      args: [this._observer, this._win, rtcConfig, Services.tm.currentThread],
       wait: true
     });
 
-    this._win = win;
     this._winID = this._win.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
 
     // Add a reference to the PeerConnection to global list.
     _globalPCList.addPC(this);
   },
 
   _getPC: function() {
     if (!this._pc) {
-      throw new Components.Exception("PeerConnection is gone (did you turn on Offline mode?)");
+      throw new Components.Exception("RTCPeerConnection is gone (did you enter Offline mode?)");
     }
     return this._pc;
   },
 
   /**
    * Add a function to the queue or run it immediately if the queue is empty.
    * Argument is an object with the func, args and wait properties; wait should
    * be set to true if the function has a success/error callback that will
@@ -330,59 +353,46 @@ PeerConnection.prototype = {
       this._pending = false;
     }
   },
 
   /**
    * An RTCConfiguration looks like this:
    *
    * { "iceServers": [ { url:"stun:23.21.150.121" },
-   *                   { url:"turn:user@turn.example.org", credential:"mypass"} ] }
+   *                   { url:"turn:turn.example.org",
+   *                     username:"jib", credential:"mypass"} ] }
    *
-   * We check for basic structure and well-formed stun/turn urls, but not
-   * validity of servers themselves, before passing along to C++.
+   * WebIDL normalizes structure for us, so we test well-formed stun/turn urls,
+   * but not validity of servers themselves, before passing along to C++.
    * ErrorMsg is passed in to detail which array-entry failed, if any.
    */
   _mustValidateRTCConfiguration: function(rtcConfig, errorMsg) {
-    function isObject(obj) {
-      return obj && (typeof obj === "object");
-    }
-    function isArraylike(obj) {
-      return isObject(obj) && ("length" in obj);
-    }
     function nicerNewURI(uriStr, errorMsg) {
       let ios = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
       try {
         return ios.newURI(uriStr, null, null);
       } catch (e if (e.result == Cr.NS_ERROR_MALFORMED_URI)) {
         throw new Components.Exception(errorMsg + " - malformed URI: " + uriStr,
                                        Cr.NS_ERROR_MALFORMED_URI);
       }
     }
     function mustValidateServer(server) {
       let url = nicerNewURI(server.url, errorMsg);
       if (!(url.scheme in { stun:1, stuns:1, turn:1, turns:1 })) {
         throw new Components.Exception(errorMsg + " - improper scheme: " + url.scheme,
                                        Cr.NS_ERROR_MALFORMED_URI);
       }
-      if (server.credential && isObject(server.credential)) {
-        throw new Components.Exception(errorMsg + " - invalid credential");
+    }
+    if (rtcConfig.iceServers) {
+      let len = rtcConfig.iceServers.length;
+      for (let i=0; i < len; i++) {
+        mustValidateServer (rtcConfig.iceServers[i], errorMsg);
       }
     }
-    if (!isObject(rtcConfig)) {
-      throw new Components.Exception(errorMsg);
-    }
-    if (!isArraylike(rtcConfig.iceServers)) {
-      throw new Components.Exception(errorMsg +
-                                     " - iceServers [] property not present");
-    }
-    let len = rtcConfig.iceServers.length;
-    for (let i=0; i < len; i++) {
-      mustValidateServer (rtcConfig.iceServers[i], errorMsg);
-    }
   },
 
   /**
    * Constraints look like this:
    *
    * {
    *   mandatory: {"OfferToReceiveAudio": true, "OfferToReceiveVideo": true },
    *   optional: [{"VoiceActivityDetection": true}, {"FooBar": 10}]
@@ -461,33 +471,112 @@ PeerConnection.prototype = {
   // the valid peer connection states defined in the WebRTC
   // spec. See Bug 831756.
   _checkClosed: function() {
     if (this._closed) {
       throw new Components.Exception("Peer connection is closed");
     }
   },
 
+  dispatchEvent: function(event) {
+    this.__DOM_IMPL__.dispatchEvent(event);
+  },
+
+  // Log error message to web console and window.onerror, if present.
+  reportError: function(msg, file, line) {
+    this.reportMsg(msg, file, line, Ci.nsIScriptError.exceptionFlag);
+  },
+
+  reportWarning: function(msg, file, line) {
+    this.reportMsg(msg, file, line, Ci.nsIScriptError.warningFlag);
+  },
+
+  reportMsg: function(msg, file, line, flag) {
+    let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
+    let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
+    scriptError.initWithWindowID(msg, file, null, line, 0, flag,
+                                 "content javascript", this._winID);
+    let console = Cc["@mozilla.org/consoleservice;1"].
+      getService(Ci.nsIConsoleService);
+    console.logMessage(scriptError);
+
+    if (flag != Ci.nsIScriptError.warningFlag) {
+      // Safely call onerror directly if present (necessary for testing)
+      try {
+        if (typeof this._win.onerror === "function") {
+          this._win.onerror(msg, file, line);
+        }
+      } catch(e) {
+        // If onerror itself throws, service it.
+        try {
+          let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
+          scriptError.initWithWindowID(e.message, e.fileName, null, e.lineNumber,
+                                       0, Ci.nsIScriptError.exceptionFlag,
+                                       "content javascript",
+                                       this._winID);
+          console.logMessage(scriptError);
+        } catch(e) {}
+      }
+    }
+  },
+
+  getEH: function(type) {
+    return this.__DOM_IMPL__.getEventHandler(type);
+  },
+
+  setEH: function(type, handler) {
+    this.__DOM_IMPL__.setEventHandler(type, handler);
+  },
+
+  makeGetterSetterEH: function(name) {
+    Object.defineProperty(this, name,
+                          {
+                            get:function()  { return this.getEH(name); },
+                            set:function(h) { return this.setEH(name, h); }
+                          });
+  },
+
+  get onicechange()       { return this._onicechange; },
+  get ongatheringchange() { return this._ongatheringchange; },
+
+  set onicechange(cb) {
+    this.deprecated("onicechange");
+    this._onicechange = cb;
+  },
+  set ongatheringchange(cb) {
+    this.deprecated("ongatheringchange");
+    this._ongatheringchange = cb;
+  },
+
+  deprecated: function(name) {
+    this.reportWarning(name + " is deprecated!", null, 0);
+  },
+
   createOffer: function(onSuccess, onError, constraints) {
     if (!constraints) {
       constraints = {};
     }
-
+    if (!onError) {
+      this.deprecated("calling createOffer without failureCallback");
+    }
     this._mustValidateConstraints(constraints, "createOffer passed invalid constraints");
     this._onCreateOfferSuccess = onSuccess;
     this._onCreateOfferFailure = onError;
 
     this._queueOrRun({
       func: this._getPC().createOffer,
       args: [constraints],
       wait: true
     });
   },
 
   _createAnswer: function(onSuccess, onError, constraints, provisional) {
+    if (!onError) {
+      this.deprecated("calling createAnswer without failureCallback");
+    }
     this._onCreateAnswerSuccess = onSuccess;
     this._onCreateAnswerFailure = onError;
 
     if (!this.remoteDescription) {
 
       this._observer.onCreateAnswerError(Ci.IPeerConnection.kInvalidState,
                                          "setRemoteDescription not called");
       return;
@@ -533,20 +622,22 @@ PeerConnection.prototype = {
     let type;
     switch (desc.type) {
       case "offer":
         type = Ci.IPeerConnection.kActionOffer;
         break;
       case "answer":
         type = Ci.IPeerConnection.kActionAnswer;
         break;
+      case "pranswer":
+        throw new Components.Exception("pranswer not yet implemented",
+                                       Cr.NS_ERROR_NOT_IMPLEMENTED);
       default:
         throw new Components.Exception("Invalid type " + desc.type +
                                        " provided to setLocalDescription");
-        break;
     }
 
     this._queueOrRun({
       func: this._getPC().setLocalDescription,
       args: [type, desc.sdp],
       wait: true,
       type: desc.type
     });
@@ -562,111 +653,139 @@ PeerConnection.prototype = {
     let type;
     switch (desc.type) {
       case "offer":
         type = Ci.IPeerConnection.kActionOffer;
         break;
       case "answer":
         type = Ci.IPeerConnection.kActionAnswer;
         break;
+      case "pranswer":
+        throw new Components.Exception("pranswer not yet implemented",
+                                       Cr.NS_ERROR_NOT_IMPLEMENTED);
       default:
         throw new Components.Exception("Invalid type " + desc.type +
                                        " provided to setRemoteDescription");
-        break;
     }
 
     this._queueOrRun({
       func: this._getPC().setRemoteDescription,
       args: [type, desc.sdp],
       wait: true,
       type: desc.type
     });
   },
 
-  updateIce: function(config, constraints, restart) {
-    return Cr.NS_ERROR_NOT_IMPLEMENTED;
+  updateIce: function(config, constraints) {
+    throw new Components.Exception("updateIce not yet implemented",
+                                   Cr.NS_ERROR_NOT_IMPLEMENTED);
   },
 
   addIceCandidate: function(cand, onSuccess, onError) {
-    if (!cand) {
-      throw new Components.Exception("NULL candidate passed to addIceCandidate!");
-    }
-
-    if (!cand.candidate || !cand.sdpMLineIndex) {
+    if (!cand.candidate && !cand.sdpMLineIndex) {
       throw new Components.Exception("Invalid candidate passed to addIceCandidate!");
     }
-
-    this._onAddIceCandidateSuccess = onSuccess;
-    this._onAddIceCandidateError = onError;
+    this._onAddIceCandidateSuccess = onSuccess || null;
+    this._onAddIceCandidateError = onError || null;
 
     this._queueOrRun({
       func: this._getPC().addIceCandidate,
       args: [cand.candidate, cand.sdpMid || "", cand.sdpMLineIndex],
       wait: true
     });
   },
 
   addStream: function(stream, constraints) {
+    if (stream.currentTime === undefined) {
+      throw new Components.Exception("Invalid stream passed to addStream!");
+    }
     // TODO: Implement constraints.
     this._queueOrRun({
       func: this._getPC().addStream,
       args: [stream],
       wait: false
     });
   },
 
   removeStream: function(stream) {
-     //Bug844295: Not implemeting this functionality.
-     return Cr.NS_ERROR_NOT_IMPLEMENTED;
+     //Bug 844295: Not implementing this functionality.
+     throw new Components.Exception("removeStream not yet implemented",
+                                    Cr.NS_ERROR_NOT_IMPLEMENTED);
+  },
+
+  getStreamById: function(id) {
+    throw new Components.Exception("getStreamById not yet implemented",
+                                   Cr.NS_ERROR_NOT_IMPLEMENTED);
   },
 
   close: function() {
     this._queueOrRun({
       func: this._getPC().close,
       args: [false],
       wait: false
     });
     this._closed = true;
+    this.changeIceConnectionState("closed");
   },
 
-  get localStreams() {
+  getLocalStreams: function() {
     this._checkClosed();
     return this._getPC().localStreams;
   },
 
-  get remoteStreams() {
+  getRemoteStreams: function() {
     this._checkClosed();
     return this._getPC().remoteStreams;
   },
 
+  // Backwards-compatible attributes
+  get localStreams() {
+    this.deprecated("localStreams");
+    return this.getLocalStreams();
+  },
+  get remoteStreams() {
+    this.deprecated("remoteStreams");
+    return this.getRemoteStreams();
+  },
+
   get localDescription() {
     this._checkClosed();
     let sdp = this._getPC().localDescription;
     if (sdp.length == 0) {
       return null;
     }
-    return {
-      type: this._localType, sdp: sdp,
-      __exposedProps__: { type: "rw", sdp: "rw" }
-    };
+    return new this._win.mozRTCSessionDescription({ type: this._localType,
+                                                    sdp: sdp });
   },
 
   get remoteDescription() {
     this._checkClosed();
     let sdp = this._getPC().remoteDescription;
     if (sdp.length == 0) {
       return null;
     }
-    return {
-      type: this._remoteType, sdp: sdp,
-      __exposedProps__: { type: "rw", sdp: "rw" }
-    };
+    return new this._win.mozRTCSessionDescription({ type: this._remoteType,
+                                                    sdp: sdp });
+  },
+
+  get signalingState()     { return "stable"; }, // not yet implemented
+  get iceGatheringState()  { return this._iceGatheringState; },
+  get iceConnectionState() { return this._iceConnectionState; },
+
+  changeIceGatheringState: function(state) {
+    this._iceGatheringState = state;
+  },
+
+  changeIceConnectionState: function(state) {
+    this._iceConnectionState = state;
+    this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
   },
 
   get readyState() {
+    this.deprecated("readyState");
     // checking for our local pc closed indication
     // before invoking the pc methods.
     if(this._closed) {
       return "closed";
     }
 
     var state="undefined";
     switch (this._getPC().readyState) {
@@ -687,17 +806,17 @@ PeerConnection.prototype = {
         break;
     }
     return state;
   },
 
   createDataChannel: function(label, dict) {
     this._checkClosed();
     if (dict == undefined) {
-	dict = {};
+      dict = {};
     }
     if (dict.maxRetransmitTime != undefined &&
         dict.maxRetransmitNum != undefined) {
       throw new Components.Exception("Both maxRetransmitTime and maxRetransmitNum cannot be provided");
     }
     let protocol;
     if (dict.protocol == undefined) {
       protocol = "";
@@ -760,107 +879,49 @@ RTCError.prototype = {
 // This is a separate object because we don't want to expose it to DOM.
 function PeerConnectionObserver(dompc) {
   this._dompc = dompc;
 }
 PeerConnectionObserver.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.IPeerConnectionObserver,
                                          Ci.nsISupportsWeakReference]),
 
+  dispatchEvent: function(event) {
+    this._dompc.dispatchEvent(event);
+  },
+
   callCB: function(callback, arg) {
     if (callback) {
       try {
-        callback.onCallback(arg);
+        callback(arg);
       } catch(e) {
         // A content script (user-provided) callback threw an error. We don't
         // want this to take down peerconnection, but we still want the user
         // to see it, so we catch it, report it, and move on.
-        //
-        // We do stack parsing in two different places for different reasons:
-
-        var msg;
-        if (e.result == Cr.NS_ERROR_XPC_JS_THREW_JS_OBJECT) {
-          // TODO(jib@mozilla.com): Revisit once bug 862153 is fixed.
-          //
-          // The actual content script frame is unavailable due to bug 862153,
-          // so users see file and line # into this file, which is not helpful.
-          //
-          // 1) Fix up the error message itself to differentiate between the
-          //    22 places we call callCB() in this file, using plain JS stack.
-          //
-          // Tweak the existing NS_ERROR_XPC_JS_THREW_JS_OBJECT message:
-          // -'Error: x' when calling method: [RTCPeerConCallback::onCallback]
-          // +'Error: x' when calling method: [RTCPeerConCallback::onCreateOfferError]
-
-          let caller = Error().stack.split("\n")[1].split("@")[0];
-          // caller ~= "PeerConnectionObserver.prototype.onCreateOfferError"
-
-          msg = e.message.replace("::onCallback", "::" + caller.split(".")[2]);
-        } else {
-          msg = e.message;
-        }
-
-        // Log error message to web console and window.onerror, if present.
-        //
-        // 2) nsIScriptError doesn't understand the nsIStackFrame format, so
-        //    do the translation by extracting file and line from XPCOM stack:
-        //
-        // e.location ~= "JS frame :: file://.js :: RTCPCCb::onCallback :: line 1"
-
-        let stack = e.location.toString().split(" :: ");
-        let file = stack[1];
-        let line = parseInt(stack[3].split(" ")[1]);
-
-        let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
-        let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
-        scriptError.initWithWindowID(msg, file, null, line, 0,
-                                     Ci.nsIScriptError.exceptionFlag,
-                                     "content javascript",
-                                     this._dompc._winID);
-        let console = Cc["@mozilla.org/consoleservice;1"].
-            getService(Ci.nsIConsoleService);
-        console.logMessage(scriptError);
-
-        // Safely call onerror directly if present (necessary for testing)
-        try {
-          if (typeof this._dompc._win.onerror === "function") {
-            this._dompc._win.onerror(msg, file, line);
-          }
-        } catch(e) {
-          // If onerror itself throws, service it.
-          try {
-            let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
-            scriptError.initWithWindowID(e.message, e.fileName, null,
-                                         e.lineNumber, 0,
-                                         Ci.nsIScriptError.exceptionFlag,
-                                         "content javascript",
-                                         this._dompc._winID);
-            console.logMessage(scriptError);
-          } catch(e) {}
-        }
+        this._dompc.reportError(e.message, e.fileName, e.lineNumber);
       }
     }
   },
 
-  onCreateOfferSuccess: function(offer) {
+  onCreateOfferSuccess: function(sdp) {
     this.callCB(this._dompc._onCreateOfferSuccess,
-                { type: "offer", sdp: offer,
-                __exposedProps__: { type: "rw", sdp: "rw" } });
+                new this._dompc._win.mozRTCSessionDescription({ type: "offer",
+                                                                sdp: sdp }));
     this._dompc._executeNext();
   },
 
   onCreateOfferError: function(code, message) {
     this.callCB(this._dompc._onCreateOfferFailure, new RTCError(code, message));
     this._dompc._executeNext();
   },
 
-  onCreateAnswerSuccess: function(answer) {
+  onCreateAnswerSuccess: function(sdp) {
     this.callCB (this._dompc._onCreateAnswerSuccess,
-                 { type: "answer", sdp: answer,
-                 __exposedProps__: { type: "rw", sdp: "rw" } });
+                 new this._dompc._win.mozRTCSessionDescription({ type: "answer",
+                                                                 sdp: sdp }));
     this._dompc._executeNext();
   },
 
   onCreateAnswerError: function(code, message) {
     this.callCB(this._dompc._onCreateAnswerFailure, new RTCError(code, message));
     this._dompc._executeNext();
   },
 
@@ -914,66 +975,71 @@ PeerConnectionObserver.prototype = {
   },
 
   onStateChange: function(state) {
     if (state != Ci.IPeerConnectionObserver.kIceState) {
       return;
     }
 
     switch (this._dompc._pc.iceState) {
-      case Ci.IPeerConnection.kIceGathering:
-        this.callCB(this._dompc.ongatheringchange, "gathering");
-        break;
       case Ci.IPeerConnection.kIceWaiting:
-        this.callCB(this._dompc.onicechange, "starting");
+        this._dompc.changeIceConnectionState("completed");
+        this.callCB(this._dompc.ongatheringchange, "complete");
+        this.callCB(this._onicechange, "starting");
+        // Now that the PC is ready to go, execute any pending operations.
         this._dompc._executeNext();
         break;
       case Ci.IPeerConnection.kIceChecking:
-        this.callCB(this._dompc.onicechange, "checking");
+        this._dompc.changeIceConnectionState("checking");
+        this.callCB(this._onicechange, "checking");
+        break;
+      case Ci.IPeerConnection.kIceGathering:
+        this._dompc.changeIceGatheringState("gathering");
+        this.callCB(this._ongatheringchange, "gathering");
         break;
       case Ci.IPeerConnection.kIceConnected:
         // ICE gathering complete.
-        this.callCB(this._dompc.onicechange, "connected");
-        this.callCB(this._dompc.ongatheringchange, "complete");
+        this._dompc.changeIceConnectionState("connected");
+        this.callCB(this._onicechange, "connected");
         break;
       case Ci.IPeerConnection.kIceFailed:
-        this.callCB(this._dompc.onicechange, "failed");
+        this._dompc.changeIceConnectionState("failed");
+        this.callCB(this._onicechange, "failed");
         break;
       default:
         // Unknown state!
         break;
     }
   },
 
-  onAddStream: function(stream, type) {
-    this.callCB(this._dompc.onaddstream,
-                { stream: stream, type: type,
-                __exposedProps__: { stream: "r", type: "r" } });
+  onAddStream: function(stream) {
+    this.dispatchEvent(new this._dompc._win.MediaStreamEvent("addstream",
+                                                             { stream: stream }));
   },
 
   onRemoveStream: function(stream, type) {
-    this.callCB(this._dompc.onremovestream,
-                { stream: stream, type: type,
-                __exposedProps__: { stream: "r", type: "r" } });
+    this.dispatchEvent(new this._dompc._win.MediaStreamEvent("removestream",
+                                                             { stream: stream }));
   },
 
-  foundIceCandidate: function(cand) {
-    this.callCB(this._dompc.onicecandidate,
-                {candidate: cand, __exposedProps__: { candidate: "rw" } });
+  foundIceCandidate: function(c) {
+    this.dispatchEvent(new this._dompc._win.RTCPeerConnectionIceEvent("icecandidate",
+                                                                      { candidate: c }));
   },
 
   notifyDataChannel: function(channel) {
-    this.callCB(this._dompc.ondatachannel,
-                { channel: channel, __exposedProps__: { channel: "r" } });
+    this.dispatchEvent(new this._dompc._win.RTCDataChannelEvent("datachannel",
+                                                                { channel: channel }));
   },
 
   notifyConnection: function() {
-    this.callCB (this._dompc.onconnection);
+    this.dispatchEvent(new this._dompc._win.Event("connection"));
   },
 
   notifyClosedConnection: function() {
-    this.callCB (this._dompc.onclosedconnection);
+    this.dispatchEvent(new this._dompc._win.Event("closedconnection"));
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
-  [GlobalPCList, IceCandidate, SessionDescription, PeerConnection]
+  [GlobalPCList, RTCIceCandidate, RTCSessionDescription, RTCPeerConnection,
+   RTCPeerConnectionIceEvent, MediaStreamEvent, RTCDataChannelEvent]
 );
--- a/dom/media/PeerConnection.manifest
+++ b/dom/media/PeerConnection.manifest
@@ -1,13 +1,15 @@
-component {7cb2b368-b1ce-4560-acac-8e0dbda7d3d0} PeerConnection.js
-component {8c5dbd70-2c8e-4ecb-a5ad-2fc919099f01} PeerConnection.js
-component {5f21ffd9-b73f-4ba0-a685-56b4667aaf1c} PeerConnection.js
+component {9878b414-afaa-4176-a887-1e02b3b047c2} PeerConnection.js
+component {02b9970c-433d-4cc2-923d-f7028ac66073} PeerConnection.js
+component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
 component {7293e901-2be3-4c02-b4bd-cbef6fc24f78} PeerConnection.js
+component {b9cd25a7-9859-4f9e-8f84-ef5181ff36c0} PeerConnection.js
+component {a722a8a9-2290-4e99-a5ed-07b504292d08} PeerConnection.js
+component {d5ed7fbf-01a8-4b18-af6c-861cf2aac920} PeerConnection.js
 
-contract @mozilla.org/dom/peerconnection;1 {7cb2b368-b1ce-4560-acac-8e0dbda7d3d0}
-contract @mozilla.org/dom/rtcicecandidate;1 {8c5dbd70-2c8e-4ecb-a5ad-2fc919099f01}
-contract @mozilla.org/dom/rtcsessiondescription;1 {5f21ffd9-b73f-4ba0-a685-56b4667aaf1c}
+contract @mozilla.org/dom/peerconnection;1 {9878b414-afaa-4176-a887-1e02b3b047c2}
+contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac66073}
+contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067bbf508a7}
 contract @mozilla.org/dom/peerconnectionmanager;1 {7293e901-2be3-4c02-b4bd-cbef6fc24f78}
-
-category JavaScript-global-constructor mozRTCPeerConnection @mozilla.org/dom/peerconnection;1
-category JavaScript-global-constructor mozRTCIceCandidate @mozilla.org/dom/rtcicecandidate;1
-category JavaScript-global-constructor mozRTCSessionDescription @mozilla.org/dom/rtcsessiondescription;1
+contract @mozilla.org/dom/rtcpeerconnectioniceevent;1 {b9cd25a7-9859-4f9e-8f84-ef5181ff36c0}
+contract @mozilla.org/dom/mediastreamevent;1 {a722a8a9-2290-4e99-a5ed-07b504292d08}
+contract @mozilla.org/dom/datachannelevent;1 {d5ed7fbf-01a8-4b18-af6c-861cf2aac920}
--- a/dom/media/bridge/IPeerConnection.idl
+++ b/dom/media/bridge/IPeerConnection.idl
@@ -49,17 +49,17 @@ interface IPeerConnectionObserver : nsIS
   void notifyDataChannel(in nsIDOMDataChannel channel);
   void notifyConnection();
   void notifyClosedConnection();
 
   /* Notification of one of several types of state changed */
   void onStateChange(in unsigned long state);
 
   /* Changes to MediaStreams */
-  void onAddStream(in nsIDOMMediaStream stream, in string type);
+  void onAddStream(in nsIDOMMediaStream stream);
   void onRemoveStream();
   void onAddTrack();
   void onRemoveTrack();
 
   /* When SDP is parsed and a candidate line is found this method is called.
    * It should hook back into the media transport to notify it of ICE candidates
    * listed in the SDP PeerConnectionImpl does not parse ICE candidates, just
    * pulls them out of the SDP.
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -7,17 +7,16 @@
 if CONFIG['MOZ_WEBRTC']:
     DIRS += ['bridge']
 
 TEST_DIRS += ['tests/mochitest']
 
 XPIDL_SOURCES += [
     'nsIDOMMediaStream.idl',
     'nsIDOMNavigatorUserMedia.idl',
-    'nsIDOMRTCPeerConnection.idl',
     'nsIMediaManager.idl',
 ]
 
 XPIDL_MODULE = 'dom_media'
 
 MODULE = 'dom'
 
 EXPORTS.mozilla += [
deleted file mode 100644
--- a/dom/media/nsIDOMRTCPeerConnection.idl
+++ /dev/null
@@ -1,100 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsIDOMMediaStream.idl"
-
-interface nsIDOMDataChannel;
-
-[scriptable, function, uuid(eb9c563c-3b09-4565-9317-eca96ae0c538)]
-interface RTCPeerConnectionCallback : nsISupports
-{
-  void onCallback(in jsval value);
-};
-
-[scriptable, function, uuid(55546efd-287b-4460-8283-0592875b890f)]
-interface RTCPeerConnectionCallbackVoid : nsISupports
-{
-  void onCallback();
-};
-
-[scriptable, uuid(05d7375e-b024-4951-a570-c6642105ad35)]
-interface nsIDOMRTCSessionDescription : nsISupports
-{
-  attribute DOMString sdp;
-  attribute DOMString type;
-};
-
-[scriptable, uuid(df176474-e20a-4f42-a85b-b0414d634cf0)]
-interface nsIDOMRTCIceCandidate : nsISupports
-{
-  attribute DOMString candidate;
-  attribute DOMString sdpMid;
-  attribute unsigned short sdpMLineIndex;
-};
-
-/* See http://dev.w3.org/2011/webrtc/editor/webrtc.html */
-[scriptable, uuid(474074ab-11f9-4933-a200-8ea1a5f84e4c)]
-interface nsIDOMRTCPeerConnection : nsISupports
-{
-  void createOffer(in RTCPeerConnectionCallback successCallback,
-    [optional] in RTCPeerConnectionCallback failureCallback,
-    [optional] in jsval constraints);
-
-  void createAnswer(in RTCPeerConnectionCallback successCallback,
-    [optional] in RTCPeerConnectionCallback failureCallback,
-    [optional] in jsval constraints,
-    [optional] in bool createProvisionalAnswer);
-
-  void setLocalDescription(in nsIDOMRTCSessionDescription desc,
-    [optional] in RTCPeerConnectionCallbackVoid successCallback,
-    [optional] in RTCPeerConnectionCallback failureCallback);
-
-  void setRemoteDescription(in nsIDOMRTCSessionDescription desc,
-    [optional] in RTCPeerConnectionCallbackVoid successCallback,
-    [optional] in RTCPeerConnectionCallback failureCallback);
-
-  void updateIce([optional] in jsval configuration,
-    [optional] in jsval constraints,
-    [optional] in bool restart);
-
-  void addIceCandidate(in nsIDOMRTCIceCandidate candidate,
-    [optional] in RTCPeerConnectionCallbackVoid successCallback,
-    [optional] in RTCPeerConnectionCallback failureCallback);
-
-  void addStream(in nsIDOMMediaStream stream,
-    [optional] in jsval constraints);
-
-  void removeStream(in nsIDOMMediaStream stream);
-  void close();
-
-  /* Readonly attributes */
-  readonly attribute DOMString iceState;
-  readonly attribute DOMString iceGatheringState;
-
-  readonly attribute DOMString readyState;
-  readonly attribute jsval localDescription;
-  readonly attribute jsval remoteDescription;
-
-  readonly attribute jsval localStreams; // MediaStream[]
-  readonly attribute jsval remoteStreams; // MediaStream[]
-
-  /* Event handlers. TODO: Use real EventTarget */
-  attribute RTCPeerConnectionCallback onaddstream;
-  attribute RTCPeerConnectionCallback onopen;
-  attribute RTCPeerConnectionCallback onremovestream;
-  attribute RTCPeerConnectionCallback onicecandidate;
-  attribute RTCPeerConnectionCallback onstatechange;
-  attribute RTCPeerConnectionCallback ongatheringchange;
-  attribute RTCPeerConnectionCallback onicechange;
-
-  /* Data channels */
-  nsIDOMDataChannel createDataChannel([optional] in ACString label,
-    [optional] in jsval options);
-  void connectDataConnection(in unsigned short localport,
-    in unsigned short remoteport, [optional] in unsigned short numstreams);
-  attribute RTCPeerConnectionCallback ondatachannel;
-  attribute RTCPeerConnectionCallbackVoid onconnection;
-  attribute RTCPeerConnectionCallbackVoid onclosedconnection;
-};
deleted file mode 100644
--- a/dom/media/tests/crashtests/837421.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=837421
--->
-<head>
-  <meta charset="utf-8">
-  <title>Bug 837421</title>
-  <script type="application/javascript">
-    function finish() {
-      document.documentElement.removeAttribute("class");
-    }
-
-    function start() {
-        var o0 = mozRTCPeerConnection();
-        var o1 = new mozRTCIceCandidate({"candidate":"127 15 UDP 1 stun.sipgate.net 134117531 type 2001:db8:85a3:0:0:8a2e:370:3478 rport","sdpMid":"application 3566220586 RTP/AVP 5000","sdpMLineIndex":-32767});
-        o0.connectDataConnection(3478,-1);
-        o0.connectDataConnection(-1,3478,2);
-        var o2 = mozRTCPeerConnection();
-        try {o2.addIceCandidate(o1);} catch(e) {} // bug 842075 - remove try when fixed
-        o2.connectDataConnection(-1,3478,0.5);
-        o2.connectDataConnection(3478,-1,0.5);
-        var o3 = new mozRTCIceCandidate({"candidate":"31 2097151 IP 33554431 ::ffff:192.0.2.128 3999799469 type numb.viagenie.ca host","sdpMid":"application 1261077875 RTP/AVP 5000","sdpMLineIndex":16777215});
-        o2.connectDataConnection(1,3478);
-        o2.connectDataConnection(3478,1);
-        try {o2.updateIce()} catch(e) {}
-        try {o2.addIceCandidate(o3);} catch(e) {} // bug 842075 - remove try when fixed
-        finish();
-    }
-  </script>
-</head>
-
-<body onload="setTimeout(start, 100)">
-</html>
--- a/dom/media/tests/crashtests/crashtests.list
+++ b/dom/media/tests/crashtests/crashtests.list
@@ -5,13 +5,12 @@ load 791270.html
 load 791278.html
 load 791330.html
 load 799419.html
 load 802982.html
 load 812785.html
 load 834100.html
 load 836349.html
 load 837324.html
-load 837421.html
 load 855796.html
 load 860143.html
 load 861958.html
 load 863929.html
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -553,42 +553,40 @@ PeerConnectionWrapper.prototype = {
       self._last_answer = answer;
       onSuccess(answer);
     }, unexpectedCallbackAndFinish(new Error));
   },
 
   /**
    * Sets the local description and automatically handles the failure case.
    *
-   * @param {object} sdp
-   *        SDP for the local description request
+   * @param {object} desc
+   *        mozRTCSessionDescription for the local description request
    * @param {function} onSuccess
    *        Callback to execute if the local description was set successfully
    */
-  setLocalDescription : function PCW_setLocalDescription(sdp, onSuccess) {
+  setLocalDescription : function PCW_setLocalDescription(desc, onSuccess) {
     var self = this;
-
-    this._pc.setLocalDescription(sdp, function () {
+    this._pc.setLocalDescription(desc, function () {
       info("Successfully set the local description for " + self.label);
       onSuccess();
     }, unexpectedCallbackAndFinish(new Error));
   },
 
   /**
    * Sets the remote description and automatically handles the failure case.
    *
-   * @param {object} sdp
-   *        SDP for the remote description request
+   * @param {object} desc
+   *        mozRTCSessionDescription for the remote description request
    * @param {function} onSuccess
    *        Callback to execute if the remote description was set successfully
    */
-  setRemoteDescription : function PCW_setRemoteDescription(sdp, onSuccess) {
+  setRemoteDescription : function PCW_setRemoteDescription(desc, onSuccess) {
     var self = this;
-
-    this._pc.setRemoteDescription(sdp, function () {
+    this._pc.setRemoteDescription(desc, function () {
       info("Successfully set remote description for " + self.label);
       onSuccess();
     }, unexpectedCallbackAndFinish(new Error));
   },
 
   /**
    * Checks that we are getting the media we expect.
    *
--- a/dom/media/tests/mochitest/test_peerConnection_bug825703.html
+++ b/dom/media/tests/mochitest/test_peerConnection_bug825703.html
@@ -37,36 +37,30 @@
     var config;
 
     try { pcs = new mozRTCPeerConnection(); } catch (e) { exception = e; }
     ok(!exception, "mozRTCPeerConnection() succeeds");
     exception = null;
 
     makePC(1, false);
 
-    makePC({}, false);
-
-    makePC([], false);
-
-    makePC({ iceServers: {}}, false);
+    makePC({}, true);
 
     makePC({ iceServers: [] }, true);
 
     makePC({ iceServers: [{ url:"" }] }, false);
 
     makePC({ iceServers: [{ url:"http:0.0.0.0" }] }, false);
 
     makePC({ iceServers: [
                 { url:"stun:0.0.0.0" },
                 { url:"stuns:x.net", foo:"" },
                 { url:"turn:[::192.9.5.5]:42", username:"p", credential:"p" },
                 { url:"turns:x.org:42", username:"p", credential:"p" }
                 ]}, true);
 
-    makePC({ iceServers: [{ url:"stun:0.0.0.0", credential:{}}] }, false);
-
     pcs = null;
     SimpleTest.finish();
   });
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_peerConnection_bug840344.html
+++ b/dom/media/tests/mochitest/test_peerConnection_bug840344.html
@@ -49,20 +49,20 @@
          "a=candidate:0 2 UDP 2113601790 192.168.129.33 62658 typ host\r\n",
     type: "offer"
   };
 
   var steps = [
     [
       "SET_REMOTE_DESCRIPTION",
       function (test) {
-        var osd = new mozRTCSessionDescription(offer);
-        test.pcLocal.setRemoteDescription(osd, function () {
-          test.next();
-        });
+        test.pcLocal.setRemoteDescription(new mozRTCSessionDescription(offer),
+                                          function () {
+                                            test.next();
+                                          });
       }
     ],
     [
       "CHECK_MULTIPLE_ANSWERS",
       function (test) {
         var answerCount = 0;
         var setLocalCount = 0;
 
--- a/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html
+++ b/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html
@@ -33,37 +33,37 @@
     info ("Testing createAnswer error callback");
     pc.createAnswer(successCallback("createAnswer before offer should fail"),
                     errorCallback(testSetLocalDescriptionError));
   };
 
   function testSetLocalDescriptionError() {
     var pc = new mozRTCPeerConnection();
     info ("Testing setLocalDescription error callback");
-    pc.setLocalDescription(
-      {sdp: "Ralph Waldo Picklechips!", type: "offer"},
+    pc.setLocalDescription(new mozRTCSessionDescription({ sdp: "Picklechips!",
+                                                          type: "offer" }),
       successCallback("setLocalDescription with nonsense SDP should fail"),
       errorCallback(testSetRemoteDescriptionError));
   };
 
   function testSetRemoteDescriptionError() {
     var pc = new mozRTCPeerConnection();
     info ("Testing setRemoteDescription error callback");
-    pc.setRemoteDescription(
-      {sdp: "I don't know him.", type: "offer"},
+    pc.setRemoteDescription(new mozRTCSessionDescription({ sdp: "Who?",
+                                                           type: "offer" }),
       successCallback("setRemoteDescription with nonsense SDP should fail"),
       errorCallback(testAddIceCandidateError));
   };
 
   function testAddIceCandidateError() {
     var pc = new mozRTCPeerConnection();
     info ("Testing addIceCandidate error callback");
-    pc.addIceCandidate(
-      {candidate: "Pony Lords, jump for your lives!",
-       sdpMid: "whee", sdpMLineIndex: 1},
+    pc.addIceCandidate(new mozRTCIceCandidate({ candidate: "Pony Lords, jump!",
+                                                sdpMid: "whee",
+                                                sdpMLineIndex: 1 }),
       successCallback("addIceCandidate with nonsense candidate should fail"),
       errorCallback(SimpleTest.finish));
   };
 
   // No test for createOffer errors -- there's nothing we can do at this
   // level to evoke an error in createOffer.
 
   runTest(function () {
--- a/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html
+++ b/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html
@@ -55,30 +55,30 @@
                 }, getFail(new Error));
                 throw new Error("Expected");
               }, getFail(new Error));
               throw new Error("Expected");
             }, getFail(new Error));
             throw new Error("Expected");
           }, getFail(new Error));
           throw new Error("Expected");
-        });
+        }, getFail(new Error));
       }, getFail(new Error));
       throw new Error("Expected");
     });
   });
 
   function finish() {
     window.onerror = oldOnError;
     is(error_count, 7, "Seven expected errors verified.");
     SimpleTest.finish();
   }
 
   function getFail(where) {
     return function (err) {
-      window.onerror = onOldError;
+      window.onerror = oldOnError;
       unexpectedCallbackAndFinish(where)(err);
     };
   }
 </script>
 </pre>
 </body>
 </html>
--- a/dom/network/interfaces/moz.build
+++ b/dom/network/interfaces/moz.build
@@ -11,22 +11,22 @@ XPIDL_SOURCES += [
     'nsIDOMTCPSocket.idl',
     'nsIDOMUSSDReceivedEvent.idl',
     'nsITCPSocketChild.idl',
     'nsITCPSocketParent.idl',
 ]
 
 if CONFIG['MOZ_B2G_RIL']:
     XPIDL_SOURCES += [
+        'nsIDOMCFStateChangeEvent.idl',
         'nsIDOMMobileConnection.idl',
+        'nsIDOMNetworkStats.idl',
+        'nsIDOMNetworkStatsManager.idl',
         'nsIMobileConnectionProvider.idl',
         'nsINavigatorMobileConnection.idl',
-        'nsIDOMNetworkStatsManager.idl',
-        'nsIDOMNetworkStats.idl',
-        'nsIDOMCFStateChangeEvent.idl',
     ]
 
 XPIDL_MODULE = 'dom_network'
 
 XPIDL_FLAGS += [
     '-I$(topsrcdir)/dom/interfaces/base',
     '-I$(topsrcdir)/dom/interfaces/events',
 ]
--- a/dom/network/src/TCPSocket.js
+++ b/dom/network/src/TCPSocket.js
@@ -47,17 +47,17 @@ function createTCPError(aErrorName, aErr
   return error;
 }
 
 
 /*
  * Debug logging function
  */
 
-let debug = true;
+let debug = false;
 function LOG(msg) {
   if (debug)
     dump("TCPSocket: " + msg + "\n");
 }
 
 /*
  * nsITCPSocketEvent object
  */
@@ -345,48 +345,48 @@ TCPSocket.prototype = {
 
   // nsIDOMTCPSocket
   open: function ts_open(host, port, options) {
     if (!this.initWindowless())
       return null;
 
     this._inChild = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
                        .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-    LOG("content process: " + (this._inChild ? "true" : "false") + "\n");
+    LOG("content process: " + (this._inChild ? "true" : "false"));
 
     // in the testing case, init won't be called and
     // hasPrivileges will be null. We want to proceed to test.
     if (this._hasPrivileges !== true && this._hasPrivileges !== null) {
       throw new Error("TCPSocket does not have permission in this context.\n");
     }
     let that = new TCPSocket();
 
     that.useWin = this.useWin;
     that.innerWindowID = this.innerWindowID;
     that._inChild = this._inChild;
 
     LOG("window init: " + that.innerWindowID);
     Services.obs.addObserver(that, "inner-window-destroyed", true);
 
-    LOG("startup called\n");
-    LOG("Host info: " + host + ":" + port + "\n");
+    LOG("startup called");
+    LOG("Host info: " + host + ":" + port);
 
     that._readyState = kCONNECTING;
     that._host = host;
     that._port = port;
     if (options !== undefined) {
       if (options.useSSL) {
           that._ssl = 'ssl';
       } else {
           that._ssl = false;
       }
       that._binaryType = options.binaryType || that._binaryType;
     }
 
-    LOG("SSL: " + that.ssl + "\n");
+    LOG("SSL: " + that.ssl);
 
     if (this._inChild) {
       that._socketBridge = Cc["@mozilla.org/tcp-socket-child;1"]
                              .createInstance(Ci.nsITCPSocketChild);
       that._socketBridge.open(that, host, port, !!that._ssl,
                               that._binaryType, this.useWin, this.useWin || this);
       return that;
     }
@@ -423,17 +423,17 @@ TCPSocket.prototype = {
 
     return that;
   },
 
   close: function ts_close() {
     if (this._readyState === kCLOSED || this._readyState === kCLOSING)
       return;
 
-    LOG("close called\n");
+    LOG("close called");
     this._readyState = kCLOSING;
 
     if (this._inChild) {
       this._socketBridge.close();
       return;
     }
 
     if (!this._multiplexStream.count) {
--- a/dom/payment/interfaces/moz.build
+++ b/dom/payment/interfaces/moz.build
@@ -1,17 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
+    'nsIDOMPaymentRequestInfo.idl',
     'nsINavigatorPayment.idl',
-    'nsIDOMPaymentRequestInfo.idl',
     'nsIPaymentFlowInfo.idl',
     'nsIPaymentUIGlue.idl',
 ]
 
 XPIDL_MODULE = 'dom_payment'
 
 XPIDL_FLAGS += [
     '-I$(topsrcdir)/dom/interfaces/base',
--- a/dom/webidl/DummyBinding.webidl
+++ b/dom/webidl/DummyBinding.webidl
@@ -5,17 +5,16 @@
  */
 
 // Dummy bindings that we need to force generation of things that
 // aren't actually referenced anywhere in IDL yet but are used in C++.
 
 interface DummyInterface {
   readonly attribute OnErrorEventHandlerNonNull onErrorEventHandler;
   FilePropertyBag fileBag();
-  RTCConfiguration rtcConfiguration();
   CFStateChangeEventDict cfstateChangeEvent();
   USSDReceivedEventDict ussdReceivedEvent();
   InspectorRGBTriple rgbTriple();
   Function getFunction();
   void funcSocketsDict(optional SocketsDict arg);
   void funcHttpConnDict(optional HttpConnDict arg);
   void funcWebSocketDict(optional WebSocketDict arg);
   void funcDNSCacheDict(optional DNSCacheDict arg);
new file mode 100644
--- /dev/null
+++ b/dom/webidl/MediaStreamEvent.webidl
@@ -0,0 +1,19 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/2011/webrtc/editor/webrtc.html#mediastreamevent
+ */
+
+dictionary MediaStreamEventInit : EventInit {
+    MediaStream? stream = null;
+};
+
+[Pref="media.peerconnection.enabled",
+ JSImplementation="@mozilla.org/dom/mediastreamevent;1",
+ Constructor(DOMString type, optional MediaStreamEventInit eventInitDict)]
+interface MediaStreamEvent : Event {
+  readonly attribute MediaStream? stream;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/OfflineAudioCompletionEvent.webidl
@@ -0,0 +1,19 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+[PrefControlled]
+interface OfflineAudioCompletionEvent : Event {
+
+    readonly attribute AudioBuffer renderedBuffer;
+
+};
+
new file mode 100644
--- /dev/null
+++ b/dom/webidl/OfflineAudioContext.webidl
@@ -0,0 +1,24 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+callback OfflineRenderSuccessCallback = void (AudioBuffer renderedData);
+
+[Constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate),
+ PrefControlled]
+interface OfflineAudioContext : AudioContext {
+
+    void startRendering();
+
+    [SetterThrows]
+    attribute EventHandler oncomplete;
+
+};
--- a/dom/webidl/RTCConfiguration.webidl
+++ b/dom/webidl/RTCConfiguration.webidl
@@ -1,12 +1,15 @@
 /* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCConfiguration
  */
 
 dictionary RTCIceServer {
     DOMString  url;
     DOMString? credential = null;
     DOMString? username = null;
 };
 
new file mode 100644
--- /dev/null
+++ b/dom/webidl/RTCDataChannelEvent.webidl
@@ -0,0 +1,21 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCDataChannelEvent
+ */
+
+interface RTCDataChannel;
+
+dictionary RTCDataChannelEventInit : EventInit {
+    RTCDataChannel? channel = null;
+};
+
+[Pref="media.peerconnection.enabled",
+ JSImplementation="@mozilla.org/dom/datachannelevent;1",
+ Constructor(DOMString type, optional RTCDataChannelEventInit eventInitDict)]
+interface RTCDataChannelEvent : Event {
+  readonly attribute RTCDataChannel? channel;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/RTCIceCandidate.webidl
@@ -0,0 +1,27 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCIceCandidate
+ */
+
+dictionary RTCIceCandidateInit {
+  DOMString? candidate = null;
+  DOMString? sdpMid = null;
+  unsigned short sdpMLineIndex;
+};
+
+[Pref="media.peerconnection.enabled",
+ JSImplementation="@mozilla.org/dom/rtcicecandidate;1",
+ Constructor(optional RTCIceCandidateInit candidateInitDict)]
+interface mozRTCIceCandidate {
+  attribute DOMString?      candidate;
+  attribute DOMString?      sdpMid;
+  attribute unsigned short? sdpMLineIndex;
+
+  // Bug 863402 serializer support
+  //
+  //serializer = {attribute};
+};
deleted file mode 100644
--- a/dom/webidl/RTCIceServer.webidl
+++ /dev/null
@@ -1,10 +0,0 @@
-/* -*- Mode: IDL; 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/.
- */
-
-dictionary RTCIceServer {
-    DOMString  url;
-    DOMString? credential = null;
-};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/RTCPeerConnection.webidl
@@ -0,0 +1,109 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCPeerConnection
+ */
+
+callback RTCSessionDescriptionCallback = void (mozRTCSessionDescription sdp);
+callback RTCPeerConnectionErrorCallback = void (DOMString errorInformation);
+callback VoidFunction = void ();
+
+enum RTCSignalingState {
+    "stable",
+    "have-local-offer",
+    "have-remote-offer",
+    "have-local-pranswer",
+    "have-remote-pranswer",
+    "closed"
+};
+
+enum RTCIceGatheringState {
+    "new",
+    "gathering",
+    "complete"
+};
+
+enum RTCIceConnectionState {
+    "new",
+    "checking",
+    "connected",
+    "completed",
+    "failed",
+    "disconnected",
+    "closed"
+};
+
+dictionary RTCDataChannelInit {
+  boolean outOfOrderAllowed;
+  unsigned short maxRetransmitTime;
+  unsigned short maxRetransmitNum;
+  DOMString protocol;
+  boolean preset;
+  unsigned short stream;
+};
+
+interface RTCDataChannel;
+
+[Pref="media.peerconnection.enabled",
+ JSImplementation="@mozilla.org/dom/peerconnection;1",
+ Constructor (optional RTCConfiguration configuration,
+              optional object? constraints)]
+// moz-prefixed until sufficiently standardized.
+interface mozRTCPeerConnection : EventTarget  {
+  void createOffer (RTCSessionDescriptionCallback successCallback,
+                    RTCPeerConnectionErrorCallback? failureCallback, // for apprtc
+                    optional object? constraints);
+  void createAnswer (RTCSessionDescriptionCallback successCallback,
+                     RTCPeerConnectionErrorCallback? failureCallback, // for apprtc
+                     optional object? constraints);
+  void setLocalDescription (mozRTCSessionDescription description,
+                            optional VoidFunction successCallback,
+                            optional RTCPeerConnectionErrorCallback failureCallback);
+  void setRemoteDescription (mozRTCSessionDescription description,
+                             optional VoidFunction successCallback,
+                             optional RTCPeerConnectionErrorCallback failureCallback);
+  readonly attribute mozRTCSessionDescription? localDescription;
+  readonly attribute mozRTCSessionDescription? remoteDescription;
+  readonly attribute RTCSignalingState signalingState;
+  void updateIce (optional RTCConfiguration configuration,
+                  optional object? constraints);
+  void addIceCandidate (mozRTCIceCandidate candidate,
+                        optional VoidFunction successCallback,
+                        optional RTCPeerConnectionErrorCallback failureCallback);
+  readonly attribute RTCIceGatheringState iceGatheringState;
+  readonly attribute RTCIceConnectionState iceConnectionState;
+  sequence<MediaStream> getLocalStreams ();
+  sequence<MediaStream> getRemoteStreams ();
+  MediaStream? getStreamById (DOMString streamId);
+  void addStream (MediaStream stream, optional object? constraints);
+  void removeStream (MediaStream stream);
+  void close ();
+  attribute EventHandler onnegotiationneeded;
+  attribute EventHandler onicecandidate;
+  attribute EventHandler onsignalingstatechange;
+  attribute EventHandler onaddstream;
+  attribute EventHandler onremovestream;
+  attribute EventHandler oniceconnectionstatechange;
+};
+
+// Mozilla extensions.
+partial interface mozRTCPeerConnection {
+  // Deprecated callbacks (use causes warning)
+  attribute RTCPeerConnectionErrorCallback onicechange;
+  attribute RTCPeerConnectionErrorCallback ongatheringchange;
+
+  // Deprecated attributes (use causes warning)
+  readonly attribute object localStreams;
+  readonly attribute object remoteStreams;
+  readonly attribute DOMString readyState;
+
+  // Data channel.
+  RTCDataChannel createDataChannel (DOMString label,
+                                    optional RTCDataChannelInit dataChannelDict);
+  attribute EventHandler ondatachannel;
+  attribute EventHandler onconnection;
+  attribute EventHandler onclosedconnection;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/RTCPeerConnectionIceEvent.webidl
@@ -0,0 +1,20 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCPeerConnectionIceEvent
+ */
+
+dictionary RTCPeerConnectionIceEventInit : EventInit {
+  mozRTCIceCandidate? candidate = null;
+};
+
+[Pref="media.peerconnection.enabled",
+ JSImplementation="@mozilla.org/dom/rtcpeerconnectioniceevent;1",
+ Constructor(DOMString type,
+             optional RTCPeerConnectionIceEventInit eventInitDict)]
+interface RTCPeerConnectionIceEvent : Event {
+  readonly attribute mozRTCIceCandidate? candidate;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/RTCSessionDescription.webidl
@@ -0,0 +1,31 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCSessionDescription
+ */
+
+enum RTCSdpType {
+  "offer",
+  "pranswer",
+  "answer"
+};
+
+dictionary RTCSessionDescriptionInit {
+  RTCSdpType? type = null;
+  DOMString? sdp = null;
+};
+
+[Pref="media.peerconnection.enabled",
+ JSImplementation="@mozilla.org/dom/rtcsessiondescription;1",
+ Constructor(optional RTCSessionDescriptionInit descriptionInitDict)]
+interface mozRTCSessionDescription {
+  attribute RTCSdpType? type;
+  attribute DOMString? sdp;
+
+  // Bug 863402 serializer support workaround
+  //serializer = {attribute};
+  object toJSON();
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -157,45 +157,53 @@ webidl_files = \
   ImageDocument.webidl \
   InspectorUtils.webidl \
   KeyboardEvent.webidl \
   LinkStyle.webidl \
   LocalMediaStream.webidl \
   Location.webidl \
   MediaError.webidl \
   MediaStream.webidl \
+  MediaStreamEvent.webidl \
   MediaStreamTrack.webidl \
   MessageEvent.webidl \
   MouseEvent.webidl \
   MouseScrollEvent.webidl \
   MozActivity.webidl \
   MozNamedAttrMap.webidl \
   MutationEvent.webidl \
   MutationObserver.webidl \
   NetDashboard.webidl \
   Node.webidl \
   NodeFilter.webidl \
   NodeIterator.webidl \
   NodeList.webidl \
   Notification.webidl \
   NotifyAudioAvailableEvent.webidl \
   NotifyPaintEvent.webidl \
+  OfflineAudioCompletionEvent.webidl \
+  OfflineAudioContext.webidl \
   PaintRequest.webidl \
   PaintRequestList.webidl \
   PannerNode.webidl \
   Performance.webidl \
   PerformanceNavigation.webidl \
   PerformanceTiming.webidl \
   Position.webidl \
   PositionError.webidl \
   ProcessingInstruction.webidl \
   Range.webidl \
   Rect.webidl \
   RGBColor.webidl \
   RTCConfiguration.webidl \
+  RTCDataChannelEvent.webidl \
+  RTCIceCandidate.webidl \
+  RTCPeerConnection.webidl \
+  RTCPeerConnectionIceEvent.webidl \
+  RTCSessionDescription.webidl \
   Screen.webidl \
   ScriptProcessorNode.webidl \
   ScrollAreaEvent.webidl \
   SimpleGestureEvent.webidl \
   StyleSheet.webidl \
   SVGAElement.webidl \
   SVGAltGlyphElement.webidl \
   SVGAngle.webidl \
--- a/gfx/cairo/cairo/src/moz.build
+++ b/gfx/cairo/cairo/src/moz.build
@@ -15,47 +15,47 @@ EXPORTS.cairo += [
     'cairo-rename.h',
     'cairo-tee.h',
     'cairo-version.h',
     'cairo.h',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXPORTS.cairo += [
+        'cairo-pdf.h',
         'cairo-win32.h',
-        'cairo-pdf.h',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'os2':
     EXPORTS.cairo += [
         'cairo-os2.h',
         'cairo-os2-private.h',
         'cairo-pdf.h',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     EXPORTS.cairo += [
+        'cairo-quartz-image.h',
         'cairo-quartz.h',
-        'cairo-quartz-image.h',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'beos':
     EXPORTS.cairo += [
         'cairo-beos.h',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
     EXPORTS.cairo += [
         'cairo-pdf.h',
         'cairo-ps.h',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
     EXPORTS.cairo += [
         'cairo-pdf.h',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
     EXPORTS.cairo += [
+        'cairo-pdf.h',
         'cairo-qt.h',
-        'cairo-pdf.h',
     ]
 
 if CONFIG['BUILD_CAIRO_SVG']:
     EXPORTS.cairo += [
         'cairo-svg.h'
     ]
 
 if CONFIG['MOZ_X11']:
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -25,13 +25,13 @@ EXPORTS += [
     'SurfaceStream.h',
     'SurfaceTypes.h',
 ]
 
 if CONFIG['MOZ_X11']:
     EXPORTS += ['GLXLibrary.h']
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXPORTS += [
+        'SharedSurfaceANGLE.h',
         'WGLLibrary.h',
-        'SharedSurfaceANGLE.h',
     ]
 if CONFIG['MOZ_ENABLE_SKIA_GPU']:
     EXPORTS += ['GLContextSkia.h']
--- a/gfx/ipc/moz.build
+++ b/gfx/ipc/moz.build
@@ -7,12 +7,12 @@
 MODULE = 'gfxipc'
 
 EXPORTS.mozilla.gfx += [
     'SharedDIB.h',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXPORTS.mozilla.gfx += [
+        'SharedDIBSurface.h',
         'SharedDIBWin.h',
-        'SharedDIBSurface.h',
     ]
 
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -42,18 +42,18 @@ EXPORTS += [
     'SharedTextureImage.h',
     'ShmemYCbCrImage.h',
     'TexturePoolOGL.h',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     if CONFIG['MOZ_ENABLE_D3D9_LAYER']:
         EXPORTS += [
+            'DeviceManagerD3D9.h',
             'LayerManagerD3D9.h',
-            'DeviceManagerD3D9.h',
         ]
     if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
         EXPORTS += [
             'LayerManagerD3D10.h',
             'ReadbackManagerD3D10.h',
         ]
         EXPORTS.mozilla.layers += [
             'CompositorD3D11.h',
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -46,25 +46,25 @@ EXPORTS += [
     'gfxUserFontSet.h',
     'gfxUtils.h',
     'nsSurfaceTexture.h',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     EXPORTS += [
         'gfxAndroidPlatform.h',
+        'gfxFT2FontBase.h',
         'gfxFT2Fonts.h',
-        'gfxFT2FontBase.h',
         'gfxPDFSurface.h',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     EXPORTS += [
         'gfxAndroidPlatform.h',
+        'gfxFT2FontBase.h',
         'gfxFT2Fonts.h',
-        'gfxFT2FontBase.h',
         'gfxPDFSurface.h',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     EXPORTS += [
         'gfxPlatformMac.h',
         'gfxQuartzImageSurface.h',
         'gfxQuartzNativeDrawing.h',
         'gfxQuartzSurface.h',
@@ -93,35 +93,35 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'os
         'gfxOS2Fonts.h',
         'gfxOS2Platform.h',
         'gfxOS2Surface.h',
         'gfxPDFSurface.h',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
     EXPORTS += [
         'gfxFT2FontBase.h',
+        'gfxPDFSurface.h',
         'gfxQPainterSurface.h',
         'gfxQtNativeRenderer.h',
         'gfxQtPlatform.h',
-        'gfxPDFSurface.h',
     ]
 
     if CONFIG['MOZ_X11']:
         EXPORTS += [
             'gfxXlibSurface.h',
         ]
 
     if CONFIG['MOZ_PANGO']:
         EXPORTS += ['gfxPangoFonts.h']
     else:
         EXPORTS += ['gfxFT2Fonts.h']
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXPORTS += [
+        'gfxD2DSurface.h',
+        'gfxDWriteFonts.h',
+        'gfxGDIFont.h',
+        'gfxGDIFontList.h',
         'gfxPDFSurface.h',
+        'gfxPlatformFontList.h',
+        'gfxWindowsNativeDrawing.h',
         'gfxWindowsPlatform.h',
         'gfxWindowsSurface.h',
-        'gfxWindowsNativeDrawing.h',
-        'gfxDWriteFonts.h',
-        'gfxD2DSurface.h',
-        'gfxGDIFont.h',
-        'gfxGDIFontList.h',
-        'gfxPlatformFontList.h',
     ]
--- a/js/src/ion/AsmJSSignalHandlers.cpp
+++ b/js/src/ion/AsmJSSignalHandlers.cpp
@@ -404,17 +404,17 @@ HandleException(PEXCEPTION_POINTERS exce
         return false;
 
     AsmJSActivation *activation = InnermostAsmJSActivation();
     if (!activation)
         return false;
 
     uint8_t **ppc = ContextToPC(context);
     uint8_t *pc = *ppc;
-	JS_ASSERT(pc == record->ExceptionAddress);
+    JS_ASSERT(pc == record->ExceptionAddress);
 
     const AsmJSModule &module = activation->module();
     if (!module.containsPC(pc))
         return false;
 
 	if (record->NumberParameters < 2)
 		return false;
 
--- a/js/src/ion/BaselineIC.cpp
+++ b/js/src/ion/BaselineIC.cpp
@@ -2536,17 +2536,17 @@ DoBinaryArithFallback(JSContext *cx, Bas
           default:
             break;
         }
     }
 
     return true;
 }
 #if defined(_MSC_VER)
-# pragma optimize("g", on)
+# pragma optimize("", on)
 #endif
 
 typedef bool (*DoBinaryArithFallbackFn)(JSContext *, BaselineFrame *, ICBinaryArith_Fallback *,
                                         HandleValue, HandleValue, MutableHandleValue);
 static const VMFunction DoBinaryArithFallbackInfo =
     FunctionInfo<DoBinaryArithFallbackFn>(DoBinaryArithFallback, PopValues(2));
 
 bool
@@ -2951,17 +2951,17 @@ DoUnaryArithFallback(JSContext *cx, Base
             return false;
         stub->addNewStub(doubleStub);
         return true;
     }
 
     return true;
 }
 #if defined(_MSC_VER)
-# pragma optimize("g", on)
+# pragma optimize("", on)
 #endif
 
 typedef bool (*DoUnaryArithFallbackFn)(JSContext *, BaselineFrame *, ICUnaryArith_Fallback *,
                                        HandleValue, MutableHandleValue);
 static const VMFunction DoUnaryArithFallbackInfo =
     FunctionInfo<DoUnaryArithFallbackFn>(DoUnaryArithFallback, PopValues(1));
 
 bool
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -4564,24 +4564,16 @@ nsXPCComponents_Utils::GetClassName(cons
     NS_ENSURE_TRUE(*aRv, NS_ERROR_OUT_OF_MEMORY);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::GetDOMClassInfo(const nsAString& aClassName,
                                        nsIClassInfo** aClassInfo)
 {
-#ifdef MOZ_WEBRTC
-    if (aClassName.EqualsLiteral("RTCPeerConnection")) {
-        NS_ADDREF(*aClassInfo =
-                  NS_GetDOMClassInfoInstance(eDOMClassInfo_RTCPeerConnection_id));
-        return NS_OK;
-    }
-#endif
-
     *aClassInfo = nullptr;
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 /***************************************************************************/
 /***************************************************************************/
 /***************************************************************************/
 
--- a/layout/base/crashtests/813372-1.html
+++ b/layout/base/crashtests/813372-1.html
@@ -29,23 +29,24 @@
 
 
 <section id="details" class="hide">
 I'm a test of hiding animation
 <button onclick="this.parentNode.classList.add('hide')">Click me to hide</button>
 </section>
 
 <script>
-var x = document.getElementById('details');
 var kNumIterations = 5;
 var currentIteration = 0;
+var inrval;
 
 function doe() {
-  x.classList.toggle('hide');
   if (++currentIteration >= kNumIterations) {
     clearInterval(inrval);
     document.documentElement.removeAttribute('class');
+  } else {
+    document.getElementById('details').classList.toggle('hide');
   }
 }
-var inrval = setInterval(doe, 800);
+document.addEventListener("MozReftestInvalidate", function(){ inrval = setInterval(doe, 1000); }, false);
 </script>
 </body>
 </html>
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2283,30 +2283,16 @@ GetFrameBorderSize(nsIFrame* aFrame)
 void
 nsLayoutUtils::GetAllInFlowRects(nsIFrame* aFrame, nsIFrame* aRelativeTo,
                                  RectCallback* aCallback, uint32_t aFlags)
 {
   BoxToRect converter(aRelativeTo, aCallback, aFlags, &GetFrameBorderSize);
   GetAllInFlowBoxes(aFrame, &converter);
 }
 
-static nsSize
-GetFramePaddingSize(nsIFrame* aFrame)
-{
-  return aFrame->GetPaddingRect().Size();
-}
-
-void
-nsLayoutUtils::GetAllInFlowPaddingRects(nsIFrame* aFrame, nsIFrame* aRelativeTo,
-                                        RectCallback* aCallback, uint32_t aFlags)
-{
-  BoxToRect converter(aRelativeTo, aCallback, aFlags, &GetFramePaddingSize);
-  GetAllInFlowBoxes(aFrame, &converter);
-}
-
 nsLayoutUtils::RectAccumulator::RectAccumulator() : mSeenFirstRect(false) {}
 
 void nsLayoutUtils::RectAccumulator::AddRect(const nsRect& aRect) {
   mResultRect.UnionRect(mResultRect, aRect);
   if (!mSeenFirstRect) {
     mSeenFirstRect = true;
     mFirstRect = aRect;
   }
@@ -2334,27 +2320,16 @@ nsLayoutUtils::GetAllInFlowRectsUnion(ns
                                       uint32_t aFlags) {
   RectAccumulator accumulator;
   GetAllInFlowRects(aFrame, aRelativeTo, &accumulator, aFlags);
   return accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect
           : accumulator.mResultRect;
 }
 
 nsRect
-nsLayoutUtils::GetAllInFlowPaddingRectsUnion(nsIFrame* aFrame,
-                                             nsIFrame* aRelativeTo,
-                                             uint32_t aFlags)
-{
-  RectAccumulator accumulator;
-  GetAllInFlowPaddingRects(aFrame, aRelativeTo, &accumulator, aFlags);
-  return accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect
-          : accumulator.mResultRect;
-}
-
-nsRect
 nsLayoutUtils::GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect,
                                        nsIFrame* aFrame,
                                        uint32_t aFlags)
 {
   const nsStyleText* textStyle = aFrame->StyleText();
   if (!textStyle->HasTextShadow(aFrame))
     return aTextAndDecorationsRect;
 
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -804,42 +804,27 @@ public:
    * If aFrame is null, no boxes are returned.
    * For SVG frames, returns one rectangle, the bounding box.
    * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting
    * the boxes into aRelativeTo coordinates, transforms (including CSS
    * and SVG transforms) are taken into account.
    */
   static void GetAllInFlowRects(nsIFrame* aFrame, nsIFrame* aRelativeTo,
                                 RectCallback* aCallback, uint32_t aFlags = 0);
-  /**
-   * The same as GetAllInFlowRects, but it collects the CSS padding-boxes
-   * rather than the CSS border-boxes. SVG frames are handled the same way
-   * as in GetAllInFlowRects.
-   */
-  static void GetAllInFlowPaddingRects(nsIFrame* aFrame, nsIFrame* aRelativeTo,
-                                RectCallback* aCallback, uint32_t aFlags = 0);
 
   /**
    * Computes the union of all rects returned by GetAllInFlowRects. If
    * the union is empty, returns the first rect.
    * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting
    * the boxes into aRelativeTo coordinates, transforms (including CSS
    * and SVG transforms) are taken into account.
    */
   static nsRect GetAllInFlowRectsUnion(nsIFrame* aFrame, nsIFrame* aRelativeTo,
                                        uint32_t aFlags = 0);
 
-  /**
-   * The same as GetAllInFlowRectsUnion, but it computes the union of the
-   * rects returned by GetAllInFlowPaddingRects.
-   */
-  static nsRect GetAllInFlowPaddingRectsUnion(nsIFrame* aFrame,
-                                              nsIFrame* aRelativeTo,
-                                              uint32_t aFlags = 0);
-
   enum {
     EXCLUDE_BLUR_SHADOWS = 0x01
   };
   /**
    * Takes a text-shadow array from the style properties of a given nsIFrame and
    * computes the union of those shadows along with the given initial rect.
    * If there are no shadows, the initial rect is returned.
    */
--- a/layout/style/nsStyleUtil.cpp
+++ b/layout/style/nsStyleUtil.cpp
@@ -5,16 +5,17 @@
 
 #include "nsStyleUtil.h"
 #include "nsStyleConsts.h"
 
 #include "nsIContent.h"
 #include "nsReadableUtils.h"
 #include "nsCSSProps.h"
 #include "nsRuleNode.h"
+#include "nsIContentSecurityPolicy.h"
 
 using namespace mozilla;
 
 //------------------------------------------------------------------------------
 // Font Algorithm Code
 //------------------------------------------------------------------------------
 
 // Compare two language strings
@@ -410,8 +411,66 @@ nsStyleUtil::IsSignificantChild(nsIConte
     return true;
   }
 
   return aTextIsSignificant && isText && aChild->TextLength() != 0 &&
          (aWhitespaceIsSignificant ||
           !aChild->TextIsOnlyWhitespace());
 }
 
+/* static */ bool
+nsStyleUtil::CSPAllowsInlineStyle(nsIPrincipal* aPrincipal,
+                                  nsIURI* aSourceURI,
+                                  uint32_t aLineNumber,
+                                  const nsSubstring& aStyleText,
+                                  nsresult* aRv)
+{
+  nsresult rv;
+
+  if (aRv) {
+    *aRv = NS_OK;
+  }
+
+  nsCOMPtr<nsIContentSecurityPolicy> csp;
+  rv = aPrincipal->GetCsp(getter_AddRefs(csp));
+
+  if (NS_FAILED(rv)) {
+    if (aRv)
+      *aRv = rv;
+    return false;
+  }
+
+  if (csp) {
+    bool inlineOK = true;
+    bool reportViolation = false;
+    rv = csp->GetAllowsInlineStyle(&reportViolation, &inlineOK);
+    if (NS_FAILED(rv)) {
+      if (aRv)
+        *aRv = rv;
+      return false;
+    }
+
+    if (reportViolation) {
+      // Inline styles are not allowed by CSP, so report the violation
+      nsAutoCString asciiSpec;
+      aSourceURI->GetAsciiSpec(asciiSpec);
+      nsAutoString styleText(aStyleText);
+
+      // cap the length of the style sample at 40 chars.
+      if (styleText.Length() > 40) {
+        styleText.Truncate(40);
+        styleText.Append(NS_LITERAL_STRING("..."));
+      }
+
+      csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_STYLE,
+                              NS_ConvertUTF8toUTF16(asciiSpec),
+                              aStyleText,
+                              aLineNumber);
+    }
+
+    if (!inlineOK) {
+        // The inline style should be blocked.
+        return false;
+    }
+  }
+  // No CSP or a CSP that allows inline styles.
+  return true;
+}
--- a/layout/style/nsStyleUtil.h
+++ b/layout/style/nsStyleUtil.h
@@ -2,16 +2,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/. */
 #ifndef nsStyleUtil_h___
 #define nsStyleUtil_h___
 
 #include "nsCoord.h"
 #include "nsCSSProperty.h"
+#include "nsIPrincipal.h"
+#include "nsSubstring.h"
 #include "gfxFontFeatures.h"
 
 class nsCSSValue;
 class nsStringComparator;
 class nsIContent;
 struct gfxFontFeature;
 class nsCSSValueList;
 template <class E> class nsTArray;
@@ -85,12 +87,28 @@ public:
   static float ColorComponentToFloat(uint8_t aAlpha);
 
   /*
    * Does this child count as significant for selector matching?
    */
   static bool IsSignificantChild(nsIContent* aChild,
                                    bool aTextIsSignificant,
                                    bool aWhitespaceIsSignificant);
+  /*
+   *  Does this principal have a CSP that blocks the application of
+   *  inline styles ? Returns false if application of the style should
+   *  be blocked.
+   *
+   *  Note that the principal passed in here needs to be the principal
+   *  of the document, not of the style sheet. The document's principal
+   *  is where any Content Security Policy that should be used to
+   *  block or allow inline styles will be located.
+   */
+  static bool CSPAllowsInlineStyle(nsIPrincipal* aPrincipal,
+                                   nsIURI* aSourceURI,
+                                   uint32_t aLineNumber,
+                                   const nsSubstring& aStyleText,
+                                   nsresult* aRv);
+
 };
 
 
 #endif /* nsStyleUtil_h___ */
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -225,24 +225,17 @@ public:
             CSFLogError(logTag, "%s: GetRemoteStream returned NULL", __FUNCTION__);
           } else {
             stream = mRemoteStream->GetMediaStream();
           }
 
           if (!stream) {
             CSFLogError(logTag, "%s: GetMediaStream returned NULL", __FUNCTION__);
           } else {
-            // We provide a type field because it is in the IDL
-            // and we want code that looks at it not to crash.
-            // We use "video" so that if an app looks for
-            // that string it has some chance of working.
-            // TODO(ekr@rtfm.com): Bug 834847
-            // The correct way for content JS to know stream type
-            // is via get{Audio,Video}Tracks. See Bug 834835.
-            mObserver->OnAddStream(stream, "video");
+            mObserver->OnAddStream(stream);
           }
           break;
         }
 
       case UPDATELOCALDESC:
         /* No action necessary */
         break;
 
@@ -384,17 +377,16 @@ PeerConnectionImpl::ConvertRTCConfigurat
   }
   JSAutoCompartment ac(aCx, &aSrc.toObject());
   RTCConfiguration config;
   JS::Rooted<JS::Value> src(aCx, aSrc);
   if (!(config.Init(aCx, src) && config.mIceServers.WasPassed())) {
     return NS_ERROR_FAILURE;
   }
   for (uint32_t i = 0; i < config.mIceServers.Value().Length(); i++) {
-    // XXXbz once this moves to WebIDL, remove RTCConfiguration in DummyBinding.webidl.
     RTCIceServer& server = config.mIceServers.Value()[i];
     if (!server.mUrl.WasPassed()) {
       return NS_ERROR_FAILURE;
     }
     nsRefPtr<nsIURI> url;
     nsresult rv;
     rv = NS_NewURI(getter_AddRefs(url), server.mUrl.Value());
     NS_ENSURE_SUCCESS(rv, rv);
--- a/media/webrtc/signaling/test/signaling_unittests.cpp
+++ b/media/webrtc/signaling/test/signaling_unittests.cpp
@@ -21,17 +21,16 @@ using namespace std;
 #include "prthread.h"
 
 #include "FakeMediaStreams.h"
 #include "FakeMediaStreamsImpl.h"
 #include "PeerConnectionImpl.h"
 #include "PeerConnectionCtx.h"
 #include "runnable_utils.h"
 #include "nsStaticComponents.h"
-#include "nsIDOMRTCPeerConnection.h"
 #include "nsServiceManagerUtils.h"
 #include "nsNetUtil.h"
 #include "nsIIOService.h"
 #include "nsIDNSService.h"
 #include "nsWeakReference.h"
 #include "nricectx.h"
 #include "mozilla/SyncRunnable.h"
 
@@ -320,24 +319,24 @@ TestObserver::OnStateChange(uint32_t sta
 
   state = stateSuccess;
   lastStateType = state_type;
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
-TestObserver::OnAddStream(nsIDOMMediaStream *stream, const char *type)
+TestObserver::OnAddStream(nsIDOMMediaStream *stream)
 {
   PR_ASSERT(stream);
 
   DOMMediaStream *ms = static_cast<DOMMediaStream *>(stream);
 
-  cout << "OnAddStream called hints=" << ms->GetHintContents() << " type=" << type << " thread=" <<
-    PR_GetCurrentThread() << endl ;
+  cout << "OnAddStream called hints=" << ms->GetHintContents()
+      << " thread=" << PR_GetCurrentThread() << endl ;
 
   onAddStreamCalled = true;
 
   streams.push_back(ms);
 
   // We know that the media stream is secretly a Fake_SourceMediaStream,
   // so now we can start it pulling from us
   Fake_SourceMediaStream *fs = static_cast<Fake_SourceMediaStream *>(ms->GetStream());
--- a/memory/build/moz.build
+++ b/memory/build/moz.build
@@ -8,11 +8,11 @@ MODULE = 'memory'
 
 EXPORTS += [
     'mozmemory.h',
     'mozmemory_wrap.h',
 ]
 
 if CONFIG['MOZ_REPLACE_MALLOC']:
     EXPORTS += [
+        'malloc_decls.h',
         'replace_malloc.h',
-        'malloc_decls.h',
     ]
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -13,17 +13,20 @@ special meaning in the frontend files fo
 
 If you are looking for the absolute authority on what the global namespace in
 the Sandbox consists of, you've come to the right place.
 """
 
 from __future__ import unicode_literals
 
 from collections import OrderedDict
-from mozbuild.util import HierarchicalStringList
+from mozbuild.util import (
+    HierarchicalStringList,
+    StrictOrderingOnAppendList,
+)
 
 
 def doc_to_paragraphs(doc):
     """Take a documentation string and converts it to paragraphs.
 
     This normalizes the inline strings in VARIABLES and elsewhere in this file.
 
     It returns a list of paragraphs. It is up to the caller to insert newlines
@@ -52,18 +55,18 @@ def doc_to_paragraphs(doc):
 # This defines the set of mutable global variables.
 #
 # Each variable is a tuple of:
 #
 #   (storage_type, input_types, default_value, docs)
 #
 VARIABLES = {
     # Variables controlling reading of other frontend files.
-    'ASFILES': (list, list, [],
-        """ Assembly file sources.
+    'ASFILES': (StrictOrderingOnAppendList, list, [],
+        """Assembly file sources.
 
         This variable contains a list of files to invoke the assembler on.
         """),
 
     'DIRS': (list, list, [],
         """Child directories to descend into looking for build frontend files.
 
         This works similarly to the DIRS variable in make files. Each str value
@@ -133,17 +136,17 @@ VARIABLES = {
         directory and that the directory does not define itself with moz.build
         files.
         """),
 
     'PARALLEL_EXTERNAL_MAKE_DIRS': (list, list, [],
         """Parallel version of EXTERNAL_MAKE_DIRS.
         """),
 
-    'CONFIGURE_SUBST_FILES': (list, list, [],
+    'CONFIGURE_SUBST_FILES': (StrictOrderingOnAppendList, list, [],
         """Output files that will be generated using configure-like substitution.
 
         This is a substitute for AC_OUTPUT in autoconf. For each path in this
         list, we will search for a file in the srcdir having the name
         {path}.in. The contents of this file will be read and variable patterns
         like @foo@ will be substituted with the values of the AC_SUBST
         variables declared during configure.
         """),
@@ -177,17 +180,17 @@ VARIABLES = {
         """Compiled executable name.
 
         If the configuration token 'BIN_SUFFIX' is set, its value will be
         automatically appended to PROGRAM. If PROGRAM already ends with
         BIN_SUFFIX, PROGRAM will remain unchanged.
         """),
 
     # IDL Generation.
-    'XPIDL_SOURCES': (list, list, [],
+    'XPIDL_SOURCES': (StrictOrderingOnAppendList, list, [],
         """XPCOM Interface Definition Files (xpidl).
 
         This is a list of files that define XPCOM interface definitions.
         Entries must be files that exist. Entries are almost certainly .idl
         files.
         """),
 
     'XPIDL_MODULE': (unicode, unicode, "",
@@ -201,17 +204,17 @@ VARIABLES = {
     'XPIDL_FLAGS': (list, list, [],
         """XPCOM Interface Definition Module Flags.
 
         This is a list of extra flags that are passed to the IDL compiler.
         Typically this is a set of -I flags that denote extra include
         directories to search for included .idl files.
         """),
 
-    'XPCSHELL_TESTS_MANIFESTS': (list, list, [],
+    'XPCSHELL_TESTS_MANIFESTS': (StrictOrderingOnAppendList, list, [],
         """XPCSHELL Test Manifest list
 
         This is a list of xpcshell.ini manifest files.
         Formerly XPCSHELL_TESTS=
         """),
 }
 
 # The set of functions exposed to the sandbox.
--- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
@@ -1,9 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
-XPIDL_SOURCES = ['foo.idl', 'bar.idl', 'biz.idl']
+XPIDL_SOURCES = ['bar.idl', 'biz.idl', 'foo.idl']
 XPIDL_MODULE = 'module_name'
 XPIDL_FLAGS = ['-Idir1', '-Idir2', '-Idir3']
 
-ASFILES = ['foo.asm', 'bar.s']
+ASFILES = ['bar.s', 'foo.asm']
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -133,26 +133,34 @@ class TestRecursiveMakeBackend(BackendTe
     def test_variable_passthru(self):
         """Ensure variable passthru is written out correctly."""
         env = self._consume('variable_passthru', RecursiveMakeBackend)
 
         backend_path = os.path.join(env.topobjdir, 'backend.mk')
         lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:-1]]
 
         expected = {
-            'ASFILES': ['ASFILES += foo.asm', 'ASFILES += bar.s'],
-            'XPIDL_FLAGS': ['XPIDL_FLAGS += -Idir1',
-                            'XPIDL_FLAGS += -Idir2',
-                            'XPIDL_FLAGS += -Idir3',
-                            ],
-            'XPIDL_MODULE': ['XPIDL_MODULE := module_name'],
-            'XPIDLSRCS': ['XPIDLSRCS += foo.idl',
-                          'XPIDLSRCS += bar.idl',
-                          'XPIDLSRCS += biz.idl']
-            }
+            'ASFILES': [
+                'ASFILES += bar.s',
+                'ASFILES += foo.asm',
+            ],
+            'XPIDL_FLAGS': [
+                'XPIDL_FLAGS += -Idir1',
+                'XPIDL_FLAGS += -Idir2',
+                'XPIDL_FLAGS += -Idir3',
+            ],
+            'XPIDL_MODULE': [
+                'XPIDL_MODULE := module_name'
+            ],
+            'XPIDLSRCS': [
+                'XPIDLSRCS += bar.idl',
+                'XPIDLSRCS += biz.idl',
+                'XPIDLSRCS += foo.idl',
+            ]
+        }
 
         for var, val in expected.items():
             # print("test_variable_passthru[%s]" % (var))
             found = [str for str in lines if str.startswith(var)]
             self.assertEqual(found, val)
 
     def test_exports(self):
         """Ensure EXPORTS is written out correctly."""
--- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
@@ -1,9 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
-XPIDL_SOURCES += ['foo.idl', 'bar.idl', 'biz.idl']
+XPIDL_SOURCES += ['bar.idl', 'biz.idl', 'foo.idl']
 XPIDL_MODULE = 'module_name'
 XPIDL_FLAGS += ['-Idir1', '-Idir2', '-Idir3']
 
-ASFILES += ['tans.s', 'fans.asm']
+ASFILES += ['fans.asm', 'tans.s']
--- a/python/mozbuild/mozbuild/test/frontend/data/xpcshell_manifests/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/xpcshell_manifests/moz.build
@@ -1,14 +1,14 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-XPCSHELL_TESTS_MANIFESTS += ['foo/xpcshell.ini', 'bar/xpcshell.ini']
+XPCSHELL_TESTS_MANIFESTS += ['bar/xpcshell.ini', 'foo/xpcshell.ini']
 XPCSHELL_TESTS_MANIFESTS += ['tans/xpcshell.ini']
 
 if CONFIG['DISABLED_VAR']:
     XPCSHELL_TESTS_MANIFESTS += ['disabled_var/xpcshell.ini']
 
 if not CONFIG['DISABLED_VAR']:
     XPCSHELL_TESTS_MANIFESTS += ['enabled_var/xpcshell.ini']
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -120,18 +120,18 @@ class TestEmitterBasic(unittest.TestCase
         reader = self.reader('variable-passthru')
         objs = self.read_topsrcdir(reader)
 
         self.assertEqual(len(objs), 2)
         self.assertIsInstance(objs[0], DirectoryTraversal)
         self.assertIsInstance(objs[1], VariablePassthru)
 
         wanted = dict(
-            ASFILES=['tans.s', 'fans.asm'],
-            XPIDLSRCS=['foo.idl', 'bar.idl', 'biz.idl'],
+            ASFILES=['fans.asm', 'tans.s'],
+            XPIDLSRCS=['bar.idl', 'biz.idl', 'foo.idl'],
             XPIDL_MODULE='module_name',
             XPIDL_FLAGS=['-Idir1', '-Idir2', '-Idir3'],
             )
 
         variables = objs[1].variables
         self.assertEqual(len(variables), len(wanted))
 
         for var, val in wanted.items():
--- a/python/mozbuild/mozbuild/test/frontend/test_sandbox.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_sandbox.py
@@ -291,19 +291,19 @@ add_tier_dir('t1', 'bat', static=True)
             sandbox.exec_source('error("This is an error.")', 'test.py')
 
         e = sce.exception
         self.assertEqual(e.message, 'This is an error.')
 
     def test_substitute_config_files(self):
         sandbox = self.sandbox()
 
-        sandbox.exec_source('CONFIGURE_SUBST_FILES += ["foo", "bar"]',
+        sandbox.exec_source('CONFIGURE_SUBST_FILES += ["bar", "foo"]',
             'test.py')
-        self.assertEqual(sandbox['CONFIGURE_SUBST_FILES'], ['foo', 'bar'])
+        self.assertEqual(sandbox['CONFIGURE_SUBST_FILES'], ['bar', 'foo'])
 
     def test_invalid_utf8_substs(self):
         """Ensure invalid UTF-8 in substs is converted with an error."""
 
         config = MockConfig()
         # This is really mbcs. It's a bunch of invalid UTF-8.
         config.substs['BAD_UTF8'] = b'\x83\x81\x83\x82\x3A'
 
--- a/python/mozbuild/mozbuild/test/test_util.py
+++ b/python/mozbuild/mozbuild/test/test_util.py
@@ -16,16 +16,18 @@ from mozunit import (
 )
 
 from mozbuild.util import (
     FileAvoidWrite,
     hash_file,
     resolve_target_to_make,
     MozbuildDeletionError,
     HierarchicalStringList,
+    StrictOrderingOnAppendList,
+    UnsortedError,
 )
 
 if sys.version_info[0] == 3:
     str_type = 'str'
 else:
     str_type = 'unicode'
 
 data_path = os.path.abspath(os.path.dirname(__file__))
@@ -212,10 +214,74 @@ class TestHierarchicalStringList(unittes
                          "Expected a list of strings, not an element of "
                          "<type 'bool'>")
 
     def test_del_exports(self):
         with self.assertRaises(MozbuildDeletionError) as mde:
             self.EXPORTS.foo += ['bar.h']
             del self.EXPORTS.foo
 
+    def test_unsorted_appends(self):
+        with self.assertRaises(UnsortedError) as ee:
+            self.EXPORTS += ['foo.h', 'bar.h']
+
+
+class TestStrictOrderingOnAppendList(unittest.TestCase):
+    def test_init(self):
+        l = StrictOrderingOnAppendList()
+        self.assertEqual(len(l), 0)
+
+        l = StrictOrderingOnAppendList(['a', 'b', 'c'])
+        self.assertEqual(len(l), 3)
+
+        with self.assertRaises(UnsortedError):
+            StrictOrderingOnAppendList(['c', 'b', 'a'])
+
+        self.assertEqual(len(l), 3)
+
+    def test_extend(self):
+        l = StrictOrderingOnAppendList()
+        l.extend(['a', 'b'])
+        self.assertEqual(len(l), 2)
+        self.assertIsInstance(l, StrictOrderingOnAppendList)
+
+        with self.assertRaises(UnsortedError):
+            l.extend(['d', 'c'])
+
+        self.assertEqual(len(l), 2)
+
+    def test_slicing(self):
+        l = StrictOrderingOnAppendList()
+        l[:] = ['a', 'b']
+        self.assertEqual(len(l), 2)
+        self.assertIsInstance(l, StrictOrderingOnAppendList)
+
+        with self.assertRaises(UnsortedError):
+            l[:] = ['b', 'a']
+
+        self.assertEqual(len(l), 2)
+
+    def test_add(self):
+        l = StrictOrderingOnAppendList()
+        l2 = l + ['a', 'b']
+        self.assertEqual(len(l), 0)
+        self.assertEqual(len(l2), 2)
+        self.assertIsInstance(l2, StrictOrderingOnAppendList)
+
+        with self.assertRaises(UnsortedError):
+            l2 = l + ['b', 'a']
+
+        self.assertEqual(len(l), 0)
+
+    def test_iadd(self):
+        l = StrictOrderingOnAppendList()
+        l += ['a', 'b']
+        self.assertEqual(len(l), 2)
+        self.assertIsInstance(l, StrictOrderingOnAppendList)
+
+        with self.assertRaises(UnsortedError):
+            l += ['b', 'a']
+
+        self.assertEqual(len(l), 2)
+
+
 if __name__ == '__main__':
     main()
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -213,16 +213,97 @@ def resolve_target_to_make(topobjdir, ta
         # We append to target every iteration, so the check below
         # happens exactly once.
         if target != 'Makefile' and os.path.exists(make_path):
             return (reldir, target)
 
         target = os.path.join(os.path.basename(reldir), target)
         reldir = os.path.dirname(reldir)
 
+
+class UnsortedError(Exception):
+    def __init__(self, srtd, original):
+        assert len(srtd) == len(original)
+
+        self.sorted = srtd
+        self.original = original
+
+        for i, orig in enumerate(original):
+            s = srtd[i]
+
+            if orig != s:
+                self.i = i
+                break
+
+    def __str__(self):
+        s = StringIO()
+
+        s.write('An attempt was made to add an unsorted sequence to a list. ')
+        s.write('The incoming list is unsorted starting at element %d. ' %
+            self.i)
+        s.write('We expected "%s" but got "%s"' % (
+            self.sorted[self.i], self.original[self.i]))
+
+        return s.getvalue()
+
+
+class StrictOrderingOnAppendList(list):
+    """A list specialized for moz.build environments.
+
+    We overload the assignment and append operations to require that incoming
+    elements be ordered. This enforces cleaner style in moz.build files.
+    """
+    @staticmethod
+    def ensure_sorted(l):
+        srtd = sorted(l)
+
+        if srtd != l:
+            raise UnsortedError(srtd, l)
+
+    def __init__(self, iterable=[]):
+        StrictOrderingOnAppendList.ensure_sorted(iterable)
+
+        list.__init__(self, iterable)
+
+    def extend(self, l):
+        if not isinstance(l, list):
+            raise ValueError('List can only be extended with other list instances.')
+
+        StrictOrderingOnAppendList.ensure_sorted(l)
+
+        return list.extend(self, l)
+
+    def __setslice__(self, i, j, sequence):
+        if not isinstance(sequence, list):
+            raise ValueError('List can only be sliced with other list instances.')
+
+        StrictOrderingOnAppendList.ensure_sorted(sequence)
+
+        return list.__setslice__(self, i, j, sequence)
+
+    def __add__(self, other):
+        if not isinstance(other, list):
+            raise ValueError('Only lists can be appended to lists.')
+
+        StrictOrderingOnAppendList.ensure_sorted(other)
+
+        # list.__add__ will return a new list. We "cast" it to our type.
+        return StrictOrderingOnAppendList(list.__add__(self, other))
+
+    def __iadd__(self, other):
+        if not isinstance(other, list):
+            raise ValueError('Only lists can be appended to lists.')
+
+        StrictOrderingOnAppendList.ensure_sorted(other)
+
+        list.__iadd__(self, other)
+
+        return self
+
+
 class MozbuildDeletionError(Exception):
     pass
 
 class HierarchicalStringList(object):
     """A hierarchy of lists of strings.
 
     Each instance of this object contains a list of strings, which can be set or
     appended to. A sub-level of the hierarchy is also an instance of this class,
@@ -236,17 +317,17 @@ class HierarchicalStringList(object):
 
     In this case, we have 3 instances (EXPORTS, EXPORTS.mozilla, and
     EXPORTS.mozilla.dom), and the first and last each have one element in their
     list.
     """
     __slots__ = ('_strings', '_children')
 
     def __init__(self):
-        self._strings = []
+        self._strings = StrictOrderingOnAppendList()
         self._children = {}
 
     def get_children(self):
         return self._children
 
     def get_strings(self):
         return self._strings
 
--- a/testing/mochitest/b2g.json
+++ b/testing/mochitest/b2g.json
@@ -22,16 +22,17 @@
     "dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html":"Test timed out.",
     "dom/encoding/test/test_stringencoding.html":"Test timed out on b2g board",
 
     "content/events/test/test_bug615597.html":"", 
     "content/html/content/test/forms/test_input_sanitization.html":"",
     "dom/tests/mochitest/ajax/jquery/test_jQuery.html":"",
  
     "content/base/test/test_CSP_inlinescript.html":"",
+    "content/base/test/test_CSP_inlinestyle.html":"",
     "content/base/test/test_XHRSendData.html":"",
     "content/base/test/test_XHR_parameters.html":"",
     "content/base/test/test_XHR_system.html":"",
     "content/base/test/test_base.xhtml":"",
     "content/base/test/test_bug338583.html":"",
     "content/base/test/test_bug372086.html":"",
     "content/base/test/test_bug466080.html":"",
     "content/base/test/test_bug475156.html":"",
--- a/toolkit/components/social/test/xpcshell/head.js
+++ b/toolkit/components/social/test/xpcshell/head.js
@@ -1,16 +1,19 @@
 /* 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/. */
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
+// Ensure history is enabled.
+Services.prefs.setBoolPref("places.history.enabled", true);
+
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
   "resource://gre/modules/commonjs/sdk/core/promise.js");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
   "resource://gre/modules/PlacesUtils.jsm");
 
 const MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
 const gProfD = do_get_profile();
 
--- a/toolkit/mozapps/update/common/moz.build
+++ b/toolkit/mozapps/update/common/moz.build
@@ -9,13 +9,13 @@ MODULE = 'libupdatecommon'
 EXPORTS += [
     'readstrings.h',
     'updatedefines.h',
     'updatelogging.h',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXPORTS += [
-        'updatehelper.h',
-        'updatehelper.cpp',
+        'pathhash.h',
         'uachelper.h',
-        'pathhash.h',
+        'updatehelper.cpp',
+        'updatehelper.h',
     ]
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -15,23 +15,23 @@ if toolkit in ('qt', 'android', 'gonk', 
 
 if toolkit == 'windows':
     DIRS += ['windows']
 
     XPIDL_SOURCES += [
         'nsIJumpListBuilder.idl',
         'nsIJumpListItem.idl',
         'nsIPrintSettingsWin.idl',
+        'nsITaskbarOverlayIconController.idl',
         'nsITaskbarPreview.idl',
+        'nsITaskbarPreviewButton.idl',
+        'nsITaskbarPreviewController.idl',
+        'nsITaskbarProgress.idl',
         'nsITaskbarTabPreview.idl',
         'nsITaskbarWindowPreview.idl',
-        'nsITaskbarPreviewController.idl',
-        'nsITaskbarPreviewButton.idl',
-        'nsITaskbarProgress.idl',
-        'nsITaskbarOverlayIconController.idl',
         'nsIWinTaskbar.idl',
     ]
 elif toolkit == 'cocoa':
     XPIDL_SOURCES += [
         'nsIMacDockSupport.idl',
         'nsIMacWebAppUtils.idl',
         'nsIStandaloneNativeMenu.idl',
         'nsITaskbarProgress.idl',
--- a/widget/nsGUIEvent.h
+++ b/widget/nsGUIEvent.h
@@ -344,17 +344,19 @@ enum nsEventStructType {
 #define NS_SIMPLE_GESTURE_MAGNIFY_START  (NS_SIMPLE_GESTURE_EVENT_START+4)
 #define NS_SIMPLE_GESTURE_MAGNIFY_UPDATE (NS_SIMPLE_GESTURE_EVENT_START+5)
 #define NS_SIMPLE_GESTURE_MAGNIFY        (NS_SIMPLE_GESTURE_EVENT_START+6)
 #define NS_SIMPLE_GESTURE_ROTATE_START   (NS_SIMPLE_GESTURE_EVENT_START+7)
 #define NS_SIMPLE_GESTURE_ROTATE_UPDATE  (NS_SIMPLE_GESTURE_EVENT_START+8)
 #define NS_SIMPLE_GESTURE_ROTATE         (NS_SIMPLE_GESTURE_EVENT_START+9)
 #define NS_SIMPLE_GESTURE_TAP            (NS_SIMPLE_GESTURE_EVENT_START+10)
 #define NS_SIMPLE_GESTURE_PRESSTAP       (NS_SIMPLE_GESTURE_EVENT_START+11)
-#define NS_SIMPLE_GESTURE_EDGEUI         (NS_SIMPLE_GESTURE_EVENT_START+12)
+#define NS_SIMPLE_GESTURE_EDGE_STARTED   (NS_SIMPLE_GESTURE_EVENT_START+12)
+#define NS_SIMPLE_GESTURE_EDGE_CANCELED  (NS_SIMPLE_GESTURE_EVENT_START+13)
+#define NS_SIMPLE_GESTURE_EDGE_COMPLETED (NS_SIMPLE_GESTURE_EVENT_START+14)
 
 // These are used to send native events to plugins.
 #define NS_PLUGIN_EVENT_START            3600
 #define NS_PLUGIN_INPUT_EVENT            (NS_PLUGIN_EVENT_START)
 #define NS_PLUGIN_FOCUS_EVENT            (NS_PLUGIN_EVENT_START+1)
 
 // Events to manipulate selection (nsSelectionEvent)
 #define NS_SELECTION_EVENT_START        3700
@@ -396,16 +398,17 @@ enum nsEventStructType {
 
 #define NS_SMIL_TIME_EVENT_START     4300
 #define NS_SMIL_BEGIN                (NS_SMIL_TIME_EVENT_START)
 #define NS_SMIL_END                  (NS_SMIL_TIME_EVENT_START + 1)
 #define NS_SMIL_REPEAT               (NS_SMIL_TIME_EVENT_START + 2)
 
 #define NS_WEBAUDIO_EVENT_START      4350
 #define NS_AUDIO_PROCESS             (NS_WEBAUDIO_EVENT_START)
+#define NS_AUDIO_COMPLETE            (NS_WEBAUDIO_EVENT_START + 1)
 
 // script notification events
 #define NS_NOTIFYSCRIPT_START        4500
 #define NS_BEFORE_SCRIPT_EXECUTE     (NS_NOTIFYSCRIPT_START)
 #define NS_AFTER_SCRIPT_EXECUTE      (NS_NOTIFYSCRIPT_START+1)
 
 #define NS_PRINT_EVENT_START         4600
 #define NS_BEFOREPRINT               (NS_PRINT_EVENT_START)
--- a/widget/windows/winrt/MetroInput.cpp
+++ b/widget/windows/winrt/MetroInput.cpp
@@ -286,17 +286,19 @@ MetroInput::MetroInput(MetroWidget* aWid
 
   mTokenPointerPressed.value = 0;
   mTokenPointerReleased.value = 0;
   mTokenPointerMoved.value = 0;
   mTokenPointerEntered.value = 0;
   mTokenPointerExited.value = 0;
   mTokenPointerWheelChanged.value = 0;
   mTokenAcceleratorKeyActivated.value = 0;
-  mTokenEdgeGesture.value = 0;
+  mTokenEdgeStarted.value = 0;
+  mTokenEdgeCanceled.value = 0;
+  mTokenEdgeCompleted.value = 0;
   mTokenManipulationStarted.value = 0;
   mTokenManipulationUpdated.value = 0;
   mTokenManipulationCompleted.value = 0;
   mTokenTapped.value = 0;
   mTokenRightTapped.value = 0;
 
   mTouches.Init();
 
@@ -360,30 +362,94 @@ MetroInput::OnAcceleratorKeyActivated(UI
     case UI::Core::CoreAcceleratorKeyEventType_UnicodeCharacter:
       OnCharacterReceived(vkey, keyStatus);
       break;
   }
 
   return S_OK;
 }
 
-// "Edge Gesture" event.  This indicates that the user has swiped in from the
-// top or bottom of the screen and means we should show our context UI.  This
-// event can also be triggered through keyboard input.
-// According to MSDN, this event will only be received through touch
-// (user swipes in from edge) or from keyboard (user presses Win+Z)
+/**
+ * When the user swipes her/his finger in from the top of the screen,
+ * we receive this event.
+ *
+ * @param sender the CoreDispatcher that fired this event
+ * @param aArgs the event-specific args we use when processing this event
+ * @returns S_OK
+ */
+HRESULT
+MetroInput::OnEdgeGestureStarted(UI::Input::IEdgeGesture* sender,
+                                 UI::Input::IEdgeGestureEventArgs* aArgs)
+{
+#ifdef DEBUG_INPUT
+  LogFunction();
+#endif
+  nsSimpleGestureEvent geckoEvent(true,
+                                  NS_SIMPLE_GESTURE_EDGE_STARTED,
+                                  mWidget.Get(),
+                                  0,
+                                  0.0);
+  mModifierKeyState.Update();
+  mModifierKeyState.InitInputEvent(geckoEvent);
+  geckoEvent.time = ::GetMessageTime();
+
+  geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
+
+  DispatchEventIgnoreStatus(&geckoEvent);
+  return S_OK;
+}
+
+/**
+ * This event can be received if the user swipes her/his finger back to
+ * the top of the screen, or continues moving her/his finger such that
+ * the movement is interpreted as a "grab this window" gesture
+ *
+ * @param sender the CoreDispatcher that fired this event
+ * @param aArgs the event-specific args we use when processing this event
+ * @returns S_OK
+ */
+HRESULT
+MetroInput::OnEdgeGestureCanceled(UI::Input::IEdgeGesture* sender,
+                                  UI::Input::IEdgeGestureEventArgs* aArgs)
+{
+#ifdef DEBUG_INPUT
+  LogFunction();
+#endif
+  nsSimpleGestureEvent geckoEvent(true,
+                                  NS_SIMPLE_GESTURE_EDGE_CANCELED,
+                                  mWidget.Get(),
+                                  0,
+                                  0.0);
+  mModifierKeyState.Update();
+  mModifierKeyState.InitInputEvent(geckoEvent);
+  geckoEvent.time = ::GetMessageTime();
+
+  geckoEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
+
+  DispatchEventIgnoreStatus(&geckoEvent);
+  return S_OK;
+}
+
+/**
+ * This event is received if the user presses ctrl+Z or lifts her/his
+ * finger after causing an EdgeGestureStarting event to fire.
+ *
+ * @param sender the CoreDispatcher that fired this event
+ * @param aArgs the event-specific args we use when processing this event
+ * @returns S_OK
+ */
 HRESULT
 MetroInput::OnEdgeGestureCompleted(UI::Input::IEdgeGesture* sender,
                                    UI::Input::IEdgeGestureEventArgs* aArgs)
 {
 #ifdef DEBUG_INPUT
   LogFunction();
 #endif
   nsSimpleGestureEvent geckoEvent(true,
-                                  NS_SIMPLE_GESTURE_EDGEUI,
+                                  NS_SIMPLE_GESTURE_EDGE_COMPLETED,
                                   mWidget.Get(),
                                   0,
                                   0.0);
   mModifierKeyState.Update();
   mModifierKeyState.InitInputEvent(geckoEvent);
   geckoEvent.time = ::GetMessageTime();
 
   UI::Input::EdgeGestureKind value;
@@ -1362,17 +1428,19 @@ MetroInput::UnregisterInputEvents() {
   // Unregister ourselves for the edge swipe event
   WRL::ComPtr<UI::Input::IEdgeGestureStatics> edgeStatics;
   if (SUCCEEDED(Foundation::GetActivationFactory(
         WRL::Wrappers::HStringReference(
               RuntimeClass_Windows_UI_Input_EdgeGesture).Get(),
       edgeStatics.GetAddressOf()))) {
     WRL::ComPtr<UI::Input::IEdgeGesture> edge;
     if (SUCCEEDED(edgeStatics->GetForCurrentView(edge.GetAddressOf()))) {
-      edge->remove_Completed(mTokenEdgeGesture);
+      edge->remove_Starting(mTokenEdgeStarted);
+      edge->remove_Canceled(mTokenEdgeCanceled);
+      edge->remove_Completed(mTokenEdgeCompleted);
     }
   }
 
   // Unregister ourselves from the AcceleratorKeyActivated event
   WRL::ComPtr<ICoreAcceleratorKeys> coreAcceleratorKeys;
   if (SUCCEEDED(mDispatcher.As<ICoreAcceleratorKeys>(&coreAcceleratorKeys))) {
     coreAcceleratorKeys->remove_AcceleratorKeyActivated(
                             mTokenAcceleratorKeyActivated);
@@ -1689,21 +1757,33 @@ MetroInput::RegisterInputEvents()
   Foundation::GetActivationFactory(
             WRL::Wrappers::HStringReference(
                     RuntimeClass_Windows_UI_Input_EdgeGesture)
             .Get(),
             edgeStatics.GetAddressOf());
   WRL::ComPtr<UI::Input::IEdgeGesture> edge;
   edgeStatics->GetForCurrentView(edge.GetAddressOf());
 
+  edge->add_Starting(
+      WRL::Callback<EdgeGestureHandler>(
+                                  this,
+                                  &MetroInput::OnEdgeGestureStarted).Get(),
+      &mTokenEdgeStarted);
+
+  edge->add_Canceled(
+      WRL::Callback<EdgeGestureHandler>(
+                                  this,
+                                  &MetroInput::OnEdgeGestureCanceled).Get(),
+      &mTokenEdgeCanceled);
+
   edge->add_Completed(
       WRL::Callback<EdgeGestureHandler>(
                                   this,
                                   &MetroInput::OnEdgeGestureCompleted).Get(),
-      &mTokenEdgeGesture);
+      &mTokenEdgeCompleted);
 
   // Set up our Gesture Recognizer to raise events for the gestures we
   // care about
   mGestureRecognizer->put_GestureSettings(
             UI::Input::GestureSettings::GestureSettings_Tap
           | UI::Input::GestureSettings::GestureSettings_DoubleTap
           | UI::Input::GestureSettings::GestureSettings_RightTap
           | UI::Input::GestureSettings::GestureSettings_Hold
--- a/widget/windows/winrt/MetroInput.h
+++ b/widget/windows/winrt/MetroInput.h
@@ -127,16 +127,20 @@ public:
                          IPointerEventArgs* aArgs);
   HRESULT OnPointerEntered(ICoreWindow* aSender,
                            IPointerEventArgs* aArgs);
   HRESULT OnPointerExited(ICoreWindow* aSender,
                           IPointerEventArgs* aArgs);
 
   // The Edge gesture event is special.  It does not come from our window
   // or from our GestureRecognizer.
+  HRESULT OnEdgeGestureStarted(IEdgeGesture* aSender,
+                               IEdgeGestureEventArgs* aArgs);
+  HRESULT OnEdgeGestureCanceled(IEdgeGesture* aSender,
+                                IEdgeGestureEventArgs* aArgs);
   HRESULT OnEdgeGestureCompleted(IEdgeGesture* aSender,
                                  IEdgeGestureEventArgs* aArgs);
 
   // These events are raised by our GestureRecognizer in response to input
   // events that we forward to it.  The ManipulationStarted,
   // ManipulationUpdated, and ManipulationEnded events are sent during
   // complex input gestures including pinch, swipe, and rotate.  Note that
   // all three gestures can occur simultaneously.
@@ -258,19 +262,21 @@ private:
   EventRegistrationToken mTokenPointerWheelChanged;
 
   // This registration token is set when we register ourselves to handle
   // the `AcceleratorKeyActivated` event received from our CoreDispatcher.
   // When we are done, we must unregister ourselves with the CoreDispatcher
   // using this token.
   EventRegistrationToken mTokenAcceleratorKeyActivated;
 
-  // When we register ourselves to handle the edge gesture, we receive a
-  // token.  When we unregister ourselves, we must use the token we received.
-  EventRegistrationToken mTokenEdgeGesture;
+  // When we register ourselves to handle edge gestures, we receive a
+  // token. To we unregister ourselves, we must use the token we received.
+  EventRegistrationToken mTokenEdgeStarted;
+  EventRegistrationToken mTokenEdgeCanceled;
+  EventRegistrationToken mTokenEdgeCompleted;
 
   // These registration tokens are set when we register ourselves to receive
   // events from our GestureRecognizer.  It's probably not a huge deal if we
   // don't unregister ourselves with our GestureRecognizer before destroying
   // the GestureRecognizer, but it can't hurt.
   EventRegistrationToken mTokenManipulationStarted;
   EventRegistrationToken mTokenManipulationUpdated;
   EventRegistrationToken mTokenManipulationCompleted;