Merge last PGO-green changeset of mozilla-inbound to mozilla-central
authorEd Morley <emorley@mozilla.com>
Tue, 16 Oct 2012 09:08:39 +0100
changeset 110511 8f145599e4bf81de2d0421c071b5863175a585dc
parent 110367 cd3270dc35cc4d623a62ba6f0d49d20964d87fa0 (current diff)
parent 110510 f0f1d1dac95394978fb043c6cedf072c897376fe (diff)
child 110512 fc883f5a1a0830fa405879998e040cd8cb651c0b
child 110526 c60f1eb791b3a29d219763d0cf93c7625b656521
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone19.0a1
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
content/canvas/test/test_mozGetAsFile.html
layout/base/nsFrameIterator.cpp
layout/base/nsFrameIterator.h
security/manager/tools/getHSTSPreloadList.py
xpcom/base/dmd.h
--- a/Makefile.in
+++ b/Makefile.in
@@ -75,17 +75,17 @@ DIST_GARBAGE = config.cache config.log c
    netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
    $(topsrcdir)/.mozconfig.mk $(topsrcdir)/.mozconfig.out
 
 default alldep all:: $(topsrcdir)/configure config.status
 	$(RM) -r $(DIST)/sdk
 	$(RM) -r $(DIST)/include
 	$(RM) -r $(DIST)/private
 	$(RM) -r $(DIST)/public
-	$(RM) $(DIST)/chrome.manifest
+	$(RM) $(DIST)/bin/chrome.manifest $(DIST)/bin/components/components.manifest
 	$(RM) -r _tests
 
 $(topsrcdir)/configure: $(topsrcdir)/configure.in
 	@echo "STOP!  configure.in has changed, and your configure is out of date."
 	@echo "Please rerun autoconf and re-configure your build directory."
 	@echo "To ignore this message, touch 'configure' in the source directory,"
 	@echo "but your build might not succeed."
 	@exit 1
--- a/accessible/src/base/AccEvent.h
+++ b/accessible/src/base/AccEvent.h
@@ -57,17 +57,17 @@ public:
      // eDoNotEmit : This event is confirmed as a duplicate, do not emit it.
      eDoNotEmit
   };
 
   // Initialize with an nsIAccessible
   AccEvent(uint32_t aEventType, Accessible* aAccessible,
            EIsFromUserInput aIsFromUserInput = eAutoDetect,
            EEventRule aEventRule = eRemoveDupes);
-  // Initialize with an nsIDOMNode
+  // Initialize with an nsINode
   AccEvent(uint32_t aEventType, nsINode* aNode,
            EIsFromUserInput aIsFromUserInput = eAutoDetect,
            EEventRule aEventRule = eRemoveDupes);
   virtual ~AccEvent() {}
 
   // AccEvent
   uint32_t GetEventType() const { return mEventType; }
   EEventRule GetEventRule() const { return mEventRule; }
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/AccTypes.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#pragma once
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * Accessible object types used when creating an accessible based on the frame.
+ */
+enum AccType {
+  eNoAccessible,
+  eHTMLBRAccessible,
+  eHTMLButtonAccessible,
+  eHTMLCanvasAccessible,
+  eHTMLCaptionAccessible,
+  eHTMLCheckboxAccessible,
+  eHTMLComboboxAccessible,
+  eHTMLFileInputAccessible,
+  eHTMLGroupboxAccessible,
+  eHTMLHRAccessible,
+  eHTMLImageMapAccessible,
+  eHTMLLabelAccessible,
+  eHTMLLiAccessible,
+  eHTMLSelectListAccessible,
+  eHTMLMediaAccessible,
+  eHTMLObjectFrameAccessible,
+  eHTMLRadioButtonAccessible,
+  eHTMLTableAccessible,
+  eHTMLTableCellAccessible,
+  eHTMLTableRowAccessible,
+  eHTMLTextFieldAccessible,
+  eHyperTextAccessible,
+  eImageAccessible,
+  eOuterDocAccessible,
+  eTextLeafAccessible
+};
+}
+}
+
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -53,16 +53,17 @@ EXPORTS = \
   nsAccessibilityService.h \
   nsAccessNode.h \
   $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/a11y
 
 EXPORTS_mozilla/a11y = \
   FocusManager.h \
+  AccTypes.h \
   States.h \
   Role.h \
   $(NULL)
 
 ifdef MOZ_DEBUG
 EXPORTS_mozilla/a11y += \
   Logging.h \
   $(NULL)
--- a/accessible/src/base/nsAccDocManager.h
+++ b/accessible/src/base/nsAccDocManager.h
@@ -35,17 +35,24 @@ public:
    */
   DocAccessible* GetDocAccessible(nsIDocument* aDocument);
 
   /**
    * Return document accessible for the given presshell.
    */
   DocAccessible* GetDocAccessible(const nsIPresShell* aPresShell)
   {
-    return aPresShell ? GetDocAccessible(aPresShell->GetDocument()) : nullptr;
+    if (!aPresShell)
+      return nullptr;
+
+    DocAccessible* doc = aPresShell->GetDocAccessible();
+    if (doc)
+      return doc;
+
+    return GetDocAccessible(aPresShell->GetDocument());
   }
 
   /**
    * Search through all document accessibles for an accessible with the given
    * unique id.
    */
   Accessible* FindAccessibleInCache(nsINode* aNode) const;
 
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -11,17 +11,16 @@
 #include "nsIAccessibleText.h"
 
 #include "nsAccessibilityService.h"
 #include "nsCoreUtils.h"
 
 #include "mozilla/dom/Element.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
-#include "nsIDOMNode.h"
 #include "nsIPersistentProperties2.h"
 #include "nsIPresShell.h"
 #include "nsPoint.h"
 
 class nsAccessNode;
 class Accessible;
 class HyperTextAccessible;
 class DocAccessible;
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -163,311 +163,81 @@ nsAccessibilityService::GetRootDocumentA
       return aCanCreate ?
         GetDocAccessible(documentNode) : GetDocAccessibleFromCache(documentNode);
     }
   }
   return nullptr;
 }
 
 already_AddRefed<Accessible>
-nsAccessibilityService::CreateOuterDocAccessible(nsIContent* aContent,
-                                                 nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new OuterDocAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLButtonAccessible(nsIContent* aContent,
-                                                   nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLButtonAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLLIAccessible(nsIContent* aContent,
-                                               nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLLIAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHyperTextAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HyperTextAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLCheckboxAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLCheckboxAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLComboboxAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLComboboxAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLCanvasAccessible(nsIContent* aContent,
-                                                   nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLCanvasAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLFileInputAccessible(nsIContent* aContent,
-                                                      nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLFileInputAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLImageAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new ImageAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLImageMapAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLImageMapAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLGroupboxAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLGroupboxAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLListboxAccessible(nsIContent* aContent,
-                                                    nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLSelectListAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLMediaAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new EnumRoleAccessible(aContent, GetDocAccessible(aPresShell),
-                           roles::GROUPING);
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame,
                                                         nsIContent* aContent,
-                                                        nsIPresShell* aPresShell)
+                                                        DocAccessible* aDoc)
 {
   // We can have several cases here:
   // 1) a text or html embedded document where the contentDocument variable in
   //    the object element holds the content;
   // 2) web content that uses a plugin, which means we will have to go to
   //    the plugin to get the accessible content;
   // 3) an image or imagemap, where the image frame points back to the object
   //    element DOMNode.
 
   if (aFrame->GetRect().IsEmpty())
     return nullptr;
 
-
   // 1) for object elements containing either HTML or TXT documents
   nsCOMPtr<nsIDOMHTMLObjectElement> obj(do_QueryInterface(aContent));
   if (obj) {
     nsCOMPtr<nsIDOMDocument> domDoc;
     obj->GetContentDocument(getter_AddRefs(domDoc));
-    if (domDoc)
-      return CreateOuterDocAccessible(aContent, aPresShell);
+    if (domDoc) {
+      Accessible* newAcc = new OuterDocAccessible(aContent, aDoc);
+      NS_ADDREF(newAcc);
+      return newAcc;
+    }
   }
 
 #if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
   // 2) for plugins
   nsRefPtr<nsNPAPIPluginInstance> pluginInstance;
   if (NS_SUCCEEDED(aFrame->GetPluginInstance(getter_AddRefs(pluginInstance))) &&
       pluginInstance) {
 #ifdef XP_WIN
     // Note: pluginPort will be null if windowless.
     HWND pluginPort = nullptr;
     aFrame->GetPluginPort(&pluginPort);
 
     Accessible* accessible =
-      new HTMLWin32ObjectOwnerAccessible(aContent, GetDocAccessible(aPresShell),
-                                         pluginPort);
+      new HTMLWin32ObjectOwnerAccessible(aContent, aDoc, pluginPort);
     NS_ADDREF(accessible);
     return accessible;
 
 #elif MOZ_ACCESSIBILITY_ATK
     if (!AtkSocketAccessible::gCanEmbed)
       return nullptr;
 
     nsCString plugId;
     nsresult rv = pluginInstance->GetValueFromPlugin(
       NPPVpluginNativeAccessibleAtkPlugId, &plugId);
     if (NS_SUCCEEDED(rv) && !plugId.IsEmpty()) {
       AtkSocketAccessible* socketAccessible =
-        new AtkSocketAccessible(aContent, GetDocAccessible(aPresShell),
-                                plugId);
+        new AtkSocketAccessible(aContent, aDoc, plugId);
 
       NS_ADDREF(socketAccessible);
       return socketAccessible;
     }
 #endif
   }
 #endif
 
   // 3) for images and imagemaps, or anything else with a child frame
   // we have the object frame, get the image frame
-  nsIFrame* frame = aFrame->GetFirstPrincipalChild();
-  return frame ? frame->CreateAccessible() : nullptr;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLRadioButtonAccessible(nsIContent* aContent,
-                                                        nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLRadioButtonAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLTableAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLTableAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLTableCellAccessible(nsIContent* aContent,
-                                                      nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLTableCellAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLTableRowAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new EnumRoleAccessible(aContent, GetDocAccessible(aPresShell), roles::ROW);
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateTextLeafAccessible(nsIContent* aContent,
-                                                 nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new TextLeafAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLTextFieldAccessible(nsIContent* aContent,
-                                                      nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLTextFieldAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLLabelAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLLabelAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLHRAccessible(nsIContent* aContent,
-                                               nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLHRAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLBRAccessible(nsIContent* aContent,
-                                               nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLBRAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLCaptionAccessible(nsIContent* aContent,
-                                                    nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLCaptionAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
+  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
+  return childFrame ? CreateAccessibleByFrameType(childFrame, aContent, aDoc) :
+    nullptr;
 }
 
 void
 nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
                                              nsIContent* aContainer,
                                              nsIContent* aStartChild,
                                              nsIContent* aEndChild)
 {
@@ -948,17 +718,17 @@ nsAccessibilityService::GetOrCreateAcces
     frame->GetRenderedText(&text, nullptr, nullptr, 0, UINT32_MAX);
     if (text.IsEmpty()) {
       if (aIsSubtreeHidden)
         *aIsSubtreeHidden = true;
 
       return nullptr;
     }
 
-    newAcc = frame->CreateAccessible();
+    newAcc = CreateAccessibleByFrameType(frame, content, aDoc);
     if (aDoc->BindToDocument(newAcc, nullptr)) {
       newAcc->AsTextLeaf()->SetText(text);
       return newAcc;
     }
 
     return nullptr;
   }
 
@@ -1105,17 +875,17 @@ nsAccessibilityService::GetOrCreateAcces
           // is no better place:
           if (aIsSubtreeHidden)
             *aIsSubtreeHidden = true;
 
           return nullptr;
         }
 
         // Try using frame to do it.
-        newAcc = frame->CreateAccessible();
+        newAcc = CreateAccessibleByFrameType(frame, content, aDoc);
       }
     }
   }
 
   if (!newAcc) {
     // Elements may implement nsIAccessibleProvider via XBL. This allows them to
     // say what kind of accessible to create.
     newAcc = CreateAccessibleByType(content, aDoc);
@@ -1654,16 +1424,105 @@ nsAccessibilityService::CreateHTMLAccess
       new HTMLProgressMeterAccessible(aContent, aDoc);
     NS_ADDREF(accessible);
     return accessible;
   }
 
   return nullptr;
  }
 
+already_AddRefed<Accessible>
+nsAccessibilityService::CreateAccessibleByFrameType(nsIFrame* aFrame,
+                                                    nsIContent* aContent,
+                                                    DocAccessible* aDoc)
+{
+  nsRefPtr<Accessible> newAcc;
+  switch (aFrame->AccessibleType()) {
+    case eNoAccessible:
+      return nullptr;
+    case eHTMLBRAccessible:
+      newAcc = new HTMLBRAccessible(aContent, aDoc);
+      break;
+    case eHTMLButtonAccessible:
+      newAcc = new HTMLButtonAccessible(aContent, aDoc);
+      break;
+    case eHTMLCanvasAccessible:
+      newAcc = new HTMLCanvasAccessible(aContent, aDoc);
+      break;
+    case eHTMLCaptionAccessible:
+      newAcc = new HTMLCaptionAccessible(aContent, aDoc);
+      break;
+    case eHTMLCheckboxAccessible:
+      newAcc = new HTMLCheckboxAccessible(aContent, aDoc);
+      break;
+    case eHTMLComboboxAccessible:
+      newAcc = new HTMLComboboxAccessible(aContent, aDoc);
+      break;
+    case eHTMLFileInputAccessible:
+      newAcc = new HTMLFileInputAccessible(aContent, aDoc);
+      break;
+    case eHTMLGroupboxAccessible:
+      newAcc = new HTMLGroupboxAccessible(aContent, aDoc);
+      break;
+    case eHTMLHRAccessible:
+      newAcc = new HTMLHRAccessible(aContent, aDoc);
+      break;
+    case eHTMLImageMapAccessible:
+      newAcc = new HTMLImageMapAccessible(aContent, aDoc);
+      break;
+    case eHTMLLabelAccessible:
+      newAcc = new HTMLLabelAccessible(aContent, aDoc);
+      break;
+    case eHTMLLiAccessible:
+      newAcc = new HTMLLIAccessible(aContent, aDoc);
+      break;
+    case eHTMLSelectListAccessible:
+      newAcc = new HTMLSelectListAccessible(aContent, aDoc);
+      break;
+    case eHTMLMediaAccessible:
+      newAcc = new EnumRoleAccessible(aContent, aDoc, roles::GROUPING);
+      break;
+    case eHTMLObjectFrameAccessible: {
+      nsObjectFrame* objectFrame = do_QueryFrame(aFrame);
+      newAcc = CreateHTMLObjectFrameAccessible(objectFrame, aContent, aDoc);
+      break;
+    }
+
+    case eHTMLRadioButtonAccessible:
+      newAcc = new HTMLRadioButtonAccessible(aContent, aDoc);
+      break;
+    case eHTMLTableAccessible:
+      newAcc = new HTMLTableAccessibleWrap(aContent, aDoc);
+      break;
+    case eHTMLTableCellAccessible:
+      newAcc = new HTMLTableCellAccessibleWrap(aContent, aDoc);
+      break;
+    case eHTMLTableRowAccessible:
+      newAcc = new EnumRoleAccessible(aContent, aDoc, roles::ROW);
+      break;
+    case eHTMLTextFieldAccessible:
+      newAcc = new HTMLTextFieldAccessible(aContent, aDoc);
+      break;
+    case eHyperTextAccessible:
+      newAcc = new HyperTextAccessibleWrap(aContent, aDoc);
+      break;
+    case eImageAccessible:
+      newAcc = new ImageAccessibleWrap(aContent, aDoc);
+      break;
+    case eOuterDocAccessible:
+      newAcc = new OuterDocAccessible(aContent, aDoc);
+      break;
+    case eTextLeafAccessible:
+      newAcc = new TextLeafAccessibleWrap(aContent, aDoc);
+      break;
+  }
+
+  return newAcc.forget();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibilityService (DON'T put methods here)
 
 Accessible*
 nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
 {
 #ifdef MOZ_ACCESSIBILITY_ATK
   ApplicationAccessible* applicationAcc = ApplicationAcc();
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -11,16 +11,17 @@
 #include "a11yGeneric.h"
 #include "nsAccDocManager.h"
 
 #include "mozilla/a11y/FocusManager.h"
 
 #include "nsIObserver.h"
 
 class nsImageFrame;
+class nsObjectFrame;
 class nsITreeView;
 
 namespace mozilla {
 namespace a11y {
 
 class ApplicationAccessible;
 
 /**
@@ -75,64 +76,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLERETRIEVAL
   NS_DECL_NSIOBSERVER
 
   // nsIAccessibilityService
   virtual Accessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
                                                 bool aCanCreate);
   already_AddRefed<Accessible>
-    CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLBRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLCanvasAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLCaptionAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLCheckboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLComboboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLFileInputAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLGroupboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLHRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLImageAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLImageMapAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLListboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLMediaAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
     CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame, nsIContent* aContent,
-                                    nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLRadioButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLTableAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLTableCellAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLTableRowAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateTextLeafAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLTextFieldAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHyperTextAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateOuterDocAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
+                                    DocAccessible* aDoc);
 
   /**
    * Adds/remove ATK root accessible for gtk+ native window to/from children
    * of the application accessible.
    */
   virtual Accessible* AddNativeRootAccessible(void* aAtkAccessible);
   virtual void RemoveNativeRootAccessible(Accessible* aRootAccessible);
 
@@ -235,16 +190,23 @@ private:
    * Create accessible for HTML node by tag name.
    */
   already_AddRefed<Accessible>
     CreateHTMLAccessibleByMarkup(nsIFrame* aFrame, nsIContent* aContent,
                                  DocAccessible* aDoc,
                                  bool aIsLegalPartOfHTMLTable);
 
   /**
+   * Create an accessible whose type depends on the given frame.
+   */
+  already_AddRefed<Accessible>
+    CreateAccessibleByFrameType(nsIFrame* aFrame, nsIContent* aContent,
+                                DocAccessible* aDoc);
+
+  /**
    * Create accessible if parent is a deck frame.
    */
   already_AddRefed<Accessible>
     CreateAccessibleForDeckChild(nsIFrame* aFrame, nsIContent* aContent,
                                  DocAccessible* aDoc);
 
 #ifdef MOZ_XUL
   /**
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -476,36 +476,16 @@ nsCoreUtils::IsErrorPage(nsIDocument *aD
   uri->GetPath(path);
 
   NS_NAMED_LITERAL_CSTRING(neterror, "neterror");
   NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
 
   return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
 }
 
-already_AddRefed<nsIDOMNode>
-nsCoreUtils::GetDOMNodeForContainer(nsIDocShellTreeItem *aContainer)
-{
-  nsCOMPtr<nsIDocShell> shell = do_QueryInterface(aContainer);
-
-  nsCOMPtr<nsIContentViewer> cv;
-  shell->GetContentViewer(getter_AddRefs(cv));
-
-  if (!cv)
-    return nullptr;
-
-  nsIDocument* doc = cv->GetDocument();
-  if (!doc)
-    return nullptr;
-
-  nsIDOMNode* node = nullptr;
-  CallQueryInterface(doc, &node);
-  return node;
-}
-
 bool
 nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID)
 {
   nsIAtom *idAttribute = aContent->GetIDAttributeName();
   return idAttribute ? aContent->GetAttr(kNameSpaceID_None, idAttribute, aID) : false;
 }
 
 bool
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -11,17 +11,16 @@
 #include "nsIBoxObject.h"
 #include "nsIPresShell.h"
 
 #include "nsIDOMDOMStringList.h"
 #include "nsPoint.h"
 #include "nsTArray.h"
 
 class nsRange;
-class nsIDOMNode;
 class nsIFrame;
 class nsIDocShellTreeItem;
 class nsITreeColumn;
 class nsITreeBoxObject;
 class nsIWidget;
 
 /**
  * Core utils.
@@ -205,22 +204,16 @@ public:
    * Return presShell for the document containing the given DOM node.
    */
   static nsIPresShell *GetPresShellFor(nsINode *aNode)
   {
     return aNode->OwnerDoc()->GetShell();
   }
 
   /**
-   * Return document node for the given document shell tree item.
-   */
-  static already_AddRefed<nsIDOMNode>
-    GetDOMNodeForContainer(nsIDocShellTreeItem *aContainer);
-
-  /**
    * Get the ID for an element, in some types of XML this may not be the ID attribute
    * @param aContent  Node to get the ID for
    * @param aID       Where to put ID string
    * @return          true if there is an ID set for this node
    */
   static bool GetID(nsIContent *aContent, nsAString& aID);
 
   /**
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -500,16 +500,18 @@ public:
   inline bool IsXULDeck() const { return mFlags & eXULDeckAccessible; }
 
   inline bool IsListControl() const { return mFlags & eListControlAccessible; }
 
   inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
 
   inline bool IsMenuPopup() const { return mFlags & eMenuPopupAccessible; }
 
+  inline bool IsProgress() const { return mFlags & eProgressAccessible; }
+
   inline bool IsRoot() const { return mFlags & eRootAccessible; }
   mozilla::a11y::RootAccessible* AsRoot();
 
   virtual mozilla::a11y::TableAccessible* AsTable() { return nullptr; }
 
   virtual mozilla::a11y::TableCellAccessible* AsTableCell() { return nullptr; }
 
   inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
@@ -771,20 +773,21 @@ protected:
     eHyperTextAccessible = 1 << 12,
     eHTMLFileInputAccessible = 1 << 13,
     eHTMLListItemAccessible = 1 << 14,
     eImageAccessible = 1 << 15,
     eImageMapAccessible = 1 << 16,
     eListControlAccessible = 1 << 17,
     eMenuButtonAccessible = 1 << 18,
     eMenuPopupAccessible = 1 << 19,
-    eRootAccessible = 1 << 20,
-    eTextLeafAccessible = 1 << 21,
-    eXULDeckAccessible = 1 << 22,
-    eXULTreeAccessible = 1 << 23
+    eProgressAccessible = 1 << 20,
+    eRootAccessible = 1 << 21,
+    eTextLeafAccessible = 1 << 22,
+    eXULDeckAccessible = 1 << 23,
+    eXULTreeAccessible = 1 << 24
   };
 
   //////////////////////////////////////////////////////////////////////////////
   // Miscellaneous helpers
 
   /**
    * Return ARIA role (helper method).
    */
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -38,16 +38,17 @@
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
 #include "nsFocusManager.h"
+#include "mozilla/Assertions.h"
 #include "mozilla/dom/Element.h"
 
 #ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
@@ -80,18 +81,18 @@ DocAccessible::
                   nsIPresShell* aPresShell) :
   HyperTextAccessibleWrap(aRootContent, this),
   mDocument(aDocument), mScrollPositionChangedTicks(0),
   mLoadState(eTreeConstructionPending), mLoadEventType(0),
   mVirtualCursor(nullptr),
   mPresShell(aPresShell)
 {
   mFlags |= eDocAccessible | eNotNodeMapEntry;
-  if (mPresShell)
-    mPresShell->SetAccDocument(this);
+  MOZ_ASSERT(mPresShell, "should have been given a pres shell");
+  mPresShell->SetDocAccessible(this);
 
   mDependentIDsHash.Init();
   // XXX aaronl should we use an algorithm for the initial cache size?
   mAccessibleCache.Init(kDefaultCacheSize);
   mNodeToAccessibleMap.Init(kDefaultCacheSize);
 
   // If this is a XUL Document, it should not implement nsHyperText
   if (mDocument && mDocument->IsXUL())
@@ -631,17 +632,17 @@ DocAccessible::Shutdown()
   if (!mPresShell) // already shutdown
     return;
 
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocDestroy))
     logging::DocDestroy("document shutdown", mDocument, this);
 #endif
 
-  mPresShell->SetAccDocument(nullptr);
+  mPresShell->SetDocAccessible(nullptr);
 
   if (mNotificationController) {
     mNotificationController->Shutdown();
     mNotificationController = nullptr;
   }
 
   RemoveEventListeners();
 
@@ -1116,16 +1117,24 @@ DocAccessible::AttributeChangedImpl(nsIC
   }
 
   if (aAttribute == nsGkAtoms::contenteditable) {
     nsRefPtr<AccEvent> editableChangeEvent =
       new AccStateChangeEvent(aContent, states::EDITABLE);
     FireDelayedAccessibleEvent(editableChangeEvent);
     return;
   }
+
+  if (aAttribute == nsGkAtoms::value) {
+    Accessible* accessible = GetAccessible(aContent);
+    if(accessible->IsProgress()) {
+      FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
+                                 aContent);
+    }
+  }
 }
 
 // DocAccessible protected member
 void
 DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
 {
   // Note: For universal/global ARIA states and properties we don't care if
   // there is an ARIA role present or not.
--- a/accessible/src/generic/FormControlAccessible.h
+++ b/accessible/src/generic/FormControlAccessible.h
@@ -16,17 +16,17 @@ namespace a11y {
   */
 template<int Max>
 class ProgressMeterAccessible : public LeafAccessible
 {
 public:
   ProgressMeterAccessible(nsIContent* aContent, DocAccessible* aDoc) :
     LeafAccessible(aContent, aDoc)
   {
-    mFlags = mFlags | eHasNumericValue;
+    mFlags |= eHasNumericValue | eProgressAccessible;
   }
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLEVALUE
 
   // Accessible
   virtual void Value(nsString& aValue);
   virtual mozilla::a11y::role NativeRole();
--- a/accessible/src/generic/RootAccessible.cpp
+++ b/accessible/src/generic/RootAccessible.cpp
@@ -470,19 +470,23 @@ RootAccessible::ProcessDOMEvent(nsIDOMEv
 
     FocusMgr()->ActiveItemChanged(nullptr);
 #ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eFocus))
       logging::ActiveItemChangeCausedBy("DOMMenuBarInactive", accessible);
 #endif
   }
   else if (eventType.EqualsLiteral("ValueChange")) {
-    targetDocument->
-      FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
-                                 targetNode, AccEvent::eRemoveDupes);
+
+    //We don't process 'ValueChange' events for progress meters since we listen
+    //@value attribute change for them.
+    if (!accessible->IsProgress())
+      targetDocument->
+        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
+                                   targetNode);
   }
 #ifdef DEBUG_DRAGDROPSTART
   else if (eventType.EqualsLiteral("mouseover")) {
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_DRAGDROP_START,
                             accessible);
   }
 #endif
 }
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -120,17 +120,17 @@ nsAccessNodeWrap::QueryService(REFGUID g
     // Make sure this is a document.
     DocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root);
     if (!docAcc)
       return E_UNEXPECTED;
 
     *ppv = static_cast<IAccessible*>(docAcc);
 
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
-    return NS_OK;
+    return S_OK;
   }
 
   // Can get to IAccessibleApplication from any node via QS
   if (guidService == IID_IAccessibleApplication) {
     ApplicationAccessible* applicationAcc = ApplicationAcc();
     if (!applicationAcc)
       return E_NOINTERFACE;
 
--- a/accessible/tests/mochitest/events/test_valuechange.html
+++ b/accessible/tests/mochitest/events/test_valuechange.html
@@ -21,86 +21,106 @@
 
 
     /**
      * Do tests.
      */
     var gQueue = null;
 
     // Value change invoker
-    function changeValue(aNodeOrID, aValuenow, aValuetext)
+    function changeARIAValue(aNodeOrID, aValuenow, aValuetext)
     {
       this.DOMNode = getNode(aNodeOrID);
 
-      this.invoke = function changeValue_invoke() {
+      this.invoke = function changeARIAValue_invoke() {
 
         // Note: this should not fire an EVENT_VALUE_CHANGE when aria-valuetext
         // is not empty
         if (aValuenow != undefined)
           this.DOMNode.setAttribute("aria-valuenow", aValuenow);
  
         // Note: this should always fire an EVENT_VALUE_CHANGE
         if (aValuetext != undefined)
           this.DOMNode.setAttribute("aria-valuetext", aValuetext);
       }
 
-      this.check = function changeValue_check() {
+      this.check = function changeARIAValue_check() {
         var acc = getAccessible(aNodeOrID, [nsIAccessibleValue]);
         if (!acc)
           return;
 
         // Note: always test against valuetext first because the existence of 
         // aria-valuetext takes precedence over aria-valuenow in gecko.
         is(acc.value, (aValuetext != undefined)? aValuetext : aValuenow,
             "Wrong value of " + prettyName(aNodeOrID));
       }
 
-      this.getID = function changeValue_getID() {
+      this.getID = function changeARIAValue_getID() {
         return prettyName(aNodeOrID) + " value changed";
       }
     }
 
-    function changeInputValue(aID, aValue)
+    function changeValue(aID, aValue)
     {
       this.DOMNode = getNode(aID);
 
-      this.invoke = function changeInputValue_invoke()
+      this.invoke = function changeValue_invoke()
       {
         this.DOMNode.value = aValue;
       }
 
-      this.check = function changeInputValue_check()
+      this.check = function changeValue_check()
       {
         var acc = getAccessible(this.DOMNode);
         is(acc.value, aValue, "Wrong value for " + prettyName(aID));
       }
 
-      this.getID = function changeInputValue_getID()
+      this.getID = function changeValue_getID()
       {
         return prettyName(aID) + " value changed";
       }
     }
 
+    function changeProcessValue(aID, aValue) {
+        this.DOMNode = getNode(aID);
+
+        this.invoke = function changeProcessValue_invoke() {
+            this.DOMNode.value = aValue;
+        }
+
+        this.check = function changeProcessValue_check() {
+            var acc = getAccessible(this.DOMNode);
+            is(acc.value, aValue+"%", "Wrong value for " + prettyName(aID));
+        }
+
+        this.getID = function changeProcessValue_getID() {
+            return prettyName(aID) + " value changed";
+        }
+    }
+
     function doTests()
     {
       // Test initial values
       testValue("slider_vn", "5", 5, 0, 1000, 0);
       testValue("slider_vnvt", "plain", 0, 0, 5, 0);
       testValue("slider_vt", "hi", 0, 0, 3, 0);
       testValue("scrollbar", "5", 5, 0, 1000, 0);
+      testValue("progress", "22%", 22, 0, 100, 0);
 
       // Test value change events
       gQueue = new eventQueue(nsIAccessibleEvent.EVENT_VALUE_CHANGE);
 
-      gQueue.push(new changeValue("slider_vn", "6", undefined));
-      gQueue.push(new changeValue("slider_vt", undefined, "hey!"));
-      gQueue.push(new changeValue("slider_vnvt", "3", "sweet"));
-      gQueue.push(new changeValue("scrollbar", "6", undefined));
+      gQueue.push(new changeARIAValue("slider_vn", "6", undefined));
+      gQueue.push(new changeARIAValue("slider_vt", undefined, "hey!"));
+      gQueue.push(new changeARIAValue("slider_vnvt", "3", "sweet"));
+      gQueue.push(new changeARIAValue("scrollbar", "6", undefined));
 
-      gQueue.push(new changeInputValue("combobox", "hello"));
+      gQueue.push(new changeValue("combobox", "hello"));
+
+      gQueue.push(new changeProcessValue("progress", "50"));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
@@ -117,16 +137,22 @@
     title="We dont expose new aria role 'scrollbar' and property aria-orientation">
    Mozilla Bug 529289
   </a>
   <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=703202"
     title="ARIA comboboxes don't fire value change events">
    Mozilla Bug 703202
   </a>
+  <a target="_blank"
+    href="https://bugzilla.mozilla.org/show_bug.cgi?id=761901"
+    title=" HTML5 progress accessible should fire value change event">
+   Mozilla Bug 761901
+  </a>
+
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <!-- ARIA sliders -->
@@ -140,10 +166,14 @@
        aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
 
   <!-- ARIA scrollbar -->
   <div id="scrollbar" role="scrollbar" aria-valuenow="5"
        aria-valuemin="0" aria-valuemax="1000">slider</div>
 
   <!-- ARIA combobox -->
   <input id="combobox" role="combobox" aria-autocomplete="inline">
+
+  <!-- progress bar -->
+  <progress id="progress" value="22" max="100"></progress>
+
 </body>
 </html>
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -850,8 +850,18 @@ window.addEventListener('ContentStart', 
 (function volumeStateTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'volume-state-changed',
       active: (aData == 'Shared')
     });
 }, 'volume-state-changed', false);
 })();
+
+Services.obs.addObserver(function(aSubject, aTopic, aData) {
+  let data = JSON.parse(aData);
+  shell.sendChromeEvent({
+    type: "activity-done",
+    success: data.success,
+    manifestURL: data.manifestURL,
+    pageURL: data.pageURL
+  });
+}, "activity-done", false);
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/debug
+++ b/b2g/config/mozconfigs/ics_armv7a_gecko/debug
@@ -1,16 +1,16 @@
 mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
 
 mk_add_options MOZ_MAKE_FLAGS="-j8"
 
 ac_add_options --enable-application=b2g
 ac_add_options --enable-b2g-camera
 
-ac_add_options --target=arm-android-eabi
+ac_add_options --target=arm-linux-androideabi
 ac_add_options --with-gonk="$topsrcdir/gonk-toolchain"
 export TOOLCHAIN_HOST=linux-x86
 export GONK_PRODUCT=generic
 ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-"
 ac_add_options --disable-elf-hack
 ac_add_options --enable-debug-symbols
 ac_add_options --enable-debug
 # IonMonkey disabled in bug 789373
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/nightly
+++ b/b2g/config/mozconfigs/ics_armv7a_gecko/nightly
@@ -2,17 +2,17 @@
 
 mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
 
 mk_add_options MOZ_MAKE_FLAGS="-j8"
 
 ac_add_options --enable-application=b2g
 ac_add_options --enable-b2g-camera
 
-ac_add_options --target=arm-android-eabi
+ac_add_options --target=arm-linux-androideabi
 ac_add_options --with-gonk="$topsrcdir/gonk-toolchain"
 export TOOLCHAIN_HOST=linux-x86
 export GONK_PRODUCT=generic
 ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-"
 ac_add_options --disable-elf-hack
 ac_add_options --enable-debug-symbols
 # ac_add_options --enable-profiling
 # IonMonkey disabled in bug 789373
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -1,13 +1,13 @@
 ; This Source Code Form is subject to the terms of the Mozilla Public
 ; License, v. 2.0. If a copy of the MPL was not distributed with this
 ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-; Package file for the B2G build. 
+; Package file for the B2G build.
 ;
 ; File format:
 ;
 ; [] designates a toplevel component. Example: [xpcom]
 ; - in front of a file specifies it to be removed from the destination
 ; * wildcard support to recursively copy the entire directory
 ; ; file comment
 ;
@@ -375,21 +375,23 @@
 @BINPATH@/components/nsDownloadManagerUI.manifest
 @BINPATH@/components/nsDownloadManagerUI.js
 @BINPATH@/components/NetworkGeolocationProvider.manifest
 @BINPATH@/components/NetworkGeolocationProvider.js
 @BINPATH@/components/GPSDGeolocationProvider.manifest
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
+#ifndef MOZ_WIDGET_GONK
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
 @BINPATH@/components/amContentHandler.js
 @BINPATH@/components/amWebInstallListener.js
 @BINPATH@/components/nsBlocklistService.js
+#endif
 
 #ifdef MOZ_UPDATER
 @BINPATH@/components/nsUpdateService.manifest
 @BINPATH@/components/nsUpdateService.js
 @BINPATH@/components/nsUpdateServiceStub.js
 #endif
 @BINPATH@/components/nsUpdateTimerManager.manifest
 @BINPATH@/components/nsUpdateTimerManager.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -110,18 +110,20 @@ pref("app.update.cert.maxErrors", 5);
 // pairs for the certificate used by the server that hosts the update xml file
 // as specified in the |app.update.url| preference. When these preferences are
 // present the following conditions apply for a successful update check:
 // 1. the uri scheme must be https
 // 2. the preference name must exist as an attribute name on the certificate and
 //    the value for the name must be the same as the value for the attribute name
 //    on the certificate.
 // If these conditions aren't met it will be treated the same as when there is
-// no update available. This validation will not be performed when using the
-// |app.update.url.override| preference for update checking.
+// no update available. This validation will not be performed when the
+// |app.update.url.override| user preference has been set for testing updates or
+// when the |app.update.cert.checkAttributes| preference is set to false. Also,
+// the |app.update.url.override| preference should ONLY be used for testing.
 pref("app.update.certs.1.issuerName", "OU=Equifax Secure Certificate Authority,O=Equifax,C=US");
 pref("app.update.certs.1.commonName", "aus3.mozilla.org");
 
 pref("app.update.certs.2.issuerName", "CN=Thawte SSL CA,O=\"Thawte, Inc.\",C=US");
 pref("app.update.certs.2.commonName", "aus3.mozilla.org");
 
 // Whether or not app updates are enabled
 pref("app.update.enabled", true);
--- a/browser/base/content/socialchat.xml
+++ b/browser/base/content/socialchat.xml
@@ -320,17 +320,17 @@
               if (aCallback)
                 aCallback(cb.iframe.contentWindow);
               return;
             }
             this.chatboxForURL.delete(aURL);
           }
           cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
           if (aMode == "minimized")
-            cb.minimized = true;
+            cb.setAttribute("minimized", "true");
           this.selectedChat = cb;
           this.insertBefore(cb, this.firstChild);
           cb.init(aProvider, aURL, aCallback);
           this.chatboxForURL.set(aURL, Cu.getWeakReference(cb));
         ]]></body>
       </method>
 
     </implementation>
--- a/browser/base/content/test/browser_social_chatwindow.js
+++ b/browser/base/content/test/browser_social_chatwindow.js
@@ -99,16 +99,17 @@ var tests = {
     ok(port, "provider has a port");
     port.postMessage({topic: "test-init"});
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "got-chatbox-message":
           ok(true, "got a chat window opened");
           let chats = document.getElementById("pinnedchats");
+          ok(chats.selectedChat.minimized, "chatbox from worker opened as minimized");
           while (chats.selectedChat) {
             chats.selectedChat.close();
           }
           ok(!chats.selectedChat, "chats are all closed");
           port.close();
           ensureSocialUrlNotRemembered(chatUrl);
           next();
           break;
--- a/browser/base/content/test/browser_social_flyout.js
+++ b/browser/base/content/test/browser_social_flyout.js
@@ -73,30 +73,40 @@ var tests = {
           SocialFlyout.dispatchPanelEvent("socialTest-MakeWider");
           break;
       }
     }
     port.postMessage({topic: "test-init"});
   },
 
   testCloseSelf: function(next) {
+    // window.close is affected by the pref dom.allow_scripts_to_close_windows,
+    // which defaults to false, but is set to true by the test harness.
+    // so temporarily set it back.
+    const ALLOW_SCRIPTS_TO_CLOSE_PREF = "dom.allow_scripts_to_close_windows";
+    // note clearUserPref doesn't do what we expect, as the test harness itself
+    // changes the pref value - so clearUserPref resets it to false rather than
+    // the true setup by the test harness.
+    let oldAllowScriptsToClose = Services.prefs.getBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF);    
+    Services.prefs.setBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF, false);
     let panel = document.getElementById("social-flyout-panel");
     let port = Social.provider.getWorkerPort();
     ok(port, "provider has a port");
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "test-init-done":
           port.postMessage({topic: "test-flyout-open"});
           break;
         case "got-flyout-visibility":
           let iframe = panel.firstChild;
           iframe.contentDocument.addEventListener("SocialTest-DoneCloseSelf", function _doneHandler() {
             iframe.contentDocument.removeEventListener("SocialTest-DoneCloseSelf", _doneHandler, false);
             is(panel.state, "closed", "flyout should have closed itself");
+            Services.prefs.setBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF, oldAllowScriptsToClose);
             next();
           }, false);
           is(panel.state, "open", "flyout should be open");
           port.close(); // so we don't get the -visibility message as it hides...
           SocialFlyout.dispatchPanelEvent("socialTest-CloseSelf");
           break;
       }
     }
--- a/browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_viewsource.js
+++ b/browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_viewsource.js
@@ -47,32 +47,25 @@ function test() {
 
     function step1() {
       function observer(aSubject, aTopic, aData) {
         if (aTopic == "domwindowclosed") {
           ok(true, "Entering the private browsing mode should close the view source window");
           Services.ww.unregisterNotification(observer);
 
           step2();
+        } else if (aTopic == "domwindowopened") {
+          ok(false, "Entering the private browsing mode should not open any view source window");
+        } else if (aTopic == "private-browsing-transition-complete") {
+          Services.obs.removeObserver(observer, "private-browsing-transition-complete");
+          step3();
         }
-        else if (aTopic == "domwindowopened")
-          ok(false, "Entering the private browsing mode should not open any view source window");
       }
       Services.ww.registerNotification(observer);
-
-      gBrowser.addTabsProgressListener({
-        onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
-          if (aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP |
-                             Ci.nsIWebProgressListener.STATE_IS_WINDOW)) {
-            gBrowser.removeTabsProgressListener(this);
-
-            step3();
-          }
-        }
-      });
+      Services.obs.addObserver(observer, "private-browsing-transition-complete", false);
 
       // enter private browsing mode
       pb.privateBrowsingEnabled = true;
     }
 
     let events = 0, step2, step3;
     step2 = step3 = function() {
       if (++events == 2)
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -618,16 +618,30 @@
           // Add observer for suggest preference
           var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                               .getService(Components.interfaces.nsIPrefBranch);
           prefs.addObserver("browser.search.suggest.enabled", this, false);
         ]]></body>
       </method>
 
       <!--
+        This overrides the searchParam property in autocomplete.xml.  We're
+        hijacking this property as a vehicle for delivering the privacy
+        information about the window into the guys of nsSearchSuggestions.
+
+        Note that the setter is the same as the parent.  We were not sure whether
+        we can override just the getter.  If that proves to be the case, the setter
+        can be removed.
+      -->
+      <property name="searchParam"
+                onget="return this.getAttribute('autocompletesearchparam') +
+                       (PrivateBrowsingUtils.isWindowPrivate(window) ? '|private' : '');"
+                onset="this.setAttribute('autocompletesearchparam', val); return val;"/>
+
+      <!--
         This method overrides the autocomplete binding's openPopup (essentially
         duplicating the logic from the autocomplete popup binding's
         openAutocompletePopup method), modifying it so that the popup is aligned with
         the inner textbox, but sized to not extend beyond the search bar border.
       -->
       <method name="openPopup">
         <body><![CDATA[
           var popup = this.popup;
--- a/browser/components/search/test/browser_426329.js
+++ b/browser/components/search/test/browser_426329.js
@@ -188,17 +188,17 @@ function test() {
 
       testSearchHistory();
     }, 5000);
   }
 
   function testSearchHistory() {
     var textbox = searchBar._textbox;
     for (var i = 0; i < searchEntries.length; i++) {
-      let exists = textbox._formHistSvc.entryExists(textbox.searchParam, searchEntries[i]);
+      let exists = textbox._formHistSvc.entryExists(textbox.getAttribute("autocompletesearchparam"), searchEntries[i]);
       ok(exists, "form history entry '" + searchEntries[i] + "' should exist");
     }
     testAutocomplete();
   }
 
   function testAutocomplete() {
     var popup = searchBar.textbox.popup;
     popup.addEventListener("popupshowing", function() {
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -683,28 +683,16 @@ var Scratchpad = {
             file = aFile;
           } else {
             file = Components.classes["@mozilla.org/file/local;1"].
                    createInstance(Components.interfaces.nsILocalFile);
             let filePath = this.getRecentFiles()[aIndex];
             file.initWithPath(filePath);
           }
 
-          if (!file.exists()) {
-            this.notificationBox.appendNotification(
-              this.strings.GetStringFromName("fileNoLongerExists.notification"),
-              "file-no-longer-exists",
-              null,
-              this.notificationBox.PRIORITY_WARNING_HIGH,
-              null);
-
-            this.clearFiles(aIndex, 1);
-            return;
-          }
-
           this.setFilename(file.path);
           this.importFromFile(file, false);
           this.setRecentFile(file);
         }
       }.bind(this));
     }.bind(this);
 
     if (aIndex > -1) {
@@ -837,33 +825,16 @@ var Scratchpad = {
                               this.strings.
                               GetStringFromName("clearRecentMenuItems.label"));
       clearItems.setAttribute("command", "sp-cmd-clearRecentFiles");
       recentFilesPopup.appendChild(clearItems);
     }
   },
 
   /**
-   * Clear a range of files from the list.
-   *
-   * @param integer aIndex
-   *        Index of file in menu to remove.
-   * @param integer aLength
-   *        Number of files from the index 'aIndex' to remove.
-   */
-  clearFiles: function SP_clearFile(aIndex, aLength)
-  {
-    let filePaths = this.getRecentFiles();
-    let branch = Services.prefs.
-                 getBranch("devtools.scratchpad.");
-    filePaths.splice(aIndex, aLength);
-    branch.setCharPref("recentFilePaths", JSON.stringify(filePaths));
-  },
-
-  /**
    * Clear all recent files.
    */
   clearRecentFiles: function SP_clearRecentFiles()
   {
     Services.prefs.clearUserPref("devtools.scratchpad.recentFilePaths");
   },
 
   /**
@@ -883,18 +854,21 @@ var Scratchpad = {
           this.populateRecentFilesMenu();
         }
 
         menu.removeAttribute("hidden");
       }
 
       let filePaths = this.getRecentFiles();
       if (maxRecent < filePaths.length) {
+        let branch = Services.prefs.
+                     getBranch("devtools.scratchpad.");
         let diff = filePaths.length - maxRecent;
-        this.clearFiles(0, diff);
+        filePaths.splice(0, diff);
+        branch.setCharPref("recentFilePaths", JSON.stringify(filePaths));
       }
     }
   },
   /**
    * Save the textbox content to the currently open file.
    *
    * @param function aCallback
    *        Optional function you want to call when file is saved
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_651942_recent_files.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_651942_recent_files.js
@@ -96,71 +96,45 @@ function testOpenOldestRecent()
 // The "devtools.scratchpad.recentFilesMax"-preference was set to zero (0).
 // This should disable the "Open Recent"-menu by hiding it (this should not
 // remove any files from the list). Test to see if it's been hidden.
 function testHideMenu()
 {
   let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
   ok(menu.hasAttribute("hidden"), "The menu was hidden successfully.");
 
-  Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 2);
+  Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 1);
 }
 
 // We have set the recentFilesMax-pref to one (1), this enables the feature,
 // removes the two oldest files, rebuilds the menu and removes the
 // "hidden"-attribute from it. Test to see if this works.
 function testChangedMaxRecent()
 {
   let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
   ok(!menu.hasAttribute("hidden"), "The menu is visible. \\o/");
 
   lists.recentFiles04 = gScratchpad.getRecentFiles();
 
-  is(lists.recentFiles04.length, 2,
+  is(lists.recentFiles04.length, 1,
      "Two recent files were successfully removed from the 'recent files'-list");
 
   let doc = gScratchpadWindow.document;
   let popup = doc.getElementById("sp-menu-open_recentPopup");
 
   let menuitemLabel = popup.children[0].getAttribute("label");
   let correctMenuItem = false;
   if (menuitemLabel === lists.recentFiles03[2] &&
-      menuitemLabel === lists.recentFiles04[1]) {
+      menuitemLabel === lists.recentFiles04[0]) {
     correctMenuItem = true;
   }
 
   is(correctMenuItem, true,
      "Two recent files were successfully removed from the 'Open Recent'-menu");
 
-  // We now remove one file from the harddrive and use the recent-menuitem for
-  // it to make sure the user is notified that the file no longer exists.
-  // This is tested in testOpenDeletedFile().
-  gFile02.remove(false);
-  gFile02 = null;
-  gScratchpad.openFile(1);
-}
-
-// By now we should have two recent files stored in the list but one of the
-// files should be missing on the harddrive.
-function testOpenDeletedFile() {
-  let doc = gScratchpadWindow.document;
-  let popup = doc.getElementById("sp-menu-open_recentPopup");
-
-  is(gScratchpad.getRecentFiles().length, 1,
-     "The missing file was successfully removed from the list.");
-  // The number of recent files stored, plus the separator and the
-  // clearRecentMenuItems-item.
-  is(popup.children.length, 3,
-     "The missing file was successfully removed from the menu.");
-  ok(gScratchpad.notificationBox.currentNotification,
-     "The notification was successfully displayed.");
-  is(gScratchpad.notificationBox.currentNotification.label,
-     gScratchpad.strings.GetStringFromName("fileNoLongerExists.notification"),
-     "The notification label is correct.");
-
   gScratchpad.clearRecentFiles();
 }
 
 // We have cleared the last file. Test to see if the last file was removed,
 // the menu is empty and was disabled successfully.
 function testClearedAll()
 {
   let doc = gScratchpadWindow.document;
@@ -281,20 +255,16 @@ var PreferenceObserver = {
         testHideMenu();
         break;
       case 6:
         this.timesFired = 7;
         testChangedMaxRecent();
         break;
       case 7:
         this.timesFired = 8;
-        testOpenDeletedFile();
-        break;
-      case 8:
-        this.timesFired = 9;
         testClearedAll();
         break;
     }
   },
 
   uninit: function PO_uninit () {
     this.branch.removeObserver("", this);
   }
@@ -302,17 +272,18 @@ var PreferenceObserver = {
 
 function test()
 {
   waitForExplicitFinish();
 
   registerCleanupFunction(function () {
     gFile01.remove(false);
     gFile01 = null;
-    // gFile02 was removed earlier.
+    gFile02.remove(false);
+    gFile02 = null;
     gFile03.remove(false);
     gFile03 = null;
     gFile04.remove(false);
     gFile04 = null;
     lists.recentFiles01 = null;
     lists.recentFiles02 = null;
     lists.recentFiles03 = null;
     lists.recentFiles04 = null;
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -719,31 +719,30 @@ Function CheckExistingInstall
       StrCpy $TmpVal "FoundMessageWindow"
       ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_INSTALL)"
       StrCpy $TmpVal "true"
     ${EndIf}
   ${EndIf}
 FunctionEnd
 
 Function LaunchApp
+  ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
+
   ClearErrors
   ${GetParameters} $0
   ${GetOptions} "$0" "/UAC:" $1
   ${If} ${Errors}
-    ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
     Exec "$\"$INSTDIR\${FileMainEXE}$\""
   ${Else}
     GetFunctionAddress $0 LaunchAppFromElevatedProcess
     UAC::ExecCodeSegment $0
   ${EndIf}
 FunctionEnd
 
 Function LaunchAppFromElevatedProcess
-  ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
-
   ; Find the installation directory when launching using GetFunctionAddress
   ; from an elevated installer since $INSTDIR will not be set in this installer
   ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
   ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
   ${GetPathFromString} "$0" $0
   ${GetParent} "$0" $1
   ; Set our current working directory to the application's install directory
   ; otherwise the 7-Zip temp directory will be in use and won't be deleted.
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
@@ -73,12 +73,8 @@ scratchpadIntro1=/*\n * This is a JavaSc
 
 # LOCALIZATION NOTE  (notification.browserContext): This is the message displayed
 # over the top of the editor when the user has switched to browser context.
 browserContext.notification=This scratchpad executes in the Browser context.
 
 # LOCALIZATION NOTE (help.openDocumentationPage): This returns a localized link with
 # documentation for Scratchpad on MDN.
 help.openDocumentationPage=https://developer.mozilla.org/en/Tools/Scratchpad
-
-# LOCALIZATION NOTE (fileExists.notification): This is the message displayed
-# over the top of the the editor when a file does not exist.
-fileNoLongerExists.notification=This file no longer exists.
old mode 100755
new mode 100644
index ce6ab03484051df84b7f9ed159cc74fbc442905b..2cd8cfe03726fe640373d5c1883ab0915cf5606b
GIT binary patch
literal 2091
zc$@(%2-Nq9P)<h;3K|Lk000e1NJLTq002M$001xu1ONa43qrJ%000N_Nkl<ZcwWWW
zYm8jwc?a;{%pA{U?Op8M^{)4VS>p``E5?MTm`e+SRs_3oX=SBBlprS*)?l;T9K?Os
zn3U3xsz73P?IuAfLLyWyQUdj*pdzK<w2>*0T7<e_6JwjTy?DJdJ3Biw=hUkFVJ>n$
zMVsIGFlY3Bc>X%)dEfV(6N~(A1*S&~5LKQ}Ux0*!03{^^5-2MPi34ot+0X{Cp>sp4
zTHRUzv};!DTwMTqbO0bGVWx{L)+8gN$x@4CBp?n9EC`3gp@B9S==}fl>Jn$#XrmU;
zW}`>VR_Q$3?a&2!?6gBW00K+B;6+Q#HP`QX(T~lS5F-G}lM3b=dZ^C~!#cd9pwgtn
zW*aalFre&{n(>^E&9}{$B<+y&p1ewV2ejL4y})-w_9+0d2ylOgVV(9%I$2)-<2lt@
ztka@khPaOm$*b1oISb^Z#r=mqSpYFJoZ)<fIz*DD{K|k2Wfdy|@XdLKb>UsNe><n%
z9JiPwa=`aZs@GwQvqgSkt*lCM8FO9Wb{!)B;~5_~svsl)pd1$mP117eC4?rBkus@X
zQo=Zz&6HIy5I2rS88I;+4$$9O8ZLE|-Yp#{^^}JDThwZGr?g)?rokP~P^-tQn(g+X
zdHzK^0Ad0e=XgScy$)&eq#l{7CS2Qjs`dKKv{{d#wSC_kt?7WQgI<(!y*bu-#t8tN
z<)=pN_JEn5w9qS77y*#5(03j5zkVcRwN9H{FQ-HRgjr)o^go-EyY&`Brj+Ztc+yJ>
z3SMxXsAhc3o5npNC+8lIqXdA+XLgye*%5J1S%ayXS<u&{Je&ji+7yPzR7;B#0F6rW
zsx=Db0IjB+sJR8LVn$7h$>>n<sr;!~Fb(1o5+b285(1I3vT(WrKnzjc#^iUt9VZ4&
zgP4S*l$1bRl>jz4y@B6G2Lv)2WF(YKnvho#0&ze}pO?MmWqnfWCEZ|)t+u#9QoW2p
zAIST_pbRz3&@9~s{hMEU!=P@n1XU|xm=2!}Zw@=cL*d+$zt5ih@6-XLY_we5`$8*h
ztc%!SyE|q4ry1_FT|>=2(CK+!75ARVS3R#&MjQwrT<v^6Gw8TRkGRs;Y*A^Ixpw)X
ztOl!n(VuxyrF-?-YQ0fSzHOzuJq94q;CAia@Qe}7Zg+`WJ!VoF0tl}$;UQU!8*q^o
zH37b0%s<Fu!VmQNVoiWAJL(SOIN=`4Tw4(!A?-4s`8)e$9ryPZxm;SJ@(Q&3P!=#@
zzh2dn4$1>29n`JbOz#^9WbJic%_0=|wNY8)BFBAVzC_h6D1WM3MjoV{=~LB4G)pOf
zlvYPn`^Z^l%7F$w_5mPNc2K+7#zbbBqun8>?1AlWGU!n`DGzG&l4@_e++X>Dyrk7a
zyH$JDO}1F$gpBV=*am>INpD%<5sw))+kGOt1rp*y0x18`@B1T{*r!_)uJU6?0r0Qp
zTi^*JS`_3g^_JrR_`aq7&|Z7>7&q!#|Kt#$WWoy;y1-Tk%`<A$rCxKwl!7o8p`Vnm
zTW+4icDl-Z`>b&ko(5*P+!D=3{n8>Wc*+<6Qf_dKvwUo)D|}AE3Wq_=470RbWtn+K
z{FlYLHM-RvW2Rye)~V8F$b9?tIm&m{X>z@02~QhSkGa01SK7%4RV!gyLQJ4bpDuHJ
z!yegKgxgRb!EU#(Nj;6O(<1LFP7~p8oMYSyKurA9T_<6tUTd7GY?ZNCgf;5S^(}vG
zA4BS)(MmfUbvmuSX_Nix#icZv??x}2x&rh$y<xv~aY-qGl1atD^b1WXii<?T0ESJ2
zn7D)(B4rR4ipQPShAzL^Jipo5RSzU-O`5f7(`>dgG+81o5eHzPZQ#a%M^7F%4zw}Q
z9d1^w)hc(p+bXT-@GaH4t@oVgtk;c&c2<;c&}^yu3>k8t3w2rMpUn~k01sbptrVc|
z;peT?rqZ9fPFaXASmmcK7pZioL6IV^^^m739$exwn)SO`SrM1|hOPcsq(LqK9{fvp
z32pNxE_Jn=s42h7sNMEpu?t)!uMB{@JnV>{cmr2h={8vf5R=s84y%p$xp%}ZvCN;y
zDoct5aDSV%LiauXI^4g<#b&G2VuevZ@;2CSfk`9*bi2nPci92{+r>%%;?h3nI)`oc
znxZp&>>Nc9CxG%blD7Tr>u~P^Lp9~OSk^n<23_tosfZYWulUR>c7Suea%vn%NLlHa
zU)brGm_?p&LJ^ci0ffEycUXV6A<b&Fnesm9cCx&(m`Xhg-U5sL#JCbwpC>vL?2(oC
zc~3j01ej0`pbX&24_&R^l%g0opkKX$q5$l%@bu$C@48rnq`0C9ClupQ-dk3_%;|k%
z$|9%tzM?DDgGkXwiY_!uT1>&X<Bk|HDz6-ea9cPPUcK%rfOWm9y=}@u7Xs)~?NvE{
z;Libk9sp$pugg2fwdR^_mIg~OrJyK`Mc}rtxkG6CscHBn&u@CVrVTIC?1NL&aEYIJ
zS*5SI*|}b`16TX9%^n2Aq&52s%bn*vKNq>kGB0^RR*3-E^p9)G)>>{kC^)LxE@hYK
z(u=$Uj;QvMlGV<4C60O1uK+}*oUm0{L8q_dm|gZl&D(Kbn``u9uWiF4>NQ%d1;^|$
zu3oDvoQ3_~aJ1&-EUn3zmYIjccG+j#<n(<Xh>1%|OPPV9f=N?CQAL1h-i|{N@PD~n
V&ytIeV<-Rs002ovPDHLkV1f_x080P>
--- a/browser/themes/pinstripe/downloads/downloads.css
+++ b/browser/themes/pinstripe/downloads/downloads.css
@@ -128,42 +128,33 @@ richlistitem[type="download"][state="1"]
   cursor: pointer;
 }
 
 /*** Button icons ***/
 
 .downloadButton.downloadCancel {
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
-.downloadButton.downloadCancel:hover {
-  -moz-image-region: rect(0px, 32px, 16px, 16px);
-}
-.downloadButton.downloadCancel:active {
-  -moz-image-region: rect(0px, 48px, 16px, 28px);
-}
 
 .downloadButton.downloadShow {
   -moz-image-region: rect(16px, 16px, 32px, 0px);
 }
-.downloadButton.downloadShow:hover {
+richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow {
   -moz-image-region: rect(16px, 32px, 32px, 16px);
 }
-.downloadButton.downloadShow:active {
+richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:hover {
   -moz-image-region: rect(16px, 48px, 32px, 32px);
 }
+richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:active {
+  -moz-image-region: rect(16px, 64px, 32px, 48px);
+}
 
 .downloadButton.downloadRetry {
   -moz-image-region: rect(32px, 16px, 48px, 0px);
 }
-.downloadButton.downloadRetry:hover {
-  -moz-image-region: rect(32px, 32px, 48px, 16px);
-}
-.downloadButton.downloadRetry:active {
-  -moz-image-region: rect(32px, 48px, 48px, 32px);
-}
 
 /*** Status and progress indicator ***/
 
 #downloads-button,
 #downloads-indicator {
   width: 35px;
 }
 
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -69,23 +69,32 @@ class RemoteAutomation(Automation):
 
         if (status == 1 and self._devicemanager.processExist(proc.procName)):
             # Then we timed out, make sure Fennec is dead
             proc.kill()
 
         return status
 
     def checkForCrashes(self, directory, symbolsPath):
-        dumpDir = tempfile.mkdtemp()
-        self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
-        automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
-        try:
-          shutil.rmtree(dumpDir)
-        except:
-          print "WARNING: unable to remove directory: %s" % (dumpDir)
+        remoteCrashDir = self._remoteProfile + '/minidumps/'
+        if self._devicemanager.dirExists(remoteCrashDir):
+            dumpDir = tempfile.mkdtemp()
+            self._devicemanager.getDirectory(remoteCrashDir, dumpDir)
+            automationutils.checkForCrashes(dumpDir, symbolsPath,
+                                            self.lastTestSeen)
+            try:
+                shutil.rmtree(dumpDir)
+            except:
+                print "WARNING: unable to remove directory: %s" % dumpDir
+        else:
+            # As of this writing, the minidumps directory is automatically
+            # created when fennec (first) starts, so its lack of presence
+            # is a hint that something went wrong.
+            print "WARNING: No crash directory (%s) on remote " \
+                "device" % remoteCrashDir
 
     def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
         # If remote profile is specified, use that instead
         if (self._remoteProfile):
             profileDir = self._remoteProfile
 
         # Hack for robocop, if app & testURL == None and extraArgs contains the rest of the stuff, lets
         # assume extraArgs is all we need
--- a/config/config.mk
+++ b/config/config.mk
@@ -119,24 +119,18 @@ OS_CONFIG	:= $(OS_ARCH)$(OS_RELEASE)
 FINAL_LINK_LIBS = $(DEPTH)/config/final-link-libs
 FINAL_LINK_COMPS = $(DEPTH)/config/final-link-comps
 FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names
 
 MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
 MOZ_WIDGET_SUPPORT_LIBS    = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
 
 ifdef _MSC_VER
-ifdef .PYMAKE
-PYCOMMANDPATH += $(topsrcdir)/build
-CC_WRAPPER ?= %cl InvokeClWithDependencyGeneration
-CXX_WRAPPER ?= %cl InvokeClWithDependencyGeneration
-else
 CC_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
 CXX_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
-endif # .PYMAKE
 endif # _MSC_VER
 
 CC := $(CC_WRAPPER) $(CC)
 CXX := $(CXX_WRAPPER) $(CXX)
 MKDIR ?= mkdir
 SLEEP ?= sleep
 TOUCH ?= touch
 
--- a/configure.in
+++ b/configure.in
@@ -1670,28 +1670,29 @@ if test -n "$MOZ_VALGRIND"; then
     MOZ_CHECK_HEADER([valgrind/valgrind.h], [],
         AC_MSG_ERROR(
             [--enable-valgrind specified but Valgrind is not installed]))
     AC_DEFINE(MOZ_VALGRIND)
 fi
 AC_SUBST(MOZ_VALGRIND)
 
 dnl ========================================================
-dnl = Use DMD
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(dmd,
-[  --enable-dmd            Enable DMD; also disables jemalloc (default=no)],
-    MOZ_DMD=1,
-    MOZ_DMD= )
-if test -n "$MOZ_DMD"; then
+dnl = Enable DMDV
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(dmdv,
+[  --enable-dmdv           Enable DMDV; also disables jemalloc (default=no)],
+    MOZ_DMDV=1,
+    MOZ_DMDV= )
+if test -n "$MOZ_DMDV"; then
     MOZ_CHECK_HEADER([valgrind/valgrind.h], [],
         AC_MSG_ERROR(
-            [--enable-dmd specified but Valgrind is not installed]))
-    AC_DEFINE(MOZ_DMD)
-fi
+            [--enable-dmdv specified but Valgrind is not installed]))
+    AC_DEFINE(MOZ_DMDV)
+fi
+AC_SUBST(MOZ_DMDV)
 
 dnl ========================================================
 dnl jprof
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(jprof,
 [  --enable-jprof          Enable jprof profiling tool (needs mozilla/tools/jprof). Implies --enable-profiling.],
     MOZ_JPROF=1,
     MOZ_JPROF= )
@@ -3779,16 +3780,23 @@ if test "$MALLOC_H" != ""; then
    AC_DEFINE_UNQUOTED(MALLOC_H, <$MALLOC_H>)
 fi
 
 MOZ_ALLOCATING_FUNCS="strndup posix_memalign memalign valloc"
 AC_CHECK_FUNCS(strndup posix_memalign memalign valloc)
 
 dnl See if compiler supports some gcc-style attributes
 
+AC_CACHE_CHECK(for __attribute__((always_inline)),
+               ac_cv_attribute_always_inline,
+               [AC_TRY_COMPILE([inline void f(void) __attribute__((always_inline));],
+                               [],
+                               ac_cv_attribute_always_inline=yes,
+                               ac_cv_attribute_always_inline=no)])
+
 AC_CACHE_CHECK(for __attribute__((malloc)),
                ac_cv_attribute_malloc,
                [AC_TRY_COMPILE([void* f(int) __attribute__((malloc));],
                                [],
                                ac_cv_attribute_malloc=yes,
                                ac_cv_attribute_malloc=no)])
 
 AC_CACHE_CHECK(for __attribute__((warn_unused_result)),
@@ -3830,16 +3838,22 @@ fi
 
 dnl Mozilla specific options
 dnl ========================================================
 dnl The macros used for command line options
 dnl are defined in build/autoconf/altoptions.m4.
 
 dnl If the compiler supports these attributes, define them as
 dnl convenience macros.
+if test "$ac_cv_attribute_always_inline" = yes ; then
+  AC_DEFINE(NS_ALWAYS_INLINE, [__attribute__((always_inline))])
+else
+  AC_DEFINE(NS_ALWAYS_INLINE,)
+fi
+
 if test "$ac_cv_attribute_malloc" = yes ; then
   AC_DEFINE(NS_ATTR_MALLOC, [__attribute__((malloc))])
 else
   AC_DEFINE(NS_ATTR_MALLOC,)
 fi
 
 if test "$ac_cv_attribute_warn_unused" = yes ; then
   AC_DEFINE(NS_WARN_UNUSED_RESULT, [__attribute__((warn_unused_result))])
@@ -6973,17 +6987,17 @@ dnl ====================================
 MOZ_ARG_ENABLE_BOOL(jemalloc,
 [  --enable-jemalloc       Replace memory allocator with jemalloc],
     MOZ_MEMORY=1,
     MOZ_MEMORY=)
 
 if test "$NS_TRACE_MALLOC"; then
     MOZ_MEMORY=
 fi
-if test "$MOZ_DMD"; then
+if test "$MOZ_DMDV"; then
     MOZ_MEMORY=
 fi
 
 if test "${OS_TARGET}" = "Android"; then
   dnl On Android, we use WRAP_LDFLAGS to link everything to mozglue
   :
 elif test "${OS_TARGET}" = "WINNT" -o "${OS_TARGET}" = "Darwin" -o "${OS_TARGET}" = "OS2"; then
   dnl On Windows, OSX and OS2, we want to link all our binaries against mozglue
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1818,21 +1818,32 @@ public:
    * Utility method for getElementsByClassName.  aRootNode is the node (either
    * document or element), which getElementsByClassName was called on.
    */
   static nsresult GetElementsByClassName(nsINode* aRootNode,
                                          const nsAString& aClasses,
                                          nsIDOMNodeList** aReturn);
 
   /**
+   * Returns a presshell for this document, if there is one. This will be
+   * aDoc's direct presshell if there is one, otherwise we'll look at all
+   * ancestor documents to try to find a presshell, so for example this can
+   * still find a presshell for documents in display:none frames that have
+   * no presentation. So you have to be careful how you use this presshell ---
+   * getting generic data like a device context or widget from it is OK, but it
+   * might not be this document's actual presentation.
+   */
+  static nsIPresShell* FindPresShellForDocument(nsIDocument* aDoc);
+
+  /**
    * Returns the widget for this document if there is one. Looks at all ancestor
    * documents to try to find a widget, so for example this can still find a
    * widget for documents in display:none frames that have no presentation.
    */
-  static nsIWidget *WidgetForDocument(nsIDocument *aDoc);
+  static nsIWidget* WidgetForDocument(nsIDocument* aDoc);
 
   /**
    * Returns a layer manager to use for the given document. Basically we
    * look up the document hierarchy for the first document which has
    * a presentation with an associated widget, and use that widget's
    * layer manager.
    *
    * @param aDoc the document for which to return a layer manager.
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6520,45 +6520,55 @@ nsContentUtils::PlatformToDOMLineBreaks(
                              NS_LITERAL_STRING("\n").get());
 
     // Mac linebreaks: Map any remaining CR to LF:
     aString.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
                              NS_LITERAL_STRING("\n").get());
   }
 }
 
-nsIWidget *
-nsContentUtils::WidgetForDocument(nsIDocument *aDoc)
+nsIPresShell*
+nsContentUtils::FindPresShellForDocument(nsIDocument* aDoc)
 {
   nsIDocument* doc = aDoc;
   nsIDocument* displayDoc = doc->GetDisplayDocument();
   if (displayDoc) {
     doc = displayDoc;
   }
 
   nsIPresShell* shell = doc->GetShell();
+  if (shell) {
+    return shell;
+  }
+
   nsCOMPtr<nsISupports> container = doc->GetContainer();
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
-  while (!shell && docShellTreeItem) {
+  while (docShellTreeItem) {
     // We may be in a display:none subdocument, or we may not have a presshell
     // created yet.
     // Walk the docshell tree to find the nearest container that has a presshell,
-    // and find the root widget from that.
+    // and return that.
     nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
     nsCOMPtr<nsIPresShell> presShell;
     docShell->GetPresShell(getter_AddRefs(presShell));
     if (presShell) {
-      shell = presShell;
-    } else {
-      nsCOMPtr<nsIDocShellTreeItem> parent;
-      docShellTreeItem->GetParent(getter_AddRefs(parent));
-      docShellTreeItem = parent;
+      return presShell;
     }
-  }
-
+    nsCOMPtr<nsIDocShellTreeItem> parent;
+    docShellTreeItem->GetParent(getter_AddRefs(parent));
+    docShellTreeItem = parent;
+  }
+
+  return nullptr;
+}
+
+nsIWidget*
+nsContentUtils::WidgetForDocument(nsIDocument* aDoc)
+{
+  nsIPresShell* shell = FindPresShellForDocument(aDoc);
   if (shell) {
     nsIViewManager* VM = shell->GetViewManager();
     if (VM) {
       nsIView* rootView = VM->GetRootView();
       if (rootView) {
         nsIView* displayRoot = nsIViewManager::GetDisplayRootFor(rootView);
         if (displayRoot) {
           return displayRoot->GetNearestWidget(nullptr);
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -2003,20 +2003,20 @@ nsHTMLCopyEncoder::GetImmediateContextCo
 {
   int32_t i = aAncestorArray.Length(), j = 0;
   while (j < i) {
     nsINode *node = aAncestorArray.ElementAt(j);
     if (!node) {
       break;
     }
     nsCOMPtr<nsIContent> content(do_QueryInterface(node));
-    if (!content || !content->IsHTML() || content->Tag() != nsGkAtoms::tr    &&
-                                          content->Tag() != nsGkAtoms::thead &&
-                                          content->Tag() != nsGkAtoms::tbody &&
-                                          content->Tag() != nsGkAtoms::tfoot &&
-                                          content->Tag() != nsGkAtoms::table) {
+    if (!content || !content->IsHTML() || (content->Tag() != nsGkAtoms::tr    &&
+                                           content->Tag() != nsGkAtoms::thead &&
+                                           content->Tag() != nsGkAtoms::tbody &&
+                                           content->Tag() != nsGkAtoms::tfoot &&
+                                           content->Tag() != nsGkAtoms::table)) {
       break;
     }
     ++j;
   }
   return j;
 }
 
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -3898,17 +3898,17 @@ nsXMLHttpRequest::GetInterface(const nsI
     *aResult = static_cast<nsITimerCallback*>(EnsureXPCOMifier().get());
     return NS_OK;
   }
 
   return QueryInterface(aIID, aResult);
 }
 
 JS::Value
-nsXMLHttpRequest::GetInterface(JSContext* aCx, nsIJSIID* aIID, ErrorResult& aRv)
+nsXMLHttpRequest::GetInterface(JSContext* aCx, nsIJSID* aIID, ErrorResult& aRv)
 {
   const nsID* iid = aIID->GetID();
   nsCOMPtr<nsISupports> result;
   JS::Value v = JSVAL_NULL;
   aRv = GetInterface(*iid, getter_AddRefs(result));
   NS_ENSURE_FALSE(aRv.Failed(), JSVAL_NULL);
 
   JSObject* global = JS_GetGlobalForObject(aCx, GetWrapper());
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -443,17 +443,17 @@ public:
   bool MozSystem();
 
   nsIChannel* GetChannel()
   {
     return mChannel;
   }
 
   // We need a GetInterface callable from JS for chrome JS
-  JS::Value GetInterface(JSContext* aCx, nsIJSIID* aIID, ErrorResult& aRv);
+  JS::Value GetInterface(JSContext* aCx, nsIJSID* aIID, ErrorResult& aRv);
 
   // This creates a trusted readystatechange event, which is not cancelable and
   // doesn't bubble.
   static nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
   // For backwards compatibility aPosition should contain the headers for upload
   // and aTotalSize is UINT64_MAX when unknown. Both those values are
   // used by nsXMLHttpProgressEvent. Normal progress event should not use
   // headers in aLoaded and aTotal is 0 when unknown.
--- a/content/base/test/chrome/Makefile.in
+++ b/content/base/test/chrome/Makefile.in
@@ -42,11 +42,12 @@ MOCHITEST_CHROME_FILES = \
     test_bug650784.html \
     test_bug750096.html \
     test_bug752226-3.xul \
     test_bug752226-4.xul \
     test_bug682305.html \
     test_bug780199.xul \
     test_bug780529.xul \
     test_csp_bug768029.html \
+    test_bug800386.xul \
     $(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/content/base/test/chrome/test_bug800386.xul
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=800386
+-->
+<window title="Mozilla Bug 800386"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=800386"
+     target="_blank">Mozilla Bug 800386</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test for Bug 800386 **/
+  Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+  SimpleTest.waitForExplicitFinish();
+
+  var triedForwarding = false;
+  var forwardFailed = false;
+
+  var xhr = new XMLHttpRequest;
+  var eventSink = xhr.getInterface(Components.interfaces.nsIProgressEventSink);
+  isnot(eventSink, null, "Should get event sink directly!");
+
+  // Now jump through some hoops to get us a getInterface call from C++
+
+  var requestor = {
+    getInterface: function(aIID) {
+      if (aIID.equals(Components.interfaces.nsIProgressEventSink)) {
+        triedForwarding = true;
+        try {
+          return xhr.getInterface(aIID);
+        } catch (e) {
+          forwardFailed = true;
+        }
+      }
+      throw Components.results.NS_ERROR_NO_INTERFACE;
+    },
+
+    QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISupports,
+                                           Components.interfaces.nsIInterfaceRequestor])
+  };
+
+  // HTTP URI so that we get progress callbacks
+  xhr.open("GET", "http://mochi.test:8888/", false);
+  xhr.channel.notificationCallbacks = requestor;
+  xhr.onreadystatechange = function() {
+    if (xhr.readyState == 4) {
+      ok(triedForwarding,
+         "Should have had an attempt to treat us as a progress event sink");
+      ok(!forwardFailed,
+         "Should have been able to forward getInterface on to the XHR");
+      SimpleTest.finish();
+    }
+  }
+  xhr.send();
+  ]]>
+  </script>
+</window>
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -56,27 +56,27 @@
 #define MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS      16    // Page 164
 #define MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS        128   // Page 164
 #define MINVALUE_GL_MAX_VARYING_VECTORS               8     // Page 164
 #define MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS           8     // Page 164
 #define MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS    0     // Page 164
 #define MINVALUE_GL_MAX_RENDERBUFFER_SIZE             1024  // Different from the spec, which sets it to 1 on page 164
 #define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS  8     // Page 164
 
-#define DECL_WEBGL_TYPEDEF(type) typedef type Web##type;
-DECL_WEBGL_TYPEDEF(GLenum)
-DECL_WEBGL_TYPEDEF(GLbitfield)
-DECL_WEBGL_TYPEDEF(GLint)
-DECL_WEBGL_TYPEDEF(GLsizei)
-DECL_WEBGL_TYPEDEF(GLsizeiptr)
-DECL_WEBGL_TYPEDEF(GLintptr)
-DECL_WEBGL_TYPEDEF(GLuint)
-DECL_WEBGL_TYPEDEF(GLfloat)
-DECL_WEBGL_TYPEDEF(GLclampf)
-typedef realGLboolean WebGLboolean;
+// Manual reflection of WebIDL typedefs
+typedef uint32_t WebGLenum;
+typedef uint32_t WebGLbitfield;
+typedef int32_t WebGLint;
+typedef int32_t WebGLsizei;
+typedef int64_t WebGLsizeiptr;
+typedef int64_t WebGLintptr;
+typedef uint32_t WebGLuint;
+typedef float WebGLfloat;
+typedef float WebGLclampf;
+typedef bool WebGLboolean;
 
 class nsIPropertyBag;
 
 namespace mozilla {
 
 class WebGLTexture;
 class WebGLBuffer;
 class WebGLProgram;
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -45,16 +45,17 @@ MOCHITEST_FILES = \
 	test_2d.composite.image.destination-in.html \
 	test_2d.composite.image.source-in.html \
 	test_2d.composite.image.source-out.html \
 	test_2d.composite.uncovered.image.destination-in.html \
 	test_2d.composite.uncovered.image.source-in.html \
 	test_2d.composite.uncovered.image.source-out.html \
 	test_2d.drawImage.zerocanvas.html \
 	test_2d.strokeRect.zero.5.html \
+	test_toBlob.html \
 	test_toDataURL_alpha.html \
 	test_toDataURL_lowercase_ascii.html \
 	test_toDataURL_parameters.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
 	test_bug753758.html \
 	test_bug764125.html \
copy from content/canvas/test/test_mozGetAsFile.html
copy to content/canvas/test/test_toBlob.html
--- a/content/canvas/test/test_mozGetAsFile.html
+++ b/content/canvas/test/test_toBlob.html
@@ -2,22 +2,22 @@
 <title>Canvas test: mozGetAsFile</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 
-var gCompares = 0;
+var gCompares = 2;
 
-function compareAsync(file, canvas, type)
+function BlobListener(type, canvas, file)
 {
-  ++gCompares;
-
+  is(file.type, type,
+     "When a valid type is specified that should be returned");
   var reader = new FileReader();
   reader.onload = 
     function(e) {
       is(e.target.result, canvas.toDataURL(type),
  "<canvas>.mozGetAsFile().getAsDataURL() should equal <canvas>.toDataURL()");
       if (--gCompares == 0) {
         SimpleTest.finish();
       }
@@ -28,23 +28,15 @@ function compareAsync(file, canvas, type
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function () {
 
 var canvas = document.getElementById('c');
 var ctx = canvas.getContext('2d');
 
 ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
 
-var pngfile = canvas.mozGetAsFile("foo.png");
-is(pngfile.type, "image/png", "Default type for mozGetAsFile should be PNG");
-compareAsync(pngfile, canvas, "image/png");
-is(pngfile.name, "foo.png", "File name should be what we passed in");
-
-var jpegfile = canvas.mozGetAsFile("bar.jpg", "image/jpeg");
-is(jpegfile.type, "image/jpeg",
-   "When a valid type is specified that should be returned");
-compareAsync(jpegfile, canvas, "image/jpeg");
-is(jpegfile.name, "bar.jpg", "File name should be what we passed in");
+canvas.toBlob(BlobListener.bind(undefined, "image/png", canvas));
+canvas.toBlob(BlobListener.bind(undefined, "image/jpeg", canvas), "image/jpeg");
 
 });
 </script>
 <img src="image_yellow75.png" id="yellow75.png" class="resource">
 
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -60,16 +60,17 @@
 #include "nsDOMDragEvent.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIDOMMozBrowserFrame.h"
 #include "nsIMozBrowserFrame.h"
 
 #include "nsCaret.h"
 
 #include "nsSubDocumentFrame.h"
+#include "nsIFrameTraversal.h"
 #include "nsLayoutCID.h"
 #include "nsLayoutUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsContentUtils.h"
 
 #include "imgIContainer.h"
 #include "nsIProperties.h"
@@ -108,16 +109,18 @@ using namespace mozilla;
 using namespace mozilla::dom;
 
 //#define DEBUG_DOCSHELL_FOCUS
 
 #define NS_USER_INTERACTION_INTERVAL 5000 // ms
 
 static const nsIntPoint kInvalidRefPoint = nsIntPoint(-1,-1);
 
+static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
+
 static bool sLeftClickOnly = true;
 static bool sKeyCausesActivation = true;
 static uint32_t sESMInstanceCount = 0;
 static int32_t sChromeAccessModifier = 0, sContentAccessModifier = 0;
 int32_t nsEventStateManager::sUserInputEventDepth = 0;
 bool nsEventStateManager::sNormalLMouseEventInProcess = false;
 nsEventStateManager* nsEventStateManager::sActiveESM = nullptr;
 nsIDocument* nsEventStateManager::sMouseOverDocument = nullptr;
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -35,16 +35,42 @@
 
 #define DEFAULT_CANVAS_WIDTH 300
 #define DEFAULT_CANVAS_HEIGHT 150
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 
+namespace {
+
+class ToBlobRunnable : public nsRunnable
+{
+public:
+  ToBlobRunnable(nsIFileCallback* aCallback,
+                 nsIDOMBlob* aBlob)
+    : mCallback(aCallback),
+      mBlob(aBlob)
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  }
+
+  NS_IMETHOD Run()
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+    mCallback->Receive(mBlob);
+    return NS_OK;
+  }
+private:
+  nsCOMPtr<nsIFileCallback> mCallback;
+  nsCOMPtr<nsIDOMBlob> mBlob;
+};
+
+} // anonymous namespace
+
 class nsHTMLCanvasPrintState : public nsIDOMMozCanvasPrintState
 {
 public:
   nsHTMLCanvasPrintState(nsHTMLCanvasElement* aCanvas,
                          nsICanvasRenderingContextInternal* aContext,
                          nsITimerCallback* aCallback)
     : mIsDone(false), mPendingNotify(false), mCanvas(aCanvas),
       mContext(aContext), mCallback(aCallback)
@@ -545,16 +571,61 @@ nsHTMLCanvasElement::ToDataURLImpl(const
   uint64_t count;
   rv = stream->Available(&count);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(count <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
 
   return Base64EncodeInputStream(stream, aDataURL, (uint32_t)count, aDataURL.Length());
 }
 
+// XXXkhuey the encoding should be off the main thread, but we're lazy.
+NS_IMETHODIMP
+nsHTMLCanvasElement::ToBlob(nsIFileCallback* aCallback,
+                            const nsAString& aType,
+                            nsIVariant* aParams,
+                            uint8_t optional_argc)
+{
+  // do a trust check if this is a write-only canvas
+  if (mWriteOnly && !nsContentUtils::IsCallerTrustedForRead()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  nsAutoString type;
+  nsresult rv = nsContentUtils::ASCIIToLower(aType, type);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  bool fallbackToPNG = false;
+
+  nsCOMPtr<nsIInputStream> stream;
+  rv = ExtractData(type, EmptyString(), getter_AddRefs(stream), fallbackToPNG);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (fallbackToPNG) {
+    type.AssignLiteral("image/png");
+  }
+
+  uint64_t imgSize;
+  rv = stream->Available(&imgSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(imgSize <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
+
+  void* imgData = nullptr;
+  rv = NS_ReadInputStreamToBuffer(stream, &imgData, imgSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // The DOMFile takes ownership of the buffer
+  nsRefPtr<nsDOMMemoryFile> blob =
+    new nsDOMMemoryFile(imgData, imgSize, type);
+
+  nsRefPtr<ToBlobRunnable> runnable = new ToBlobRunnable(aCallback, blob);
+  return NS_DispatchToCurrentThread(runnable);
+}
+
 NS_IMETHODIMP
 nsHTMLCanvasElement::MozGetAsFile(const nsAString& aName,
                                   const nsAString& aType,
                                   uint8_t optional_argc,
                                   nsIDOMFile** aResult)
 {
   // do a trust check if this is a write-only canvas
   if ((mWriteOnly) &&
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -520,17 +520,16 @@ MediaStreamGraphImpl::GetDesiredBufferEn
       MillisecondsToMediaTime(NS_MAX(AUDIO_TARGET_MS, VIDEO_TARGET_MS));
 }
 
 void
 MediaStreamGraphImpl::FinishStream(MediaStream* aStream)
 {
   if (aStream->mFinished)
     return;
-  printf("MediaStreamGraphImpl::FinishStream\n");
   LOG(PR_LOG_DEBUG, ("MediaStream %p will finish", aStream));
   aStream->mFinished = true;
   // Force at least one more iteration of the control loop, since we rely
   // on UpdateCurrentTime to notify our listeners once the stream end
   // has been reached.
   EnsureNextIteration();
 }
 
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -954,17 +954,16 @@ void nsBuiltinDecoder::SeekingStoppedAtE
 
     // An additional seek was requested while the current seek was
     // in operation.
     if (mRequestedSeekTime >= 0.0) {
       ChangeState(PLAY_STATE_SEEKING);
       seekWasAborted = true;
     } else {
       UnpinForSeek();
-      printf("nsBuiltinDecoder::SeekingStoppedAtEnd, next state=PLAY_STATE_ENDED\n");
       fireEnded = true;
       ChangeState(PLAY_STATE_ENDED);
     }
   }
 
   if (mElement) {
     UpdateReadyStateForData();
     if (!seekWasAborted) {
@@ -1044,19 +1043,16 @@ void nsBuiltinDecoder::PlaybackPositionC
         // Only update the current playback position if we're not seeking.
         // If we are seeking, the update could have been scheduled on the
         // state machine thread while we were playing but after the seek
         // algorithm set the current playback position on the main thread,
         // and we don't want to override the seek algorithm and change the
         // current time after the seek has started but before it has
         // completed.
         mCurrentTime = mDecoderStateMachine->GetCurrentTime();
-      } else {
-        printf("Suppressed timeupdate during seeking: currentTime=%f, new time=%f\n",
-               mCurrentTime, mDecoderStateMachine->GetCurrentTime());
       }
       mDecoderStateMachine->ClearPositionChangeFlag();
     }
   }
 
   // Invalidate the frame so any video data is displayed.
   // Do this before the timeupdate event so that if that
   // event runs JavaScript that queries the media size, the
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -2133,17 +2133,16 @@ nsresult nsBuiltinDecoderStateMachine::R
         return NS_OK;
       }
  
       StopAudioThread();
       if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING) {
         int64_t videoTime = HasVideo() ? mVideoFrameEndTime : 0;
         int64_t clockTime = NS_MAX(mEndTime, NS_MAX(videoTime, GetAudioClock()));
         UpdatePlaybackPosition(clockTime);
-        printf("nsBuiltinDecoderStateMachine::RunStateMachine queuing nsBuiltinDecoder::PlaybackEnded\n");
         nsCOMPtr<nsIRunnable> event =
           NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::PlaybackEnded);
         NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
       }
       return NS_OK;
     }
   }
 
new file mode 100644
--- /dev/null
+++ b/content/media/test/crashtests/789075-1.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+</head>
+<body>
+<video src="789075.webm" onloadedmetadata="document.documentElement.className=undefined"></video>
+</body>
+</html>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..602e53fca23f3619079e199fc20a0eb8ffa241fd
GIT binary patch
literal 12294
zc%1Fpy-NaN90%~{4ilHig2W;)3=9NMF$!J8t|Eej;Katte1W7$Dhpcf(L1|nY)dM_
zDGDiq5}h1cb987ZXlSkmw_emIq@};$`|x?-_dMU{IgV%k^-n$JIno>!F-tkI{xjdH
zPW+$-F|BMz!>i&R<wce9W=W2>jykK|f!rp$77UbG)gxUfreGl<U23fjQv8z*Nac3s
zJo}UN&YZ{E_ZAyVmd@I1*O@NSKe?~@{c>|FARndHccN>{gDIEb6~-KHm)8*=iG`OU
zQTP1#KVjqd*mr#eR*cptw{fpLoLE*el*_82h0vVmnT6)7v@Kam^A)K`$x!A+^ZVFq
zP26s^&IpIEl;n*>IG}{c#%jkgXHVKHJefAAs-`L$&l9~#SJ%_XY2q<A?AZkX00000
z000000000000000000000I<rRU!@Fb^xCr)cI$7SecufwcdYKLQ|^tm+jIOk`j(j<
--- a/content/media/test/crashtests/crashtests.list
+++ b/content/media/test/crashtests/crashtests.list
@@ -6,8 +6,9 @@ load 474744-1.html
 HTTP load 481136-1.html # needs to be HTTP to recognize the ogg as an audio file?
 load 493915-1.html
 skip-if(Android) load 495794-1.html
 load 492286-1.xhtml
 load 576612-1.html
 skip-if(Android) load 691096-1.html # Android sound API can't handle playing large number of sounds at once.
 load 752784-1.html
 HTTP load 795892-1.html
+load 789075-1.html
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -700,24 +700,24 @@ bool nsWebMReader::DecodeVideoFrame(bool
       b.mPlanes[0].mData = img->planes[0];
       b.mPlanes[0].mStride = img->stride[0];
       b.mPlanes[0].mHeight = img->d_h;
       b.mPlanes[0].mWidth = img->d_w;
       b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0;
 
       b.mPlanes[1].mData = img->planes[1];
       b.mPlanes[1].mStride = img->stride[1];
-      b.mPlanes[1].mHeight = img->d_h >> img->y_chroma_shift;
-      b.mPlanes[1].mWidth = img->d_w >> img->x_chroma_shift;
+      b.mPlanes[1].mHeight = (img->d_h + 1) >> img->y_chroma_shift;
+      b.mPlanes[1].mWidth = (img->d_w + 1) >> img->x_chroma_shift;
       b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0;
  
       b.mPlanes[2].mData = img->planes[2];
       b.mPlanes[2].mStride = img->stride[2];
-      b.mPlanes[2].mHeight = img->d_h >> img->y_chroma_shift;
-      b.mPlanes[2].mWidth = img->d_w >> img->x_chroma_shift;
+      b.mPlanes[2].mHeight = (img->d_h + 1) >> img->y_chroma_shift;
+      b.mPlanes[2].mWidth = (img->d_w + 1) >> img->x_chroma_shift;
       b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
   
       nsIntRect picture = mPicture;
       if (img->d_w != static_cast<uint32_t>(mInitialFrame.width) ||
           img->d_h != static_cast<uint32_t>(mInitialFrame.height)) {
         // Frame size is different from what the container reports. This is legal
         // in WebM, and we will preserve the ratio of the crop rectangle as it
         // was reported relative to the picture size reported by the container.
--- a/content/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -9,16 +9,23 @@
 #define DEFAULT_PORT 5555
 
 #define SAMPLE_RATE 256000
 #define SAMPLE_FREQUENCY 16000
 #define SAMPLE_LENGTH ((SAMPLE_FREQUENCY*10)/1000)
 
 namespace mozilla {
 
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* gMediaManagerLog;
+#define LOG(msg) PR_LOG(gMediaManagerLog, PR_LOG_DEBUG, msg)
+#else
+#define LOG(msg)
+#endif
+
 /**
  * Webrtc audio source.
  */
 NS_IMPL_THREADSAFE_ISUPPORTS0(MediaEngineWebRTCAudioSource)
 
 void
 MediaEngineWebRTCAudioSource::GetName(nsAString& aName)
 {
@@ -202,19 +209,17 @@ MediaEngineWebRTCAudioSource::Process(co
   const webrtc::ProcessingTypes type, sample* audio10ms,
   const int length, const int samplingFreq, const bool isStereo)
 {
   ReentrantMonitorAutoEnter enter(mMonitor);
 
   nsRefPtr<SharedBuffer> buffer = SharedBuffer::Create(length * sizeof(sample));
 
   sample* dest = static_cast<sample*>(buffer->Data());
-  for (int i = 0; i < length; i++) {
-    dest[i] = audio10ms[i];
-  }
+  memcpy(dest, audio10ms, length * sizeof(sample));
 
   AudioSegment segment;
   segment.Init(CHANNELS);
   segment.AppendFrames(
     buffer.forget(), length, 0, length, nsAudioStream::FORMAT_S16
   );
   mSource->AppendToTrack(mTrackID, &segment);
 
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -4,16 +4,23 @@
 
 #include "MediaEngineWebRTC.h"
 #include "Layers.h"
 #include "ImageTypes.h"
 #include "ImageContainer.h"
 
 namespace mozilla {
 
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* gMediaManagerLog;
+#define LOG(msg) PR_LOG(gMediaManagerLog, PR_LOG_DEBUG, msg)
+#else
+#define LOG(msg)
+#endif
+
 /**
  * Webrtc video source.
  */
 NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineWebRTCVideoSource, nsIRunnable)
 
 MediaEngineWebRTCVideoSource::MediaEngineWebRTCVideoSource(webrtc::VideoEngine* aVideoEnginePtr,
                                                            int aIndex, int aMinFps)
   : mVideoEngine(aVideoEnginePtr)
@@ -60,16 +67,17 @@ MediaEngineWebRTCVideoSource::DeliverFra
     mInSnapshotMode = false;
     PR_NotifyCondVar(mSnapshotCondVar);
     PR_Unlock(mSnapshotLock);
     return 0;
   }
 
   // Check for proper state.
   if (mState != kStarted) {
+    LOG(("DeliverFrame: video not started"));
     return 0;
   }
 
   // Create a video frame and append it to the track.
   ImageFormat format = PLANAR_YCBCR;
   nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&format, 1);
 
   layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -11105,18 +11105,18 @@ nsDocShell::AddURIVisit(nsIURI* aURI,
         if (aResponseStatus >= 300 && aResponseStatus < 400) {
             visitURIFlags |= IHistory::REDIRECT_SOURCE;
         }
         // Errors 400-501 and 505 are considered unrecoverable, in the sense a
         // simple retry attempt by the user is unlikely to solve them.
         // 408 is special cased, since may actually indicate a temporary
         // connection problem.
         else if (aResponseStatus != 408 &&
-                 (aResponseStatus >= 400 && aResponseStatus <= 501 ||
-                  aResponseStatus == 505)) {
+                 ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
+                   aResponseStatus == 505)) {
             visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
         }
 
         (void)history->VisitURI(aURI, aPreviousURI, visitURIFlags);
     }
     else if (mGlobalHistory) {
         // Falls back to sync global history interface.
         (void)mGlobalHistory->AddURI(aURI,
--- a/dom/activities/src/ActivitiesService.jsm
+++ b/dom/activities/src/ActivitiesService.jsm
@@ -162,17 +162,17 @@ let Activities = {
     this.messages.forEach(function(msgName) {
       ppmm.addMessageListener(msgName, this);
     }, this);
 
     Services.obs.addObserver(this, "xpcom-shutdown", false);
 
     this.db = new ActivitiesDb();
     this.db.init();
-    this.mm = {};
+    this.callers = {};
   },
 
   observe: function activities_observe(aSubject, aTopic, aData) {
     this.messages.forEach(function(msgName) {
       ppmm.removeMessageListener(msgName, this);
     }, this);
     ppmm = null;
 
@@ -189,34 +189,34 @@ let Activities = {
   startActivity: function activities_startActivity(aMsg) {
     debug("StartActivity: " + JSON.stringify(aMsg));
 
     let successCb = function successCb(aResults) {
       debug(JSON.stringify(aResults));
 
       // We have no matching activity registered, let's fire an error.
       if (aResults.options.length === 0) {
-        Activities.mm[aMsg.id].sendAsyncMessage("Activity:FireError", {
+        Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireError", {
           "id": aMsg.id,
           "error": "NO_PROVIDER"
         });
-        delete Activities.mm[aMsg.id];
+        delete Activities.callers[aMsg.id];
         return;
       }
 
       function getActivityChoice(aChoice) {
         debug("Activity choice: " + aChoice);
 
         // The user has cancelled the choice, fire an error.
         if (aChoice === -1) {
-          Activities.mm[aMsg.id].sendAsyncMessage("Activity:FireError", {
+          Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireError", {
             "id": aMsg.id,
             "error": "USER_ABORT"
           });
-          delete Activities.mm[aMsg.id];
+          delete Activities.callers[aMsg.id];
           return;
         }
 
         let sysmm = Cc["@mozilla.org/system-message-internal;1"]
                       .getService(Ci.nsISystemMessagesInternal);
         if (!sysmm) {
           // System message is not present, what should we do?
           return;
@@ -228,21 +228,23 @@ let Activities = {
             "id": aMsg.id,
             "payload": aMsg.options,
             "target": result.description
           },
           Services.io.newURI(result.description.href, null, null),
           Services.io.newURI(result.manifest, null, null));
 
         if (!result.description.returnValue) {
-          Activities.mm[aMsg.id].sendAsyncMessage("Activity:FireSuccess", {
+          Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireSuccess", {
             "id": aMsg.id,
             "result": null
           });
-          delete Activities.mm[aMsg.id];
+          // No need to notify observers, since we don't want the caller
+          // to be raised on the foreground that quick.
+          delete Activities.callers[aMsg.id];
         }
       };
 
       let glue = Cc["@mozilla.org/dom/activities/ui-glue;1"]
                    .createInstance(Ci.nsIActivityUIGlue);
       glue.chooseActivity(aResults.name, aResults.options, getActivityChoice);
     };
 
@@ -266,29 +268,47 @@ let Activities = {
     };
 
     this.db.find(aMsg, successCb, errorCb, matchFunc);
   },
 
   receiveMessage: function activities_receiveMessage(aMessage) {
     let mm = aMessage.target;
     let msg = aMessage.json;
+
+    let caller;
+    let obsData;
+
+    if (aMessage.name == "Activity:FireSuccess" ||
+        aMessage.name == "Activity:FireError") {
+      caller = this.callers[msg.id];
+      if (caller) {
+        obsData = JSON.stringify({ manifestURL: caller.manifestURL,
+                                   pageURL: caller.pageURL,
+                                   success: aMessage.name == "Activity:FireSuccess" });
+      }
+    }
+
     switch(aMessage.name) {
       case "Activity:Start":
-        this.mm[msg.id] = aMessage.target;
+        this.callers[msg.id] = { mm: aMessage.target,
+                                 manifestURL: msg.manifestURL,
+                                 pageURL: msg.pageURL };
         this.startActivity(msg);
         break;
 
       case "Activity:PostResult":
-        this.mm[msg.id].sendAsyncMessage("Activity:FireSuccess", msg);
-        delete this.mm[msg.id];
+        caller.mm.sendAsyncMessage("Activity:FireSuccess", msg);
+        Services.obs.notifyObservers(null, "activity-done", obsData);
+        delete this.callers[msg.id];
         break;
       case "Activity:PostError":
-        this.mm[msg.id].sendAsyncMessage("Activity:FireError", msg);
-        delete this.mm[msg.id];
+        caller.mm.sendAsyncMessage("Activity:FireError", msg);
+        Services.obs.notifyObservers(null, "activity-done", obsData);
+        delete this.callers[msg.id];
         break;
 
       case "Activities:Register":
         this.db.add(msg, function onSuccess(aEvent) {
           mm.sendAsyncMessage("Activities:Register:OK", msg);
         },
         function onError(aEvent) {
           msg.error = "REGISTER_ERROR";
--- a/dom/activities/src/ActivityProxy.js
+++ b/dom/activities/src/ActivityProxy.js
@@ -6,16 +6,17 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
+Cu.import("resource://gre/modules/Webapps.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsISyncMessageSender");
 
 function debug(aMsg) {
   //dump("-- ActivityProxy " + Date.now() + " : " + aMsg + "\n");
 }
@@ -35,17 +36,28 @@ ActivityProxy.prototype = {
   startActivity: function actProxy_startActivity(aActivity, aOptions, aWindow) {
     debug("startActivity");
 
     this.window = aWindow;
     this.activity = aActivity;
     this.id = Cc["@mozilla.org/uuid-generator;1"]
                 .getService(Ci.nsIUUIDGenerator)
                 .generateUUID().toString();
-    cpmm.sendAsyncMessage("Activity:Start", { id: this.id, options: aOptions });
+    // Retrieve the app's manifest url from the principal, so that we can
+    // later notify when the activity handler called postResult or postError
+    let principal = aWindow.document.nodePrincipal;
+    let appId = principal.appId;
+    let manifestURL = (appId != Ci.nsIScriptSecurityManager.NO_APP_ID &&
+                       appId != Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID)
+                        ? DOMApplicationRegistry.getManifestURLByLocalId(appId)
+                        : null;
+    cpmm.sendAsyncMessage("Activity:Start", { id: this.id,
+                                              options: aOptions,
+                                              manifestURL: manifestURL,
+                                              pageURL: aWindow.document.location.href });
 
     cpmm.addMessageListener("Activity:FireSuccess", this);
     cpmm.addMessageListener("Activity:FireError", this);
   },
 
   receiveMessage: function actProxy_receiveMessage(aMessage) {
     debug("Got message: " + aMessage.name);
     let msg = aMessage.json;
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -61,16 +61,17 @@ EXPORTS = \
   nsIScriptContext.h	\
   nsIScriptExternalNameSet.h \
   nsIScriptGlobalObject.h \
   nsIScriptGlobalObjectOwner.h \
   nsIScriptNameSpaceManager.h \
   nsIScriptObjectPrincipal.h \
   nsIScriptRuntime.h \
   nsIScriptTimeoutHandler.h \
+  nsJSEnvironment.h \
   nsJSUtils.h \
   nsPIDOMWindow.h \
   nsPIWindowRoot.h \
   nsFocusManager.h \
   nsWrapperCache.h \
   nsWrapperCacheInlines.h \
   nsContentPermissionHelper.h \
   nsStructuredCloneContainer.h \
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -549,18 +549,16 @@ using mozilla::dom::indexedDB::IDBWrappe
 #include "GeneratedEvents.h"
 #include "mozilla/Likely.h"
 #include "nsDebug.h"
 
 #ifdef MOZ_WEBRTC
 #include "nsIDOMDataChannel.h"
 #endif
 
-#undef None // something included above defines this preprocessor symbol, maybe Xlib headers
-#include "WebGLContext.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
@@ -5340,20 +5338,19 @@ GetDocument(JSObject *obj)
 }
 
 // static
 JSBool
 nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
                                           JSHandleId id, unsigned flags,
                                           JSMutableHandleObject objp)
 {
-  if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_QUALIFIED) ||
-      !JSID_IS_STRING(id)) {
-    // Nothing to do here if we're assigning, doing a qualified resolve, or
-    // resolving a non-string property.
+  if ((flags & JSRESOLVE_ASSIGNING) || !JSID_IS_STRING(id)) {
+    // Nothing to do here if we're assigning or resolving a non-string
+    // property.
 
     return JS_TRUE;
   }
 
   nsHTMLDocument *document = GetDocument(obj);
 
   if (!document) {
     // If we don't have a document, return early.
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -26,17 +26,17 @@
 #include "nsIHTMLDocument.h"
 #include "nsIDocShell.h"
 #include "nsIEditorDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsLayoutUtils.h"
 #include "nsIPresShell.h"
 #include "nsIContentViewer.h"
-#include "nsFrameIterator.h"
+#include "nsFrameTraversal.h"
 #include "nsObjectFrame.h"
 #include "nsEventDispatcher.h"
 #include "nsEventStateManager.h"
 #include "nsIMEStateManager.h"
 #include "nsIWebNavigation.h"
 #include "nsCaret.h"
 #include "nsIBaseWindow.h"
 #include "nsIViewManager.h"
@@ -2265,27 +2265,34 @@ nsFocusManager::GetSelectionLocation(nsI
         startContent->AppendTextTo(nodeValue);
 
         bool isFormControl =
           startContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL);
 
         if (nodeValue.Length() == (uint32_t)startOffset && !isFormControl &&
             startContent != aDocument->GetRootElement()) {
           // Yes, indeed we were at the end of the last node
-          nsFrameIterator frameTraversal(presContext, startFrame,
-                                         eLeaf, nsFrameIterator::FLAG_FOLLOW_OUT_OF_FLOW);
+          nsCOMPtr<nsIFrameEnumerator> frameTraversal;
+          nsresult rv = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
+                                             presContext, startFrame,
+                                             eLeaf,
+                                             false, // aVisual
+                                             false, // aLockInScrollView
+                                             true      // aFollowOOFs
+                                             );
+          NS_ENSURE_SUCCESS(rv, rv);
 
           nsIFrame *newCaretFrame = nullptr;
           nsCOMPtr<nsIContent> newCaretContent = startContent;
           bool endOfSelectionInStartNode(startContent == endContent);
           do {
             // Continue getting the next frame until the primary content for the frame
             // we are on changes - we don't want to be stuck in the same place
-            frameTraversal.Next();
-            newCaretFrame = static_cast<nsIFrame*>(frameTraversal.CurrentItem());
+            frameTraversal->Next();
+            newCaretFrame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
             if (nullptr == newCaretFrame)
               break;
             newCaretContent = newCaretFrame->GetContent();
           } while (!newCaretContent || newCaretContent == startContent);
 
           if (newCaretFrame && newCaretContent) {
             // If the caret is exactly at the same position of the new frame,
             // then we can use the newCaretFrame and newCaretContent for our position
@@ -2691,39 +2698,46 @@ nsFocusManager::GetNextTabbableContent(n
       if (iterStartContent)
         continue;
 
       // otherwise, as a last attempt, just look at the root content
       iterStartContent = aRootContent;
       continue;
     }
 
-    nsFrameIterator frameTraversal(presContext, startFrame,
-                                   ePreOrder, nsFrameIterator::FLAG_FOLLOW_OUT_OF_FLOW);
+    nsCOMPtr<nsIFrameEnumerator> frameTraversal;
+    nsresult rv = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
+                                       presContext, startFrame,
+                                       ePreOrder,
+                                       false, // aVisual
+                                       false, // aLockInScrollView
+                                       true      // aFollowOOFs
+                                       );
+    NS_ENSURE_SUCCESS(rv, rv);
 
     if (iterStartContent == aRootContent) {
       if (!aForward) {
-        frameTraversal.Last();
+        frameTraversal->Last();
       } else if (aRootContent->IsFocusable()) {
-        frameTraversal.Next();
+        frameTraversal->Next();
       }
     }
     else if (getNextFrame &&
              (!iterStartContent || iterStartContent->Tag() != nsGkAtoms::area ||
               !iterStartContent->IsHTML())) {
       // Need to do special check in case we're in an imagemap which has multiple
       // content nodes per frame, so don't skip over the starting frame.
       if (aForward)
-        frameTraversal.Next();
+        frameTraversal->Next();
       else
-        frameTraversal.Prev();
+        frameTraversal->Prev();
     }
 
     // Walk frames to find something tabbable matching mCurrentTabIndex
-    nsIFrame* frame = static_cast<nsIFrame*>(frameTraversal.CurrentItem());
+    nsIFrame* frame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
     while (frame) {
       // TabIndex not set defaults to 0 for form elements, anchors and other
       // elements that are normally focusable. Tabindex defaults to -1
       // for elements that are not normally focusable.
       // The returned computed tabindex from IsFocusable() is as follows:
       //          < 0 not tabbable at all
       //          == 0 in normal tab order (last after positive tabindexed items)
       //          > 0 can be tabbed to in the order specified by this value
@@ -2783,20 +2797,20 @@ nsFocusManager::GetNextTabbableContent(n
                     NS_ADDREF(*aResultContent);
                     return NS_OK;
                   }
                 }
               }
               Element* rootElement = subdoc->GetRootElement();
               nsIPresShell* subShell = subdoc->GetShell();
               if (rootElement && subShell) {
-                nsresult rv = GetNextTabbableContent(subShell, rootElement,
-                                                     aOriginalStartContent, rootElement,
-                                                     aForward, (aForward ? 1 : 0),
-                                                     false, aResultContent);
+                rv = GetNextTabbableContent(subShell, rootElement,
+                                            aOriginalStartContent, rootElement,
+                                            aForward, (aForward ? 1 : 0),
+                                            false, aResultContent);
                 NS_ENSURE_SUCCESS(rv, rv);
                 if (*aResultContent)
                   return NS_OK;
               }
             }
           }
           // otherwise, use this as the next content node to tab to, unless
           // this was the element we started on. This would happen for
@@ -2830,20 +2844,20 @@ nsFocusManager::GetNextTabbableContent(n
       // Otherwise, a loop will occur in the following example:
       //   <span tabindex="1">...<a/><a/>...</span>
       // where the text wraps onto multiple lines. Tabbing from the second
       // link can find one of the span's continuation frames between the link
       // and the end of the span, and the span would end up getting focused
       // again.
       do {
         if (aForward)
-          frameTraversal.Next();
+          frameTraversal->Next();
         else
-          frameTraversal.Prev();
-        frame = static_cast<nsIFrame*>(frameTraversal.CurrentItem());
+          frameTraversal->Prev();
+        frame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
       } while (frame && frame->GetPrevContinuation());
     }
 
     // If already at lowest priority tab (0), end search completely.
     // A bit counterintuitive but true, tabindex order goes 1, 2, ... 32767, 0
     if (aCurrentTabIndex == (aForward ? 0 : 1)) {
       // if going backwards, the canvas should be focused once the beginning
       // has been reached.
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2714,34 +2714,34 @@ static JSFunctionSpec JProfFunctions[] =
     JS_FS("JProfStopProfiling",         JProfStopProfilingJS,       0, 0),
     JS_FS("JProfClearCircular",         JProfClearCircularJS,       0, 0),
     JS_FS("JProfSaveCircular",          JProfSaveCircularJS,        0, 0),
     JS_FS_END
 };
 
 #endif /* defined(MOZ_JPROF) */
 
-#ifdef MOZ_DMD
+#ifdef MOZ_DMDV
 
 // See https://wiki.mozilla.org/Performance/MemShrink/DMD for instructions on
-// how to use DMD.
+// how to use DMDV.
 
 static JSBool
-DMDCheckJS(JSContext *cx, unsigned argc, jsval *vp)
+DMDVCheckAndDumpJS(JSContext *cx, unsigned argc, jsval *vp)
 {
-  mozilla::DMDCheckAndDump();
+  mozilla::DMDVCheckAndDump();
   return JS_TRUE;
 }
 
-static JSFunctionSpec DMDFunctions[] = {
-    JS_FS("DMD",                        DMDCheckJS,                 0, 0),
+static JSFunctionSpec DMDVFunctions[] = {
+    JS_FS("DMDV",                       DMDVCheckAndDumpJS,         0, 0),
     JS_FS_END
 };
 
-#endif /* defined(MOZ_DMD) */
+#endif /* defined(MOZ_DMDV) */
 
 nsresult
 nsJSContext::InitClasses(JSObject* aGlobalObj)
 {
   nsresult rv = InitializeExternalClasses();
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSAutoRequest ar(mContext);
@@ -2756,19 +2756,19 @@ nsJSContext::InitClasses(JSObject* aGlob
   ::JS_DefineFunctions(mContext, aGlobalObj, TraceMallocFunctions);
 #endif
 
 #ifdef MOZ_JPROF
   // Attempt to initialize JProf functions
   ::JS_DefineFunctions(mContext, aGlobalObj, JProfFunctions);
 #endif
 
-#ifdef MOZ_DMD
-  // Attempt to initialize DMD functions
-  ::JS_DefineFunctions(mContext, aGlobalObj, DMDFunctions);
+#ifdef MOZ_DMDV
+  // Attempt to initialize DMDV functions
+  ::JS_DefineFunctions(mContext, aGlobalObj, DMDVFunctions);
 #endif
 
   return rv;
 }
 
 void
 nsJSContext::WillInitializeContext()
 {
--- a/dom/base/test/Makefile.in
+++ b/dom/base/test/Makefile.in
@@ -9,16 +9,17 @@ VPATH = @srcdir@
 relativesrcdir = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_FILES = \
   test_domrequest.html \
   test_gsp-standards.html \
   test_gsp-quirks.html \
+  test_gsp-qualified.html \
   test_nondomexception.html \
   test_screen_orientation.html \
   $(NULL)
 
 MOCHITEST_CHROME_FILES = \
    test_bug715041.xul \
    test_bug715041_removal.xul \
    $(NULL)
copy from dom/base/test/test_gsp-standards.html
copy to dom/base/test/test_gsp-qualified.html
--- a/dom/base/test/test_gsp-standards.html
+++ b/dom/base/test/test_gsp-qualified.html
@@ -1,27 +1,38 @@
 <!DOCTYPE HTML>
 <html>
 <!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=622491
+https://bugzilla.mozilla.org/show_bug.cgi?id=799875
 -->
 <head>
   <meta charset="utf-8">
-  <title>Test for Bug 622491</title>
+  <title>Test for Bug 799875</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622491">Mozilla Bug 622491</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=799875">Mozilla Bug 799875</a>
 <p id="display"></p>
 <div id="content" style="display: none">
-  
+  <iframe src="data:text/html,<div id='test2'>"></iframe>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
-/** Test for Bug 622491 **/
-is(test, document.getElementById("test"), "Global scope polluter should map ids")
+/** Test for Bug 799875 **/
+SimpleTest.waitForExplicitFinish();
 
+addLoadEvent(function() {
+  is(window.test, document.getElementById("test"),
+     "Global scope polluter should map ids even when qualified")
+  isnot(document.getElementById("test"), null,
+        "Should have element");
+  is(window[0].test2, window[0].document.getElementById("test2"),
+     "Global scope polluter should map ids across globals");
+  isnot(window[0].document.getElementById("test2"), null,
+        "Should have element in subframe");
+  SimpleTest.finish();
+});
 </script>
 </pre>
 </body>
 </html>
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -226,32 +226,40 @@ DOMInterfaces = {
 {
     'headerFile': 'HTMLPropertiesCollection.h',
     'prefable': True,
     'resultNotAddRefed': [ 'item', 'namedItem', 'names' ]
 }],
 
 'IID': [
 {
-    'nativeType': 'nsIJSIID',
+    'nativeType': 'nsIJSID',
     'headerFile': 'xpcjsid.h',
 },
 {
     'workers': True,
 }],
 
 'InputStream': [
 {
     'nativeType': 'nsIInputStream',
     'notflattened': True
 },
 {
     'workers': True,
 }],
 
+'MediaStreamList': {
+    'headerFile': 'MediaStreamList.h',
+    'wrapperCache': False,
+    'nativeOwnership': 'owned',
+    'resultNotAddRefed': [ '__indexedGetter' ],
+    'binaryNames': { '__indexedGetter': 'IndexedGetter' }
+},
+
 'MozChannel': [
 {
     'nativeType': 'nsIChannel',
     'notflattened': True
 },
 {
     'workers': True,
 }],
@@ -608,16 +616,17 @@ addExternalIface('CSSRule')
 addExternalIface('CSSValue')
 addExternalIface('DOMStringList', nativeType='nsDOMStringList',
                  headerFile='nsDOMLists.h')
 addExternalIface('Element', nativeType='nsGenericElement')
 addExternalIface('File')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('HTMLElement')
 addExternalIface('ImageData', nativeType='mozilla::dom::ImageData')
+addExternalIface('MediaStream')
 addExternalIface('Node', nativeType='nsINode')
 addExternalIface('PaintRequest')
 addExternalIface('SVGLength')
 addExternalIface('SVGMatrix')
 addExternalIface('SVGNumber')
 addExternalIface('SVGPathSeg')
 addExternalIface('SVGPoint')
 addExternalIface('SVGTransform')
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -69,16 +69,17 @@ EXPORTS_$(binding_include_path) = \
   UnionTypes.h \
   $(exported_binding_headers) \
   $(NULL)
 
 LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \
   -I$(topsrcdir)/js/xpconnect/wrappers \
   -I$(topsrcdir)/content/canvas/src \
   -I$(topsrcdir)/content/html/content/src \
+  -I$(topsrcdir)/media/webrtc/signaling/src/peerconnection \
   -I$(topsrcdir)/dom/base \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 # If you change bindinggen_dependencies here, change it in
 # dom/bindings/test/Makefile.in too.
 bindinggen_dependencies := \
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -154,16 +154,37 @@ BluetoothOppManager::Connect(const nsASt
 
 void
 BluetoothOppManager::Disconnect()
 {
   CloseSocket();
 }
 
 bool
+BluetoothOppManager::Listen()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  CloseSocket();
+
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
+    return false;
+  }
+
+  nsresult rv = bs->ListenSocketViaService(BluetoothReservedChannels::OPUSH,
+                                           BluetoothSocketType::RFCOMM,
+                                           true,
+                                           false,
+                                           this);
+  return NS_FAILED(rv) ? false : true;
+}
+
+bool
 BluetoothOppManager::SendFile(BlobParent* aActor,
                               BluetoothReplyRunnable* aRunnable)
 {
   if (mBlob) {
     // Means there's a sending process. Reply error.
     return false;
   }
 
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -41,16 +41,17 @@ public:
    * percentage of file. At the end, the application will get another
    * system message indicating that te process is complete, then it can
    * either call Disconnect() to close RFCOMM connection or start another
    * file-sending thread via calling SendFile() again.
    */
   bool Connect(const nsAString& aDeviceObjectPath,
                BluetoothReplyRunnable* aRunnable);
   void Disconnect();
+  bool Listen();
 
   bool SendFile(BlobParent* aBlob,
                 BluetoothReplyRunnable* aRunnable);
   bool StopSendingFile(BluetoothReplyRunnable* aRunnable);
 
   void SendConnectRequest();
   void SendPutHeaderRequest(const nsAString& aFileName, int aFileSize);
   void SendPutRequest(uint8_t* aFileBody, int aFileBodyLength,
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -752,30 +752,42 @@ class PrepareProfileManagersRunnable : p
 public:
   NS_IMETHOD
   Run()
   {
     BluetoothHfpManager* h = BluetoothHfpManager::Get();
     if (h) {
       h->Listen();
     }
+
+    BluetoothOppManager* opp = BluetoothOppManager::Get();
+    if (opp) {
+      opp->Listen();
+    }
+
     return NS_OK;
   }
 };
 
 class ShutdownProfileManagersRunnable : public nsRunnable
 {
 public:
   NS_IMETHOD
   Run()
   {
     BluetoothHfpManager* h = BluetoothHfpManager::Get();
     if (h) {
       h->CloseSocket();
     }
+
+    BluetoothOppManager* opp = BluetoothOppManager::Get();
+    if (opp) {
+      opp->CloseSocket();
+    }
+
     return NS_OK;
   }
 };
 
 class PrepareAdapterRunnable : public nsRunnable
 {
 public:
   PrepareAdapterRunnable(const nsAString& aPath) :
@@ -788,16 +800,17 @@ public:
   Run()
   {
     MOZ_ASSERT(!NS_IsMainThread());
 
     nsTArray<uint32_t> uuids;
 
     uuids.AppendElement((uint32_t)(BluetoothServiceUuid::HandsfreeAG >> 32));
     uuids.AppendElement((uint32_t)(BluetoothServiceUuid::HeadsetAG >> 32));
+    uuids.AppendElement((uint32_t)(BluetoothServiceUuid::ObjectPush >> 32));
 
     // TODO/qdot: This needs to be held for the life of the bluetooth connection
     // so we could clean it up. For right now though, we can throw it away.
     nsTArray<uint32_t> handles;
 
     if (!BluetoothDBusService::AddReservedServicesInternal(mPath, uuids, handles)) {
       NS_WARNING("Failed to add reserved services");
 #ifdef MOZ_WIDGET_GONK
--- a/dom/browser-element/BrowserElementChild.js
+++ b/dom/browser-element/BrowserElementChild.js
@@ -396,26 +396,26 @@ BrowserElementChild.prototype = {
 
     this._ctxCounter++;
     this._ctxHandlers = {};
 
     var elem = e.target;
     var menuData = {systemTargets: [], contextmenu: null};
     var ctxMenuId = null;
 
-    while (elem && elem.hasAttribute) {
+    while (elem && elem.parentNode) {
       var ctxData = this._getSystemCtxMenuData(elem);
       if (ctxData) {
         menuData.systemTargets.push({
           nodeName: elem.nodeName,
           data: ctxData
         });
       }
 
-      if (!ctxMenuId && elem.hasAttribute('contextmenu')) {
+      if (!ctxMenuId && 'hasAttribute' in elem && elem.hasAttribute('contextmenu')) {
         ctxMenuId = elem.getAttribute('contextmenu');
       }
       elem = elem.parentNode;
     }
 
     if (ctxMenuId) {
       var menu = e.target.ownerDocument.getElementById(ctxMenuId);
       if (menu) {
--- a/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js
+++ b/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js
@@ -15,17 +15,17 @@ var iframeScript = function() {
   };
 
   XPCNativeWrapper.unwrap(content).onerror = function(e) {
     sendAsyncMessage('test:errorTriggered', {data: e});
   };
 
   content.fireContextMenu(content.document.body);
   content.fireContextMenu(content.document.getElementById('menu1-trigger'));
-  content.fireContextMenu(content.document.getElementById('inner-link'));
+  content.fireContextMenu(content.document.getElementById('inner-link').childNodes[0]);
   content.fireContextMenu(content.document.getElementById('menu2-trigger'));
 }
 
 var trigger1 = function() {
   content.fireContextMenu(content.document.getElementById('menu1-trigger'));
 };
 
 function runTest() {
--- a/dom/interfaces/css/nsIDOMCSS2Properties.idl
+++ b/dom/interfaces/css/nsIDOMCSS2Properties.idl
@@ -9,17 +9,17 @@
  * The nsIDOMCSS2Properties interface is a datatype for additional
  * reflection of data already provided in nsIDOMCSSStyleDeclaration in
  * the Document Object Model.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Style
  */
 
-[builtinclass, scriptable, uuid(2ae61565-1a66-4e6e-960d-b999c631e5c6)]
+[builtinclass, scriptable, uuid(df3491fd-2243-427f-bd93-b0dd3c3e7834)]
 interface nsIDOMCSS2Properties : nsISupports
 {
            attribute DOMString        background;
                                         // raises(DOMException) on setting
 
            attribute DOMString        backgroundAttachment;
                                         // raises(DOMException) on setting
 
@@ -798,35 +798,35 @@ interface nsIDOMCSS2Properties : nsISupp
                                         // raises(DOMException) on setting
 
            attribute DOMString        borderImageRepeat;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozBorderImage;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        MozAlignItems;
+           attribute DOMString        alignItems;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        MozAlignSelf;
+           attribute DOMString        alignSelf;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        MozFlex;
+           attribute DOMString        flex;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        MozFlexBasis;
+           attribute DOMString        flexBasis;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        MozFlexDirection;
+           attribute DOMString        flexDirection;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        MozFlexGrow;
+           attribute DOMString        flexGrow;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        MozFlexShrink;
+           attribute DOMString        flexShrink;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        MozOrder;
+           attribute DOMString        order;
                                         // raises(DOMException) on setting
 
-           attribute DOMString        MozJustifyContent;
+           attribute DOMString        justifyContent;
                                         // raises(DOMException) on setting
 };
--- a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl
@@ -15,16 +15,17 @@
  * <canvas> element.
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#graphics
  *
  * @status UNDER_DEVELOPMENT
  */
 
+interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIVariant;
 interface nsIInputStreamCallback;
 
 [scriptable, builtinclass, uuid(8d5fb8a0-7782-11e1-b0c4-0800200c9a67)]
 interface nsIDOMMozCanvasPrintState : nsISupports
 {
   // A canvas rendering context.
@@ -35,16 +36,21 @@ interface nsIDOMMozCanvasPrintState : ns
 };
 
 [scriptable, function, uuid(8d5fb8a0-7782-11e1-b0c4-0800200c9a66)]
 interface nsIPrintCallback : nsISupports
 {
   void render(in nsIDOMMozCanvasPrintState ctx);
 };
 
+[scriptable, function, uuid(6e9ffb59-2067-4aef-a51c-65e65a3e0d81)]
+interface nsIFileCallback : nsISupports {
+  void receive(in nsIDOMBlob file);
+};
+
 [scriptable, uuid(a7062fca-41c6-4520-b777-3bb30fd77273)]
 interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
 {
   attribute unsigned long width;
   attribute unsigned long height;
   attribute boolean mozOpaque;
 
   nsISupports getContext(in DOMString contextId,
@@ -59,16 +65,20 @@ interface nsIDOMHTMLCanvasElement : nsID
                                       [optional] in nsIVariant params);
 
   // Valid calls are
   // mozGetAsFile(name);              -- defaults to image/png
   // mozGetAsFile(name, type);        -- uses given type
   [optional_argc] nsIDOMFile mozGetAsFile(in DOMString name,
                                           [optional] in DOMString type);
 
+  [optional_argc] void toBlob(in nsIFileCallback callback,
+                              [optional] in DOMString type,
+                              [optional] in nsIVariant params);
+
   // A Mozilla-only extension to get a canvas context backed by double-buffered
   // shared memory. Only privileged callers can call this.
   nsISupports MozGetIPCContext(in DOMString contextId);
 
   // A Mozilla-only extension that returns the canvas' image data as a data
   // stream in the desired image format.
   void mozFetchAsStream(in nsIInputStreamCallback callback,
                                         [optional] in DOMString type);
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -15,16 +15,17 @@
 #include "ContentChild.h"
 #include "CrashReporterChild.h"
 #include "TabChild.h"
 #if defined(MOZ_SYDNEYAUDIO)
 #include "AudioChild.h"
 #endif
 
 #include "mozilla/Attributes.h"
+#include "mozilla/MemoryInfoDumper.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
 #include "mozilla/dom/PCrashReporterChild.h"
 #include "mozilla/dom/StorageChild.h"
 #include "mozilla/Hal.h"
 #include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/ipc/XPCShellEnvironment.h"
 #include "mozilla/jsipc/PContextWrapperChild.h"
@@ -442,22 +443,27 @@ ContentChild::DeallocPMemoryReportReques
     return true;
 }
 
 bool
 ContentChild::RecvDumpMemoryReportsToFile(const nsString& aIdentifier,
                                           const bool& aMinimizeMemoryUsage,
                                           const bool& aDumpChildProcesses)
 {
-    nsCOMPtr<nsIMemoryReporterManager> mgr =
-        do_GetService("@mozilla.org/memory-reporter-manager;1");
-    NS_ENSURE_TRUE(mgr, true);
-    mgr->DumpMemoryReportsToFile(aIdentifier,
-                                 aMinimizeMemoryUsage,
-                                 aDumpChildProcesses);
+    MemoryInfoDumper::DumpMemoryReportsToFile(
+        aIdentifier, aMinimizeMemoryUsage, aDumpChildProcesses);
+    return true;
+}
+
+bool
+ContentChild::RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier,
+                                        const bool& aDumpChildProcesses)
+{
+    MemoryInfoDumper::DumpGCAndCCLogsToFile(
+        aIdentifier, aDumpChildProcesses);
     return true;
 }
 
 PCompositorChild*
 ContentChild::AllocPCompositor(mozilla::ipc::Transport* aTransport,
                                base::ProcessId aOtherProcess)
 {
     return CompositorChild::Create(aTransport, aOtherProcess);
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -106,19 +106,22 @@ public:
 
     virtual bool
     DeallocPMemoryReportRequest(PMemoryReportRequestChild* actor);
 
     virtual bool
     RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child);
 
     virtual bool
-    RecvDumpMemoryReportsToFile(const nsString& identifier,
+    RecvDumpMemoryReportsToFile(const nsString& aIdentifier,
                                 const bool& aMinimizeMemoryUsage,
                                 const bool& aDumpChildProcesses);
+    virtual bool
+    RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier,
+                              const bool& aDumpChildProcesses);
 
     virtual PTestShellChild* AllocPTestShell();
     virtual bool DeallocPTestShell(PTestShellChild*);
     virtual bool RecvPTestShellConstructor(PTestShellChild*);
 
     virtual PAudioChild* AllocPAudio(const int32_t&,
                                      const int32_t&,
                                      const int32_t&);
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -197,22 +197,31 @@ both:
 
 child:
     PMemoryReportRequest();
 
     /**
      * Dump the contents of about:memory to a file in our temp directory.
      *
      * For documentation on the args, see
-     * nsIMemoryReporterManager::dumpMemoryReportsToFile.
+     * MemoryInfoDumper::dumpMemoryReportsToFile.
      */
     async DumpMemoryReportsToFile(nsString identifier,
                                   bool minimizeMemoryUsage,
                                   bool dumpChildProcesses);
 
+    /**
+     * Dump this process's GC and CC logs.
+     *
+     * For documentation on the args, see
+     * MemoryInfoDumper::dumpGCAndCCLogsToFile.
+     */
+    async DumpGCAndCCLogsToFile(nsString identifier,
+                                bool dumpChildProcesses);
+
     PTestShell();
 
     RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources,
                    OverrideMapping[] overrides, nsCString locale);
 
     async SetOffline(bool offline);
 
     async NotifyVisited(URIParams uri);
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -23,21 +23,22 @@
 /* Using WebRTC backend on Desktops (Mac, Windows, Linux), otherwise default */
 #include "MediaEngineDefault.h"
 #if defined(MOZ_WEBRTC)
 #include "MediaEngineWebRTC.h"
 #endif
 
 namespace mozilla {
 
-// We only support 1 audio and 1 video track for now.
-enum {
-  kVideoTrack = 1,
-  kAudioTrack = 2
-};
+#ifdef PR_LOGGING
+PRLogModuleInfo* gMediaManagerLog = PR_NewLogModule("MediaManager");
+#define LOG(msg) PR_LOG(gMediaManagerLog, PR_LOG_DEBUG, msg)
+#else
+#define LOG(msg)
+#endif
 
 
 /**
  * Send an error back to content. The error is the form a string.
  * Do this only on the main thread. The success callback is also passed here
  * so it can be released correctly.
  */
 class ErrorCallbackRunnable : public nsRunnable
@@ -199,87 +200,102 @@ MediaDevice::GetSource()
 }
 
 /**
  * Creates a MediaStream, attaches a listener and fires off a success callback
  * to the DOM with the stream. We also pass in the error callback so it can
  * be released correctly.
  *
  * All of this must be done on the main thread!
+ *
+ * Note that the various GetUserMedia Runnable classes currently allow for
+ * two streams.  If we ever need to support getting more than two streams
+ * at once, we could convert everything to nsTArray<nsRefPtr<blah> >'s,
+ * though that would complicate the constructors some.  Currently the 
+ * GetUserMedia spec does not allow for more than 2 streams to be obtained in
+ * one call, to simplify handling of constraints.
  */
 class GetUserMediaStreamRunnable : public nsRunnable
 {
 public:
   GetUserMediaStreamRunnable(
     already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
-    MediaEngineSource* aSource, StreamListeners* aListeners,
-    uint64_t aWindowID, TrackID aTrackID)
+    StreamListeners* aListeners,
+    uint64_t aWindowID,
+    MediaEngineSource* aAudioSource,
+    MediaEngineSource* aVideoSource)
     : mSuccess(aSuccess)
     , mError(aError)
-    , mSource(aSource)
+    , mAudioSource(aAudioSource)
+    , mVideoSource(aVideoSource)
     , mListeners(aListeners)
-    , mWindowID(aWindowID)
-    , mTrackID(aTrackID) {}
+    , mWindowID(aWindowID) {}
 
   ~GetUserMediaStreamRunnable() {}
 
   NS_IMETHOD
   Run()
   {
     NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
     // Create a media stream.
     nsCOMPtr<nsDOMMediaStream> stream;
-    if (mTrackID == kVideoTrack) {
-      stream = nsDOMMediaStream::CreateInputStream(
-        nsDOMMediaStream::HINT_CONTENTS_VIDEO
-      );
-    } else {
-      stream = nsDOMMediaStream::CreateInputStream(
-        nsDOMMediaStream::HINT_CONTENTS_AUDIO
-      );
-    }
+    uint32_t hints = (mAudioSource ? nsDOMMediaStream::HINT_CONTENTS_AUDIO : 0);
+    hints |= (mVideoSource ? nsDOMMediaStream::HINT_CONTENTS_VIDEO : 0);
+
+    stream = nsDOMMediaStream::CreateInputStream(hints);
 
     nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
       (nsGlobalWindow::GetInnerWindowWithId(mWindowID));
+    WindowTable* activeWindows = MediaManager::Get()->GetActiveWindows();
+
+    if (!stream) {
+      if (activeWindows->Get(mWindowID)) {
+        nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
+        LOG(("Returning error for getUserMedia() - no stream"));
+        error->OnError(NS_LITERAL_STRING("NO_STREAM"));
+      }
+      return NS_OK;
+    }
 
     if (window && window->GetExtantDoc()) {
       stream->CombineWithPrincipal(window->GetExtantDoc()->NodePrincipal());
     }
 
     // Add our listener. We'll call Start() on the source when get a callback
     // that the MediaStream has started consuming. The listener is freed
     // when the page is invalidated (on navigation or close).
     GetUserMediaCallbackMediaStreamListener* listener =
-      new GetUserMediaCallbackMediaStreamListener(mSource, stream, mTrackID);
+      new GetUserMediaCallbackMediaStreamListener(stream, mAudioSource,
+                                                  mVideoSource);
     stream->GetStream()->AddListener(listener);
 
     // No need for locking because we always do this in the main thread.
     mListeners->AppendElement(listener);
 
     // We're in the main thread, so no worries here either.
     nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success(mSuccess);
     nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
 
-    WindowTable* activeWindows = MediaManager::Get()->GetActiveWindows();
     if (activeWindows->Get(mWindowID)) {
+      LOG(("Returning success for getUserMedia()"));
       success->OnSuccess(stream);
     }
 
     return NS_OK;
   }
 
 private:
   already_AddRefed<nsIDOMGetUserMediaSuccessCallback> mSuccess;
   already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
-  nsRefPtr<MediaEngineSource> mSource;
+  nsRefPtr<MediaEngineSource> mAudioSource;
+  nsRefPtr<MediaEngineSource> mVideoSource;
   StreamListeners* mListeners;
   uint64_t mWindowID;
-  TrackID mTrackID;
 };
 
 /**
  * Runs on a seperate thread and is responsible for enumerating devices.
  * Depending on whether a picture or stream was asked for, either
  * ProcessGetUserMedia or ProcessGetUserMediaSnapshot is called, and the results
  * are sent back to the DOM.
  *
@@ -291,27 +307,35 @@ class GetUserMediaRunnable : public nsRu
 public:
   /**
    * The caller can choose to provide a MediaDevice as the last argument,
    * if one is not provided, a default device is automatically chosen.
    */
   GetUserMediaRunnable(bool aAudio, bool aVideo, bool aPicture,
     already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
-    StreamListeners* aListeners, uint64_t aWindowID, MediaDevice* aDevice)
+    StreamListeners* aListeners, uint64_t aWindowID, 
+    MediaDevice* aAudioDevice, MediaDevice* aVideoDevice)
     : mAudio(aAudio)
     , mVideo(aVideo)
     , mPicture(aPicture)
     , mSuccess(aSuccess)
     , mError(aError)
     , mListeners(aListeners)
     , mWindowID(aWindowID)
-    , mDevice(aDevice)
     , mDeviceChosen(true)
-    , mBackendChosen(false) {}
+    , mBackendChosen(false)
+    {
+      if (mAudio) {
+        mAudioDevice = aAudioDevice;
+      } 
+      if (mVideo) {
+        mVideoDevice = aVideoDevice;
+      }
+    }
 
   GetUserMediaRunnable(bool aAudio, bool aVideo, bool aPicture,
     already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
     StreamListeners* aListeners, uint64_t aWindowID)
     : mAudio(aAudio)
     , mVideo(aVideo)
     , mPicture(aPicture)
@@ -370,39 +394,23 @@ public:
     // It is an error if audio or video are requested along with picture.
     if (mPicture && (mAudio || mVideo)) {
       NS_DispatchToMainThread(new ErrorCallbackRunnable(
         mSuccess, mError, NS_LITERAL_STRING("NOT_SUPPORTED_ERR"), mWindowID
       ));
       return NS_OK;
     }
 
-    // XXX: Implement merging two streams (See bug 758391).
-    if (mAudio && mVideo) {
-      NS_DispatchToMainThread(new ErrorCallbackRunnable(
-        mSuccess, mError, NS_LITERAL_STRING("NOT_IMPLEMENTED"), mWindowID
-      ));
+    if (mPicture) {
+      ProcessGetUserMediaSnapshot(mVideoDevice->GetSource(), 0);
       return NS_OK;
     }
 
-    if (mPicture) {
-      ProcessGetUserMediaSnapshot(mDevice->GetSource(), 0);
-      return NS_OK;
-    }
-
-    if (mVideo) {
-      ProcessGetUserMedia(mDevice->GetSource(), kVideoTrack);
-      return NS_OK;
-    }
-
-    if (mAudio) {
-      ProcessGetUserMedia(mDevice->GetSource(), kAudioTrack);
-      return NS_OK;
-    }
-
+    ProcessGetUserMedia(mAudio ? mAudioDevice->GetSource() : nullptr,
+                        mVideo ? mVideoDevice->GetSource() : nullptr);
     return NS_OK;
   }
 
   nsresult
   Denied()
   {
     if (NS_IsMainThread()) {
       nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
@@ -412,19 +420,27 @@ public:
         mSuccess, mError, NS_LITERAL_STRING("PERMISSION_DENIED"), mWindowID
       ));
     }
 
     return NS_OK;
   }
 
   nsresult
-  SetDevice(MediaDevice* aDevice)
+  SetAudioDevice(MediaDevice* aAudioDevice)
   {
-    mDevice = aDevice;
+    mAudioDevice = aAudioDevice;
+    mDeviceChosen = true;
+    return NS_OK;
+  }
+
+  nsresult
+  SetVideoDevice(MediaDevice* aVideoDevice)
+  {
+    mVideoDevice = aVideoDevice;
     mDeviceChosen = true;
     return NS_OK;
   }
 
   nsresult
   SelectDevice()
   {
     uint32_t count;
@@ -434,51 +450,71 @@ public:
 
       count = videoSources.Length();
       if (count <= 0) {
         NS_DispatchToMainThread(new ErrorCallbackRunnable(
           mSuccess, mError, NS_LITERAL_STRING("NO_DEVICES_FOUND"), mWindowID
         ));
         return NS_ERROR_FAILURE;
       }
-      mDevice = new MediaDevice(videoSources[0]);
-    } else {
+      mVideoDevice = new MediaDevice(videoSources[0]);
+      LOG(("Selected video device"));
+    }
+    if (mAudio) {
       nsTArray<nsRefPtr<MediaEngineAudioSource> > audioSources;
       mBackend->EnumerateAudioDevices(&audioSources);
 
       count = audioSources.Length();
       if (count <= 0) {
         NS_DispatchToMainThread(new ErrorCallbackRunnable(
           mSuccess, mError, NS_LITERAL_STRING("NO_DEVICES_FOUND"), mWindowID
         ));
         return NS_ERROR_FAILURE;
       }
-      mDevice = new MediaDevice(audioSources[0]);
+      mAudioDevice = new MediaDevice(audioSources[0]);
+      LOG(("Selected audio device"));
     }
 
     return NS_OK;
   }
 
   /**
    * Allocates a video or audio device and returns a MediaStream via
    * a GetUserMediaStreamRunnable. Runs off the main thread.
    */
   void
-  ProcessGetUserMedia(MediaEngineSource* aSource, TrackID aTrackID)
+  ProcessGetUserMedia(MediaEngineSource* aAudioSource, MediaEngineSource* aVideoSource)
   {
-    nsresult rv = aSource->Allocate();
-    if (NS_FAILED(rv)) {
-      NS_DispatchToMainThread(new ErrorCallbackRunnable(
-        mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
-      ));
-      return;
+    nsresult rv;
+    if (aAudioSource) {
+      rv = aAudioSource->Allocate();
+      if (NS_FAILED(rv)) {
+        LOG(("Failed to allocate audiosource %d",rv));
+        NS_DispatchToMainThread(new ErrorCallbackRunnable(
+                                  mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
+                                                          ));
+        return;
+      }
+    }
+    if (aVideoSource) {
+      rv = aVideoSource->Allocate();
+      if (NS_FAILED(rv)) {
+        LOG(("Failed to allocate videosource %d\n",rv));
+        if (aAudioSource) {
+          aAudioSource->Deallocate();
+        }
+        NS_DispatchToMainThread(new ErrorCallbackRunnable(
+          mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
+                                                          ));
+        return;
+      }
     }
 
     NS_DispatchToMainThread(new GetUserMediaStreamRunnable(
-      mSuccess, mError, aSource, mListeners, mWindowID, aTrackID
+      mSuccess, mError, mListeners, mWindowID, aAudioSource, aVideoSource
     ));
     return;
   }
 
   /**
    * Allocates a video device, takes a snapshot and returns a DOMFile via
    * a SuccessRunnable or an error via the ErrorRunnable. Off the main thread.
    */
@@ -510,17 +546,18 @@ private:
   bool mAudio;
   bool mVideo;
   bool mPicture;
 
   already_AddRefed<nsIDOMGetUserMediaSuccessCallback> mSuccess;
   already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
   StreamListeners* mListeners;
   uint64_t mWindowID;
-  nsRefPtr<MediaDevice> mDevice;
+  nsRefPtr<MediaDevice> mAudioDevice;
+  nsRefPtr<MediaDevice> mVideoDevice;
 
   bool mDeviceChosen;
   bool mBackendChosen;
 
   MediaEngine* mBackend;
   MediaManager* mManager;
 };
 
@@ -611,29 +648,38 @@ MediaManager::GetUserMedia(bool aPrivile
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aParams->GetAudio(&audio);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aParams->GetVideo(&video);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIMediaDevice> device;
-  rv = aParams->GetDevice(getter_AddRefs(device));
+  nsCOMPtr<nsIMediaDevice> audiodevice;
+  rv = aParams->GetAudioDevice(getter_AddRefs(audiodevice));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIMediaDevice> videodevice;
+  rv = aParams->GetVideoDevice(getter_AddRefs(videodevice));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If a device was provided, make sure it support the type of stream requested.
-  if (device) {
+  // Doesn't handle hard-specifying both audio and video
+  if (audiodevice) {
     nsString type;
-    device->GetType(type);
-    if ((picture || video) && !type.EqualsLiteral("video")) {
+    audiodevice->GetType(type);
+    if (audio && !type.EqualsLiteral("audio")) {
       return NS_ERROR_FAILURE;
     }
-    if (audio && !type.EqualsLiteral("audio")) {
-      return NS_ERROR_FAILURE;
+  }
+  if (videodevice) {
+    nsString type;
+    videodevice->GetType(type);
+    if ((picture || video) && !type.EqualsLiteral("video")) {
+        return NS_ERROR_FAILURE;
     }
   }
 
   // We only support "front" or "back". TBD: Send to GetUserMediaRunnable.
   nsString cameraType;
   rv = aParams->GetCamera(cameraType);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -691,34 +737,41 @@ MediaManager::GetUserMedia(bool aPrivile
    */
   nsRefPtr<GetUserMediaRunnable> gUMRunnable;
   if (fake) {
     // Fake stream from default backend.
     gUMRunnable = new GetUserMediaRunnable(
       audio, video, onSuccess.forget(), onError.forget(), listeners,
       windowID, new MediaEngineDefault()
     );
-  } else if (device) {
+  } else if (audiodevice || videodevice) {
     // Stream from provided device.
     gUMRunnable = new GetUserMediaRunnable(
       audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
-      windowID, static_cast<MediaDevice*>(device.get())
+      windowID, 
+      static_cast<MediaDevice*>(audiodevice.get()),
+      static_cast<MediaDevice*>(videodevice.get())
     );
   } else {
     // Stream from default device from WebRTC backend.
     gUMRunnable = new GetUserMediaRunnable(
       audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
       windowID
     );
   }
 
+#ifdef ANDROID
   if (picture) {
     // ShowFilePickerForMimeType() must run on the Main Thread! (on Android)
     NS_DispatchToMainThread(gUMRunnable);
-  } else if (aPrivileged || fake) {
+  }
+  // XXX No support for Audio or Video in Android yet
+#else
+  // XXX No full support for picture in Desktop yet (needs proper UI)
+  if (aPrivileged || fake) {
     if (!mMediaThread) {
       nsresult rv = NS_NewThread(getter_AddRefs(mMediaThread));
       NS_ENSURE_SUCCESS(rv, rv);
     }
     mMediaThread->Dispatch(gUMRunnable, NS_DISPATCH_NORMAL);
   } else {
     // Ask for user permission, and dispatch runnable (or not) when a response
     // is received via an observer notification. Each call is paired with its
@@ -751,16 +804,17 @@ MediaManager::GetUserMedia(bool aPrivile
 
     data.Append(NS_LITERAL_STRING(", \"callID\":\""));
     data.Append(callID);
     data.Append(NS_LITERAL_STRING("\"}"));
 
     nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     obs->NotifyObservers(aParams, "getUserMedia:request", data.get());
   }
+#endif
 
   return NS_OK;
 }
 
 nsresult
 MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
   nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
   nsIDOMGetUserMediaErrorCallback* aOnError)
@@ -857,21 +911,30 @@ MediaManager::Observe(nsISupports* aSubj
     // Reuse the same thread to save memory.
     if (!mMediaThread) {
       nsresult rv = NS_NewThread(getter_AddRefs(mMediaThread));
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     if (aSubject) {
       // A particular device was chosen by the user.
+      // NOTE: does not allow setting a device to null; assumes nullptr
       nsCOMPtr<nsIMediaDevice> device = do_QueryInterface(aSubject);
       if (device) {
         GetUserMediaRunnable* gUMRunnable =
           static_cast<GetUserMediaRunnable*>(runnable.get());
-        gUMRunnable->SetDevice(static_cast<MediaDevice*>(device.get()));
+        nsString type;
+        device->GetType(type);
+        if (type.EqualsLiteral("video")) {
+          gUMRunnable->SetVideoDevice(static_cast<MediaDevice*>(device.get()));
+        } else if (type.EqualsLiteral("audio")) {
+          gUMRunnable->SetAudioDevice(static_cast<MediaDevice*>(device.get()));
+        } else {
+          NS_WARNING("Unknown device type in getUserMedia");
+        }
       }
     }
 
     mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
     mActiveCallbacks.Remove(key);
     return NS_OK;
   }
 
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -9,19 +9,33 @@
 #include "nsGlobalWindow.h"
 #include "nsClassHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsObserverService.h"
 
 #include "nsPIDOMWindow.h"
 #include "nsIDOMNavigatorUserMedia.h"
 #include "mozilla/Attributes.h"
+#include "prlog.h"
 
 namespace mozilla {
 
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* gMediaManagerLog;
+#define MM_LOG(msg) PR_LOG(gMediaManagerLog, PR_LOG_DEBUG, msg)
+#else
+#define MM_LOG(msg)
+#endif
+
+// We only support 1 audio and 1 video track for now.
+enum {
+  kVideoTrack = 1,
+  kAudioTrack = 2
+};
+
 class GetUserMediaNotificationEvent: public nsRunnable
 {
   public:
     enum GetUserMediaStatus {
       STARTING,
       STOPPING
     };
     GetUserMediaNotificationEvent(GetUserMediaStatus aStatus)
@@ -54,69 +68,82 @@ class GetUserMediaNotificationEvent: pub
 /**
  * This class is an implementation of MediaStreamListener. This is used
  * to Start() and Stop() the underlying MediaEngineSource when MediaStreams
  * are assigned and deassigned in content.
  */
 class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener
 {
 public:
-  GetUserMediaCallbackMediaStreamListener(MediaEngineSource* aSource,
-    nsDOMMediaStream* aStream, TrackID aListenId)
-    : mSource(aSource)
+  GetUserMediaCallbackMediaStreamListener(nsDOMMediaStream* aStream,
+    MediaEngineSource* aAudioSource,
+    MediaEngineSource* aVideoSource)
+    : mAudioSource(aAudioSource)
+    , mVideoSource(aVideoSource)
     , mStream(aStream)
-    , mID(aListenId)
     , mValid(true) {}
 
   void
   Invalidate()
   {
     if (!mValid) {
       return;
     }
 
     mValid = false;
-    mSource->Stop();
-    mSource->Deallocate();
-
+    if (mAudioSource) {
+      mAudioSource->Stop();
+      mAudioSource->Deallocate();
+    }
+    if (mVideoSource) {
+      mVideoSource->Stop();
+      mVideoSource->Deallocate();
+    }
     nsCOMPtr<GetUserMediaNotificationEvent> event =
       new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STOPPING);
 
     NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
   }
 
   void
   NotifyConsumptionChanged(MediaStreamGraph* aGraph, Consumption aConsuming)
   {
     if (aConsuming == CONSUMED) {
+      nsresult rv;
+
       SourceMediaStream* stream = mStream->GetStream()->AsSourceStream();
-      mSource->Start(stream, mID);
+      if (mAudioSource) {
+        rv = mAudioSource->Start(stream, kAudioTrack);
+        if (NS_FAILED(rv)) {
+          MM_LOG(("Starting audio failed, rv=%d",rv));
+        }
+      }
+      if (mVideoSource) {
+        rv = mVideoSource->Start(stream, kVideoTrack);
+        if (NS_FAILED(rv)) {
+          MM_LOG(("Starting video failed, rv=%d",rv));
+        }
+      }
+      MM_LOG(("started all sources"));
       nsCOMPtr<GetUserMediaNotificationEvent> event =
         new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING);
 
       NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
       return;
     }
 
     // NOT_CONSUMED
     Invalidate();
     return;
   }
 
-  void NotifyBlockingChanged(MediaStreamGraph* aGraph, Blocking aBlocked) {}
-  void NotifyOutput(MediaStreamGraph* aGraph) {}
-  void NotifyFinished(MediaStreamGraph* aGraph) {}
-  void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
-    TrackRate aTrackRate, TrackTicks aTrackOffset,
-    uint32_t aTrackEvents, const MediaSegment& aQueuedMedia) {}
-
 private:
-  nsRefPtr<MediaEngineSource> mSource;
+  nsRefPtr<MediaEngineSource> mAudioSource;
+  nsRefPtr<MediaEngineSource> mVideoSource;
   nsCOMPtr<nsDOMMediaStream> mStream;
-  TrackID mID;
   bool mValid;
 };
 
 typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
 typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable;
 
 class MediaDevice : public nsIMediaDevice
 {
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -141,16 +141,17 @@ function PeerConnection() {
 
   // Public attributes.
   this.onaddstream = null;
   this.onremovestream = null;
   this.onicecandidate = null;
   this.onstatechange = null;
   this.ongatheringchange = null;
   this.onicechange = null;
+  this.remoteDescription = null;
 
   // Data channel.
   this.ondatachannel = null;
   this.onconnection = null;
   this.onclosedconnection = null;
 }
 PeerConnection.prototype = {
   classID: PC_CID,
@@ -243,60 +244,66 @@ PeerConnection.prototype = {
 
     this._queueOrRun({
       func: this._pc.createOffer,
       args: [constraints],
       wait: true
     });
   },
 
-  createAnswer: function(offer, onSuccess, onError, constraints, provisional) {
+  createAnswer: function(onSuccess, onError, constraints, provisional) {
     if (this._onCreateAnswerSuccess) {
       if (onError) {
-        onError.onCallback("createAnswer already called");
+        try {
+          onError.onCallback("createAnswer already called");
+        } catch(e) {}
       }
       return;
     }
 
+    if (!this.remoteDescription) {
+      if (onError) {
+        try {
+          onError.onCallback("setRemoteDescription not called");
+        } catch(e) {}
+      }
+    }
+
+    if (this.remoteDescription.type != "offer") {
+      if (onError) {
+        try {
+          onError.onCallback("No outstanding offer");
+        } catch(e) {}
+      }
+    }
+
     this._onCreateAnswerSuccess = onSuccess;
     this._onCreateAnswerFailure = onError;
 
-    if (offer.type != "offer") {
-      if (onError) {
-        onError.onCallback("Invalid type " + offer.type + " passed");
-      }
-      return;
-    }
-
-    if (!offer.sdp) {
-      if (onError) {
-        onError.onCallback("SDP not provided to createAnswer");
-      }
-      return;
-    }
-
     if (!constraints) {
       constraints = "";
     }
     if (!provisional) {
       provisional = false;
     }
 
     // TODO: Implement provisional answer & constraints.
     this._queueOrRun({
       func: this._pc.createAnswer,
-      args: ["", offer.sdp],
+      args: ["", this.remoteDescription.sdp],
       wait: true
     });
   },
 
   setLocalDescription: function(desc, onSuccess, onError) {
     if (this._onSetLocalDescriptionSuccess) {
       if (onError) {
-        onError.onCallback("setLocalDescription already called");
+        try {
+          onError.onCallback("setLocalDescription already called");
+        } catch(e) {}
       }
       return;
     }
 
     this._onSetLocalDescriptionSuccess = onSuccess;
     this._onSetLocalDescriptionFailure = onError;
 
     let type;
@@ -304,35 +311,39 @@ PeerConnection.prototype = {
       case "offer":
         type = Ci.IPeerConnection.kActionOffer;
         break;
       case "answer":
         type = Ci.IPeerConnection.kActionAnswer;
         break;
       default:
         if (onError) {
-          onError.onCallback(
-            "Invalid type " + desc.type + " provided to setLocalDescription"
-          );
+          try {
+            onError.onCallback(
+              "Invalid type " + desc.type + " provided to setLocalDescription"
+            );
+          } catch(e) {}
           return;
         }
         break;
     }
 
     this._queueOrRun({
       func: this._pc.setLocalDescription,
       args: [type, desc.sdp],
       wait: true
     });
   },
 
   setRemoteDescription: function(desc, onSuccess, onError) {
     if (this._onSetRemoteDescriptionSuccess) {
       if (onError) {
-        onError.onCallback("setRemoteDescription already called");
+        try {
+          onError.onCallback("setRemoteDescription already called");
+        } catch(e) {}
       }
       return;
     }
 
     this._onSetRemoteDescriptionSuccess = onSuccess;
     this._onSetRemoteDescriptionFailure = onError;
 
     let type;
@@ -340,24 +351,31 @@ PeerConnection.prototype = {
       case "offer":
         type = Ci.IPeerConnection.kActionOffer;
         break;
       case "answer":
         type = Ci.IPeerConnection.kActionAnswer;
         break;
       default:
         if (onError) {
-          onError.onCallback(
-            "Invalid type " + desc.type + " provided to setLocalDescription"
-          );
+          try {
+            onError.onCallback(
+              "Invalid type " + desc.type + " provided to setRemoteDescription"
+            );
+          } catch(e) {}
           return;
         }
         break;
     }
 
+    this.remoteDescription = {
+      type: desc.type, sdp: desc.sdp,
+      __exposedProps__: { type: "rw", sdp: "rw" }
+    };
+
     this._queueOrRun({
       func: this._pc.setRemoteDescription,
       args: [type, desc.sdp],
       wait: true
     });
   },
 
   updateIce: function(config, constraints, restart) {
@@ -399,16 +417,23 @@ PeerConnection.prototype = {
   close: function() {
     this._queueOrRun({
       func: this._pc.close,
       args: [],
       wait: false
     });
   },
 
+  get localStreams() {
+    return this._pc.localStreams;
+  },
+  get remoteStreams() {
+    return this._pc.remoteStreams;
+  },
+
   createDataChannel: function(label, dict) {
     if (dict &&
         dict.maxRetransmitTime != undefined &&
         dict.maxRetransmitNum != undefined) {
       throw new Error("Both maxRetransmitTime and maxRetransmitNum cannot be provided");
     }
 
     // Must determine the type where we still know if entries are undefined.
--- a/dom/media/bridge/IPeerConnection.idl
+++ b/dom/media/bridge/IPeerConnection.idl
@@ -78,16 +78,19 @@ interface IPeerConnection : nsISupports
   void setLocalDescription(in long action, in string sdp);
   void setRemoteDescription(in long action, in string sdp);
 
   /* Adds the stream created by GetUserMedia */
   void addStream(in nsIDOMMediaStream stream);
   void removeStream(in nsIDOMMediaStream stream);
   void closeStreams();
 
+  [implicit_jscontext] readonly attribute jsval localStreams; // MediaStream[]
+  [implicit_jscontext] readonly attribute jsval remoteStreams; // MediaStream[]
+
   /* As the ICE candidates roll in this one should be called each time
    * in order to keep the candidate list up-to-date for the next SDP-related
    * call PeerConnectionImpl does not parse ICE candidates, just sticks them
    * into the SDP.
    */
   void addIceCandidate(in string candidate, in string mid, in unsigned short level);
 
   /* Puts the SIPCC engine back to 'kIdle', shuts down threads, deletes state */
--- a/dom/media/nsIDOMNavigatorUserMedia.idl
+++ b/dom/media/nsIDOMNavigatorUserMedia.idl
@@ -30,25 +30,26 @@ interface nsIDOMGetUserMediaSuccessCallb
 };
 
 [scriptable, function, uuid(2614bbcf-85cc-43e5-8740-964f52bdc7ca)]
 interface nsIDOMGetUserMediaErrorCallback : nsISupports
 {
   void onError(in DOMString error);
 };
 
-[scriptable, uuid(36d9c3b7-7594-4035-8a7e-92c2cecdb2c5)]
+[scriptable, uuid(f34a3616-395a-43cd-b275-bf81750ac8b9)]
 interface nsIMediaStreamOptions : nsISupports
 {
   readonly attribute boolean fake;
   readonly attribute boolean audio;
   readonly attribute boolean video;
   readonly attribute boolean picture;
   readonly attribute DOMString camera;
-  readonly attribute nsIMediaDevice device;
+  readonly attribute nsIMediaDevice audioDevice;
+  readonly attribute nsIMediaDevice videoDevice;
 };
 
 [scriptable, uuid(381e0071-0be5-4f6b-ae21-8e3407a37faa)]
 interface nsIDOMNavigatorUserMedia : nsISupports
 {
   void mozGetUserMedia(in nsIMediaStreamOptions params,
     in nsIDOMGetUserMediaSuccessCallback onsuccess,
     in nsIDOMGetUserMediaErrorCallback onerror);
--- a/dom/media/nsIDOMRTCPeerConnection.idl
+++ b/dom/media/nsIDOMRTCPeerConnection.idl
@@ -30,25 +30,24 @@ interface nsIDOMRTCSessionDescription : 
 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(807b9b54-25a1-421e-9133-27ae6efcfcfd)]
+[scriptable, uuid(f888648c-5e6b-4af9-91ad-a911e53d7a39)]
 interface nsIDOMRTCPeerConnection : nsISupports
 {
   void createOffer(in RTCPeerConnectionCallback successCallback,
     [optional] in RTCPeerConnectionCallback failureCallback,
     [optional] in jsval constraints);
 
-  void createAnswer(in nsIDOMRTCSessionDescription offer,
-    in RTCPeerConnectionCallback successCallback,
+  void createAnswer(in RTCPeerConnectionCallback successCallback,
     [optional] in RTCPeerConnectionCallback failureCallback,
     [optional] in jsval constraints,
     [optional] in bool createProvisionalAnswer);
 
   void setLocalDescription(in nsIDOMRTCSessionDescription desc,
     [optional] in RTCPeerConnectionCallback successCallback,
     [optional] in RTCPeerConnectionCallback failureCallback);
 
--- a/dom/plugins/base/nsIPluginInstanceOwner.idl
+++ b/dom/plugins/base/nsIPluginInstanceOwner.idl
@@ -14,17 +14,17 @@ interface nsIDocument;
 #include "nsNPAPIPluginInstance.h"
 class nsPluginEvent;
 %}
 
 [ptr] native nsNPAPIPluginInstancePtr(nsNPAPIPluginInstance);
 
 // Do not make this interface scriptable, because the virtual functions in C++
 // blocks will make script call the wrong functions.
-[uuid(CE1EE148-B201-4DC7-8A65-311143EA01BF)]
+[uuid(59BE4CA5-3CB0-40E6-A111-9A88C8477610)]
 interface nsIPluginInstanceOwner : nsISupports
 {
   /**
    * Let the owner know what its instance is
    */
   void setInstance(in nsNPAPIPluginInstancePtr aInstance);
 
   /**
@@ -106,20 +106,16 @@ interface nsIPluginInstanceOwner : nsISu
   virtual NPError InitAsyncSurface(NPSize *size, NPImageFormat format,
                                    void *initData, NPAsyncSurface *surface) = 0;
   virtual NPError FinalizeAsyncSurface(NPAsyncSurface *surface) = 0;
   virtual void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) = 0;
 %}
 
   void setEventModel(in int32_t eventModel);
 
-%{C++
-  virtual void SendIdleEvent() = 0;
-%}
-
   /**
    * Call NPP_SetWindow on the plugin.
    */
   void callSetWindow();
 
   /**
    * Get the contents scale factor for the screen the plugin is
    * drawn on.
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -2122,17 +2122,17 @@ NPError NP_CALLBACK
      *(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
 
      return NPERR_NO_ERROR;
    }
 
 
 #ifndef NP_NO_CARBON
   case NPNVsupportsCarbonBool: {
-    *(NPBool*)result = true;
+    *(NPBool*)result = false;
 
     return NPERR_NO_ERROR;
   }
 #endif
   case NPNVsupportsCocoaBool: {
     *(NPBool*)result = true;
 
     return NPERR_NO_ERROR;
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -363,21 +363,16 @@ nsPluginHost::nsPluginHost()
 
   PR_LOG(nsPluginLogging::gNPNLog, PLUGIN_LOG_ALWAYS,("NPN Logging Active!\n"));
   PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_ALWAYS,("General Plugin Logging Active! (nsPluginHost::ctor)\n"));
   PR_LOG(nsPluginLogging::gNPPLog, PLUGIN_LOG_ALWAYS,("NPP Logging Active!\n"));
 
   PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("nsPluginHost::ctor\n"));
   PR_LogFlush();
 #endif
-
-#ifdef MAC_CARBON_PLUGINS
-  mVisiblePluginTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  mHiddenPluginTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-#endif
 }
 
 nsPluginHost::~nsPluginHost()
 {
   PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("nsPluginHost::dtor\n"));
 
   UnloadPlugins();
   sInst = nullptr;
@@ -3805,84 +3800,18 @@ nsPluginHost::GetPluginTagForInstance(ns
     return NS_ERROR_FAILURE;
 
   *aPluginTag = TagForPlugin(plugin);
 
   NS_ADDREF(*aPluginTag);
   return NS_OK;
 }
 
-#ifdef MAC_CARBON_PLUGINS
-// Flash requires a minimum of 8 events per second to avoid audio skipping.
-// Since WebKit uses a hidden plugin event rate of 4 events per second Flash
-// uses a Carbon timer for WebKit which fires at 8 events per second.
-#define HIDDEN_PLUGIN_DELAY 125
-#define VISIBLE_PLUGIN_DELAY 20
-#endif
-
-void nsPluginHost::AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, bool isVisible)
-{
-#ifdef MAC_CARBON_PLUGINS
-  nsTObserverArray<nsIPluginInstanceOwner*> *targetArray;
-  if (isVisible) {
-    targetArray = &mVisibleTimerTargets;
-  } else {
-    targetArray = &mHiddenTimerTargets;
-  }
-
-  if (targetArray->Contains(objectFrame)) {
-    return;
-  }
-
-  targetArray->AppendElement(objectFrame);
-  if (targetArray->Length() == 1) {
-    if (isVisible) {
-      mVisiblePluginTimer->InitWithCallback(this, VISIBLE_PLUGIN_DELAY, nsITimer::TYPE_REPEATING_SLACK);
-    } else {
-      mHiddenPluginTimer->InitWithCallback(this, HIDDEN_PLUGIN_DELAY, nsITimer::TYPE_REPEATING_SLACK);
-    }
-  }
-#endif
-}
-
-void nsPluginHost::RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame)
-{
-#ifdef MAC_CARBON_PLUGINS
-  bool visibleRemoved = mVisibleTimerTargets.RemoveElement(objectFrame);
-  if (visibleRemoved && mVisibleTimerTargets.IsEmpty()) {
-    mVisiblePluginTimer->Cancel();
-  }
-
-  bool hiddenRemoved = mHiddenTimerTargets.RemoveElement(objectFrame);
-  if (hiddenRemoved && mHiddenTimerTargets.IsEmpty()) {
-    mHiddenPluginTimer->Cancel();
-  }
-
-  NS_ASSERTION(!(hiddenRemoved && visibleRemoved), "Plugin instance received visible and hidden idle event notifications");
-#endif
-}
-
 NS_IMETHODIMP nsPluginHost::Notify(nsITimer* timer)
 {
-#ifdef MAC_CARBON_PLUGINS
-  if (timer == mVisiblePluginTimer) {
-    nsTObserverArray<nsIPluginInstanceOwner*>::ForwardIterator iter(mVisibleTimerTargets);
-    while (iter.HasMore()) {
-      iter.GetNext()->SendIdleEvent();
-    }
-    return NS_OK;
-  } else if (timer == mHiddenPluginTimer) {
-    nsTObserverArray<nsIPluginInstanceOwner*>::ForwardIterator iter(mHiddenTimerTargets);
-    while (iter.HasMore()) {
-      iter.GetNext()->SendIdleEvent();
-    }
-    return NS_OK;
-  }
-#endif
-
   nsRefPtr<nsPluginTag> pluginTag = mPlugins;
   while (pluginTag) {
     if (pluginTag->mUnloadTimer == timer) {
       if (!IsRunningPlugin(pluginTag)) {
         pluginTag->TryUnloadPlugin(false);
       }
       return NS_OK;
     }
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
@@ -33,20 +33,16 @@
 class nsNPAPIPlugin;
 class nsIComponentManager;
 class nsIFile;
 class nsIChannel;
 class nsPluginNativeWindow;
 class nsObjectLoadingContent;
 class nsPluginInstanceOwner;
 
-#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
-#define MAC_CARBON_PLUGINS
-#endif
-
 class nsInvalidPluginTag : public nsISupports
 {
 public:
   nsInvalidPluginTag(const char* aFullPath, int64_t aLastModifiedTime = 0);
   virtual ~nsInvalidPluginTag();
   
   NS_DECL_ISUPPORTS
   
@@ -315,23 +311,16 @@ private:
 
   nsWeakPtr mCurrentDocument; // weak reference, we use it to id document only
 
   static nsIFile *sPluginTempDir;
 
   // We need to hold a global ptr to ourselves because we register for
   // two different CIDs for some reason...
   static nsPluginHost* sInst;
-
-#ifdef MAC_CARBON_PLUGINS
-  nsCOMPtr<nsITimer> mVisiblePluginTimer;
-  nsTObserverArray<nsIPluginInstanceOwner*> mVisibleTimerTargets;
-  nsCOMPtr<nsITimer> mHiddenPluginTimer;
-  nsTObserverArray<nsIPluginInstanceOwner*> mHiddenTimerTargets;
-#endif
 };
 
 class NS_STACK_CLASS PluginDestructionGuard : protected PRCList
 {
 public:
   PluginDestructionGuard(nsNPAPIPluginInstance *aInstance)
     : mInstance(aInstance)
   {
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -316,27 +316,24 @@ nsPluginInstanceOwner::nsPluginInstanceO
   mPluginDocumentActiveState = true;
   mNumCachedAttrs = 0;
   mNumCachedParams = 0;
   mCachedAttrParamNames = nullptr;
   mCachedAttrParamValues = nullptr;
 
 #ifdef XP_MACOSX
 #ifndef NP_NO_CARBON
+  // We don't support Carbon, but it is still the default model for i386 NPAPI.
   mEventModel = NPEventModelCarbon;
 #else
   mEventModel = NPEventModelCocoa;
 #endif
   mUseAsyncRendering = false;
 #endif
 
-#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
-  mRegisteredScrollPositionListener = false;
-#endif
-
   mWaitingForPaint = false;
 
 #ifdef MOZ_WIDGET_ANDROID
   mFullScreen = false;
   mJavaView = nullptr;
 #endif
 }
 
@@ -346,20 +343,16 @@ nsPluginInstanceOwner::~nsPluginInstance
 
   if (mWaitingForPaint) {
     // We don't care when the event is dispatched as long as it's "soon",
     // since whoever needs it will be waiting for it.
     nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, true);
     NS_DispatchToMainThread(event);
   }
 
-#ifdef MAC_CARBON_PLUGINS
-  CancelTimer();
-#endif
-
   mObjectFrame = nullptr;
 
   for (cnt = 0; cnt < (mNumCachedAttrs + 1 + mNumCachedParams); cnt++) {
     if (mCachedAttrParamNames && mCachedAttrParamNames[cnt]) {
       NS_Free(mCachedAttrParamNames[cnt]);
       mCachedAttrParamNames[cnt] = nullptr;
     }
 
@@ -762,27 +755,17 @@ NS_IMETHODIMP nsPluginInstanceOwner::Get
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
 NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(int32_t eventModel)
 {
 #ifdef XP_MACOSX
-  NPEventModel newEventModel = static_cast<NPEventModel>(eventModel);
-#ifndef NP_NO_CARBON
-  bool eventModelChange = (mEventModel != newEventModel);
-  if (eventModelChange)
-    RemoveScrollPositionListener();
-#endif
-  mEventModel = static_cast<NPEventModel>(newEventModel);
-#ifndef NP_NO_CARBON
-  if (eventModelChange)
-    AddScrollPositionListener();
-#endif
+  mEventModel = static_cast<NPEventModel>(eventModel);
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
 NPError nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu* menu, void* event)
 {
@@ -1348,30 +1331,16 @@ nsresult nsPluginInstanceOwner::EnsureCa
     nextAttrParamIndex++;
   }
 
   return NS_OK;
 }
 
 #ifdef XP_MACOSX
 
-#ifndef NP_NO_CARBON
-static void InitializeEventRecord(EventRecord* event, ::Point* aMousePosition)
-{
-  memset(event, 0, sizeof(EventRecord));
-  if (aMousePosition) {
-    event->where = *aMousePosition;
-  } else {
-    ::GetGlobalMouse(&event->where);
-  }
-  event->when = ::TickCount();
-  event->modifiers = ::GetCurrentKeyModifiers();
-}
-#endif
-
 static void InitializeNPCocoaEvent(NPCocoaEvent* event)
 {
   memset(event, 0, sizeof(NPCocoaEvent));
 }
 
 NPDrawingModel nsPluginInstanceOwner::GetDrawingModel()
 {
 #ifndef NP_NO_QUICKDRAW
@@ -1590,29 +1559,16 @@ void* nsPluginInstanceOwner::SetPluginPo
 {
   if (!mPluginWindow)
     return nullptr;
   void* pluginPort = GetPluginPortFromWidget();
   if (!pluginPort)
     return nullptr;
   mPluginWindow->window = pluginPort;
 
-#ifndef NP_NO_CARBON
-  if (GetEventModel() == NPEventModelCarbon &&
-      GetDrawingModel() == NPDrawingModelCoreGraphics) {
-    NP_CGContext* windowCGPort = static_cast<NP_CGContext*>(mPluginWindow->window);
-    if ((windowCGPort->context != mCGPluginPortCopy.context) ||
-        (windowCGPort->window != mCGPluginPortCopy.window)) {
-      mCGPluginPortCopy.context = windowCGPort->context;
-      mCGPluginPortCopy.window = windowCGPort->window;
-      mPluginPortChanged = true;
-    }
-  }
-#endif
-
   return mPluginWindow->window;
 }
 
 void nsPluginInstanceOwner::BeginCGPaint()
 {
   ++mInCGPaintLevel;
 }
 
@@ -1645,64 +1601,16 @@ nsPluginInstanceOwner::GetEventloopNesti
   // we make sure we always tear the plugin down eventually.
   if (!currentLevel) {
     currentLevel++;
   }
 
   return currentLevel;
 }
 
-void nsPluginInstanceOwner::ScrollPositionWillChange(nscoord aX, nscoord aY)
-{
-#ifdef MAC_CARBON_PLUGINS
-  if (GetEventModel() != NPEventModelCarbon)
-    return;
-
-  CancelTimer();
-
-  if (mInstance) {
-    nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
-    if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
-      EventRecord scrollEvent;
-      InitializeEventRecord(&scrollEvent, nullptr);
-      scrollEvent.what = NPEventType_ScrollingBeginsEvent;
-
-      void* window = FixUpPluginWindow(ePluginPaintDisable);
-      if (window) {
-        mInstance->HandleEvent(&scrollEvent, nullptr);
-      }
-      pluginWidget->EndDrawPlugin();
-    }
-  }
-#endif
-}
-
-void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX, nscoord aY)
-{
-#ifdef MAC_CARBON_PLUGINS
-  if (GetEventModel() != NPEventModelCarbon)
-    return;
-
-  if (mInstance) {
-    nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
-    if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
-      EventRecord scrollEvent;
-      InitializeEventRecord(&scrollEvent, nullptr);
-      scrollEvent.what = NPEventType_ScrollingEndsEvent;
-
-      void* window = FixUpPluginWindow(ePluginPaintEnable);
-      if (window) {
-        mInstance->HandleEvent(&scrollEvent, nullptr);
-      }
-      pluginWidget->EndDrawPlugin();
-    }
-  }
-#endif
-}
-
 #ifdef MOZ_WIDGET_ANDROID
 
 // Modified version of nsFrame::GetOffsetToCrossDoc that stops when it
 // hits an element with a displayport (or runs out of frames). This is
 // not really the right thing to do, but it's better than what was here before.
 static nsPoint
 GetOffsetRootContent(nsIFrame* aFrame)
 {
@@ -1933,45 +1841,16 @@ nsresult nsPluginInstanceOwner::Text(nsI
 
   return NS_OK;
 }
 #endif
 
 nsresult nsPluginInstanceOwner::ProcessKeyPress(nsIDOMEvent* aKeyEvent)
 {
 #ifdef XP_MACOSX
-#ifndef NP_NO_CARBON
-  if (GetEventModel() == NPEventModelCarbon) {
-    // KeyPress events are really synthesized keyDown events.
-    // Here we check the native message of the event so that
-    // we won't send the plugin two keyDown events.
-    nsEvent *theEvent = aKeyEvent->GetInternalNSEvent();
-    const EventRecord *ev;
-    if (theEvent &&
-        theEvent->message == NS_KEY_PRESS &&
-        (ev = (EventRecord*)(((nsGUIEvent*)theEvent)->pluginEvent)) &&
-        ev->what == keyDown)
-      return aKeyEvent->PreventDefault(); // consume event
-
-    // Nasty hack to avoid recursive event dispatching with Java. Java can
-    // dispatch key events to a TSM handler, which comes back and calls 
-    // [ChildView insertText:] on the cocoa widget, which sends a key
-    // event back down.
-    static bool sInKeyDispatch = false;
-
-    if (sInKeyDispatch)
-      return aKeyEvent->PreventDefault(); // consume event
-
-    sInKeyDispatch = true;
-    nsresult rv =  DispatchKeyToPlugin(aKeyEvent);
-    sInKeyDispatch = false;
-    return rv;
-  }
-#endif
-
   return DispatchKeyToPlugin(aKeyEvent);
 #else
   if (SendNativeEvents())
     DispatchKeyToPlugin(aKeyEvent);
 
   if (mInstance) {
     // If this event is going to the plugin, we want to kill it.
     // Not actually sending keypress to the plugin, since we didn't before.
@@ -2148,146 +2027,81 @@ nsEventStatus nsPluginInstanceOwner::Pro
 
   nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
   if (!pluginWidget || NS_FAILED(pluginWidget->StartDrawPlugin()))
     return nsEventStatus_eIgnore;
 
   NPEventModel eventModel = GetEventModel();
 
   // If we have to synthesize an event we'll use one of these.
-#ifndef NP_NO_CARBON
-  EventRecord synthCarbonEvent;
-#endif
   NPCocoaEvent synthCocoaEvent;
   void* event = anEvent.pluginEvent;
   nsPoint pt =
   nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
   mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
   nsPresContext* presContext = mObjectFrame->PresContext();
   // Plugin event coordinates need to be translated from device pixels
   // into "display pixels" in HiDPI modes.
   double scaleFactor = 1.0;
   GetContentsScaleFactor(&scaleFactor);
   size_t intScaleFactor = ceil(scaleFactor);
   nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x) / intScaleFactor,
                   presContext->AppUnitsToDevPixels(pt.y) / intScaleFactor);
-#ifndef NP_NO_CARBON
-  nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
-  ::Point carbonPt = { static_cast<short>(ptPx.y + geckoScreenCoords.y / intScaleFactor),
-                       static_cast<short>(ptPx.x + geckoScreenCoords.x / intScaleFactor) };
-  if (eventModel == NPEventModelCarbon) {
-    if (event && anEvent.eventStructType == NS_MOUSE_EVENT) {
-      static_cast<EventRecord*>(event)->where = carbonPt;
-    }
-  }
-#endif
+
   if (!event) {
-#ifndef NP_NO_CARBON
-    if (eventModel == NPEventModelCarbon) {
-      InitializeEventRecord(&synthCarbonEvent, &carbonPt);
-    } else
-#endif
-    {
-      InitializeNPCocoaEvent(&synthCocoaEvent);
-    }
-    
+    InitializeNPCocoaEvent(&synthCocoaEvent);
     switch (anEvent.message) {
-      case NS_FOCUS_CONTENT:
-      case NS_BLUR_CONTENT:
-#ifndef NP_NO_CARBON
-        if (eventModel == NPEventModelCarbon) {
-          synthCarbonEvent.what = (anEvent.message == NS_FOCUS_CONTENT) ?
-          NPEventType_GetFocusEvent : NPEventType_LoseFocusEvent;
-          event = &synthCarbonEvent;
-        }
-#endif
-        break;
       case NS_MOUSE_MOVE:
       {
         // Ignore mouse-moved events that happen as part of a dragging
         // operation that started over another frame.  See bug 525078.
         nsRefPtr<nsFrameSelection> frameselection = mObjectFrame->GetFrameSelection();
         if (!frameselection->GetMouseDownState() ||
-            (nsIPresShell::GetCapturingContent() == mObjectFrame->GetContent())) {
-#ifndef NP_NO_CARBON
-          if (eventModel == NPEventModelCarbon) {
-            synthCarbonEvent.what = osEvt;
-            event = &synthCarbonEvent;
-          } else
-#endif
-          {
-            synthCocoaEvent.type = NPCocoaEventMouseMoved;
-            synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
-            synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
-            event = &synthCocoaEvent;
-          }
+          (nsIPresShell::GetCapturingContent() == mObjectFrame->GetContent())) {
+          synthCocoaEvent.type = NPCocoaEventMouseMoved;
+          synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
+          synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
+          event = &synthCocoaEvent;
         }
       }
         break;
       case NS_MOUSE_BUTTON_DOWN:
-#ifndef NP_NO_CARBON
-        if (eventModel == NPEventModelCarbon) {
-          synthCarbonEvent.what = mouseDown;
-          event = &synthCarbonEvent;
-        } else
-#endif
-        {
-          synthCocoaEvent.type = NPCocoaEventMouseDown;
-          synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
-          synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
-          event = &synthCocoaEvent;
-        }
+        synthCocoaEvent.type = NPCocoaEventMouseDown;
+        synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
+        synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
+        event = &synthCocoaEvent;
         break;
       case NS_MOUSE_BUTTON_UP:
         // If we're in a dragging operation that started over another frame,
-        // either ignore the mouse-up event (in the Carbon Event Model) or
         // convert it into a mouse-entered event (in the Cocoa Event Model).
         // See bug 525078.
         if ((static_cast<const nsMouseEvent&>(anEvent).button == nsMouseEvent::eLeftButton) &&
             (nsIPresShell::GetCapturingContent() != mObjectFrame->GetContent())) {
-          if (eventModel == NPEventModelCocoa) {
-            synthCocoaEvent.type = NPCocoaEventMouseEntered;
-            synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
-            synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
-            event = &synthCocoaEvent;
-          }
+          synthCocoaEvent.type = NPCocoaEventMouseEntered;
+          synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
+          synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
+          event = &synthCocoaEvent;
         } else {
-#ifndef NP_NO_CARBON
-          if (eventModel == NPEventModelCarbon) {
-            synthCarbonEvent.what = mouseUp;
-            event = &synthCarbonEvent;
-          } else
-#endif
-          {
-            synthCocoaEvent.type = NPCocoaEventMouseUp;
-            synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
-            synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
-            event = &synthCocoaEvent;
-          }
+          synthCocoaEvent.type = NPCocoaEventMouseUp;
+          synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
+          synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
+          event = &synthCocoaEvent;
         }
         break;
       default:
         break;
     }
 
     // If we still don't have an event, bail.
     if (!event) {
       pluginWidget->EndDrawPlugin();
       return nsEventStatus_eIgnore;
     }
   }
 
-#ifndef NP_NO_CARBON
-  // Work around an issue in the Flash plugin, which can cache a pointer
-  // to a doomed TSM document (one that belongs to a NSTSMInputContext)
-  // and try to activate it after it has been deleted. See bug 183313.
-  if (eventModel == NPEventModelCarbon && anEvent.message == NS_FOCUS_CONTENT)
-    ::DeactivateTSMDocument(::TSMGetActiveDocument());
-#endif
-
   int16_t response = kNPEventNotHandled;
   void* window = FixUpPluginWindow(ePluginPaintEnable);
   if (window || (eventModel == NPEventModelCocoa)) {
     mInstance->HandleEvent(event, &response);
   }
 
   if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) {
     pluginWidget->StartComplexTextInputForCurrentEvent();
@@ -2750,20 +2564,16 @@ nsEventStatus nsPluginInstanceOwner::Pro
 }
 
 nsresult
 nsPluginInstanceOwner::Destroy()
 {
   if (mObjectFrame)
     mObjectFrame->SetInstanceOwner(nullptr);
 
-#ifdef MAC_CARBON_PLUGINS
-  // stop the timer explicitly to reduce reference count.
-  CancelTimer();
-#endif
 #ifdef XP_MACOSX
   RemoveFromCARefreshTimer();
   if (mColorProfile)
     ::CGColorSpaceRelease(mColorProfile);  
 #endif
 
   // unregister context menu listener
   if (mCXMenuListener) {
@@ -2831,30 +2641,17 @@ void nsPluginInstanceOwner::Paint(const 
     ::CGContextScaleCTM(cgContext, scaleFactor, scaleFactor);
     // Convert aDirtyRect from device pixels to "display pixels"
     // for HiDPI modes
     dirtyRectCopy.ScaleRoundOut(1.0 / scaleFactor);
   }
 
   nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
   if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
-#ifndef NP_NO_CARBON
-    void* window = FixUpPluginWindow(ePluginPaintEnable);
-    if (GetEventModel() == NPEventModelCarbon && window) {
-      EventRecord updateEvent;
-      InitializeEventRecord(&updateEvent, nullptr);
-      updateEvent.what = updateEvt;
-      updateEvent.message = UInt32(window);
-
-      mInstance->HandleEvent(&updateEvent, nullptr);
-    } else if (GetEventModel() == NPEventModelCocoa)
-#endif
-    {
-      DoCocoaEventDrawRect(dirtyRectCopy, cgContext);
-    }
+    DoCocoaEventDrawRect(dirtyRectCopy, cgContext);
     pluginWidget->EndDrawPlugin();
   }
 }
 
 void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext)
 {
   if (!mInstance || !mObjectFrame)
     return;
@@ -3173,60 +2970,16 @@ nsPluginInstanceOwner::Renderer::DrawWit
     exposeEvent.minor_code = 0;
 
     instance->HandleEvent(&pluginEvent, nullptr);
   }
   return NS_OK;
 }
 #endif
 
-void nsPluginInstanceOwner::SendIdleEvent()
-{
-#ifdef MAC_CARBON_PLUGINS
-  // validate the plugin clipping information by syncing the plugin window info to
-  // reflect the current widget location. This makes sure that everything is updated
-  // correctly in the event of scrolling in the window.
-  if (mInstance) {
-    nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
-    if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
-      void* window = FixUpPluginWindow(ePluginPaintEnable);
-      if (window) {
-        EventRecord idleEvent;
-        InitializeEventRecord(&idleEvent, nullptr);
-        idleEvent.what = nullEvent;
-
-        // give a bogus 'where' field of our null event when hidden, so Flash
-        // won't respond to mouse moves in other tabs, see bug 120875
-        if (!mWidgetVisible)
-          idleEvent.where.h = idleEvent.where.v = 20000;
-
-        mInstance->HandleEvent(&idleEvent, nullptr);
-      }
-
-      pluginWidget->EndDrawPlugin();
-    }
-  }
-#endif
-}
-
-#ifdef MAC_CARBON_PLUGINS
-void nsPluginInstanceOwner::StartTimer(bool isVisible)
-{
-  if (GetEventModel() != NPEventModelCarbon)
-    return;
-
-  mPluginHost->AddIdleTimeTarget(this, isVisible);
-}
-
-void nsPluginInstanceOwner::CancelTimer()
-{
-  mPluginHost->RemoveIdleTimeTarget(this);
-}
-#endif
-
 nsresult nsPluginInstanceOwner::Init(nsIContent* aContent)
 {
   mLastEventloopNestingLevel = GetEventloopNestingLevel();
 
   mContent = aContent;
 
   // Get a frame, don't reflow. If a reflow was necessary it should have been
   // done at a higher level than this (content).
@@ -3408,20 +3161,16 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
     NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
     mFlash10Quirks = StringBeginsWith(description, flash10Head);
 #endif
   } else if (mWidget) {
     // mPluginWindow->type is used in |GetPluginPort| so it must
     // be initialized first
     mPluginWindow->type = NPWindowTypeWindow;
     mPluginWindow->window = GetPluginPortFromWidget();
-#ifdef MAC_CARBON_PLUGINS
-    // start the idle timer.
-    StartTimer(true);
-#endif
     // tell the plugin window about the widget
     mPluginWindow->SetPluginWidget(mWidget);
     
     // tell the widget about the current plugin instance owner.
     nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
     if (pluginWidget) {
       pluginWidget->SetPluginInstanceOwner(this);
     }
@@ -3435,46 +3184,33 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
 // Mac specific code to fix up the port location and clipping region
 #ifdef XP_MACOSX
 
 void* nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState)
 {
   if (!mWidget || !mPluginWindow || !mInstance || !mObjectFrame)
     return nullptr;
 
-  NPEventModel eventModel = GetEventModel();
-
   nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
   if (!pluginWidget)
     return nullptr;
 
   // If we've already set up a CGContext in nsObjectFrame::PaintPlugin(), we
   // don't want calls to SetPluginPortAndDetectChange() to step on our work.
-  void* pluginPort = nullptr;
-  if (mInCGPaintLevel > 0) {
-    pluginPort = mPluginWindow->window;
-  } else {
-    pluginPort = SetPluginPortAndDetectChange();
+  if (mInCGPaintLevel < 1) {
+    SetPluginPortAndDetectChange();
   }
 
-#ifdef MAC_CARBON_PLUGINS
-  if (eventModel == NPEventModelCarbon && !pluginPort)
-    return nullptr;
-#endif
-
   // We'll need the top-level Cocoa window for the Cocoa event model.
-  void* cocoaTopLevelWindow = nullptr;
-  if (eventModel == NPEventModelCocoa) {
-    nsIWidget* widget = mObjectFrame->GetNearestWidget();
-    if (!widget)
-      return nullptr;
-    cocoaTopLevelWindow = widget->GetNativeData(NS_NATIVE_WINDOW);
-    if (!cocoaTopLevelWindow)
-      return nullptr;
-  }
+  nsIWidget* widget = mObjectFrame->GetNearestWidget();
+  if (!widget)
+    return nullptr;
+  void *cocoaTopLevelWindow = widget->GetNativeData(NS_NATIVE_WINDOW);
+  if (!cocoaTopLevelWindow)
+    return nullptr;
 
   nsIntPoint pluginOrigin;
   nsIntRect widgetClip;
   bool widgetVisible;
   pluginWidget->GetPluginClipRect(widgetClip, pluginOrigin, widgetVisible);
   mWidgetVisible = widgetVisible;
 
   // printf("GetPluginClipRect returning visible %d\n", widgetVisible);
@@ -3482,24 +3218,17 @@ void* nsPluginInstanceOwner::FixUpPlugin
   // This would be a lot easier if we could use obj-c here,
   // but we can't. Since we have only nsIWidget and we can't
   // use its native widget (an obj-c object) we have to go
   // from the widget's screen coordinates to its window coords
   // instead of straight to window coords.
   nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
 
   nsRect windowRect;
-#ifndef NP_NO_CARBON
-  if (eventModel == NPEventModelCarbon) {
-    NS_NPAPI_CarbonWindowFrame(static_cast<WindowRef>(static_cast<NP_CGContext*>(pluginPort)->window), windowRect);
-  } else
-#endif
-  {
-    NS_NPAPI_CocoaWindowFrame(cocoaTopLevelWindow, windowRect);
-  }
+  NS_NPAPI_CocoaWindowFrame(cocoaTopLevelWindow, windowRect);
 
   double scaleFactor = 1.0;
   GetContentsScaleFactor(&scaleFactor);
   int intScaleFactor = ceil(scaleFactor);
 
   // Convert geckoScreenCoords from device pixels to "display pixels"
   // for HiDPI modes.
   mPluginWindow->x = geckoScreenCoords.x/intScaleFactor - windowRect.x;
@@ -3521,66 +3250,43 @@ void* nsPluginInstanceOwner::FixUpPlugin
     mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left + widgetClip.width; 
   }
 
   // if the clip rect changed, call SetWindow()
   // (RealPlayer needs this to draw correctly)
   if (mPluginWindow->clipRect.left    != oldClipRect.left   ||
       mPluginWindow->clipRect.top     != oldClipRect.top    ||
       mPluginWindow->clipRect.right   != oldClipRect.right  ||
-      mPluginWindow->clipRect.bottom  != oldClipRect.bottom)
+      mPluginWindow->clipRect.bottom  != oldClipRect.bottom ||
+      mPluginPortChanged)
   {
     if (UseAsyncRendering()) {
       mInstance->AsyncSetWindow(mPluginWindow);
     }
     else {
       mPluginWindow->CallSetWindow(mInstance);
     }
     mPluginPortChanged = false;
-#ifdef MAC_CARBON_PLUGINS
-    // if the clipRect is of size 0, make the null timer fire less often
-    CancelTimer();
-    if (mPluginWindow->clipRect.left == mPluginWindow->clipRect.right ||
-        mPluginWindow->clipRect.top == mPluginWindow->clipRect.bottom) {
-      StartTimer(false);
-    }
-    else {
-      StartTimer(true);
-    }
-#endif
-  } else if (mPluginPortChanged) {
-    if (UseAsyncRendering()) {
-      mInstance->AsyncSetWindow(mPluginWindow);
-    }
-    else {
-      mPluginWindow->CallSetWindow(mInstance);
-    }
-    mPluginPortChanged = false;
   }
 
   // After the first NPP_SetWindow call we need to send an initial
   // top-level window focus event.
-  if (eventModel == NPEventModelCocoa && !mSentInitialTopLevelWindowEvent) {
+  if (!mSentInitialTopLevelWindowEvent) {
     // Set this before calling ProcessEvent to avoid endless recursion.
     mSentInitialTopLevelWindowEvent = true;
 
     nsPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, nullptr);
     NPCocoaEvent cocoaEvent;
     InitializeNPCocoaEvent(&cocoaEvent);
     cocoaEvent.type = NPCocoaEventWindowFocusChanged;
     cocoaEvent.data.focus.hasFocus = NS_NPAPI_CocoaWindowIsMain(cocoaTopLevelWindow);
     pluginEvent.pluginEvent = &cocoaEvent;
     ProcessEvent(pluginEvent);
   }
 
-#ifdef MAC_CARBON_PLUGINS
-  if (GetDrawingModel() == NPDrawingModelCoreGraphics && eventModel == NPEventModelCarbon)
-    return static_cast<NP_CGContext*>(pluginPort)->window;
-#endif
-
   return nullptr;
 }
 
 void
 nsPluginInstanceOwner::HidePluginWindow()
 {
   if (!mPluginWindow || !mInstance) {
     return;
@@ -3684,75 +3390,29 @@ nsPluginInstanceOwner::CallSetWindow()
     } else {
       mInstance->SetWindow(mPluginWindow);
     }
   }
 
   return NS_OK;
 }
 
-#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
-void nsPluginInstanceOwner::AddScrollPositionListener()
-{
-  // We need to register as a scroll position listener on every scrollable frame up to the top.
-  if (!mRegisteredScrollPositionListener && GetEventModel() == NPEventModelCarbon) {
-    for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
-      nsIScrollableFrame* sf = do_QueryFrame(f);
-      if (sf) {
-        sf->AddScrollPositionListener(this);
-      }
-    }
-    mRegisteredScrollPositionListener = true;
-  }
-}
-
-void nsPluginInstanceOwner::RemoveScrollPositionListener()
-{
-  // Our frame is changing or going away, unregister for a scroll position listening.
-  // It's OK to unregister when we didn't register, so don't be strict about unregistering.
-  // Better to unregister when we didn't have to than to not unregister when we should.
-  if (mRegisteredScrollPositionListener) {
-    for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
-      nsIScrollableFrame* sf = do_QueryFrame(f);
-      if (sf) {
-        sf->RemoveScrollPositionListener(this);
-      }
-    }
-    mRegisteredScrollPositionListener = false;
-  }
-}
-#endif
-
 NS_IMETHODIMP
 nsPluginInstanceOwner::GetContentsScaleFactor(double *result)
 {
   NS_ENSURE_ARG_POINTER(result);
   double scaleFactor = 1.0;
   // On Mac, device pixels need to be translated to (and from) "display pixels"
   // for plugins. On other platforms, plugin coordinates are always in device
   // pixels.
 #if defined(XP_MACOSX)
-  if (mWidget) {
-    scaleFactor = mWidget->GetDefaultScale();
-  } else {
-    nsCOMPtr<nsIScreenManager> screenMgr =
-      do_GetService("@mozilla.org/gfx/screenmanager;1");
-    if (screenMgr) {
-      nsCOMPtr<nsIScreen> screen;
-      nsIntRect screenRect = mObjectFrame->GetScreenRect();
-      screenMgr->ScreenForRect(screenRect.x, screenRect.y,
-                               screenRect.width, screenRect.height,
-                               getter_AddRefs(screen));
-      if (screen) {
-        nsresult rv = screen->GetContentsScaleFactor(&scaleFactor);
-        if (NS_FAILED(rv)) {
-          scaleFactor = 1.0;
-        }
-      }
-    }
+  nsIPresShell* presShell = nsContentUtils::FindPresShellForDocument(mContent->OwnerDoc());
+  if (presShell) {
+    scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/
+      presShell->GetPresContext()->DeviceContext()->UnscaledAppUnitsPerDevPixel();
   }
 #endif
   *result = scaleFactor;
   return NS_OK;
 }
 
 void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
 {
@@ -3782,21 +3442,16 @@ void nsPluginInstanceOwner::SetFrame(nsO
       }
       // Important! Unlock here otherwise SetCurrentImageInTransaction will deadlock with
       // our lock if we have a RemoteImage.
       autoLock.Unlock();
 #endif
       container->SetCurrentImageInTransaction(nullptr);
     }
 
-    // Scroll position listening is only required for Carbon event model plugins on Mac OS X.
-#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
-    RemoveScrollPositionListener();
-#endif
-
     // Make sure the old frame isn't holding a reference to us.
     mObjectFrame->SetInstanceOwner(nullptr);
   }
 
   // Swap in the new frame (or no frame)
   mObjectFrame = aFrame;
 
   // Set up a new frame
@@ -3804,21 +3459,16 @@ void nsPluginInstanceOwner::SetFrame(nsO
     mObjectFrame->SetInstanceOwner(this);
     // Can only call PrepForDrawing on an object frame once. Don't do it here unless
     // widget creation is complete. Doesn't matter if we actually have a widget.
     if (mWidgetCreationComplete) {
       mObjectFrame->PrepForDrawing(mWidget);
     }
     mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
     mObjectFrame->InvalidateFrame();
-
-    // Scroll position listening is only required for Carbon event model plugins on Mac OS X.
-#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
-    AddScrollPositionListener();
-#endif
     
     nsFocusManager* fm = nsFocusManager::GetFocusManager();
     const nsIContent* content = aFrame->GetContent();
     if (fm && content) {
       mContentFocused = (content == fm->GetFocusedContent());
     }
   }
 }
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -8,17 +8,16 @@
 #define nsPluginInstanceOwner_h_
 
 #include "npapi.h"
 #include "nsCOMPtr.h"
 #include "nsIPluginInstanceOwner.h"
 #include "nsIPluginTagInfo.h"
 #include "nsIPrivacyTransitionObserver.h"
 #include "nsIDOMEventListener.h"
-#include "nsIScrollPositionListener.h"
 #include "nsPluginHost.h"
 #include "nsPluginNativeWindow.h"
 #include "nsWeakReference.h"
 #include "gfxRect.h"
 
 #ifdef XP_MACOSX
 #include "mozilla/gfx/QuartzSupport.h"
 #include <ApplicationServices/ApplicationServices.h>
@@ -43,17 +42,16 @@ class gfxXlibSurface;
 #define INCL_PM
 #define INCL_GPI
 #include <os2.h>
 #endif
 
 class nsPluginInstanceOwner : public nsIPluginInstanceOwner,
                               public nsIPluginTagInfo,
                               public nsIDOMEventListener,
-                              public nsIScrollPositionListener,
                               public nsIPrivacyTransitionObserver,
                               public nsSupportsWeakReference
 {
 public:
   nsPluginInstanceOwner();
   virtual ~nsPluginInstanceOwner();
   
   NS_DECL_ISUPPORTS
@@ -98,27 +96,17 @@ public:
   void DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext);
 #elif defined(MOZ_X11) || defined(ANDROID)
   void Paint(gfxContext* aContext,
              const gfxRect& aFrameRect,
              const gfxRect& aDirtyRect);
 #elif defined(XP_OS2)
   void Paint(const nsRect& aDirtyRect, HPS aHPS);
 #endif
-  
-#ifdef MAC_CARBON_PLUGINS
-  void CancelTimer();
-  void StartTimer(bool isVisible);
-#endif
-  void SendIdleEvent();
-  
-  // nsIScrollPositionListener interface
-  virtual void ScrollPositionWillChange(nscoord aX, nscoord aY);
-  virtual void ScrollPositionDidChange(nscoord aX, nscoord aY);
-  
+
   //locals
   
   nsresult Init(nsIContent* aContent);
   
   void* GetPluginPortFromWidget();
   void ReleasePluginPort(void* pluginPort);
 
   nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
@@ -270,21 +258,16 @@ private:
 #ifdef MOZ_WIDGET_ANDROID
   gfxRect GetPluginRect();
   bool AddPluginView(const gfxRect& aRect = gfxRect(0, 0, 0, 0));
   void RemovePluginView();
 
   bool mFullScreen;
   void* mJavaView;
 #endif 
-
-#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
-  void AddScrollPositionListener();
-  void RemoveScrollPositionListener();
-#endif
  
   nsPluginNativeWindow       *mPluginWindow;
   nsRefPtr<nsNPAPIPluginInstance> mInstance;
   nsObjectFrame              *mObjectFrame;
   nsIContent                 *mContent; // WEAK, content owns us
   nsCString                   mDocumentBase;
   char                       *mTagText;
   bool                        mWidgetCreationComplete;
@@ -312,19 +295,16 @@ private:
   bool                        mPluginPortChanged;
 #endif
 #ifdef MOZ_X11
   // Used with windowless plugins only, initialized in CreateWidget().
   bool                        mFlash10Quirks;
 #endif
   bool                        mPluginWindowVisible;
   bool                        mPluginDocumentActiveState;
-#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
-  bool                        mRegisteredScrollPositionListener;
-#endif
 
   uint16_t          mNumCachedAttrs;
   uint16_t          mNumCachedParams;
   char              **mCachedAttrParamNames;
   char              **mCachedAttrParamValues;
   
 #ifdef XP_MACOSX
   NPEventModel mEventModel;
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -212,18 +212,30 @@ PluginModuleParent::TimeoutChanged(const
       unused << static_cast<PluginModuleParent*>(aModule)->SendSetParentHangTimeout(timeoutSecs);
     }
     return 0;
 }
 
 void
 PluginModuleParent::CleanupFromTimeout()
 {
-    if (!mShutdown && OkToCleanup())
-        Close();
+    if (mShutdown) {
+      return;
+    }
+
+    if (!OkToCleanup()) {
+        // there's still plugin code on the C++ stack, try again
+        MessageLoop::current()->PostDelayedTask(
+            FROM_HERE,
+            mTaskFactory.NewRunnableMethod(
+                &PluginModuleParent::CleanupFromTimeout), 10);
+        return;
+    }
+
+    Close();
 }
 
 #ifdef XP_WIN
 namespace {
 
 uint64_t
 FileTimeToUTC(const FILETIME& ftime) 
 {
@@ -283,16 +295,37 @@ GetProcessCpuUsage(const InfallibleTArra
   }
 
   return true;
 }
 
 } // anonymous namespace
 #endif // #ifdef XP_WIN
 
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+static bool
+CreateFlashMinidump(DWORD processId, ThreadId childThread,
+                    nsIFile* parentMinidump, const nsACString& name)
+{
+  if (processId == 0) {
+    return false;
+  }
+
+  base::ProcessHandle handle;
+  if (!base::OpenPrivilegedProcessHandle(processId, &handle)) {
+    return false;
+  }
+
+  bool res = CreateAdditionalChildMinidump(handle, 0, parentMinidump, name);
+  base::CloseProcessHandle(handle);
+
+  return res;
+}
+#endif
+
 bool
 PluginModuleParent::ShouldContinueFromReplyTimeout()
 {
 #ifdef MOZ_CRASHREPORTER
     CrashReporterParent* crashReporter = CrashReporter();
     crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("PluginHang"),
                                        NS_LITERAL_CSTRING("1"));
     if (crashReporter->GeneratePairedMinidump(this)) {
@@ -305,29 +338,23 @@ PluginModuleParent::ShouldContinueFromRe
 
 #ifdef MOZ_CRASHREPORTER_INJECTOR
         nsCOMPtr<nsIFile> pluginDumpFile;
 
         if (GetMinidumpForID(mPluginDumpID, getter_AddRefs(pluginDumpFile)) &&
             pluginDumpFile) {
           nsCOMPtr<nsIFile> childDumpFile;
 
-          if (mFlashProcess1 &&
-              TakeMinidumpForChild(mFlashProcess1,
-                                   getter_AddRefs(childDumpFile))) {
+          if (CreateFlashMinidump(mFlashProcess1, 0, pluginDumpFile,
+                                  NS_LITERAL_CSTRING("flash1"))) {
             additionalDumps.Append(",flash1");
-            RenameAdditionalHangMinidump(pluginDumpFile, childDumpFile,
-                                         NS_LITERAL_CSTRING("flash1"));
           }
-          if (mFlashProcess2 &&
-              TakeMinidumpForChild(mFlashProcess2,
-                                   getter_AddRefs(childDumpFile))) {
+          if (CreateFlashMinidump(mFlashProcess2, 0, pluginDumpFile,
+                                  NS_LITERAL_CSTRING("flash2"))) {
             additionalDumps.Append(",flash2");
-            RenameAdditionalHangMinidump(pluginDumpFile, childDumpFile,
-                                         NS_LITERAL_CSTRING("flash2"));
           }
         }
 #endif
 
         crashReporter->AnnotateCrashReport(
             NS_LITERAL_CSTRING("additional_minidumps"),
             additionalDumps);
     } else {
--- a/dom/plugins/test/testplugin/nptest_macosx.mm
+++ b/dom/plugins/test/testplugin/nptest_macosx.mm
@@ -64,30 +64,16 @@ pluginInstanceInit(InstanceData* instanc
   if ((NPN_GetValue(npp, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) == NPERR_NO_ERROR) &&
       supportsCoreGraphics) {
     NPN_SetValue(npp, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics);
   } else {
     printf("CoreGraphics drawing model not supported, can't create a plugin instance.\n");
     return NPERR_INCOMPATIBLE_VERSION_ERROR;
   }
 
-#ifndef NP_NO_CARBON
-  // The test plugin will test using Carbon NPAPI if it is available. This
-  // is simply because we want to test Gecko's Carbon NPAPI support. You can
-  // override this behavior with an environment variable.
-  if (!getenv("TEST_COCOA_NPAPI")) {
-    NPBool supportsCarbonEvents = false;
-    if ((NPN_GetValue(npp, NPNVsupportsCarbonBool, &supportsCarbonEvents) == NPERR_NO_ERROR) &&
-        supportsCarbonEvents) {
-      instanceData->eventModel = NPEventModelCarbon;
-      return NPERR_NO_ERROR;
-    }
-  }
-#endif
-
   NPBool supportsCocoaEvents = false;
   if ((NPN_GetValue(npp, NPNVsupportsCocoaBool, &supportsCocoaEvents) == NPERR_NO_ERROR) &&
       supportsCocoaEvents) {
     NPN_SetValue(npp, NPPVpluginEventModel, (void*)NPEventModelCocoa);
     instanceData->eventModel = NPEventModelCocoa;
   } else {
     printf("Cocoa event model not supported, can't create a plugin instance.\n");
     return NPERR_INCOMPATIBLE_VERSION_ERROR;
@@ -153,26 +139,17 @@ pluginDraw(InstanceData* instanceData, N
     return;
   
   const char* uaString = NPN_UserAgent(npp);
   if (!uaString)
     return;
 
   NPWindow window = instanceData->window;
 
-  CGContextRef cgContext = NULL;
-#ifndef NP_NO_CARBON
-  if (instanceData->eventModel == NPEventModelCocoa) {
-    cgContext = event->data.draw.context;
-  } else {
-    cgContext = ((NP_CGContext*)(window.window))->context;
-  }
-#else
-  cgContext = event->data.draw.context;
-#endif
+  CGContextRef cgContext = event->data.draw.context;
 
   float windowWidth = window.width;
   float windowHeight = window.height;
 
   switch(instanceData->scriptableObject->drawMode) {
   case DM_DEFAULT: {
     CFStringRef uaCFString = CFStringCreateWithCString(kCFAllocatorDefault, uaString, kCFStringEncodingASCII);
     // save the cgcontext gstate
@@ -250,50 +227,16 @@ pluginDraw(InstanceData* instanceData, N
     break;
   }
   }
 }
 
 int16_t
 pluginHandleEvent(InstanceData* instanceData, void* event)
 {
-#ifndef NP_NO_CARBON
-  if (instanceData->eventModel == NPEventModelCarbon) {
-    EventRecord* carbonEvent = (EventRecord*)event;
-    if (!carbonEvent)
-      return kNPEventNotHandled;
-
-    NPWindow* w = &instanceData->window;
-    switch (carbonEvent->what) {
-      case updateEvt:
-        pluginDraw(instanceData, NULL);
-        break;
-      case mouseDown:
-      case mouseUp:
-      case osEvt:
-      {
-        Rect globalBounds = {0};
-        WindowRef nativeWindow = static_cast<WindowRef>(static_cast<NP_CGContext*>(w->window)->window);
-        if (nativeWindow)
-          ::GetWindowBounds(nativeWindow, kWindowStructureRgn, &globalBounds);
-        instanceData->lastMouseX = carbonEvent->where.h - w->x - globalBounds.left;
-        instanceData->lastMouseY = carbonEvent->where.v - w->y - globalBounds.top;
-        if (carbonEvent->what == mouseUp) {
-          instanceData->mouseUpEventCount++;
-        }
-        break;
-      }
-      default:
-        return kNPEventNotHandled;
-    }
-
-    return kNPEventHandled;
-  }
-#endif
-
   NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)event;
   if (!cocoaEvent)
     return kNPEventNotHandled;
 
   switch (cocoaEvent->type) {
     case NPCocoaEventDrawRect:
       pluginDraw(instanceData, cocoaEvent);
       break;
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -581,17 +581,17 @@ nsresult nsGeolocationService::Init()
 #ifdef MOZ_WIDGET_ANDROID
   provider = new AndroidLocationProvider();
   if (provider) {
     mProviders.AppendObject(provider);
   }
 #endif
 
 #ifdef MOZ_WIDGET_GONK
-  provider = GonkGPSGeolocationProvider::GetSingleton();
+  provider = do_GetService(GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID);
   if (provider) {
     mProviders.AppendObject(provider);
   }
 #endif
 
   return NS_OK;
 }
 
--- a/dom/system/gonk/GonkGPSGeolocationProvider.h
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.h
@@ -20,16 +20,22 @@
 #include <hardware/gps.h> // for GpsInterface
 #include "nsCOMPtr.h"
 #include "nsIGeolocationProvider.h"
 #include "nsIRadioInterfaceLayer.h"
 #include "nsString.h"
 
 class nsIThread;
 
+#define GONK_GPS_GEOLOCATION_PROVIDER_CID \
+{ 0x48525ec5, 0x5a7f, 0x490a, { 0x92, 0x77, 0xba, 0x66, 0xe0, 0xd2, 0x2c, 0x8b } }
+
+#define GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID \
+"@mozilla.org/gonk-gps-geolocation-provider;1"
+
 class GonkGPSGeolocationProvider : public nsIGeolocationProvider
                                  , public nsIRILDataCallback
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIGEOLOCATIONPROVIDER
   NS_DECL_NSIRILDATACALLBACK
 
--- a/dom/system/gonk/Makefile.in
+++ b/dom/system/gonk/Makefile.in
@@ -66,17 +66,20 @@ CPPSRCS += \
   Volume.cpp \
   VolumeCommand.cpp \
   VolumeManager.cpp \
   VolumeServiceIOThread.cpp \
   VolumeServiceTest.cpp \
   $(NULL)
 # for our local copy of AudioSystem.h
 LOCAL_INCLUDES += -I$(topsrcdir)/media/libsydneyaudio/src
-EXPORTS = nsVolume.h
+EXPORTS = \
+  nsVolume.h \
+  GonkGPSGeolocationProvider.h \
+  $(NULL)
 endif
 
 EXTRA_COMPONENTS = \
   NetworkManager.manifest \
   NetworkManager.js \
   RadioInterfaceLayer.manifest \
   RadioInterfaceLayer.js \
   RILContentHelper.js \
--- a/dom/tests/mochitest/bugs/Makefile.in
+++ b/dom/tests/mochitest/bugs/Makefile.in
@@ -124,16 +124,17 @@ MOCHITEST_FILES	= \
 		test_bug739038.html \
 		test_bug740811.html \
 		test_bug743615.html \
 		utils_bug743615.js \
 		worker_bug743615.js \
 		test_bug750051.html \
 		test_bug755320.html \
 		test_bug777628.html \
+		test_bug665548.html \
 		$(NULL)
 
 ifneq (Linux,$(OS_ARCH))
 MOCHITEST_FILES += \
 		test_resize_move_windows.html \
 		$(NULL)
 else
 $(warning test_resize_move_windows.html is disabled on Linux for timeouts. Bug 677841)
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug665548.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=665548
+-->
+<head>
+  <title>Test for Bug 665548</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=665548">Mozilla Bug 665548</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe name='location'></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 665548 **/
+
+isnot(window.location, window.frames[0],
+      "window.location shouldn't be the frame named location");
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/tests/mochitest/localstorage/frame_clear_browser_data.html
+++ b/dom/tests/mochitest/localstorage/frame_clear_browser_data.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html>
+  <body>
+  </body>
   <script>
-    dump("\n frame created \n\n");
     addEventListener('message', function(e) {
       if (e.data == 'clear') {
         navigator.mozApps.getSelf().onsuccess = function() {
-          dump("\n clearing browser data \n\n");
           this.result.clearBrowserData();
+          document.body.innerHTML = "<done></done>";
         };
       }
     });
   </script>
 </html>
--- a/dom/tests/mochitest/localstorage/test_clear_browser_data.html
+++ b/dom/tests/mochitest/localstorage/test_clear_browser_data.html
@@ -186,45 +186,53 @@ function browserLoadEvent() {
   gBrowserStorage.localStorage = window.frames[1].frames[0].localStorage;
   gBrowserStorage.sessionStorage = window.frames[1].frames[0].sessionStorage;
 
   setupStorage(gAppStorage.localStorage);
   setupStorage(gAppStorage.sessionStorage);
   setupStorage(gBrowserStorage.localStorage);
   setupStorage(gBrowserStorage.sessionStorage);
 
-  dump("\n send message to iframe \n\n");
   frames[1].postMessage("clear", "http://www.example.com");
 
-  SimpleTest.executeSoon(function() {
-    dump("\n call getAll() \n\n");
-    navigator.mozApps.mgmt.getAll().onsuccess = function() {
-      dump("\n get getAll() results \n\n");
-      for (i in this.result) {
-        var app = this.result[i];
-        if (app.manifestURL == gManifestURL) {
-          is(gBrowserStorage.localStorage.getItem("foo"), null, "localstorage data have been deleted");
-          is(gBrowserStorage.sessionStorage.getItem("foo"), "bar", "sessionstorage data have not been deleted");
-
-          is(gAppStorage.localStorage.getItem("foo"), "bar", "data are still there");
-          is(gAppStorage.sessionStorage.getItem("foo"), "bar", "data are still there");
+  waitForClearBrowserData();
+};
 
-          is(gWitnessStorage.localStorage.getItem("foo"), "bar", "data are still there");
-          is(gWitnessStorage.sessionStorage.getItem("foo"), "bar", "data are still there");
-
-          Webapps.DOMApplicationRegistry.allAppsLaunchable = gPreviousLaunchableValue;
+function waitForClearBrowserData() {
+  SimpleTest.executeSoon(function() {
+    if (frames[1].document.getElementsByTagName('done').length == 0) {
+      waitForClearBrowserData();
+    } else {
+      checks();
+    }
+  });
+}
+function checks() {
+  navigator.mozApps.mgmt.getAll().onsuccess = function() {
+    for (i in this.result) {
+      var app = this.result[i];
+      if (app.manifestURL == gManifestURL) {
+        is(gBrowserStorage.localStorage.getItem("foo"), null, "localstorage data have been deleted");
+        is(gBrowserStorage.sessionStorage.getItem("foo"), "bar", "sessionstorage data have not been deleted");
 
-          // Now we uninstall the app and make sure everything is clean.
-          app.uninstall().onsuccess = function() {
-            finish();
-          };
-        }
+        is(gAppStorage.localStorage.getItem("foo"), "bar", "data are still there");
+        is(gAppStorage.sessionStorage.getItem("foo"), "bar", "data are still there");
+
+        is(gWitnessStorage.localStorage.getItem("foo"), "bar", "data are still there");
+        is(gWitnessStorage.sessionStorage.getItem("foo"), "bar", "data are still there");
+
+        Webapps.DOMApplicationRegistry.allAppsLaunchable = gPreviousLaunchableValue;
+
+        // Now we uninstall the app and make sure everything is clean.
+        app.uninstall().onsuccess = function() {
+          finish();
+        };
       }
-    };
-  });
+    }
+  };
 }
 
 /**
  * This method will be called when the test will be done. It is going to clear
  * all storage data, permissions, etc.
  */
 function finish() {
   gWitnessStorage.localStorage.clear();
new file mode 100644
--- /dev/null
+++ b/dom/webidl/MediaStreamList.webidl
@@ -0,0 +1,13 @@
+/* -*- 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/.
+ */
+
+interface MediaStream;
+
+[NoInterfaceObject]
+interface MediaStreamList {
+  getter MediaStream? (unsigned long index);
+  readonly attribute unsigned long length;
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -50,16 +50,22 @@ webidl_files = \
   $(NULL)
 
 ifdef MOZ_WEBGL
 webidl_files += \
   WebGLRenderingContext.webidl \
   $(NULL)
 endif
 
+ifdef MOZ_WEBRTC
+webidl_files += \
+  MediaStreamList.webidl \
+  $(NULL)
+endif
+
 ifdef ENABLE_TESTS
 test_webidl_files := \
   TestCodeGen.webidl \
   TestDictionary.webidl \
   TestTypedef.webidl \
   $(NULL)
 else
 test_webidl_files := $(NULL)
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -123,21 +123,22 @@ var WifiManager = (function() {
 
     voidControlMessage("load_driver", function(status) {
       driverLoaded = (status >= 0);
       callback(status)
     });
   }
 
   function unloadDriver(callback) {
-    // Otoro ICS can't unload and then load the driver, so never unload it.
-    if (device === "otoro") {
-      callback(0);
-      return;
-    }
+    // Unloading drivers is generally unnecessary and
+    // can trigger bugs in some drivers.
+    // On properly written drivers, bringing the interface
+    // down powers down the interface.
+    callback(0);
+    return;
 
     voidControlMessage("unload_driver", function(status) {
       driverLoaded = (status < 0);
       callback(status);
     });
   }
 
   function startSupplicant(callback) {
--- a/editor/libeditor/base/tests/test_bug795785.html
+++ b/editor/libeditor/base/tests/test_bug795785.html
@@ -7,17 +7,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795785">Mozilla Bug 795785</a>
 <div id="display">
-  <textarea id="textarea" style="overflow: hidden; height: 3em; width: 5em;"></textarea>
+  <textarea id="textarea" style="overflow: hidden; height: 3em; width: 5em; word-wrap: normal;"></textarea>
   <div id="div" contenteditable style="overflow: hidden; height: 3em; width: 5em;"></div>
 </div>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 </pre>
 
@@ -33,17 +33,17 @@ function hitEventLoop(aFunc, aTimes)
 {
   if (--aTimes) {
     setTimeout(hitEventLoop, 0, aFunc, aTimes);
   } else {
     setTimeout(aFunc, 20);
   }
 }
 
-function doEnterKeyAndArrowKeyTest(aElement, aElementDescription, aCallback)
+function doKeyEventTest(aElement, aElementDescription, aCallback)
 {
   aElement.focus();
   aElement.scrollTop = 0;
   hitEventLoop(function () {
     is(aElement.scrollTop, 0,
        aElementDescription + "'s scrollTop isn't 0");
     synthesizeKey("VK_RETURN", { });
     synthesizeKey("VK_RETURN", { });
@@ -66,17 +66,39 @@ function doEnterKeyAndArrowKeyTest(aElem
         synthesizeKey("VK_DOWN", { });
         synthesizeKey("VK_DOWN", { });
         synthesizeKey("VK_DOWN", { });
         synthesizeKey("VK_DOWN", { });
         synthesizeKey("VK_DOWN", { });
         hitEventLoop(function () {
           is(aElement.scrollTop, scrollTop,
              aElementDescription + " was not scrolled by down key events");
-          aCallback();
+          var longWord = "aaaaaaaaaaaaaaaaaaaa";
+          sendString(longWord);
+          hitEventLoop(function () {
+            isnot(aElement.scrollLeft, 0,
+                  aElementDescription + " was not scrolled by typing long word");
+            var scrollLeft = aElement.scrollLeft;
+            var i;
+            for (i = 0; i < longWord.length; i++) {
+              synthesizeKey("VK_LEFT", { });
+            }
+            hitEventLoop(function () {
+              isnot(aElement.scrollLeft, scrollLeft,
+                    aElementDescription + " was not scrolled by left key events");
+              for (i = 0; i < longWord.length; i++) {
+                synthesizeKey("VK_RIGHT", { });
+              }
+              hitEventLoop(function () {
+                is(aElement.scrollLeft, scrollLeft,
+                   aElementDescription + " was not scrolled by right key events");
+                aCallback();
+              }, 20);
+            }, 20);
+          }, 20);
         }, 20);
       }, 20);
     }, 20);
   }, 20);
 }
 
 function doCompositionTest(aElement, aElementDescription, aCallback)
 {
@@ -119,20 +141,20 @@ function doCompositionTest(aElement, aEl
         aCallback();
       }, 20);
     }, 20);
   }, 20);
 }
 
 function runTests()
 {
-  doEnterKeyAndArrowKeyTest(textarea, "textarea",
+  doKeyEventTest(textarea, "textarea",
     function () {
       textarea.value = "";
-      doEnterKeyAndArrowKeyTest(div, "div (contenteditable)",
+      doKeyEventTest(div, "div (contenteditable)",
         function () {
           div.innerHTML = "";
           doCompositionTest(textarea, "textarea",
             function () {
               doCompositionTest(div, "div (contenteditable)",
                 function () {
                   SimpleTest.finish();
                 });
--- a/editor/libeditor/html/TextEditorTest.cpp
+++ b/editor/libeditor/html/TextEditorTest.cpp
@@ -19,17 +19,17 @@
 #include "nsIHTMLEditor.h"
 #include "nsIPlaintextEditor.h"
 #include "nsISelection.h"
 #include "nsLiteralString.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsStringFwd.h"
 
-#define TEST_RESULT(r) { if (NS_FAILED(r)) {printf("FAILURE result=%X\n", r); return r; } }
+#define TEST_RESULT(r) { if (NS_FAILED(r)) {printf("FAILURE result=%X\n", static_cast<uint32_t>(r)); return r; } }
 #define TEST_POINTER(p) { if (!p) {printf("FAILURE null pointer\n"); return NS_ERROR_NULL_POINTER; } }
 
 TextEditorTest::TextEditorTest()
 {
   printf("constructed a TextEditorTest\n");
 }
 
 TextEditorTest::~TextEditorTest()
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -1223,17 +1223,18 @@ nsHTMLEditor::ReplaceHeadContentsWithHTM
                                         getter_AddRefs(docfrag));
 
   //XXXX BUG 50965: This is not returning the text between <title> ... </title>
   // Special code is needed in JS to handle title anyway, so it really doesn't matter!
 
   if (NS_FAILED(res))
   {
 #ifdef DEBUG
-    printf("Couldn't create contextual fragment: error was %d\n", res);
+    printf("Couldn't create contextual fragment: error was %X\n",
+           static_cast<uint32_t>(res));
 #endif
     return res;
   }
   NS_ENSURE_TRUE(docfrag, NS_ERROR_NULL_POINTER);
 
   nsCOMPtr<nsIDOMNode> child;
 
   // First delete all children in head
--- a/embedding/tests/winEmbed/winEmbed.cpp
+++ b/embedding/tests/winEmbed/winEmbed.cpp
@@ -193,16 +193,18 @@ int main(int argc, char *argv[])
 
     XRE_TermEmbedding =
         (XRE_TermEmbeddingType) GetProcAddress(xulModule, "XRE_TermEmbedding");
     if (!XRE_TermEmbedding) {
         fprintf(stderr, "Error: %i\n", GetLastError());
         return 5;
     }
 
+    int result = 0;
+
     // Scope all the XPCOM stuff
     {
         strcpy(lastslash, "\\xulrunner");
 
         nsCOMPtr<nsIFile> xuldir;
         rv = NS_NewNativeLocalFile(nsCString(path), false,
                                    getter_AddRefs(xuldir));
         if (NS_FAILED(rv))
@@ -215,37 +217,36 @@ int main(int argc, char *argv[])
                                    getter_AddRefs(appdir));
         if (NS_FAILED(rv))
             return 8;
 
         rv = XRE_InitEmbedding2(xuldir, appdir, nullptr);
         if (NS_FAILED(rv))
             return 9;
 
-        int result = 0;
         if (NS_FAILED(StartupProfile())) {
             result = 8;
         }
         else {
             InitializeWindowCreator();
 
             // Open the initial browser window
             OpenWebPage(gFirstURL);
 
             // Main message loop.
             // NOTE: We use a fake event and a timeout in order to process idle stuff for
             //       Mozilla every 1/10th of a second.
             bool runCondition = true;
 
-            rv = AppCallbacks::RunEventLoop(runCondition);
+            result = AppCallbacks::RunEventLoop(runCondition);
         }
     }
     XRE_TermEmbedding();
 
-    return rv;
+    return result;
 }
 
 /* InitializeWindowCreator creates and hands off an object with a callback
    to a window creation function. This is how all new windows are opened,
    except any created directly by the embedding app. */
 nsresult
 InitializeWindowCreator()
 {
--- a/extensions/universalchardet/src/base/JpCntx.cpp
+++ b/extensions/universalchardet/src/base/JpCntx.cpp
@@ -176,18 +176,18 @@ int32_t SJISContextAnalysis::GetOrder(co
     return (unsigned char)*(str+1) - (unsigned char)0x9f;
   return -1;
 }
 
 int32_t EUCJPContextAnalysis::GetOrder(const char* str, uint32_t *charLen)
 {
   //find out current char's byte length
   if ((unsigned char)*str == (unsigned char)0x8e ||
-      (unsigned char)*str >= (unsigned char)0xa1 && 
-      (unsigned char)*str <= (unsigned char)0xfe)
+      ((unsigned char)*str >= (unsigned char)0xa1 &&
+       (unsigned char)*str <= (unsigned char)0xfe))
       *charLen = 2;
   else if ((unsigned char)*str == (unsigned char)0x8f)
     *charLen = 3;
   else
     *charLen = 1;
 
   //return its order if it is hiragana
   if ((unsigned char)*str == (unsigned char)0xa4 &&
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -1273,35 +1273,39 @@ BasicShadowLayerManager::IsCompositingCh
 
 void
 BasicShadowLayerManager::SetIsFirstPaint()
 {
   ShadowLayerForwarder::SetIsFirstPaint();
 }
 
 bool
-BasicShadowLayerManager::ShouldAbortProgressiveUpdate(bool aHasPendingNewThebesContent)
+BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
+                                                   gfx::Rect& aViewport,
+                                                   float& aScaleX,
+                                                   float& aScaleY)
 {
 #ifdef MOZ_WIDGET_ANDROID
   Layer* primaryScrollable = GetPrimaryScrollableLayer();
   if (primaryScrollable) {
     const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
 
     // This is derived from the code in
     // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
     const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
     float devPixelRatioX = 1 / rootTransform.GetXScale();
     float devPixelRatioY = 1 / rootTransform.GetYScale();
     gfx::Rect displayPort((metrics.mDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
                           (metrics.mDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
                           metrics.mDisplayPort.width * devPixelRatioX,
                           metrics.mDisplayPort.height * devPixelRatioY);
 
-    return AndroidBridge::Bridge()->ShouldAbortProgressiveUpdate(
-      aHasPendingNewThebesContent, displayPort, devPixelRatioX);
+    return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
+      aHasPendingNewThebesContent, displayPort, devPixelRatioX,
+      aViewport, aScaleX, aScaleY);
   }
 #endif
 
   return false;
 }
 
 already_AddRefed<ThebesLayer>
 BasicShadowLayerManager::CreateThebesLayer()
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -88,17 +88,17 @@ public:
   virtual bool IsWidgetLayerManager() { return mWidget != nullptr; }
 
   virtual void BeginTransaction();
   virtual void BeginTransactionWithTarget(gfxContext* aTarget);
   virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT);
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags aFlags = END_DEFAULT);
-  virtual bool AreComponentAlphaLayersEnabled() { return HasShadowManager(); }
+  virtual bool AreComponentAlphaLayersEnabled() { return HasShadowManager() || !IsWidgetLayerManager(); }
 
   void AbortTransaction();
 
   virtual void SetRoot(Layer* aLayer);
 
   virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
   virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
   virtual already_AddRefed<ImageLayer> CreateImageLayer();
@@ -268,22 +268,29 @@ public:
   virtual bool IsCompositingCheap();
   virtual bool HasShadowManagerInternal() const { return HasShadowManager(); }
 
   virtual void SetIsFirstPaint() MOZ_OVERRIDE;
 
   void SetRepeatTransaction() { mRepeatTransaction = true; }
 
   /**
-   * Determines if a progressive update should be cancelled. This is only called
-   * if gfxPlatform::UseProgressiveTilePainting() returns true.
-   * aHasPendingNewThebesContent is true if there is a Thebes layer update
-   * that will cause its valid region to expand.
+   * Called for each iteration of a progressive tile update. Fills
+   * aViewport, aScaleX and aScaleY with the current scale and viewport
+   * being used to composite the layers in this manager, to determine what area
+   * intersects with the target render rectangle.
+   * Returns true if the update should continue, or false if it should be
+   * cancelled.
+   * This is only called if gfxPlatform::UseProgressiveTilePainting() returns
+   * true.
    */
-  bool ShouldAbortProgressiveUpdate(bool aHasPendingNewThebesContent);
+  bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
+                                 gfx::Rect& aViewport,
+                                 float& aScaleX,
+                                 float& aScaleY);
 
 private:
   /**
    * Forward transaction results to the parent context.
    */
   void ForwardTransaction();
 
   // The bounds of |mTarget| in device pixels.
--- a/gfx/layers/basic/BasicTiledThebesLayer.cpp
+++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp
@@ -245,20 +245,21 @@ BasicTiledThebesLayer::PaintThebes(gfxCo
     NS_ASSERTION(false, "Shadow requested for painting\n");
     return;
   }
 
   if (mTiledBuffer.HasFormatChanged(this)) {
     mValidRegion = nsIntRegion();
   }
 
-  nsIntRegion regionToPaint = mVisibleRegion;
-  regionToPaint.Sub(regionToPaint, mValidRegion);
-  if (regionToPaint.IsEmpty())
+  nsIntRegion invalidRegion = mVisibleRegion;
+  invalidRegion.Sub(invalidRegion, mValidRegion);
+  if (invalidRegion.IsEmpty())
     return;
+  nsIntRegion regionToPaint = invalidRegion;
 
   gfxSize resolution(1, 1);
   for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
     const FrameMetrics& metrics = parent->GetFrameMetrics();
     resolution.width *= metrics.mResolution.width;
     resolution.height *= metrics.mResolution.height;
   }
 
@@ -272,77 +273,109 @@ BasicTiledThebesLayer::PaintThebes(gfxCo
   }
   int32_t scrollDiffX = scrollOffset.x - mLastScrollOffset.x;
   int32_t scrollDiffY = scrollOffset.y - mLastScrollOffset.y;
 
   // Only draw progressively when we're panning and the resolution is unchanged.
   if (gfxPlatform::UseProgressiveTilePainting() &&
       mTiledBuffer.GetResolution() == resolution &&
       (scrollDiffX != 0 || scrollDiffY != 0)) {
-    // Paint tiles that have no content before tiles that only have stale content.
-    nsIntRegion staleRegion = mTiledBuffer.GetValidRegion();
-    staleRegion.And(staleRegion, regionToPaint);
-    bool hasNewContent = !staleRegion.Contains(regionToPaint);
-    if (!staleRegion.IsEmpty() && hasNewContent) {
-      regionToPaint.Sub(regionToPaint, staleRegion);
+    // Find out if we have any non-stale content to update.
+    nsIntRegion freshRegion = mTiledBuffer.GetValidRegion();
+    freshRegion.And(freshRegion, invalidRegion);
+    freshRegion.Sub(invalidRegion, freshRegion);
+
+    // Find out the current view transform to determine which tiles to draw
+    // first, and see if we should just abort this paint. Aborting is usually
+    // caused by there being an incoming, more relevant paint.
+    gfx::Rect viewport;
+    float scaleX, scaleY;
+    if (BasicManager()->ProgressiveUpdateCallback(!freshRegion.IsEmpty(), viewport, scaleX, scaleY)) {
+      return;
     }
 
-    // Find out if we should just abort this paint, usually due to there being
-    // an incoming, more relevant paint.
-    if (BasicManager()->ShouldAbortProgressiveUpdate(hasNewContent)) {
-      return;
+    // Prioritise tiles that are currently visible on the screen.
+
+    // Get the transform to the current layer.
+    gfx3DMatrix transform = GetEffectiveTransform();
+    // XXX Not sure if this code for intermediate surfaces is correct.
+    //     It rarely gets hit though, and shouldn't have terrible consequences
+    //     even if it is wrong.
+    for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
+      if (parent->UseIntermediateSurface()) {
+        transform.PreMultiply(parent->GetEffectiveTransform());
+      }
+    }
+    transform.Invert();
+
+    // Transform the screen coordinates into local layer coordinates.
+    gfxRect transformedViewport(viewport.x - (scrollOffset.x * resolution.width),
+                                viewport.y - (scrollOffset.y * resolution.height),
+                                viewport.width, viewport.height);
+    transformedViewport.Scale((scaleX / resolution.width) / resolution.width,
+                              (scaleY / resolution.height) / resolution.height);
+    transformedViewport = transform.TransformBounds(transformedViewport);
+
+    nsIntRect roundedTransformedViewport((int32_t)floor(transformedViewport.x),
+                                         (int32_t)floor(transformedViewport.y),
+                                         (int32_t)ceil(transformedViewport.width),
+                                         (int32_t)ceil(transformedViewport.height));
+
+    // Paint tiles that have no content before tiles that only have stale content.
+    if (!freshRegion.IsEmpty()) {
+      regionToPaint = freshRegion;
+    }
+    if (regionToPaint.Intersects(roundedTransformedViewport)) {
+      regionToPaint.And(regionToPaint, roundedTransformedViewport);
     }
 
     // The following code decides what order to draw tiles in, based on the
     // current scroll direction of the primary scrollable layer.
-    // XXX While this code is of a reasonable size currently, it is likely
-    //     we'll want to add more comprehensive methods of deciding what
-    //     tiles to draw. This is a good candidate for splitting out into a
-    //     separate function.
+    NS_ASSERTION(!regionToPaint.IsEmpty(), "Unexpectedly empty paint region!");
+    nsIntRect paintBounds = regionToPaint.GetBounds();
+
+    int startX, incX, startY, incY;
+    if (scrollOffset.x >= mLastScrollOffset.x) {
+      startX = mTiledBuffer.RoundDownToTileEdge(paintBounds.x);
+      incX = mTiledBuffer.GetTileLength();
+    } else {
+      startX = mTiledBuffer.RoundDownToTileEdge(paintBounds.XMost() - 1);
+      incX = -mTiledBuffer.GetTileLength();
+    }
 
-    // First, decide whether to iterate on the region from the beginning or end
-    // of the rect list. This relies on the specific behaviour of nsRegion when
-    // subtracting rects. If we're moving more in the X direction, we draw
-    // tiles by column, otherwise by row.
-    nsIntRegionRectIterator it(regionToPaint);
-    const nsIntRect* rect;
-    if ((NS_ABS(scrollDiffY) > NS_ABS(scrollDiffX) && scrollDiffY >= 0)) {
-      rect = it.Next();
+    if (scrollOffset.y >= mLastScrollOffset.y) {
+      startY = mTiledBuffer.RoundDownToTileEdge(paintBounds.y);
+      incY = mTiledBuffer.GetTileLength();
     } else {
-      const nsIntRect* lastRect;
-      while ((lastRect = it.Next())) {
-        rect = lastRect;
+      startY = mTiledBuffer.RoundDownToTileEdge(paintBounds.YMost() - 1);
+      incY = -mTiledBuffer.GetTileLength();
+    }
+
+    // Find a tile to draw.
+    nsIntRect tileBounds(startX, startY,
+                         mTiledBuffer.GetTileLength(),
+                         mTiledBuffer.GetTileLength());
+    // This loop will always terminate, as there is at least one tile area
+    // along the first/last row/column intersecting with regionToPaint, or its
+    // bounds would have been smaller.
+    while (true) {
+      regionToPaint.And(invalidRegion, tileBounds);
+      if (!regionToPaint.IsEmpty()) {
+        break;
+      }
+      if (NS_ABS(scrollDiffY) >= NS_ABS(scrollDiffX)) {
+        tileBounds.x += incX;
+      } else {
+        tileBounds.y += incY;
       }
     }
 
-    // Second, decide what direction to start drawing rects from by checking
-    // the scroll offset difference of the primary scrollable layer. If we're
-    // scrolling to the right, make sure to start from the left, downwards
-    // start from the top, etc.
-    int paintTileStartX, paintTileStartY;
-    if (scrollOffset.x >= mLastScrollOffset.x) {
-      paintTileStartX = mTiledBuffer.RoundDownToTileEdge(rect->x);
-    } else {
-      paintTileStartX = mTiledBuffer.RoundDownToTileEdge(rect->XMost() - 1);
-    }
-
-    if (scrollOffset.y >= mLastScrollOffset.y) {
-      paintTileStartY = mTiledBuffer.RoundDownToTileEdge(rect->y);
-    } else {
-      paintTileStartY = mTiledBuffer.RoundDownToTileEdge(rect->YMost() - 1);
-    }
-
-    nsIntRegion maxPaint(
-      nsIntRect(paintTileStartX, paintTileStartY,
-                mTiledBuffer.GetTileLength(), mTiledBuffer.GetTileLength()));
-
-    if (!maxPaint.Contains(regionToPaint)) {
+    if (!regionToPaint.Contains(invalidRegion)) {
       // The region needed to paint is larger then our progressive chunk size
       // therefore update what we want to paint and ask for a new paint transaction.
-      regionToPaint.And(regionToPaint, maxPaint);
       BasicManager()->SetRepeatTransaction();
 
       // Make sure that tiles that fall outside of the visible region are discarded.
       mValidRegion.And(mValidRegion, mVisibleRegion);
     } else {
       // The transaction is completed, store the last scroll offset.
       mLastScrollOffset = scrollOffset;
     }
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -20,16 +20,19 @@
 #include "ReadbackLayerD3D10.h"
 #include "ImageLayerD3D10.h"
 #include "mozilla/layers/PLayerChild.h"
 #include "mozilla/WidgetUtils.h"
 
 #include "../d3d9/Nv3DVUtils.h"
 
 #include "gfxCrashReporterUtils.h"
+#ifdef MOZ_METRO
+#include "DXGI1_2.h"
+#endif
 
 using namespace std;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)(
--- a/gfx/qcms/qcmsint.h
+++ b/gfx/qcms/qcmsint.h
@@ -274,25 +274,25 @@ void qcms_transform_data_rgba_out_lut_ss
                                           size_t length);
 
 extern qcms_bool qcms_supports_iccv4;
 
 #ifdef NATIVE_OUTPUT
 # define RGB_OUTPUT_COMPONENTS 4
 # define RGBA_OUTPUT_COMPONENTS 4
 # ifdef IS_LITTLE_ENDIAN
-#  define OUTPUT_INDEX_A 3
-#  define OUTPUT_INDEX_R 2
-#  define OUTPUT_INDEX_G 1
-#  define OUTPUT_INDEX_B 0
+#  define OUTPUT_A_INDEX 3
+#  define OUTPUT_R_INDEX 2
+#  define OUTPUT_G_INDEX 1
+#  define OUTPUT_B_INDEX 0
 # else
-#  define OUTPUT_INDEX_A 0
-#  define OUTPUT_INDEX_R 1
-#  define OUTPUT_INDEX_G 2
-#  define OUTPUT_INDEX_B 3
+#  define OUTPUT_A_INDEX 0
+#  define OUTPUT_R_INDEX 1
+#  define OUTPUT_G_INDEX 2
+#  define OUTPUT_B_INDEX 3
 # endif
 #else
 # define RGB_OUTPUT_COMPONENTS 3
 # define RGBA_OUTPUT_COMPONENTS 4
 # define OUTPUT_R_INDEX 0
 # define OUTPUT_G_INDEX 1
 # define OUTPUT_B_INDEX 2
 # define OUTPUT_A_INDEX 3
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -684,16 +684,22 @@ gfxUtils::GetYCbCrToRGBDestFormatAndSize
 
 void
 gfxUtils::ConvertYCbCrToRGB(const PlanarYCbCrImage::Data& aData,
                             const gfxASurface::gfxImageFormat& aDestFormat,
                             const gfxIntSize& aDestSize,
                             unsigned char* aDestBuffer,
                             int32_t aStride)
 {
+  // ConvertYCbCrToRGB et al. assume the chroma planes are rounded up if the
+  // luma plane is odd sized.
+  MOZ_ASSERT((aData.mCbCrSize.width == aData.mYSize.width ||
+              aData.mCbCrSize.width == (aData.mYSize.width + 1) >> 1) &&
+             (aData.mCbCrSize.height == aData.mYSize.height ||
+              aData.mCbCrSize.height == (aData.mYSize.height + 1) >> 1));
   gfx::YUVType yuvtype =
     gfx::TypeFromSize(aData.mYSize.width,
                       aData.mYSize.height,
                       aData.mCbCrSize.width,
                       aData.mCbCrSize.height);
 
   // Convert from YCbCr to RGB now, scaling the image if needed.
   if (aDestSize != aData.mPicSize) {
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -251,16 +251,17 @@ RasterImage::RasterImage(imgStatusTracke
 RasterImage::~RasterImage()
 {
   ScaleRequest::Stop(mScaleRequest.image);
 
   delete mAnim;
 
   for (unsigned int i = 0; i < mFrames.Length(); ++i)
     delete mFrames[i];
+  mFrames.Clear();
 
   // Discardable statistics
   if (mDiscardable) {
     num_discardable_containers--;
     discardable_source_bytes -= mSourceData.Length();
 
     PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG,
             ("CompressedImageAccounting: destroying RasterImage %p.  "
--- a/image/src/imgStatusTracker.cpp
+++ b/image/src/imgStatusTracker.cpp
@@ -47,34 +47,36 @@ NS_IMETHODIMP imgStatusTrackerObserver::
 /** imgIDecoderObserver methods **/
 
 NS_IMETHODIMP imgStatusTrackerObserver::OnStartDecode()
 {
   LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::OnStartDecode");
   NS_ABORT_IF_FALSE(mTracker->GetImage(),
                     "OnStartDecode callback before we've created our image");
 
-  if (!mTracker->GetRequest()->GetMultipart()) {
+  if (mTracker->GetRequest() && !mTracker->GetRequest()->GetMultipart()) {
     MOZ_ASSERT(!mTracker->mBlockingOnload);
     mTracker->mBlockingOnload = true;
 
     mTracker->RecordBlockOnload();
 
     nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
     while (iter.HasMore()) {
       mTracker->SendBlockOnload(iter.GetNext());
     }
   }
 
   /* In the case of streaming jpegs, it is possible to get multiple OnStartDecodes which
      indicates the beginning of a new decode.
      The cache entry's size therefore needs to be reset to 0 here.  If we do not do this,
      the code in imgStatusTrackerObserver::OnStopFrame will continue to increase the data size cumulatively.
   */
-  mTracker->GetRequest()->ResetCacheEntry();
+  if (mTracker->GetRequest()) {
+    mTracker->GetRequest()->ResetCacheEntry();
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP imgStatusTrackerObserver::OnStartRequest()
 {
   NS_NOTREACHED("imgRequest(imgIDecoderObserver)::OnStartRequest");
   return NS_OK;
@@ -151,32 +153,34 @@ FireFailureNotification(imgRequest* aReq
 NS_IMETHODIMP imgStatusTrackerObserver::OnStopDecode(nsresult aStatus)
 {
   LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::OnStopDecode");
   NS_ABORT_IF_FALSE(mTracker->GetImage(),
                     "OnStopDecode callback before we've created our image");
 
   // We finished the decode, and thus have the decoded frames. Update the cache
   // entry size to take this into account.
-  mTracker->GetRequest()->UpdateCacheEntrySize();
+  if (mTracker->GetRequest()) {
+    mTracker->GetRequest()->UpdateCacheEntrySize();
+  }
 
   bool preexistingError = mTracker->GetImageStatus() == imgIRequest::STATUS_ERROR;
 
   mTracker->RecordStopDecode(aStatus);
 
   nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
   while (iter.HasMore()) {
     mTracker->SendStopDecode(iter.GetNext(), aStatus);
   }
 
   // This is really hacky. We need to handle the case where we start decoding,
   // block onload, but then hit an error before we get to our first frame.
   mTracker->MaybeUnblockOnload();
 
-  if (NS_FAILED(aStatus) && !preexistingError) {
+  if (NS_FAILED(aStatus) && !preexistingError && mTracker->GetRequest()) {
     FireFailureNotification(mTracker->GetRequest());
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP imgStatusTrackerObserver::OnStopRequest(bool aLastPart)
 {
@@ -188,17 +192,19 @@ NS_IMETHODIMP imgStatusTrackerObserver::
 NS_IMETHODIMP imgStatusTrackerObserver::OnDiscard()
 {
   NS_ABORT_IF_FALSE(mTracker->GetImage(),
                     "OnDiscard callback before we've created our image");
 
   mTracker->RecordDiscard();
 
   // Update the cache entry size, since we just got rid of frame data
-  mTracker->GetRequest()->UpdateCacheEntrySize();
+  if (mTracker->GetRequest()) {
+    mTracker->GetRequest()->UpdateCacheEntrySize();
+  }
 
   nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
   while (iter.HasMore()) {
     mTracker->SendDiscard(iter.GetNext());
   }
 
   return NS_OK;
 }
@@ -697,17 +703,17 @@ imgStatusTracker::OnStopRequest(bool aLa
 
   RecordStopRequest(aLastPart, aStatus);
   /* notify the kids */
   nsTObserverArray<imgRequestProxy*>::ForwardIterator srIter(mConsumers);
   while (srIter.HasMore()) {
     SendStopRequest(srIter.GetNext(), aLastPart, aStatus);
   }
 
-  if (NS_FAILED(aStatus) && !preexistingError) {
+  if (NS_FAILED(aStatus) && !preexistingError && GetRequest()) {
     FireFailureNotification(GetRequest());
   }
 }
 
 void
 imgStatusTracker::OnDataAvailable()
 {
   // Notify any imgRequestProxys that are observing us that we have an Image.
--- a/intl/unicharutil/util/nsUnicharUtils.cpp
+++ b/intl/unicharutil/util/nsUnicharUtils.cpp
@@ -31,27 +31,27 @@ static const uint8_t gASCIIToLower [128]
 #define IS_ASCII_UPPER(u) (('A' <= (u)) && ((u) <= 'Z'))
 #define IS_ASCII_LOWER(u) (('a' <= (u)) && ((u) <= 'z'))
 #define IS_ASCII_ALPHA(u) (IS_ASCII_UPPER(u) || IS_ASCII_LOWER(u))
 #define IS_ASCII_SPACE(u) (' ' == (u))
 
 // We want ToLowerCase(uint32_t) and ToLowerCaseASCII(uint32_t) to be fast
 // when they're called from within the case-insensitive comparators, so we
 // define inlined versions.
-static MOZ_ALWAYS_INLINE uint32_t
+static NS_ALWAYS_INLINE uint32_t
 ToLowerCase_inline(uint32_t aChar)
 {
   if (IS_ASCII(aChar)) {
     return gASCIIToLower[aChar];
   }
 
   return mozilla::unicode::GetLowercase(aChar);
 }
 
-static MOZ_ALWAYS_INLINE uint32_t
+static NS_ALWAYS_INLINE uint32_t
 ToLowerCaseASCII_inline(const uint32_t aChar)
 {
   if (IS_ASCII(aChar)) {
     return gASCIIToLower[aChar];
   }
 
   return aChar;
 }
@@ -266,17 +266,17 @@ CaseInsensitiveCompare(const PRUnichar *
 
 // Calculates the codepoint of the UTF8 sequence starting at aStr.  Sets aNext
 // to the byte following the end of the sequence.
 //
 // If the sequence is invalid, or if computing the codepoint would take us off
 // the end of the string (as marked by aEnd), returns -1 and does not set
 // aNext.  Note that this function doesn't check that aStr < aEnd -- it assumes
 // you've done that already.
-static MOZ_ALWAYS_INLINE uint32_t
+static NS_ALWAYS_INLINE uint32_t
 GetLowerUTF8Codepoint(const char* aStr, const char* aEnd, const char **aNext)
 {
   // Convert to unsigned char so that stuffing chars into PRUint32s doesn't
   // sign extend.
   const unsigned char *str = (unsigned char*)aStr;
 
   if (UTF8traits::isASCII(str[0])) {
     // It's ASCII; just convert to lower-case and return it.
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -119,24 +119,18 @@ OS_CONFIG	:= $(OS_ARCH)$(OS_RELEASE)
 FINAL_LINK_LIBS = $(DEPTH)/config/final-link-libs
 FINAL_LINK_COMPS = $(DEPTH)/config/final-link-comps
 FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names
 
 MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
 MOZ_WIDGET_SUPPORT_LIBS    = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
 
 ifdef _MSC_VER
-ifdef .PYMAKE
-PYCOMMANDPATH += $(topsrcdir)/build
-CC_WRAPPER ?= %cl InvokeClWithDependencyGeneration
-CXX_WRAPPER ?= %cl InvokeClWithDependencyGeneration
-else
 CC_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
 CXX_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
-endif # .PYMAKE
 endif # _MSC_VER
 
 CC := $(CC_WRAPPER) $(CC)
 CXX := $(CXX_WRAPPER) $(CXX)
 MKDIR ?= mkdir
 SLEEP ?= sleep
 TOUCH ?= touch
 
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -3089,16 +3089,23 @@ if test "$MALLOC_H" != ""; then
    AC_DEFINE_UNQUOTED(MALLOC_H, <$MALLOC_H>)
 fi
 
 MOZ_ALLOCATING_FUNCS="strndup posix_memalign memalign valloc"
 AC_CHECK_FUNCS(strndup posix_memalign memalign valloc)
 
 dnl See if compiler supports some gcc-style attributes
 
+AC_CACHE_CHECK(for __attribute__((always_inline)),
+               ac_cv_attribute_always_inline,
+               [AC_TRY_COMPILE([inline void f(void) __attribute__((always_inline));],
+                               [],
+                               ac_cv_attribute_always_inline=yes,
+                               ac_cv_attribute_always_inline=no)])
+
 AC_CACHE_CHECK(for __attribute__((malloc)),
                ac_cv_attribute_malloc,
                [AC_TRY_COMPILE([void* f(int) __attribute__((malloc));],
                                [],
                                ac_cv_attribute_malloc=yes,
                                ac_cv_attribute_malloc=no)])
 
 AC_CACHE_CHECK(for __attribute__((warn_unused_result)),
@@ -3140,16 +3147,22 @@ fi
 
 dnl Mozilla specific options
 dnl ========================================================
 dnl The macros used for command line options
 dnl are defined in build/autoconf/altoptions.m4.
 
 dnl If the compiler supports these attributes, define them as
 dnl convenience macros.
+if test "$ac_cv_attribute_always_inline" = yes ; then
+  AC_DEFINE(NS_ALWAYS_INLINE, [__attribute__((always_inline))])
+else
+  AC_DEFINE(NS_ALWAYS_INLINE,)
+fi
+
 if test "$ac_cv_attribute_malloc" = yes ; then
   AC_DEFINE(NS_ATTR_MALLOC, [__attribute__((malloc))])
 else
   AC_DEFINE(NS_ATTR_MALLOC,)
 fi
 
 if test "$ac_cv_attribute_warn_unused" = yes ; then
   AC_DEFINE(NS_WARN_UNUSED_RESULT, [__attribute__((warn_unused_result))])
--- a/js/src/ion/arm/MacroAssembler-arm.cpp
+++ b/js/src/ion/arm/MacroAssembler-arm.cpp
@@ -1347,17 +1347,17 @@ bool
 MacroAssemblerARMCompat::buildOOLFakeExitFrame(void *fakeReturnAddr)
 {
     DebugOnly<uint32> initialDepth = framePushed();
     uint32 descriptor = MakeFrameDescriptor(framePushed(), IonFrame_JS);
 
     Push(Imm32(descriptor)); // descriptor_
 
     enterNoPool();
-    push(Imm32((uint32) fakeReturnAddr));
+    Push(Imm32((uint32) fakeReturnAddr));
     leaveNoPool();
 
     return true;
 }
 
 void
 MacroAssemblerARMCompat::callWithExitFrame(IonCode *target)
 {
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -657,19 +657,16 @@ js::FunctionToString(JSContext *cx, Hand
         JS_ASSERT_IF(!funCon, src->length() > 0 && chars[0] == '(');
 
         // If a function inherits strict mode by having scopes above it that
         // have "use strict", we insert "use strict" into the body of the
         // function. This ensures that if the result of toString is evaled, the
         // resulting function will have the same semantics.
         bool addUseStrict = script->strictModeCode && !script->explicitUseStrict;
 
-        // Functions created with the constructor can't have inherited strict
-        // mode.
-        JS_ASSERT(!funCon || !addUseStrict);
         bool buildBody = funCon && !bodyOnly;
         if (buildBody) {
             // This function was created with the Function constructor. We don't
             // have source for the arguments, so we have to generate that. Part
             // of bug 755821 should be cobbling the arguments passed into the
             // Function constructor into the source string.
             if (!out.append("("))
                 return NULL;
@@ -687,20 +684,27 @@ js::FunctionToString(JSContext *cx, Hand
                 }
             }
             if (!out.append(") {\n"))
                 return NULL;
         }
         if ((bodyOnly && !funCon) || addUseStrict) {
             // We need to get at the body either because we're only supposed to
             // return the body or we need to insert "use strict" into the body.
-            JS_ASSERT(!buildBody);
-            size_t bodyStart = 0, bodyEnd = 0;
-            if (!FindBody(cx, fun, chars, src->length(), &bodyStart, &bodyEnd))
-                return NULL;
+            size_t bodyStart = 0, bodyEnd;
+
+            // If the function is defined in the Function constructor, we
+            // already have a body.
+            if (!funCon) {
+                JS_ASSERT(!buildBody);
+                if (!FindBody(cx, fun, chars, src->length(), &bodyStart, &bodyEnd))
+                    return NULL;
+            } else {
+                bodyEnd = src->length();
+            }
 
             if (addUseStrict) {
                 // Output source up to beginning of body.
                 if (!out.append(chars, bodyStart))
                     return NULL;
                 if (exprBody) {
                     // We can't insert a statement into a function with an
                     // expression body. Do what the decompiler did, and insert a
@@ -710,17 +714,17 @@ js::FunctionToString(JSContext *cx, Hand
                 } else {
                     if (!out.append("\n\"use strict\";\n"))
                         return NULL;
                 }
             }
 
             // Output just the body (for bodyOnly) or the body and possibly
             // closing braces (for addUseStrict).
-            size_t dependentEnd = (bodyOnly) ? bodyEnd : src->length();
+            size_t dependentEnd = bodyOnly ? bodyEnd : src->length();
             if (!out.append(chars + bodyStart, dependentEnd - bodyStart))
                 return NULL;
         } else {
             if (!out.append(src))
                 return NULL;
         }
         if (buildBody) {
             if (!out.append("\n}"))
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -2362,35 +2362,33 @@ bool
 Proxy::hasOwn(JSContext *cx, JSObject *proxy_, jsid id, bool *bp)
 {
     JS_CHECK_RECURSION(cx, return false);
     RootedObject proxy(cx, proxy_);
     return GetProxyHandler(proxy)->hasOwn(cx, proxy, id, bp);
 }
 
 bool
-Proxy::get(JSContext *cx, HandleObject proxy_, HandleObject receiver, HandleId id,
+Proxy::get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
            MutableHandleValue vp)
 {
     JS_CHECK_RECURSION(cx, return false);
-    RootedObject proxy(cx, proxy_);
     BaseProxyHandler *handler = GetProxyHandler(proxy);
     bool own = false;
     if (!handler->hasPrototype() || (handler->hasOwn(cx, proxy, id, &own) && own))
         return handler->get(cx, proxy, receiver, id, vp.address());
     INVOKE_ON_PROTOTYPE(cx, handler, proxy, JSObject::getGeneric(cx, proto, receiver, id, vp));
 }
 
 bool
-Proxy::getElementIfPresent(JSContext *cx, HandleObject proxy_, HandleObject receiver, uint32_t index,
+Proxy::getElementIfPresent(JSContext *cx, HandleObject proxy, HandleObject receiver, uint32_t index,
                            MutableHandleValue vp, bool *present)
 {
     JS_CHECK_RECURSION(cx, return false);
 
-    RootedObject proxy(cx, proxy_);
     BaseProxyHandler *handler = GetProxyHandler(proxy);
 
     if (!handler->hasPrototype()) {
         return GetProxyHandler(proxy)->getElementIfPresent(cx, proxy, receiver, index,
                                                            vp.address(), present);
     }
 
     RootedId id(cx);
@@ -2406,21 +2404,20 @@ Proxy::getElementIfPresent(JSContext *cx
         return GetProxyHandler(proxy)->get(cx, proxy, receiver, id, vp.address());
     }
 
     INVOKE_ON_PROTOTYPE(cx, handler, proxy,
                         JSObject::getElementIfPresent(cx, proto, receiver, index, vp, present));
 }
 
 bool
-Proxy::set(JSContext *cx, HandleObject proxy_, HandleObject receiver, HandleId id, bool strict,
+Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id, bool strict,
            MutableHandleValue vp)
 {
     JS_CHECK_RECURSION(cx, return false);
-    RootedObject proxy(cx, proxy_);
     BaseProxyHandler *handler = GetProxyHandler(proxy);
     RootedObject proto(cx);
     if (handler->hasPrototype()) {
         // If we're using a prototype, we still want to use the proxy trap unless
         // we have a non-own property with a setter.
         bool hasOwn;
         AutoPropertyDescriptorRooter desc(cx);
         if (handler->hasOwn(cx, proxy, id, &hasOwn) && !hasOwn &&
@@ -2440,20 +2437,19 @@ bool
 Proxy::keys(JSContext *cx, JSObject *proxy_, AutoIdVector &props)
 {
     JS_CHECK_RECURSION(cx, return false);
     RootedObject proxy(cx, proxy_);
     return GetProxyHandler(proxy)->keys(cx, proxy, props);
 }
 
 bool
-Proxy::iterate(JSContext *cx, HandleObject proxy_, unsigned flags, MutableHandleValue vp)
+Proxy::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp)
 {
     JS_CHECK_RECURSION(cx, return false);
-    RootedObject proxy(cx, proxy_);
     BaseProxyHandler *handler = GetProxyHandler(proxy);
     if (!handler->hasPrototype())
         return GetProxyHandler(proxy)->iterate(cx, proxy, flags, vp.address());
     AutoIdVector props(cx);
     // The other Proxy::foo methods do the prototype-aware work for us here.
     if ((flags & JSITER_OWNONLY)
         ? !Proxy::keys(cx, proxy, props)
         : !Proxy::enumerate(cx, proxy, props)) {
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/extensions/strict-function-toSource.js
@@ -0,0 +1,17 @@
+/*
+ * Bug 800407 - Functions defined with Function construcor
+ * do have strict mode when JSOPTION_STRICT_MODE is on.
+ */
+
+options("strict_mode");
+function testRunOptionStrictMode(str, arg, result) {
+    var strict_inner = new Function('return typeof this == "undefined";');
+    return strict_inner;
+}
+assertEq(eval(uneval(testRunOptionStrictMode()))(), true);
+
+if (typeof decompileBody !== "undefined") {
+    assertEq(decompileBody(new Function('x', 'return x*2;')).contains('\n"use strict"'), true);
+}
+
+reportCompare(true, true);
--- a/js/src/tests/js1_5/extensions/regress-406572.js
+++ b/js/src/tests/js1_5/extensions/regress-406572.js
@@ -1,44 +1,37 @@
-// |reftest| skip
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 406572;
 var summary = 'JSOP_CLOSURE unconditionally replaces properties of the variable object - Browser only';
 var actual = '';
 var expect = '';
 
 printBugNumber(BUGNUMBER);
 printStatus (summary);
 
 if (typeof window != 'undefined')
 {
-  try
-  {
-    expect = 'TypeError: redeclaration of const document';
-    var d = document;
+  var d = document;
 
-    d.writeln(uneval(document));
-    document = 1;
-    d.writeln(uneval(document));
+  d.writeln(uneval(document));
+  document = 1;
+  d.writeln(uneval(document));
 
-    if (1) 
-      function document() { return 1; }
+  if (1)
+    function document() { return 1; }
 
-    d.writeln(uneval(document));
-  }
-  catch(ex)
-  {
-    actual = ex + '';
-    print(actual);
-  }
+  d.writeln(uneval(document));
+
+  // The test harness relies on document having its original value: restore it.
+  document = d;
 }
 else
 {
   expect = actual = 'Test can only run in a Gecko 1.9 browser or later.';
   print(actual);
 }
 reportCompare(expect, actual, summary);
 
old mode 100644
new mode 100755
--- a/js/xpconnect/src/dombindings.cpp
+++ b/js/xpconnect/src/dombindings.cpp
@@ -33,18 +33,16 @@ enum {
 };
 
 static jsid s_prototype_id = JSID_VOID;
 
 static jsid s_length_id = JSID_VOID;
 
 static jsid s_iterator_id = JSID_VOID;
 
-static jsid s_VOID_id = JSID_VOID;
-
 bool
 DefineStaticJSVal(JSContext *cx, jsid &id, const char *string)
 {
     if (JSString *str = ::JS_InternString(cx, string)) {
         id = INTERNED_STRING_TO_JSID(cx, str);
         return true;
     }
     return false;
@@ -131,24 +129,24 @@ bool
 Unwrap(JSContext *cx, jsval v, NoType **ppArg, nsISupports **ppArgRef, jsval *vp)
 {
     NS_RUNTIMEABORT("We try to unwrap an argument for a noop?");
     return false;
 }
 
 template<class LC>
 typename ListBase<LC>::Properties ListBase<LC>::sProtoProperties[] = {
-    { s_VOID_id, NULL, NULL }
+    { JSID_VOID, NULL, NULL }
 };
 template<class LC>
 size_t ListBase<LC>::sProtoPropertiesCount = 0;
 
 template<class LC>
 typename ListBase<LC>::Methods ListBase<LC>::sProtoMethods[] = {
-    { s_VOID_id, NULL, 0 }
+    { JSID_VOID, NULL, 0 }
 };
 template<class LC>
 size_t ListBase<LC>::sProtoMethodsCount = 0;
 
 template<class LC>
 ListBase<LC> ListBase<LC>::instance;
 
 template<class LC>
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -34,115 +34,86 @@
 //#define DEBUG_DISPLAY_ITEM_DATA
 #endif
 
 using namespace mozilla::layers;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 
-FrameLayerBuilder::DisplayItemData::DisplayItemData(LayerManagerData* aParent, nsIFrame* aFrame, uint32_t aKey, 
+FrameLayerBuilder::DisplayItemData::DisplayItemData(LayerManagerData* aParent, uint32_t aKey, 
                                                     Layer* aLayer, LayerState aLayerState, uint32_t aGeneration)
 
   : mParent(aParent)
   , mLayer(aLayer)
   , mDisplayItemKey(aKey)
   , mContainerLayerGeneration(aGeneration)
   , mLayerState(aLayerState)
-  , mUsed(false)
-  , mCopiedInto(nullptr)
+  , mUsed(true)
 {
-  AddFrame(aFrame);
 }
 
 FrameLayerBuilder::DisplayItemData::DisplayItemData(DisplayItemData &toCopy)
 {
   // This isn't actually a copy-constructor; notice that it steals toCopy's
   // mGeometry pointer.  Be careful.
   mParent = toCopy.mParent;
   mLayer = toCopy.mLayer;
   mInactiveManager = toCopy.mInactiveManager;
   mFrameList = toCopy.mFrameList;
   mGeometry = toCopy.mGeometry;
   mDisplayItemKey = toCopy.mDisplayItemKey;
   mClip = toCopy.mClip;
   mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
   mLayerState = toCopy.mLayerState;
   mUsed = toCopy.mUsed;
-  mCopiedInto = toCopy.mCopiedInto;
+}
+
+void
+FrameLayerBuilder::DisplayItemData::AddFrame(nsIFrame* aFrame)
+{
+  mFrameList.AppendElement(aFrame);
+
+  nsTArray<DisplayItemData*> *array = 
+    reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty()));
+  if (!array) {
+    array = new nsTArray<DisplayItemData*>();
+    aFrame->Properties().Set(FrameLayerBuilder::LayerManagerDataProperty(), array);
+  }
+  array->AppendElement(this);
 }
 
 void
-FrameLayerBuilder::DisplayItemData::CopyInto(DisplayItemData* aOther)
+FrameLayerBuilder::DisplayItemData::UpdateContents(Layer* aLayer, LayerState aState, uint32_t aContainerLayerGeneration)
 {
-  if (mCopiedInto) {
-    NS_ASSERTION(mCopiedInto == aOther, "Can't copy a single DisplayItemData into multiple places!");
-    return;
-  }
-  NS_ABORT_IF_FALSE(mParent == aOther->mParent, "Must be a matching display item to copy!");
-  aOther->mLayer = mLayer;
-  aOther->mOptLayer = mOptLayer;
-  aOther->mInactiveManager = mInactiveManager;
-  NS_ABORT_IF_FALSE(mDisplayItemKey == aOther->mDisplayItemKey, "Must be a matching display item to copy!");
-  NS_ABORT_IF_FALSE(FrameListMatches(aOther), "Must be a matching display item to copy!");
-  mFrameList.Clear();
-  aOther->mGeometry = mGeometry;
-  aOther->mClip = mClip;
-  aOther->mLayerState = mLayerState;
-  aOther->mUsed = false;
-  mCopiedInto = aOther;
+  mLayer = aLayer;
+  mOptLayer = nullptr;
+  mInactiveManager = nullptr;
+  mLayerState = aState;
+  mContainerLayerGeneration = aContainerLayerGeneration;
+  mGeometry = nullptr;
+  mClip.mHaveClipRect = false;
+  mClip.mRoundedClipRects.Clear();
+  mUsed = true;
 }
 
-void
-FrameLayerBuilder::DisplayItemData::RemoveFrameData(nsIFrame* aSkip /* = nullptr */)
+static nsIFrame* sDestroyedFrame = NULL;
+FrameLayerBuilder::DisplayItemData::~DisplayItemData()
 {
   for (uint32_t i = 0; i < mFrameList.Length(); i++) {
     nsIFrame* frame = mFrameList[i];
-    if (frame == aSkip) {
+    if (frame == sDestroyedFrame) {
       continue;
     }
     nsTArray<DisplayItemData*> *array = 
       reinterpret_cast<nsTArray<DisplayItemData*>*>(frame->Properties().Get(LayerManagerDataProperty()));
     array->RemoveElement(this);
   }
 }
 
-static nsIFrame* sDestroyedFrame = NULL;
-FrameLayerBuilder::DisplayItemData::~DisplayItemData()
-{
-#ifdef DEBUG
-  /* TODO: Sanity check that we've removed our reference from all frames in mFrameList */
-  for (uint32_t i = 0; i < mFrameList.Length(); i++) {
-    if (mFrameList[i] == sDestroyedFrame) {
-      continue;
-    }
-    nsTArray<DisplayItemData*> *array = 
-      reinterpret_cast<nsTArray<DisplayItemData*>*>(mFrameList[i]->Properties().Get(LayerManagerDataProperty()));
-    if (!array) {
-      continue;
-    }
-
-    NS_ABORT_IF_FALSE(!array->Contains(this), "Must have removed ourselves from the frames!");
-  }
-#endif
-}
-
-bool
-FrameLayerBuilder::DisplayItemData::FrameListMatches(DisplayItemData* aOther)
-{
-  nsAutoTArray<nsIFrame*, 4> copy = mFrameList;
-  for (uint32_t i = 0; i < aOther->mFrameList.Length(); ++i) {
-    if (!copy.RemoveElement(aOther->mFrameList[i])) {
-      return false;
-    }
-  }
-
-  return copy.IsEmpty();
-}
-
 bool
 FrameLayerBuilder::DisplayItemData::FrameListMatches(nsDisplayItem* aOther)
 {
   nsAutoTArray<nsIFrame*, 4> copy = mFrameList;
   if (!copy.RemoveElement(aOther->GetUnderlyingFrame())) {
     return false;
   }
 
@@ -159,28 +130,26 @@ FrameLayerBuilder::DisplayItemData::Fram
 
 /**
  * This is the userdata we associate with a layer manager.
  */
 class LayerManagerData : public LayerUserData {
 public:
   LayerManagerData(LayerManager *aManager)
     : mLayerManager(aManager)
+#ifdef DEBUG_DISPLAY_ITEM_DATA
     , mParent(nullptr)
+#endif
     , mInvalidateAllLayers(false)
   {
     MOZ_COUNT_CTOR(LayerManagerData);
     mDisplayItems.Init();
   }
   ~LayerManagerData() {
     MOZ_COUNT_DTOR(LayerManagerData);
-    // Remove display item data properties now, since we won't be able
-    // to find these frames again without mFramesWithLayers.
-    mDisplayItems.EnumerateEntries(
-        FrameLayerBuilder::RemoveDisplayItemDataForFrame, nullptr);
   }
  
 #ifdef DEBUG_DISPLAY_ITEM_DATA
   void Dump(const char *aPrefix = "") {
     printf("%sLayerManagerData %p\n", aPrefix, this);
     nsAutoCString prefix;
     prefix += aPrefix;
     prefix += "  ";
@@ -188,17 +157,19 @@ public:
         FrameLayerBuilder::DumpDisplayItemDataForFrame, (void*)prefix.get());
   }
 #endif
 
   /**
    * Tracks which frames have layers associated with them.
    */
   LayerManager *mLayerManager;
+#ifdef DEBUG_DISPLAY_ITEM_DATA
   LayerManagerData *mParent;
+#endif
   nsTHashtable<nsRefPtrHashKey<FrameLayerBuilder::DisplayItemData> > mDisplayItems;
   bool mInvalidateAllLayers;
 };
 
 /* static */ void
 FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame)
 {
   FrameProperties props = aFrame->Properties();
@@ -236,17 +207,17 @@ public:
     mLayerBuilder(aLayerBuilder),
     mContainerFrame(aContainerFrame),
     mContainerLayer(aContainerLayer),
     mParameters(aParameters),
     mNextFreeRecycledThebesLayer(0)
   {
     nsPresContext* presContext = aContainerFrame->PresContext();
     mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
-    mContainerReferenceFrame = aContainerItem ? aContainerItem->ReferenceFrame() :
+    mContainerReferenceFrame = aContainerItem ? aContainerItem->ReferenceFrameForChildren() :
       mBuilder->FindReferenceFrameFor(mContainerFrame);
     // When AllowResidualTranslation is false, display items will be drawn
     // scaled with a translation by integer pixels, so we know how the snapping
     // will work.
     mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() &&
       !mParameters.AllowResidualTranslation();
     mRecycledMaskImageLayers.Init();
     CollectOldLayers();
@@ -822,16 +793,31 @@ InvalidatePostTransformRegion(ThebesLaye
   aLayer->InvalidateRegion(rgn);
 #ifdef DEBUG_INVALIDATIONS
   nsAutoCString str;
   AppendToString(str, rgn);
   printf("Invalidating layer %p: %s\n", aLayer, str.get());
 #endif
 }
 
+static void
+InvalidatePostTransformRegion(ThebesLayer* aLayer, const nsRect& aRect, 
+                              const FrameLayerBuilder::Clip& aClip,
+                              const nsIntPoint& aTranslation)
+{
+  ThebesDisplayItemLayerUserData* data =
+      static_cast<ThebesDisplayItemLayerUserData*>(aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
+
+  nsRect rect = aClip.ApplyNonRoundedIntersection(aRect);
+
+  nsIntRect pixelRect = rect.ScaleToOutsidePixels(data->mXScale, data->mYScale, data->mAppUnitsPerDevPixel);
+  InvalidatePostTransformRegion(aLayer, pixelRect, aTranslation);
+}
+
+
 static nsIntPoint
 GetTranslationForThebesLayer(ThebesLayer* aLayer)
 {
   ThebesDisplayItemLayerUserData* data = 
     static_cast<ThebesDisplayItemLayerUserData*>
       (aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
   NS_ASSERTION(data, "Must be a tracked thebes layer!");
 
@@ -842,17 +828,17 @@ GetTranslationForThebesLayer(ThebesLayer
  * Some frames can have multiple, nested, retaining layer managers
  * associated with them (normal manager, inactive managers, SVG effects).
  * In these cases we store the 'outermost' LayerManager data property
  * on the frame since we can walk down the chain from there.
  *
  * If one of these frames has just been destroyed, we will free the inner
  * layer manager when removing the entry from mFramesWithLayers. Destroying
  * the layer manager destroys the LayerManagerData and calls into 
- * RemoveDisplayItemDataForFrame. If the inner layer manager had any
+ * the DisplayItemData destructor. If the inner layer manager had any
  * items with the same frame, then we attempt to retrieve properties
  * from the deleted frame.
  *
  * Cache the destroyed frame pointer here so we can avoid crashing in this case.
  */
 
 /* static */ void
 FrameLayerBuilder::RemoveFrameFromLayerManager(nsIFrame* aFrame,
@@ -890,17 +876,16 @@ FrameLayerBuilder::RemoveFrameFromLayerM
       if (thebesData) {
         nsRegion old = data->mGeometry->ComputeInvalidationRegion();
         nsIntRegion rgn = old.ScaleToOutsidePixels(thebesData->mXScale, thebesData->mYScale, thebesData->mAppUnitsPerDevPixel);
         rgn.MoveBy(-GetTranslationForThebesLayer(t));
         thebesData->mRegionToInvalidate.Or(thebesData->mRegionToInvalidate, rgn);
       }
     }
 
-    data->RemoveFrameData(aFrame);
     data->mParent->mDisplayItems.RemoveEntry(data);
   }
 
   arrayCopy.Clear();
   delete array;
   sDestroyedFrame = NULL;
 }
 
@@ -914,24 +899,25 @@ FrameLayerBuilder::DidBeginRetainedLayer
     mInvalidateAllLayers = data->mInvalidateAllLayers;
   } else {
     data = new LayerManagerData(aManager);
     aManager->SetUserData(&gLayerManagerUserData, data);
   }
 }
 
 void
-FrameLayerBuilder::StoreOptimizedLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey, Layer* aImage)
+FrameLayerBuilder::StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer)
 {
-  DisplayItemKey key(aFrame, aDisplayItemKey);
-  DisplayItemHashData *entry = mNewDisplayItemData.GetEntry(key);
-  if (!entry)
+  if (!mRetainingManager) {
     return;
-
-  entry->mData->mOptLayer = aImage;
+  }
+
+  DisplayItemData* data = GetDisplayItemDataForManager(aItem, aLayer->Manager());
+  NS_ASSERTION(data, "Must have already stored data for this item!");
+  data->mOptLayer = aLayer;
 }
 
 void
 FrameLayerBuilder::DidEndTransaction()
 {
   GetMaskLayerImageCache()->Sweep();
 }
 
@@ -942,22 +928,17 @@ FrameLayerBuilder::WillEndTransaction()
     return;
   }
 
   // We need to save the data we'll need to support retaining.
   LayerManagerData* data = static_cast<LayerManagerData*>
     (mRetainingManager->GetUserData(&gLayerManagerUserData));
   NS_ASSERTION(data, "Must have data!");
   // Update all the frames that used to have layers.
-  data->mDisplayItems.EnumerateEntries(UpdateDisplayItemDataForFrame, this);
-  
-  // Now go through all the frames that didn't have any retained
-  // display items before, and record those retained display items.
-  // This also empties mNewDisplayItemData.
-  mNewDisplayItemData.EnumerateEntries(StoreNewDisplayItemData, data);
+  data->mDisplayItems.EnumerateEntries(UpdateDisplayItemDataForFrame, nullptr);
   data->mInvalidateAllLayers = false;
 }
 
 struct ProcessRemovedDisplayItemsData
 {
   ProcessRemovedDisplayItemsData(Layer* aLayer, FrameLayerBuilder* aLayerBuilder)
     : mLayer(aLayer)
     , mLayerBuilder(aLayerBuilder)
@@ -978,69 +959,39 @@ FrameLayerBuilder::ProcessRemovedDisplay
   FrameLayerBuilder* layerBuilder = userData->mLayerBuilder;
 
   DisplayItemData* item = aEntry->GetKey();
   ThebesLayer* t = item->mLayer->AsThebesLayer();
   if (!item->mUsed && t && (t == layer)) {
 #ifdef DEBUG_INVALIDATIONS
     printf("Invalidating unused display item (%i) belonging to frame %p from layer %p\n", item->mDisplayItemKey, item->mFrameList[0], t);
 #endif
-    ThebesDisplayItemLayerUserData* data =
-        static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
-    InvalidatePostTransformRegion(t,
-        item->mGeometry->ComputeInvalidationRegion().
-          ScaleToOutsidePixels(data->mXScale, data->mYScale, data->mAppUnitsPerDevPixel),
-        layerBuilder->GetLastPaintOffset(t));
+    InvalidatePostTransformRegion(t, 
+                                  item->mGeometry->ComputeInvalidationRegion(), 
+                                  item->mClip, 
+                                  layerBuilder->GetLastPaintOffset(t));
   }
   return PL_DHASH_NEXT;
 }
 
 /* static */ PLDHashOperator
 FrameLayerBuilder::UpdateDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                                  void* aUserArg)
 {
-  FrameLayerBuilder* builder = static_cast<FrameLayerBuilder*>(aUserArg);
   DisplayItemData* data = aEntry->GetKey();
-  DisplayItemKey key(data->mFrameList[0], data->mDisplayItemKey);
-
-  DisplayItemHashData* newDisplayItems =
-    builder ? builder->mNewDisplayItemData.GetEntry(key) : nullptr;
-
-  if (!newDisplayItems || !newDisplayItems->mData->FrameListMatches(data)) {
+  if (!data->mUsed) {
     // This item was visible, but isn't anymore.
-
-    // Go through all frames on the DisplayItemData, and then remove ourselves from that frame.
-    data->RemoveFrameData();
     return PL_DHASH_REMOVE;
   }
 
-  // Our frame(s) already have a pointer to the current DisplayItemData, so
-  // copy the contents of the new into it rather than replacing it.
-  newDisplayItems->mData->CopyInto(data);
-  // Don't need to process this frame again
-  builder->mNewDisplayItemData.RawRemoveEntry(newDisplayItems);
-  for (uint32_t i = 1; i < data->mFrameList.Length(); i++) {
-    key.mFrame = data->mFrameList[i];
-    builder->mNewDisplayItemData.RemoveEntry(key);
-  }
+  data->mUsed = false;
   return PL_DHASH_NEXT;
 }
   
 /* static */ PLDHashOperator 
-FrameLayerBuilder::RemoveDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry,
-                                                 void* aClosure)
-{
-  DisplayItemData* data = aEntry->GetKey();
-  // If this was called from a frame destructor then the prop is definitely already gone,
-  // and we could crash trying to check. See the definition of sDestroyedFrame.
-  data->RemoveFrameData(sDestroyedFrame);
-  return PL_DHASH_REMOVE;
-}
-
-/* static */ PLDHashOperator 
 FrameLayerBuilder::DumpDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                                void* aClosure)
 {
 #ifdef DEBUG_DISPLAY_ITEM_DATA
   DisplayItemData *data = aEntry->GetKey();
 
   nsAutoCString prefix;
   prefix += static_cast<const char*>(aClosure);
@@ -1086,36 +1037,16 @@ FrameLayerBuilder::DumpDisplayItemDataFo
     LayerManagerData* lmd = static_cast<LayerManagerData*>
       (data->mInactiveManager->GetUserData(&gLayerManagerUserData));
     lmd->Dump(prefix.get());
   }
 #endif
   return PL_DHASH_NEXT;
 }
 
-/* static */ PLDHashOperator
-FrameLayerBuilder::StoreNewDisplayItemData(DisplayItemHashData* aEntry,
-                                           void* aUserArg)
-{
-  LayerManagerData* data = static_cast<LayerManagerData*>(aUserArg);
-  const DisplayItemKey& key = aEntry->GetKey();
-
-  // Remember that this frame has display items in retained layers
-  data->mDisplayItems.PutEntry(aEntry->mData);
-
-  nsTArray<DisplayItemData*> *array = 
-    reinterpret_cast<nsTArray<DisplayItemData*>*>(key.mFrame->Properties().Get(LayerManagerDataProperty()));
-  if (!array) {
-    array = new nsTArray<DisplayItemData*>();
-    key.mFrame->Properties().Set(LayerManagerDataProperty(), array);
-  }
-  array->AppendElement(aEntry->mData);
-  return PL_DHASH_REMOVE;
-}
-
 /* static */ FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem, 
                                                 LayerManager* aManager)
 {
   nsTArray<DisplayItemData*> *array = 
     reinterpret_cast<nsTArray<DisplayItemData*>*>(aItem->GetUnderlyingFrame()->Properties().Get(LayerManagerDataProperty()));
   if (array) {
     for (uint32_t i = 0; i < array->Length(); i++) {
@@ -1344,17 +1275,18 @@ ContainerState::CreateOrRecycleThebesLay
     // final layer tree, so it's a convenient time to invalidate the
     // content that changed where we don't know what ThebesLayer it belonged
     // to, or if we need to invalidate the entire layer, we can do that.
     // This needs to be done before we update the ThebesLayer to its new
     // transform. See nsGfxScrollFrame::InvalidateInternal, where
     // we ensure that mInvalidThebesContent is updated according to the
     // scroll position as of the most recent paint.
     if (!FuzzyEqual(data->mXScale, mParameters.mXScale, 0.00001) ||
-        !FuzzyEqual(data->mYScale, mParameters.mYScale, 0.00001)) {
+        !FuzzyEqual(data->mYScale, mParameters.mYScale, 0.00001) ||
+        data->mAppUnitsPerDevPixel != mAppUnitsPerDevPixel) {
       InvalidateEntireThebesLayer(layer, aActiveScrolledRoot);
       didResetScrollPositionForLayerPixelAlignment = true;
     }
     if (!data->mRegionToInvalidate.IsEmpty()) {
 #ifdef DEBUG_INVALIDATIONS
       printf("Invalidating deleted frame content from layer %p\n", layer.get());
 #endif
       layer->InvalidateRegion(data->mRegionToInvalidate);
@@ -1420,17 +1352,17 @@ ContainerState::CreateOrRecycleThebesLay
   } else if (didResetScrollPositionForLayerPixelAlignment) {
     data->mActiveScrolledRootPosition = activeScrolledRootTopLeft;
   }
 #endif
 
   return layer.forget();
 }
 
-#ifdef DEBUG
+#ifdef MOZ_DUMP_PAINTING
 /**
  * Returns the appunits per dev pixel for the item's frame. The item must
  * have a frame because only nsDisplayClip items don't have a frame,
  * and those items are flattened away by ProcessDisplayItems.
  */
 static int32_t
 AppUnitsPerDevPixel(nsDisplayItem* aItem)
 {
@@ -1562,18 +1494,17 @@ ContainerState::PopThebesLayerData()
       imageLayer->SetPostScale(mParameters.mXScale,
                                mParameters.mYScale);
       if (data->mItemClip.mHaveClipRect) {
         nsIntRect clip = ScaleToNearestPixels(data->mItemClip.mClipRect);
         clip.MoveBy(mParameters.mOffset);
         imageLayer->IntersectClipRect(clip);
       }
       layer = imageLayer;
-      mLayerBuilder->StoreOptimizedLayerForFrame(data->mImage->GetUnderlyingFrame(), 
-                                                 data->mImage->GetPerFrameKey(),
+      mLayerBuilder->StoreOptimizedLayerForFrame(data->mImage,
                                                  imageLayer);
     } else {
       nsRefPtr<ColorLayer> colorLayer = CreateOrRecycleColorLayer(data->mLayer);
       colorLayer->SetIsFixedPosition(data->mLayer->GetIsFixedPosition());
       colorLayer->SetColor(data->mSolidColor);
 
       // Copy transform
       colorLayer->SetBaseTransform(data->mLayer->GetBaseTransform());
@@ -2065,32 +1996,39 @@ ContainerState::ProcessDisplayItems(cons
           layerState == LAYER_ACTIVE))) {
 
       // LAYER_ACTIVE_EMPTY means the layer is created just for its metadata.
       // We should never see an empty layer with any visible content!
       NS_ASSERTION(layerState != LAYER_ACTIVE_EMPTY ||
                    itemVisibleRect.IsEmpty(),
                    "State is LAYER_ACTIVE_EMPTY but visible rect is not.");
 
+      // As long as the new layer isn't going to be a ThebesLayer, 
+      // InvalidateForLayerChange doesn't need the new layer pointer.
+      // We also need to check the old data now, because BuildLayer
+      // can overwrite it.
+      InvalidateForLayerChange(item, nullptr, aClip, topLeft, geometry);
+
       // If the item would have its own layer but is invisible, just hide it.
       // Note that items without their own layers can't be skipped this
       // way, since their ThebesLayer may decide it wants to draw them
       // into its buffer even if they're currently covered.
       if (itemVisibleRect.IsEmpty() && layerState != LAYER_ACTIVE_EMPTY) {
-        InvalidateForLayerChange(item, nullptr, aClip, topLeft, geometry);
         continue;
       }
 
       // Just use its layer.
       nsRefPtr<Layer> ownLayer = item->BuildLayer(mBuilder, mManager, mParameters);
       if (!ownLayer) {
-        InvalidateForLayerChange(item, ownLayer, aClip, topLeft, geometry);
         continue;
       }
 
+      NS_ASSERTION(!ownLayer->AsThebesLayer(), 
+                   "Should never have created a dedicated Thebes layer!");
+
       nsRect invalid;
       if (item->IsInvalid(invalid)) {
         ownLayer->SetInvalidRectToVisibleRegion();
       }
 
       // If it's not a ContainerLayer, we need to apply the scale transform
       // ourselves.
       if (!ownLayer->AsContainerLayer()) {
@@ -2135,18 +2073,16 @@ ContainerState::ProcessDisplayItems(cons
 
       ContainerLayer* oldContainer = ownLayer->GetParent();
       if (oldContainer && oldContainer != mContainerLayer) {
         oldContainer->RemoveChild(ownLayer);
       }
       NS_ASSERTION(!mNewChildLayers.Contains(ownLayer),
                    "Layer already in list???");
 
-      InvalidateForLayerChange(item, ownLayer, aClip, topLeft, geometry);
-
       mNewChildLayers.AppendElement(ownLayer);
       mLayerBuilder->AddLayerDisplayItem(ownLayer, item, 
                                          aClip, layerState, 
                                          topLeft, nullptr,
                                          geometry);
     } else {
       ThebesLayerData* data =
         FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, aClip,
@@ -2163,16 +2099,47 @@ ContainerState::ProcessDisplayItems(cons
 
       // check to see if the new item has rounded rect clips in common with
       // other items in the layer
       data->UpdateCommonClipCount(aClip);
     }
   }
 }
 
+/**
+ * Combine two clips and returns true if clipping
+ * needs to be applied.
+ *
+ * @param aClip Current clip
+ * @param aOldClip Optional clip from previous paint.
+ * @param aShift Offet to apply to aOldClip
+ * @param aCombined Outparam - Computed clip region
+ * @return True if the clip should be applied, false
+ *         otherwise.
+ */
+static bool ComputeCombinedClip(const FrameLayerBuilder::Clip& aClip,
+                                FrameLayerBuilder::Clip* aOldClip,
+                                const nsPoint& aShift,
+                                nsRegion& aCombined)
+{
+  if (!aClip.mHaveClipRect ||
+      (aOldClip && !aOldClip->mHaveClipRect)) {
+    return false;
+  }
+
+  if (aOldClip) {
+    aCombined = aOldClip->NonRoundedIntersection();
+    aCombined.MoveBy(aShift);
+    aCombined.Or(aCombined, aClip.NonRoundedIntersection());
+  } else {
+    aCombined = aClip.NonRoundedIntersection();
+  }
+  return true;
+}
+
 void
 ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, 
                                          Layer* aNewLayer,
                                          const FrameLayerBuilder::Clip& aClip,
                                          const nsPoint& aTopLeft,
                                          nsDisplayItemGeometry *aGeometry)
 {
   NS_ASSERTION(aItem->GetUnderlyingFrame(),
@@ -2188,31 +2155,27 @@ ContainerState::InvalidateForLayerChange
     ThebesLayer* t = oldLayer->AsThebesLayer();
     if (t) {
       // Note that whenever the layer's scale changes, we invalidate the whole thing,
       // so it doesn't matter whether we are using the old scale at last paint
       // or a new scale here
 #ifdef DEBUG_INVALIDATIONS
       printf("Display item type %s(%p) changed layers %p to %p!\n", aItem->Name(), aItem->GetUnderlyingFrame(), t, aNewLayer);
 #endif
-      ThebesDisplayItemLayerUserData* data =
-          static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
       InvalidatePostTransformRegion(t,
-          oldGeometry->ComputeInvalidationRegion().
-            ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
+          oldGeometry->ComputeInvalidationRegion(),
+          *oldClip,
           mLayerBuilder->GetLastPaintOffset(t));
     }
     if (aNewLayer) {
       ThebesLayer* newThebesLayer = aNewLayer->AsThebesLayer();
       if (newThebesLayer) {
-        ThebesDisplayItemLayerUserData* data =
-            static_cast<ThebesDisplayItemLayerUserData*>(newThebesLayer->GetUserData(&gThebesDisplayItemLayerUserData));
         InvalidatePostTransformRegion(newThebesLayer,
-            aGeometry->ComputeInvalidationRegion().
-              ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
+            aGeometry->ComputeInvalidationRegion(),
+            aClip,
             GetTranslationForThebesLayer(newThebesLayer));
       }
     }
     return;
   } 
   if (!aNewLayer) {
     return;
   }
@@ -2224,41 +2187,49 @@ ContainerState::InvalidateForLayerChange
 
   ThebesDisplayItemLayerUserData* data =
     static_cast<ThebesDisplayItemLayerUserData*>(newThebesLayer->GetUserData(&gThebesDisplayItemLayerUserData));
   // If the frame is marked as invalidated, and didn't specify a rect to invalidate  then we want to 
   // invalidate both the old and new bounds, otherwise we only want to invalidate the changed areas.
   // If we do get an invalid rect, then we want to add this on top of the change areas.
   nsRect invalid;
   nsRegion combined;
+  nsPoint shift = aTopLeft - data->mLastActiveScrolledRootOrigin;
   if (!oldLayer) {
     // This item is being added for the first time, invalidate its entire area.
     //TODO: We call GetGeometry again in AddThebesDisplayItem, we should reuse this.
-    combined = aGeometry->ComputeInvalidationRegion();
+    combined = aClip.ApplyNonRoundedIntersection(aGeometry->ComputeInvalidationRegion());
 #ifdef DEBUG_INVALIDATIONS
     printf("Display item type %s(%p) added to layer %p!\n", aItem->Name(), aItem->GetUnderlyingFrame(), aNewLayer);
 #endif
   } else if (aItem->IsInvalid(invalid) && invalid.IsEmpty()) {
     // Either layout marked item as needing repainting, invalidate the entire old and new areas.
-    combined.Or(aGeometry->ComputeInvalidationRegion(), oldGeometry->ComputeInvalidationRegion());
+    combined = oldClip->ApplyNonRoundedIntersection(oldGeometry->ComputeInvalidationRegion());
+    combined.MoveBy(shift);
+    combined.Or(combined, aClip.ApplyNonRoundedIntersection(aGeometry->ComputeInvalidationRegion()));
 #ifdef DEBUG_INVALIDATIONS
     printf("Display item type %s(%p) (in layer %p) belongs to an invalidated frame!\n", aItem->Name(), aItem->GetUnderlyingFrame(), aNewLayer);
 #endif
   } else {
     // Let the display item check for geometry changes and decide what needs to be
     // repainted.
-    nsPoint shift = aTopLeft - data->mLastActiveScrolledRootOrigin;
     oldGeometry->MoveBy(shift);
     aItem->ComputeInvalidationRegion(mBuilder, oldGeometry, &combined);
     oldClip->AddOffsetAndComputeDifference(shift, oldGeometry->ComputeInvalidationRegion(),
                                            aClip, aGeometry->ComputeInvalidationRegion(),
                                            &combined);
 
     // Add in any rect that the frame specified
-    combined = combined.Or(combined, invalid);
+    combined.Or(combined, invalid);
+
+    // Restrict invalidation to the clipped region
+    nsRegion clip;
+    if (ComputeCombinedClip(aClip, oldClip, shift, clip)) {
+      combined.And(combined, clip);
+    }
 #ifdef DEBUG_INVALIDATIONS
     if (!combined.IsEmpty()) {
       printf("Display item type %s(%p) (in layer %p) changed geometry!\n", aItem->Name(), aItem->GetUnderlyingFrame(), aNewLayer);
     }
 #endif
   }
   if (!combined.IsEmpty()) {
     InvalidatePostTransformRegion(newThebesLayer,
@@ -2298,25 +2269,43 @@ void
 FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
                                         nsDisplayItem* aItem,
                                         const Clip& aClip,
                                         nsIFrame* aContainerLayerFrame,
                                         LayerState aLayerState,
                                         const nsPoint& aTopLeft,
                                         nsAutoPtr<nsDisplayItemGeometry> aGeometry)
 {
+  ThebesDisplayItemLayerUserData* thebesData =
+    static_cast<ThebesDisplayItemLayerUserData*>(aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
   nsRefPtr<LayerManager> tempManager;
+  nsIntRect intClip;
+  bool hasClip = false;
   if (aLayerState != LAYER_NONE) {
     DisplayItemData *data = GetDisplayItemDataForManager(aItem, aLayer->Manager());
     if (data) {
       tempManager = data->mInactiveManager;
     }
     if (!tempManager) {
       tempManager = new BasicLayerManager();
     }
+        
+    // We need to grab these before calling AddLayerDisplayItem because it will overwrite them.
+    nsRegion clip;
+    FrameLayerBuilder::Clip* oldClip = nullptr;
+    GetOldLayerFor(aItem, nullptr, &oldClip);
+    hasClip = ComputeCombinedClip(aClip, oldClip, 
+                                  aTopLeft - thebesData->mLastActiveScrolledRootOrigin,
+                                  clip);
+
+    if (hasClip) {
+      intClip = clip.GetBounds().ScaleToOutsidePixels(thebesData->mXScale, 
+                                                      thebesData->mYScale, 
+                                                      thebesData->mAppUnitsPerDevPixel);
+    }
   }
 
   AddLayerDisplayItem(aLayer, aItem, aClip, aLayerState, aTopLeft, tempManager, aGeometry);
 
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
   if (entry) {
     entry->mContainerLayerFrame = aContainerLayerFrame;
     if (entry->mContainerLayerGeneration == 0) {
@@ -2341,81 +2330,108 @@ FrameLayerBuilder::AddThebesDisplayItem(
         tempManager->EndTransaction(nullptr, nullptr);
         tempManager->SetUserData(&gLayerManagerLayerBuilder, nullptr);
         return;
       }
 
       // If BuildLayer didn't call BuildContainerLayerFor, then our new layer won't have been
       // stored in layerBuilder. Manually add it now.
       if (mRetainingManager) {
+#ifdef DEBUG_DISPLAY_ITEM_DATA
         LayerManagerData* parentLmd = static_cast<LayerManagerData*>
           (aLayer->Manager()->GetUserData(&gLayerManagerUserData));
         LayerManagerData* lmd = static_cast<LayerManagerData*>
           (tempManager->GetUserData(&gLayerManagerUserData));
         lmd->mParent = parentLmd;
-        nsRefPtr<DisplayItemData> data = 
-          new DisplayItemData(lmd, aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey(), 
-                              layer, LAYER_ACTIVE, mContainerLayerGeneration);
-        layerBuilder->StoreDataForFrame(aItem, data);
+#endif
+        layerBuilder->StoreDataForFrame(aItem, layer, LAYER_ACTIVE);
       }
 
       tempManager->SetRoot(layer);
       layerBuilder->WillEndTransaction();
 
       nsIntPoint offset = GetLastPaintOffset(aLayer) - GetTranslationForThebesLayer(aLayer);
       props->MoveBy(-offset);
       nsIntRect invalid = props->ComputeDifferences(layer, nullptr);
       if (aLayerState == LAYER_SVG_EFFECTS) {
         invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem->GetUnderlyingFrame(), invalid);
       }
       if (!invalid.IsEmpty()) {
 #ifdef DEBUG_INVALIDATIONS
         printf("Inactive LayerManager(%p) for display item %s(%p) has an invalid region - invalidating layer %p\n", tempManager.get(), aItem->Name(), aItem->GetUnderlyingFrame(), aLayer);
 #endif
-        ThebesDisplayItemLayerUserData* data =
-          static_cast<ThebesDisplayItemLayerUserData*>(aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
-        invalid.ScaleRoundOut(data->mXScale, data->mYScale);
+        if (hasClip) {
+          invalid = invalid.Intersect(intClip);
+        }
+
+        invalid.ScaleRoundOut(thebesData->mXScale, thebesData->mYScale);
         InvalidatePostTransformRegion(aLayer, invalid,
                                       GetTranslationForThebesLayer(aLayer));
       }
     }
     ClippedDisplayItem* cdi =
       entry->mItems.AppendElement(ClippedDisplayItem(aItem, aClip,
                                                      mContainerLayerGeneration));
     cdi->mInactiveLayer = tempManager;
   }
 }
 
-void
-FrameLayerBuilder::StoreDataForFrame(nsDisplayItem* aItem, DisplayItemData* aData)
+FrameLayerBuilder::DisplayItemData*
+FrameLayerBuilder::StoreDataForFrame(nsDisplayItem* aItem, Layer* aLayer, LayerState aState)
 {
-  DisplayItemKey key(aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey());
-  DisplayItemHashData *entry = mNewDisplayItemData.GetEntry(key);
-  if (entry) {
-    return;
-  }
-  entry = mNewDisplayItemData.PutEntry(key);
-  if (entry) {
-    entry->mData = aData;
-    entry->mContainerLayerGeneration = mContainerLayerGeneration;
+  DisplayItemData* oldData = GetDisplayItemDataForManager(aItem, mRetainingManager);
+  if (oldData) {
+    if (!oldData->mUsed) {
+      oldData->UpdateContents(aLayer, aState, mContainerLayerGeneration);
+    }
+    return oldData;
   }
   
+  LayerManagerData* lmd = static_cast<LayerManagerData*>
+    (mRetainingManager->GetUserData(&gLayerManagerUserData));
+  
+  nsRefPtr<DisplayItemData> data = 
+    new DisplayItemData(lmd, aItem->GetPerFrameKey(),
+                        aLayer, aState, mContainerLayerGeneration);
+
+  data->AddFrame(aItem->GetUnderlyingFrame());
+
   nsAutoTArray<nsIFrame*,4> mergedFrames;
   aItem->GetMergedFrames(&mergedFrames);
 
   for (uint32_t i = 0; i < mergedFrames.Length(); ++i) {
-    nsIFrame* mergedFrame = mergedFrames[i];
-    DisplayItemKey key(mergedFrame, aItem->GetPerFrameKey());
-    entry = mNewDisplayItemData.PutEntry(key);
-    if (entry) {
-      entry->mData = aData;
-      entry->mContainerLayerGeneration = mContainerLayerGeneration;
-      aData->AddFrame(mergedFrame);
-    }
+    data->AddFrame(mergedFrames[i]);
   }
+
+  lmd->mDisplayItems.PutEntry(data);
+  return data;
+}
+
+void
+FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame,
+                                     uint32_t aDisplayItemKey,
+                                     Layer* aLayer,
+                                     LayerState aState)
+{
+  DisplayItemData* oldData = GetDisplayItemData(aFrame, aDisplayItemKey);
+  if (oldData && oldData->mFrameList.Length() == 1) {
+    oldData->UpdateContents(aLayer, aState, mContainerLayerGeneration);
+    return;
+  }
+  
+  LayerManagerData* lmd = static_cast<LayerManagerData*>
+    (mRetainingManager->GetUserData(&gLayerManagerUserData));
+
+  nsRefPtr<DisplayItemData> data =
+    new DisplayItemData(lmd, aDisplayItemKey, aLayer,
+                        aState, mContainerLayerGeneration);
+
+  data->AddFrame(aFrame);
+
+  lmd->mDisplayItems.PutEntry(data);
 }
 
 FrameLayerBuilder::ClippedDisplayItem::~ClippedDisplayItem()
 {
   if (mInactiveLayer) {
     // We always start a transaction during layer construction for all inactive
     // layers, but we don't necessarily call EndTransaction during painting.
     // If the transaaction is still open, end it to avoid assertions.
@@ -2434,35 +2450,23 @@ FrameLayerBuilder::AddLayerDisplayItem(L
                                        LayerState aLayerState,
                                        const nsPoint& aTopLeft,
                                        LayerManager* aManager,
                                        nsAutoPtr<nsDisplayItemGeometry> aGeometry)
 {
   if (aLayer->Manager() != mRetainingManager)
     return;
 
-  LayerManagerData* lmd = static_cast<LayerManagerData*>
-    (aLayer->Manager()->GetUserData(&gLayerManagerUserData));
-  nsRefPtr<DisplayItemData> data = 
-    new DisplayItemData(lmd, aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey(), 
-                        aLayer, aLayerState, mContainerLayerGeneration);
-    
+  DisplayItemData *data = StoreDataForFrame(aItem, aLayer, aLayerState);
   ThebesLayer *t = aLayer->AsThebesLayer();
   if (t) {
     data->mGeometry = aGeometry;
     data->mClip = aClip;
   }
   data->mInactiveManager = aManager;
-
-  StoreDataForFrame(aItem, data);
-
-  DisplayItemData* oldData = GetDisplayItemDataForManager(aItem, mRetainingManager);
-  if (oldData) {
-    oldData->mUsed = true;
-  }
 }
 
 nsIntPoint
 FrameLayerBuilder::GetLastPaintOffset(ThebesLayer* aLayer)
 {
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
   if (entry) {
     if (entry->mContainerLayerGeneration == 0) {
@@ -2674,33 +2678,37 @@ ChooseScaleAndSetTransform(FrameLayerBui
   }
   if (isRetained && (!canDraw2D || transform2d.HasNonIntegerTranslation())) {
     result.mDisableSubpixelAntialiasingInDescendants = true;
   }
   return result;
 }
 
 /* static */ PLDHashOperator
-FrameLayerBuilder::RestoreDisplayItemData(DisplayItemHashData* aEntry, void* aUserArg)
+FrameLayerBuilder::RestoreDisplayItemData(nsRefPtrHashKey<DisplayItemData>* aEntry, void* aUserArg)
 {
+  DisplayItemData* data = aEntry->GetKey();
   uint32_t *generation = static_cast<uint32_t*>(aUserArg);
 
-  if (aEntry->mContainerLayerGeneration >= *generation) {
+  if (data->mUsed && data->mContainerLayerGeneration >= *generation) {
     return PL_DHASH_REMOVE;
   }
 
   return PL_DHASH_NEXT;
 }
 
 /* static */ PLDHashOperator
 FrameLayerBuilder::RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry, void* aUserArg)
 {
   uint32_t *generation = static_cast<uint32_t*>(aUserArg);
 
   if (aEntry->mContainerLayerGeneration >= *generation) {
+    // We can just remove these items rather than attempting to revert them
+    // because we're going to want to invalidate everything when transitioning
+    // to component alpha flattening.
     return PL_DHASH_REMOVE;
   }
 
   for (uint32_t i = 0; i < aEntry->mItems.Length(); i++) {
     if (aEntry->mItems[i].mContainerLayerGeneration >= *generation) {
       aEntry->mItems.TruncateLength(i);
       return PL_DHASH_NEXT;
     }
@@ -2720,20 +2728,16 @@ FrameLayerBuilder::BuildContainerLayerFo
 {
   uint32_t containerDisplayItemKey =
     aContainerItem ? aContainerItem->GetPerFrameKey() : 0;
   NS_ASSERTION(aContainerFrame, "Container display items here should have a frame");
   NS_ASSERTION(!aContainerItem ||
                aContainerItem->GetUnderlyingFrame() == aContainerFrame,
                "Container display item must match given frame");
 
-  
-  LayerManagerData* data = static_cast<LayerManagerData*>
-    (aManager->GetUserData(&gLayerManagerUserData));
-
   nsRefPtr<ContainerLayer> containerLayer;
   if (aManager == mRetainingManager) {
     // Using GetOldLayerFor will search merged frames, as well as the underlying
     // frame. The underlying frame can change when a page scrolls, so this
     // avoids layer recreation in the situation that a new underlying frame is
     // picked for a layer.
     Layer* oldLayer = nullptr;
     if (aContainerItem) {
@@ -2783,42 +2787,25 @@ FrameLayerBuilder::BuildContainerLayerFo
     ChooseScaleAndSetTransform(this, aBuilder, aContainerFrame, aTransform, aParameters,
                                containerLayer, state);
 
   uint32_t oldGeneration = mContainerLayerGeneration;
   mContainerLayerGeneration = ++mMaxContainerLayerGeneration;
 
   nsRefPtr<RefCountedRegion> thebesLayerInvalidRegion = nullptr;
   if (mRetainingManager) {
-    nsRefPtr<DisplayItemData> did =
-      new DisplayItemData(data, aContainerFrame, containerDisplayItemKey, containerLayer,
-                          LAYER_ACTIVE, mContainerLayerGeneration);
-
-    DisplayItemKey key(aContainerFrame, containerDisplayItemKey);
-    DisplayItemHashData* entry = mNewDisplayItemData.PutEntry(key);
-    if (entry) {
-      entry->mData = did;
-      entry->mContainerLayerGeneration = mContainerLayerGeneration;
-    }
-  
-    nsAutoTArray<nsIFrame*,4> mergedFrames;
     if (aContainerItem) {
-      aContainerItem->GetMergedFrames(&mergedFrames);
-    }
-    for (uint32_t i = 0; i < mergedFrames.Length(); ++i) {
-      nsIFrame* mergedFrame = mergedFrames[i];
-      DisplayItemKey key(mergedFrame, containerDisplayItemKey);
-      DisplayItemHashData* mergedEntry = mNewDisplayItemData.PutEntry(key);
-      if (mergedEntry) {
-        mergedEntry->mData = did;
-        mergedEntry->mContainerLayerGeneration = mContainerLayerGeneration;
-        did->AddFrame(mergedFrame);
-      }
+      StoreDataForFrame(aContainerItem, containerLayer, LAYER_ACTIVE);
+    } else {
+      StoreDataForFrame(aContainerFrame, containerDisplayItemKey, containerLayer, LAYER_ACTIVE);
     }
   }
+  
+  LayerManagerData* data = static_cast<LayerManagerData*>
+    (aManager->GetUserData(&gLayerManagerUserData));
 
   nsRect bounds;
   nsIntRect pixBounds;
   int32_t appUnitsPerDevPixel;
   uint32_t stateFlags =
     (aContainerFrame->GetStateBits() & NS_FRAME_NO_COMPONENT_ALPHA) ?
       ContainerState::NO_COMPONENT_ALPHA : 0;
   uint32_t flags;
@@ -2842,17 +2829,17 @@ FrameLayerBuilder::BuildContainerLayerFo
         mRetainingManager &&
         !mRetainingManager->AreComponentAlphaLayersEnabled() &&
         !stateFlags) {
       // Since we don't want any component alpha layers on BasicLayers, we repeat
       // the layer building process with this explicitely forced off.
       // We restore the previous FrameLayerBuilder state since the first set
       // of layer building will have changed it.
       stateFlags = ContainerState::NO_COMPONENT_ALPHA;
-      mNewDisplayItemData.EnumerateEntries(RestoreDisplayItemData,
+      data->mDisplayItems.EnumerateEntries(RestoreDisplayItemData,
                                            &mContainerLayerGeneration);
       mThebesLayerItems.EnumerateEntries(RestoreThebesLayerItemEntries,
                                          &mContainerLayerGeneration);
       aContainerFrame->AddStateBits(NS_FRAME_NO_COMPONENT_ALPHA);
       continue;
     }
     break;
   }
@@ -2927,22 +2914,26 @@ FrameLayerBuilder::GetDedicatedLayer(nsI
   //TODO: This isn't completely correct, since a frame could exist as a layer
   // in the normal widget manager, and as a different layer (or no layer)
   // in the secondary manager
 
   nsTArray<DisplayItemData*> *array = 
     reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(LayerManagerDataProperty()));
   if (array) {
     for (uint32_t i = 0; i < array->Length(); i++) {
-      if (array->ElementAt(i)->mDisplayItemKey == aDisplayItemKey) {
-        if (array->ElementAt(i)->mOptLayer) {
-          return array->ElementAt(i)->mOptLayer;
+      DisplayItemData *element = array->ElementAt(i);
+      if (!element->mParent->mLayerManager->IsWidgetLayerManager()) {
+        continue;
+      }
+      if (element->mDisplayItemKey == aDisplayItemKey) {
+        if (element->mOptLayer) {
+          return element->mOptLayer;
         }
 
-        Layer* layer = array->ElementAt(i)->mLayer;
+        Layer* layer = element->mLayer;
         if (!layer->HasUserData(&gColorLayerUserData) &&
             !layer->HasUserData(&gImageLayerUserData) &&
             !layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
           return layer;
         }
       }
     }
   }
@@ -3439,24 +3430,40 @@ FrameLayerBuilder::Clip::IsRectClippedBy
     }
   }
   return false;
 }
 
 nsRect
 FrameLayerBuilder::Clip::NonRoundedIntersection() const
 {
+  NS_ASSERTION(mHaveClipRect, "Must have a clip rect!");
   nsRect result = mClipRect;
   for (uint32_t i = 0, iEnd = mRoundedClipRects.Length();
        i < iEnd; ++i) {
     result.IntersectRect(result, mRoundedClipRects[i].mRect);
   }
   return result;
 }
 
+nsRect
+FrameLayerBuilder::Clip::ApplyNonRoundedIntersection(const nsRect& aRect) const
+{
+  if (!mHaveClipRect) {
+    return aRect;
+  }
+
+  nsRect result = aRect.Intersect(mClipRect);
+  for (uint32_t i = 0, iEnd = mRoundedClipRects.Length();
+       i < iEnd; ++i) {
+    result.Intersect(mRoundedClipRects[i].mRect);
+  }
+  return result;
+}
+
 void
 FrameLayerBuilder::Clip::RemoveRoundedCorners()
 {
   if (mRoundedClipRects.IsEmpty())
     return;
 
   mClipRect = NonRoundedIntersection();
   mRoundedClipRects.Clear();
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -100,17 +100,16 @@ public:
   FrameLayerBuilder() :
     mRetainingManager(nullptr),
     mDetectedDOMModification(false),
     mInvalidateAllLayers(false),
     mContainerLayerGeneration(0),
     mMaxContainerLayerGeneration(0)
   {
     MOZ_COUNT_CTOR(FrameLayerBuilder);
-    mNewDisplayItemData.Init();
     mThebesLayerItems.Init();
   }
   ~FrameLayerBuilder()
   {
     MOZ_COUNT_DTOR(FrameLayerBuilder);
   }
 
   static void Shutdown();
@@ -357,17 +356,17 @@ public:
   static gfxSize GetThebesLayerScaleForFrame(nsIFrame* aFrame);
 
   /**
    * Stores a Layer as the dedicated layer in the DisplayItemData for a given frame/key pair.
    *
    * Used when we optimize a ThebesLayer into an ImageLayer and want to retroactively update the 
    * DisplayItemData so we can retrieve the layer from within layout.
    */
-  void StoreOptimizedLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey, Layer* aImage);
+  void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer);
 
   /**
    * Clip represents the intersection of an optional rectangle with a
    * list of rounded rectangles.
    */
   struct Clip {
     struct RoundedRect {
       nsRect mRect;
@@ -433,16 +432,20 @@ public:
     // this clip. Returns true if aRect is clipped by a rounded corner in this
     // clip or it can not be quickly determined that it is not clipped by a
     // rounded corner in this clip.
     bool IsRectClippedByRoundedCorner(const nsRect& aRect) const;
 
     // Intersection of all rects in this clip ignoring any rounded corners.
     nsRect NonRoundedIntersection() const;
 
+    // Intersect the given rects with all rects in this clip, ignoring any
+    // rounded corners.
+    nsRect ApplyNonRoundedIntersection(const nsRect& aRect) const;
+
     // Gets rid of any rounded corners in this clip.
     void RemoveRoundedCorners();
 
     // Adds the difference between Intersect(*this + aPoint, aBounds) and
     // Intersect(aOther, aOtherBounds) to aDifference.
     void AddOffsetAndComputeDifference(const nsPoint& aPoint, const nsRect& aBounds,
                                        const Clip& aOther, const nsRect& aOtherBounds,
                                        nsRegion* aDifference);
@@ -462,139 +465,72 @@ public:
 
 protected:
   /**
    * Retained data storage:
    *
    * Each layer manager (widget, and inactive) stores a LayerManagerData object
    * that keeps a hash-set of DisplayItemData items that were drawn into it.
    * Each frame also keeps a list of DisplayItemData pointers that were
-   * created for that frame.
-   *
-   * During layer construction we build a hashtable of DisplayItemHashData items, keyed
-   * using (frame,display item key). Since some display items can be associated with multiple
-   * frames (because of merging), multiple entries in this hashtable can refer to the same
-   * DisplayItemData.
+   * created for that frame. DisplayItemData objects manage these lists automatically.
    *
-   * Once layer building is complete, we sync the new items into the retained storage and update
-   * any frames that have changed lists.
-   */
-
-  /**
-   * nsIFrame/display item 'per frame key' pair used to key  our hashtable of DisplayItemHashData items.
+   * During layer construction we update the data in the LayerManagerData object, marking
+   * items that are modified. At the end we sweep the LayerManagerData hash-set and remove
+   * all items that haven't been modified.
    */
-  class DisplayItemKey {
-  public:
-    DisplayItemKey(nsIFrame* aFrame, uint32_t aKey)
-      : mFrame(aFrame)
-      , mKey(aKey)
-    { }
-
-    bool operator==(const DisplayItemKey& aOther) const {
-      return mFrame == aOther.mFrame &&
-             mKey == aOther.mKey;
-    }
-
-    nsIFrame* mFrame;
-    uint32_t mKey;
-  };
 
   /**
    * Retained data for a display item.
    */
   class DisplayItemData {
   public:
 
-    DisplayItemData(LayerManagerData* aParent, nsIFrame* aFrame, uint32_t aKey, Layer* aLayer, LayerState aLayerState, uint32_t aGeneration);
+    DisplayItemData(LayerManagerData* aParent, uint32_t aKey, Layer* aLayer, LayerState aLayerState, uint32_t aGeneration);
     DisplayItemData(DisplayItemData &toCopy);
+
+    /**
+     * Removes any references to this object from frames
+     * in mFrameList.
+     */
     ~DisplayItemData();
 
     NS_INLINE_DECL_REFCOUNTING(DisplayItemData)
 
-    void AddFrame(nsIFrame* aFrame)
-    {
-      mFrameList.AppendElement(aFrame);
-    }
-
-    /** 
-     * Check for this item stored under the LayerManagerDataProperty
-     * for every frame in mFrameList and remove it.
-     * Optionally skips aSkip
+    /**
+     * Associates this DisplayItemData with a frame, and adds it
+     * to the LayerManagerDataProperty list on the frame.
      */
-    void RemoveFrameData(nsIFrame* aSkip = nullptr);
-
+    void AddFrame(nsIFrame* aFrame);
     bool FrameListMatches(nsDisplayItem* aOther);
-    bool FrameListMatches(DisplayItemData* aOther);
 
     /**
-     * Copies the contents of this item into aDest and
-     * leaves this item invalid.
+     * Updates the contents of this item to a new set of data, instead of allocating a new
+     * object.
+     * Set the passed in parameters, and clears the opt layer, inactive manager, geometry
+     * and clip.
+     * Parent, frame list and display item key are assumed to be the same.
      */
-    void CopyInto(DisplayItemData* aDest);
+    void UpdateContents(Layer* aLayer, LayerState aState, uint32_t aContainerLayerGeneration);
 
     LayerManagerData* mParent;
     nsRefPtr<Layer> mLayer;
     nsRefPtr<Layer> mOptLayer;
     nsRefPtr<LayerManager> mInactiveManager;
     nsAutoTArray<nsIFrame*, 1> mFrameList;
     nsAutoPtr<nsDisplayItemGeometry> mGeometry;
     Clip            mClip;
     uint32_t        mDisplayItemKey;
     uint32_t        mContainerLayerGeneration;
     LayerState      mLayerState;
 
     /**
      * Used to track if data currently stored in mFramesWithLayers (from an existing
-     * paint) is also used in the current paint and has an equivalent data object
-     * in mNewDisplayItemData.
+     * paint) has been updated in the current paint.
      */
     bool            mUsed;
-    DisplayItemData *mCopiedInto;
-  };
-
-  /**
-   * Hashtable entry wrapping a DisplayItemData.
-   * 
-   * Implemented as a separate class so that we can have multiple entries
-   * for a single DisplayItemData (in the case of merged display items).
-   */
-  class DisplayItemHashData : public PLDHashEntryHdr {
-  public:
-    typedef const DisplayItemKey& KeyType;
-    typedef const DisplayItemKey* KeyTypePointer;
-
-    DisplayItemHashData(KeyTypePointer aKey)
-      : mKey(*aKey)
-      , mContainerLayerGeneration(0)
-    { }
-    DisplayItemHashData(DisplayItemHashData &toCopy)
-      : mKey(toCopy.mKey)
-      , mData(toCopy.mData)
-      , mContainerLayerGeneration(toCopy.mContainerLayerGeneration)
-    { 
-      toCopy.mData = nullptr;
-    }
-
-    KeyType GetKey() const { 
-      return mKey; 
-    }
-    bool KeyEquals(KeyTypePointer aKey) const { 
-      return *aKey == mKey; 
-    }
-    static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
-
-    static PLDHashNumber HashKey(const KeyTypePointer aKey) {
-      return mozilla::HashGeneric(aKey->mFrame, aKey->mKey);
-    }
-                                       
-    enum { ALLOW_MEMMOVE = false };
-
-    DisplayItemKey mKey;
-    nsRefPtr<DisplayItemData> mData;
-    uint32_t mContainerLayerGeneration;
   };
 
   friend class LayerManagerData;
 
   static void RemoveFrameFromLayerManager(nsIFrame* aFrame, void* aPropertyValue);
 
   /**
    * Given a frame and a display item key that uniquely identifies a
@@ -604,17 +540,21 @@ protected:
    * that renders many display items.
    */
   DisplayItemData* GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey);
 
   /**
    * Stores DisplayItemData associated with aFrame, stores the data in
    * mNewDisplayItemData.
    */
-  void StoreDataForFrame(nsDisplayItem* aItem, DisplayItemData* data);
+  DisplayItemData* StoreDataForFrame(nsDisplayItem* aItem, Layer* aLayer, LayerState aState);
+  void StoreDataForFrame(nsIFrame* aFrame,
+                         uint32_t aDisplayItemKey,
+                         Layer* aLayer,
+                         LayerState aState);
 
   // Flash the area within the context clip if paint flashing is enabled.
   static void FlashPaint(gfxContext *aContext);
 
   /*
    * Get the DisplayItemData array associated with this frame, or null if one
    * doesn't exist.
    *
@@ -632,24 +572,16 @@ protected:
                                                        LayerManager* aManager);
   static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, 
                                                        uint32_t aDisplayItemKey);
   static DisplayItemData* GetDisplayItemDataForManager(nsDisplayItem* aItem, LayerManager* aManager);
   static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, 
                                                        uint32_t aDisplayItemKey, 
                                                        LayerManagerData* aData);
 
-  /**
-   * A useful hashtable iteration function that removes the
-   * DisplayItemData property for the frame and returns PL_DHASH_REMOVE.
-   * aClosure is ignored.
-   */
-  static PLDHashOperator RemoveDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry,
-                                                       void* aClosure);
-
   static PLDHashOperator DumpDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                                      void* aClosure);
   /**
    * We store one of these for each display item associated with a
    * ThebesLayer, in a hashtable that maps each ThebesLayer to an array
    * of ClippedDisplayItems. (ThebesLayerItemsEntry is the hash entry
    * for that hashtable.)
    * These are only stored during the paint process, so that the
@@ -724,19 +656,17 @@ public:
                                                     void* aUserArg);
 protected:
   void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer,
                                                     bool aRemoveThebesItems,
                                                     bool aRemoveOwnerData);
 
   static PLDHashOperator UpdateDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                                        void* aUserArg);
-  static PLDHashOperator StoreNewDisplayItemData(DisplayItemHashData* aEntry,
-                                                 void* aUserArg);
-  static PLDHashOperator RestoreDisplayItemData(DisplayItemHashData* aEntry,
+  static PLDHashOperator RestoreDisplayItemData(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                                 void *aUserArg);
 
   static PLDHashOperator RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry,
                                                        void *aUserArg);
 
   /**
    * Returns true if the DOM has been modified since we started painting,
    * in which case we should bail out and not paint anymore. This should
@@ -754,21 +684,16 @@ protected:
    */
   nsRefPtr<nsRootPresContext>         mRootPresContext;
 
   /**
    * The display list builder being used.
    */
   nsDisplayListBuilder*               mDisplayListBuilder;
   /**
-   * A map from frames to a list of (display item key, layer) pairs that
-   * describes what layers various parts of the frame are assigned to.
-   */
-  nsTHashtable<DisplayItemHashData>  mNewDisplayItemData;
-  /**
    * A map from ThebesLayers to the list of display items (plus
    * clipping data) to be rendered in the layer.
    */
   nsTHashtable<ThebesLayerItemsEntry> mThebesLayerItems;
   /**
    * Saved generation counter so we can detect DOM changes.
    */
   uint32_t                            mInitialDOMGeneration;
--- a/layout/base/Makefile.in
+++ b/layout/base/Makefile.in
@@ -12,16 +12,17 @@ include $(DEPTH)/config/autoconf.mk
 
 TEST_DIRS += tests
 
 MODULE		= layout
 XPIDL_MODULE	= layout_base
 GRE_MODULE	= 1
 LIBRARY_NAME	= gkbase_s
 LIBXUL_LIBRARY	= 1
+FAIL_ON_WARNINGS = 1
 
 
 
 XPIDLSRCS	= \
 		nsIStyleSheetService.idl	\
 		$(NULL)
 
 EXPORTS_NAMESPACES = mozilla
@@ -37,17 +38,18 @@ EXPORTS		= \
 		nsChangeHint.h \
 		nsCompatibility.h \
 		nsDisplayItemTypes.h \
 		nsDisplayItemTypesList.h \
 		nsDisplayList.h \
 		nsDisplayListInvalidation.h \
 		nsFrameManager.h \
 		nsFrameManagerBase.h \
-		nsFrameIterator.h \
+		nsFrameTraversal.h \
+		nsIFrameTraversal.h \
 		nsILayoutDebugger.h \
 		nsILayoutHistoryState.h \
 		nsIPercentHeightObserver.h  \
 		nsIPresShell.h \
 		nsIReflowCallback.h \
 		nsLayoutUtils.h \
 		nsPresArena.h \
 		nsPresContext.h \
@@ -73,17 +75,17 @@ CPPSRCS		= \
 		nsCSSRenderingBorders.cpp \
 		nsCaret.cpp \
 		nsChildIterator.cpp \
 		nsCounterManager.cpp \
 		nsDisplayList.cpp \
 		nsDisplayListInvalidation.cpp \
 		nsDocumentViewer.cpp \
 		nsFrameManager.cpp \
-		nsFrameIterator.cpp \
+		nsFrameTraversal.cpp \
 		nsGenConList.cpp \
 		nsLayoutDebugger.cpp \
 		nsLayoutHistoryState.cpp \
 		nsLayoutUtils.cpp \
 		nsPresArena.cpp \
 		nsPresContext.cpp \
 		nsPresShell.cpp \
 		nsQuoteList.cpp \
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -2097,17 +2097,18 @@ bool nsBidiPresUtils::WriteLogicalToVisu
         NS_ASSERTION(src >= aSrc && src < aSrc + aSrcLength,
                      "logical index out of range");
         NS_ASSERTION(dest < aDest + aSrcLength, "visual index out of range");
         *(dest++) = *(src++);
       } while (--length);
     }
   }
 
-  NS_ASSERTION(dest - aDest == aSrcLength, "whole string not copied");
+  NS_ASSERTION(static_cast<uint32_t>(dest - aDest) == aSrcLength,
+               "whole string not copied");
   return true;
 }
 
 void nsBidiPresUtils::CopyLogicalToVisual(const nsAString& aSource,
                                           nsAString& aDest,
                                           nsBidiLevel aBaseDirection,
                                           bool aOverride)
 {
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -7990,40 +7990,75 @@ nsCSSFrameConstructor::CharacterDataChan
   }
 
   return rv;
 }
 
 NS_DECLARE_FRAME_PROPERTY(ChangeListProperty, nullptr)
 
 /**
- * Return true if aFrame's subtree has placeholders for abs-pos or fixed-pos
- * content.
+ * Return true if aFrame's subtree has placeholders for out-of-flow content
+ * whose 'position' style's bit in aPositionMask is set.
  */
 static bool
-FrameHasAbsPosPlaceholderDescendants(nsIFrame* aFrame)
+FrameHasPositionedPlaceholderDescendants(nsIFrame* aFrame, uint32_t aPositionMask)
 {
   const nsIFrame::ChildListIDs skip(nsIFrame::kAbsoluteList |
                                     nsIFrame::kFixedList);
   for (nsIFrame::ChildListIterator lists(aFrame); !lists.IsDone(); lists.Next()) {
     if (!skip.Contains(lists.CurrentID())) {
       for (nsFrameList::Enumerator childFrames(lists.CurrentList());
            !childFrames.AtEnd(); childFrames.Next()) {
         nsIFrame* f = childFrames.get();
-        if ((f->GetType() == nsGkAtoms::placeholderFrame &&
-             nsPlaceholderFrame::GetRealFrameForPlaceholder(f)->IsAbsolutelyPositioned()) ||
-            FrameHasAbsPosPlaceholderDescendants(f)) {
+        if (f->GetType() == nsGkAtoms::placeholderFrame) {
+          nsIFrame* outOfFlow = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
+          // If SVG text frames could appear here, they could confuse us since
+          // they ignore their position style ... but they can't.
+          NS_ASSERTION(!outOfFlow->IsSVGText(),
+                       "SVG text frames can't be out of flow");
+          if (aPositionMask & (1 << outOfFlow->GetStyleDisplay()->mPosition)) {
+            return true;
+          }
+        }
+        if (FrameHasPositionedPlaceholderDescendants(f, aPositionMask)) {
           return true;
         }
       }
     }
   }
   return false;
 }
 
+static bool
+NeedToReframeForAddingOrRemovingTransform(nsIFrame* aFrame)
+{
+  MOZ_STATIC_ASSERT(0 <= NS_STYLE_POSITION_ABSOLUTE &&
+                    NS_STYLE_POSITION_ABSOLUTE < 32, "Style constant out of range");
+  MOZ_STATIC_ASSERT(0 <= NS_STYLE_POSITION_FIXED &&
+                    NS_STYLE_POSITION_FIXED < 32, "Style constant out of range");
+
+  uint32_t positionMask;
+  // Don't call aFrame->IsPositioned here, since that returns true if
+  // the frame already has a transform, and we want to ignore that here
+  if (aFrame->IsAbsolutelyPositioned() ||
+      aFrame->IsRelativelyPositioned()) {
+    // This frame is a container for abs-pos descendants whether or not it
+    // has a transform.
+    // So abs-pos descendants are no problem; we only need to reframe if
+    // we have fixed-pos descendants.
+    positionMask = 1 << NS_STYLE_POSITION_FIXED;
+  } else {
+    // This frame may not be a container for abs-pos descendants already.
+    // So reframe if we have abs-pos or fixed-pos descendants.
+    positionMask = (1 << NS_STYLE_POSITION_FIXED) |
+        (1 << NS_STYLE_POSITION_ABSOLUTE);
+  }
+  return FrameHasPositionedPlaceholderDescendants(aFrame, positionMask);
+}
+
 nsresult
 nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
 {
   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                "Someone forgot a script blocker");
   int32_t count = aChangeList.Count();
   if (!count)
     return NS_OK;
@@ -8076,17 +8111,17 @@ nsCSSFrameConstructor::ProcessRestyledFr
     // skip any frame that has been destroyed due to a ripple effect
     if (frame) {
       if (!propTable->Get(frame, ChangeListProperty()))
         continue;
     }
 
     if ((hint & nsChangeHint_AddOrRemoveTransform) && frame &&
         !(hint & nsChangeHint_ReconstructFrame)) {
-      if (FrameHasAbsPosPlaceholderDescendants(frame)) {
+      if (NeedToReframeForAddingOrRemovingTransform(frame)) {
         NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
       } else {
         // We can just add this state bit unconditionally, since it's
         // conservative. Normally frame construction would set this if needed,
         // but we're not going to reconstruct the frame so we need to set it.
         // It's because we need to set this bit on each affected frame
         // that we can't coalesce nsChangeHint_AddOrRemoveTransform hints up
         // to ancestors (i.e. it can't be an inherited change hint).
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -1046,16 +1046,21 @@ public:
   }
   /**
    * @return the root of the display list's frame (sub)tree, whose origin
    * establishes the coordinate system for the display list
    */
   const nsIFrame* ReferenceFrame() const { return mReferenceFrame; }
 
   /**
+   * Returns the reference frame for display item children of this item.
+   */
+  virtual const nsIFrame* ReferenceFrameForChildren() const { return mReferenceFrame; }
+
+  /**
    * Checks if this display item (or any children) contains content that might
    * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
    * bounds of the area that needs component alpha, or an empty rect if nothing
    * in the item does.
    */
   virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) { return nsRect(); }
 
   /**
@@ -2584,16 +2589,26 @@ public:
                                              const ContainerParameters& aContainerParameters) MOZ_OVERRIDE;
   virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder,
                                    nsRegion *aVisibleRegion,
                                    const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
   virtual bool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem) MOZ_OVERRIDE;
   
   virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); }
 
+  virtual const nsIFrame* ReferenceFrameForChildren() const MOZ_OVERRIDE {
+    // If we were created using a transform-getter, then we don't
+    // belong to a transformed frame, and aren't a reference frame
+    // for our children.
+    if (!mTransformGetter) {
+      return mFrame;
+    }
+    return nsDisplayItem::ReferenceFrameForChildren(); 
+  }
+
   enum {
     INDEX_MAX = UINT32_MAX >> nsDisplayItem::TYPE_BITS
   };
 
   const gfx3DMatrix& GetTransform(float aAppUnitsPerPixel);
 
   float GetHitDepthAtPoint(const nsPoint& aPoint);
 
deleted file mode 100644
--- a/layout/base/nsFrameIterator.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsFrameIterator.h"
-#include "nsIFrame.h"
-#include "nsGkAtoms.h"
-#include "nsPlaceholderFrame.h"
-
-nsFrameIterator::nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
-                                 nsIteratorType aType, uint32_t aFlags)
-  : mPresContext(aPresContext)
-  , mOffEdge(0)
-  , mType(aType)
-{
-  mFollowOOFs = (aFlags & FLAG_FOLLOW_OUT_OF_FLOW) != 0;
-  mLockScroll = (aFlags & FLAG_LOCK_SCROLL) != 0;
-  mVisual = (aFlags & FLAG_VISUAL) != 0;
-  if (mFollowOOFs && aStart)
-    aStart = nsPlaceholderFrame::GetRealFrameFor(aStart);
-  setStart(aStart);
-  setCurrent(aStart);
-  setLast(aStart);
-}
-
-nsIFrame*
-nsFrameIterator::CurrentItem()
-{
-  return mOffEdge ? nullptr : mCurrent;
-}
-
-bool
-nsFrameIterator::IsDone()
-{
-  return mOffEdge != 0;
-}
-
-void
-nsFrameIterator::First()
-{
-  mCurrent = mStart;
-}
-
-static bool
-IsRootFrame(nsIFrame* aFrame)
-{
-  nsIAtom* atom = aFrame->GetType();
-  return (atom == nsGkAtoms::canvasFrame) ||
-         (atom == nsGkAtoms::rootFrame);
-}
-
-void
-nsFrameIterator::Last()
-{
-  nsIFrame* result;
-  nsIFrame* parent = getCurrent();
-  // If the current frame is a popup, don't move farther up the tree.
-  // Otherwise, get the nearest root frame or popup.
-  if (parent->GetType() != nsGkAtoms::menuPopupFrame) {
-    while (!IsRootFrame(parent) && (result = GetParentFrameNotPopup(parent)))
-      parent = result;
-  }
-
-  while ((result = GetLastChild(parent))) {
-    parent = result;
-  }
-
-  setCurrent(parent);
-  if (!parent)
-    setOffEdge(1);
-}
-
-void
-nsFrameIterator::Next()
-{
-  // recursive-oid method to get next frame
-  nsIFrame *result = nullptr;
-  nsIFrame *parent = getCurrent();
-  if (!parent)
-    parent = getLast();
-
-  if (mType == eLeaf) {
-    // Drill down to first leaf
-    while ((result = GetFirstChild(parent))) {
-      parent = result;
-    }
-  } else if (mType == ePreOrder) {
-    result = GetFirstChild(parent);
-    if (result)
-      parent = result;
-  }
-
-  if (parent != getCurrent()) {
-    result = parent;
-  } else {
-    while (parent) {
-      result = GetNextSibling(parent);
-      if (result) {
-        if (mType != ePreOrder) {
-          parent = result;
-          while ((result = GetFirstChild(parent))) {
-            parent = result;
-          }
-          result = parent;
-        }
-        break;
-      }
-      else {
-        result = GetParentFrameNotPopup(parent);
-        if (!result || IsRootFrame(result) ||
-            (mLockScroll && result->GetType() == nsGkAtoms::scrollFrame)) {
-          result = nullptr;
-          break;
-        }
-        if (mType == ePostOrder)
-          break;
-        parent = result;
-      }
-    }
-  }
-
-  setCurrent(result);
-  if (!result) {
-    setOffEdge(1);
-    setLast(parent);
-  }
-}
-
-void
-nsFrameIterator::Prev()
-{
-  // recursive-oid method to get prev frame
-  nsIFrame *result = nullptr;
-  nsIFrame *parent = getCurrent();
-  if (!parent)
-    parent = getLast();
-
-  if (mType == eLeaf) {
-    // Drill down to last leaf
-    while ((result = GetLastChild(parent))) {
-      parent = result;
-    }
-  } else if (mType == ePostOrder) {
-    result = GetLastChild(parent);
-    if (result)
-      parent = result;
-  }
-
-  if (parent != getCurrent()) {
-    result = parent;
-  } else {
-    while (parent) {
-      result = GetPrevSibling(parent);
-      if (result) {
-        if (mType != ePostOrder) {
-          parent = result;
-          while ((result = GetLastChild(parent))) {
-            parent = result;
-          }
-          result = parent;
-        }
-        break;
-      } else {
-        result = GetParentFrameNotPopup(parent);
-        if (!result || IsRootFrame(result) ||
-            (mLockScroll && result->GetType() == nsGkAtoms::scrollFrame)) {
-          result = nullptr;
-          break;
-        }
-        if (mType == ePreOrder)
-          break;
-        parent = result;
-      }
-    }
-  }
-
-  setCurrent(result);
-  if (!result) {
-    setOffEdge(-1);
-    setLast(parent);
-  }
-}
-
-nsIFrame*
-nsFrameIterator::GetParentFrame(nsIFrame* aFrame)
-{
-  if (mFollowOOFs)
-    aFrame = GetPlaceholderFrame(aFrame);
-  if (aFrame)
-    return aFrame->GetParent();
-
-  return nullptr;
-}
-
-nsIFrame*
-nsFrameIterator::GetParentFrameNotPopup(nsIFrame* aFrame)
-{
-  if (mFollowOOFs)
-    aFrame = GetPlaceholderFrame(aFrame);
-  if (aFrame) {
-    nsIFrame* parent = aFrame->GetParent();
-    if (!IsPopupFrame(parent))
-      return parent;
-  }
-
-  return nullptr;
-}
-
-nsIFrame*
-nsFrameIterator::GetFirstChild(nsIFrame* aFrame)
-{
-  nsIFrame* result = GetFirstChildInner(aFrame);
-  if (mLockScroll && result && result->GetType() == nsGkAtoms::scrollFrame)
-    return nullptr;
-  if (result && mFollowOOFs) {
-    result = nsPlaceholderFrame::GetRealFrameFor(result);
-
-    if (IsPopupFrame(result))
-      result = GetNextSibling(result);
-  }
-  return result;
-}
-
-nsIFrame*
-nsFrameIterator::GetLastChild(nsIFrame* aFrame)
-{
-  nsIFrame* result = GetLastChildInner(aFrame);
-  if (mLockScroll && result && result->GetType() == nsGkAtoms::scrollFrame)
-    return nullptr;
-  if (result && mFollowOOFs) {
-    result = nsPlaceholderFrame::GetRealFrameFor(result);
-
-    if (IsPopupFrame(result))
-      result = GetPrevSibling(result);
-  }
-  return result;
-}
-
-nsIFrame*
-nsFrameIterator::GetNextSibling(nsIFrame* aFrame)
-{
-  nsIFrame* result = nullptr;
-  if (mFollowOOFs)
-    aFrame = GetPlaceholderFrame(aFrame);
-  if (aFrame) {
-    result = GetNextSiblingInner(aFrame);
-    if (result && mFollowOOFs)
-      result = nsPlaceholderFrame::GetRealFrameFor(result);
-  }
-
-  if (mFollowOOFs && IsPopupFrame(result))
-    result = GetNextSibling(result);
-
-  return result;
-}
-
-nsIFrame*
-nsFrameIterator::GetPrevSibling(nsIFrame* aFrame)
-{
-  nsIFrame* result = nullptr;
-  if (mFollowOOFs)
-    aFrame = GetPlaceholderFrame(aFrame);
-  if (aFrame) {
-    result = GetPrevSiblingInner(aFrame);
-    if (result && mFollowOOFs)
-      result = nsPlaceholderFrame::GetRealFrameFor(result);
-  }
-
-  if (mFollowOOFs && IsPopupFrame(result))
-    result = GetPrevSibling(result);
-
-  return result;
-}
-
-nsIFrame*
-nsFrameIterator::GetFirstChildInner(nsIFrame* aFrame) {
-  if (mVisual) {
-    return aFrame->PrincipalChildList().GetNextVisualFor(nullptr);
-  }
-  return aFrame->GetFirstPrincipalChild();
-}
-
-nsIFrame*
-nsFrameIterator::GetLastChildInner(nsIFrame* aFrame) {
-  if (mVisual) {
-    return aFrame->PrincipalChildList().GetPrevVisualFor(nullptr);
-  }
-  return aFrame->PrincipalChildList().LastChild();
-}
-
-nsIFrame*
-nsFrameIterator::GetNextSiblingInner(nsIFrame* aFrame) {
-  if (mVisual) {
-    nsIFrame* parent = GetParentFrame(aFrame);
-    if (!parent)
-      return nullptr;
-    return parent->PrincipalChildList().GetNextVisualFor(aFrame);
-  }
-  return aFrame->GetNextSibling();
-}
-
-nsIFrame*
-nsFrameIterator::GetPrevSiblingInner(nsIFrame* aFrame) {
-  if (mVisual) {
-    nsIFrame* parent = GetParentFrame(aFrame);
-    if (!parent)
-      return nullptr;
-    return parent->PrincipalChildList().GetPrevVisualFor(aFrame);
-  }
-  return aFrame->GetPrevSibling();
-}
-
-nsIFrame*
-nsFrameIterator::GetPlaceholderFrame(nsIFrame* aFrame)
-{
-  nsIFrame* result = aFrame;
-  nsIPresShell *presShell = mPresContext->GetPresShell();
-  if (presShell) {
-    nsIFrame* placeholder = presShell->GetPlaceholderFrameFor(aFrame);
-    if (placeholder)
-      result = placeholder;
-  }
-
-  if (result != aFrame)
-    result = GetPlaceholderFrame(result);
-
-  return result;
-}
-
-bool
-nsFrameIterator::IsPopupFrame(nsIFrame* aFrame)
-{
-  return (aFrame &&
-          aFrame->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_POPUP);
-}
-
deleted file mode 100644
--- a/layout/base/nsFrameIterator.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#ifndef NSFRAMEITERATOR_H
-#define NSFRAMEITERATOR_H
-
-#include "mozilla/StandardInteger.h"
-
-class nsPresContext;
-class nsIFrame;
-
-enum nsIteratorType {
-  eLeaf,
-  ePreOrder,
-  ePostOrder
-};
-
-class nsFrameIterator
-{
-public:
-  nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
-                  nsIteratorType aType, uint32_t aFlags);
-
-  ~nsFrameIterator() {}
-
-  void First();
-  void Next();
-  nsIFrame* CurrentItem();
-  bool IsDone();
-
-  void Last();
-  void Prev();
-
-  enum FrameIteratorFlags {
-    FLAG_NONE = 0,
-    FLAG_LOCK_SCROLL = 1 << 1,
-    FLAG_FOLLOW_OUT_OF_FLOW = 1 << 2,
-    FLAG_VISUAL = 1 << 3
-  };
-protected:
-  void      setCurrent(nsIFrame *aFrame){mCurrent = aFrame;}
-  nsIFrame *getCurrent(){return mCurrent;}
-  void      setStart(nsIFrame *aFrame){mStart = aFrame;}
-  nsIFrame *getStart(){return mStart;}
-  nsIFrame *getLast(){return mLast;}
-  void      setLast(nsIFrame *aFrame){mLast = aFrame;}
-  int8_t    getOffEdge(){return mOffEdge;}
-  void      setOffEdge(int8_t aOffEdge){mOffEdge = aOffEdge;}
-  void      SetLockInScrollView(bool aLockScroll){mLockScroll = aLockScroll;}
-
-  /*
-   Our own versions of the standard frame tree navigation
-   methods, which, if the iterator is following out-of-flows,
-   apply the following rules for placeholder frames:
-
-   - If a frame HAS a placeholder frame, getting its parent
-   gets the placeholder's parent.
-
-   - If a frame's first child or next/prev sibling IS a
-   placeholder frame, then we instead return the real frame.
-
-   - If a frame HAS a placeholder frame, getting its next/prev
-   sibling gets the placeholder frame's next/prev sibling.
-
-   These are all applied recursively to support multiple levels of
-   placeholders.
-   */
-
-  nsIFrame* GetParentFrame(nsIFrame* aFrame);
-  // like GetParentFrame but returns null once a popup frame is reached
-  nsIFrame* GetParentFrameNotPopup(nsIFrame* aFrame);
-
-  nsIFrame* GetFirstChild(nsIFrame* aFrame);
-  nsIFrame* GetLastChild(nsIFrame* aFrame);
-
-  nsIFrame* GetNextSibling(nsIFrame* aFrame);
-  nsIFrame* GetPrevSibling(nsIFrame* aFrame);
-
-  /*
-   These methods are different in visual mode to have the
-   semantics of "get first child in visual order", "get last child in visual
-   order", "get next sibling in visual order" and "get previous sibling in visual
-   order".
-  */
-
-  nsIFrame* GetFirstChildInner(nsIFrame* aFrame);
-  nsIFrame* GetLastChildInner(nsIFrame* aFrame);
-
-  nsIFrame* GetNextSiblingInner(nsIFrame* aFrame);
-  nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame);
-
-  nsIFrame* GetPlaceholderFrame(nsIFrame* aFrame);
-  bool      IsPopupFrame(nsIFrame* aFrame);
-
-  nsPresContext* mPresContext;
-  nsIFrame *mStart;
-  nsIFrame *mCurrent;
-  nsIFrame *mLast; //the last one that was in current;
-  int8_t    mOffEdge; //0= no -1 to far prev, 1 to far next;
-  nsIteratorType mType;
-  bool mLockScroll;
-  bool mFollowOOFs;
-  bool mVisual;
-};
-
-#endif //NSFRAMEITERATOR_H
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -447,18 +447,18 @@ nsFrameManager::AppendFrames(nsIFrame*  
 
 nsresult
 nsFrameManager::InsertFrames(nsIFrame*       aParentFrame,
                              ChildListID     aListID,
                              nsIFrame*       aPrevFrame,
                              nsFrameList&    aFrameList)
 {
   NS_PRECONDITION(!aPrevFrame || (!aPrevFrame->GetNextContinuation()
-                  || ((aPrevFrame->GetNextContinuation()->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER))
-                  && !(aPrevFrame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)),
+                  || (((aPrevFrame->GetNextContinuation()->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER))
+                  && !(aPrevFrame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER))),
                   "aPrevFrame must be the last continuation in its chain!");
 
   if (aParentFrame->IsAbsoluteContainer() &&
       aListID == aParentFrame->GetAbsoluteListID()) {
     return aParentFrame->GetAbsoluteContainingBlock()->
            InsertFrames(aParentFrame, aListID, aPrevFrame, aFrameList);
   } else {
     return aParentFrame->InsertFrames(aListID, aPrevFrame, aFrameList);
new file mode 100644
--- /dev/null
+++ b/layout/base/nsFrameTraversal.cpp
@@ -0,0 +1,528 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "nsCOMPtr.h"
+#include "nsGkAtoms.h"
+
+#include "nsFrameTraversal.h"
+#include "nsFrameList.h"
+#include "nsPlaceholderFrame.h"
+
+
+class nsFrameIterator : public nsIFrameEnumerator
+{
+public:
+  typedef nsIFrame::ChildListID ChildListID;
+
+  NS_DECL_ISUPPORTS
+
+  virtual ~nsFrameIterator() {}
+
+  virtual void First();
+  virtual void Next();
+  virtual nsIFrame* CurrentItem();
+  virtual bool IsDone();
+
+  virtual void Last();
+  virtual void Prev();
+
+  nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
+                  nsIteratorType aType, bool aLockScroll, bool aFollowOOFs);
+
+protected:
+  void      setCurrent(nsIFrame *aFrame){mCurrent = aFrame;}
+  nsIFrame *getCurrent(){return mCurrent;}
+  void      setStart(nsIFrame *aFrame){mStart = aFrame;}
+  nsIFrame *getStart(){return mStart;}
+  nsIFrame *getLast(){return mLast;}
+  void      setLast(nsIFrame *aFrame){mLast = aFrame;}
+  PRInt8    getOffEdge(){return mOffEdge;}
+  void      setOffEdge(PRInt8 aOffEdge){mOffEdge = aOffEdge;}
+  void      SetLockInScrollView(bool aLockScroll){mLockScroll = aLockScroll;}
+
+  /*
+   Our own versions of the standard frame tree navigation
+   methods, which, if the iterator is following out-of-flows,
+   apply the following rules for placeholder frames:
+   
+   - If a frame HAS a placeholder frame, getting its parent
+   gets the placeholder's parent.
+   
+   - If a frame's first child or next/prev sibling IS a
+   placeholder frame, then we instead return the real frame.
+   
+   - If a frame HAS a placeholder frame, getting its next/prev
+   sibling gets the placeholder frame's next/prev sibling.
+   
+   These are all applied recursively to support multiple levels of
+   placeholders.
+   */  
+  
+  nsIFrame* GetParentFrame(nsIFrame* aFrame);
+  // like GetParentFrame but returns null once a popup frame is reached
+  nsIFrame* GetParentFrameNotPopup(nsIFrame* aFrame);
+
+  nsIFrame* GetFirstChild(nsIFrame* aFrame);
+  nsIFrame* GetLastChild(nsIFrame* aFrame);
+
+  nsIFrame* GetNextSibling(nsIFrame* aFrame);
+  nsIFrame* GetPrevSibling(nsIFrame* aFrame);
+
+  /*
+   These methods are overridden by the bidi visual iterator to have the
+   semantics of "get first child in visual order", "get last child in visual
+   order", "get next sibling in visual order" and "get previous sibling in visual
+   order".
+  */
+  
+  virtual nsIFrame* GetFirstChildInner(nsIFrame* aFrame);
+  virtual nsIFrame* GetLastChildInner(nsIFrame* aFrame);  
+
+  virtual nsIFrame* GetNextSiblingInner(nsIFrame* aFrame);
+  virtual nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame);
+
+  nsIFrame* GetPlaceholderFrame(nsIFrame* aFrame);
+  bool      IsPopupFrame(nsIFrame* aFrame);
+
+  nsPresContext* mPresContext;
+  bool mLockScroll;
+  bool mFollowOOFs;
+  nsIteratorType mType;
+
+private:
+  nsIFrame *mStart;
+  nsIFrame *mCurrent;
+  nsIFrame *mLast; //the last one that was in current;
+  PRInt8    mOffEdge; //0= no -1 to far prev, 1 to far next;
+};
+
+
+
+// Bidi visual iterator
+class nsVisualIterator: public nsFrameIterator
+{
+public:
+  nsVisualIterator(nsPresContext* aPresContext, nsIFrame *aStart,
+                   nsIteratorType aType, bool aLockScroll, bool aFollowOOFs) :
+  nsFrameIterator(aPresContext, aStart, aType, aLockScroll, aFollowOOFs) {}
+
+protected:
+  nsIFrame* GetFirstChildInner(nsIFrame* aFrame);
+  nsIFrame* GetLastChildInner(nsIFrame* aFrame);  
+  
+  nsIFrame* GetNextSiblingInner(nsIFrame* aFrame);
+  nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame);  
+};
+
+/************IMPLEMENTATIONS**************/
+
+nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult)
+{
+  NS_ENSURE_ARG_POINTER(aResult);
+  *aResult = nullptr;
+
+  nsCOMPtr<nsIFrameTraversal> t(new nsFrameTraversal());
+
+  *aResult = t;
+  NS_ADDREF(*aResult);
+
+  return NS_OK;
+}
+
+nsresult
+NS_NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
+                     nsPresContext* aPresContext,
+                     nsIFrame *aStart,
+                     nsIteratorType aType,
+                     bool aVisual,
+                     bool aLockInScrollView,
+                     bool aFollowOOFs)
+{
+  if (!aEnumerator || !aStart)
+    return NS_ERROR_NULL_POINTER;
+  nsCOMPtr<nsIFrameEnumerator> trav;
+  if (aVisual) {
+    trav = new nsVisualIterator(aPresContext, aStart, aType,
+                                aLockInScrollView, aFollowOOFs);
+  } else {
+    trav = new nsFrameIterator(aPresContext, aStart, aType,
+                               aLockInScrollView, aFollowOOFs);
+  }
+  trav.forget(aEnumerator);
+  return NS_OK;
+}
+
+
+nsFrameTraversal::nsFrameTraversal()
+{
+}
+
+nsFrameTraversal::~nsFrameTraversal()
+{
+}
+
+NS_IMPL_ISUPPORTS1(nsFrameTraversal,nsIFrameTraversal)
+
+NS_IMETHODIMP 
+ nsFrameTraversal::NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
+                                     nsPresContext* aPresContext,
+                                     nsIFrame *aStart,
+                                     PRInt32 aType,
+                                     bool aVisual,
+                                     bool aLockInScrollView,
+                                     bool aFollowOOFs)
+{
+  return NS_NewFrameTraversal(aEnumerator, aPresContext, aStart,
+                              static_cast<nsIteratorType>(aType),
+                              aVisual, aLockInScrollView, aFollowOOFs);  
+}
+
+// nsFrameIterator implementation
+
+NS_IMPL_ISUPPORTS1(nsFrameIterator, nsIFrameEnumerator)
+
+nsFrameIterator::nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
+                                 nsIteratorType aType, bool aLockInScrollView,
+                                 bool aFollowOOFs)
+{
+  mOffEdge = 0;
+  mPresContext = aPresContext;
+  if (aFollowOOFs && aStart)
+    aStart = nsPlaceholderFrame::GetRealFrameFor(aStart);
+  setStart(aStart);
+  setCurrent(aStart);
+  setLast(aStart);
+  mType = aType;
+  SetLockInScrollView(aLockInScrollView);
+  mFollowOOFs = aFollowOOFs;
+}
+
+
+
+nsIFrame*
+nsFrameIterator::CurrentItem()
+{
+  if (mOffEdge)
+    return nullptr;
+
+  return mCurrent;
+}
+
+
+
+bool
+nsFrameIterator::IsDone()
+{
+  return mOffEdge != 0;
+}
+
+void
+nsFrameIterator::First()
+{
+  mCurrent = mStart;
+}
+
+static bool
+IsRootFrame(nsIFrame* aFrame)
+{
+  nsIAtom* atom = aFrame->GetType();
+  return (atom == nsGkAtoms::canvasFrame) ||
+         (atom == nsGkAtoms::rootFrame);
+}
+
+void
+nsFrameIterator::Last()
+{
+  nsIFrame* result;
+  nsIFrame* parent = getCurrent();
+  // If the current frame is a popup, don't move farther up the tree.
+  // Otherwise, get the nearest root frame or popup.
+  if (parent->GetType() != nsGkAtoms::menuPopupFrame) {
+    while (!IsRootFrame(parent) && (result = GetParentFrameNotPopup(parent)))
+      parent = result;
+  }
+
+  while ((result = GetLastChild(parent))) {
+    parent = result;
+  }
+  
+  setCurrent(parent);
+  if (!parent)
+    setOffEdge(1);
+}
+
+void
+nsFrameIterator::Next()
+{
+  // recursive-oid method to get next frame
+  nsIFrame *result = nullptr;
+  nsIFrame *parent = getCurrent();
+  if (!parent)
+    parent = getLast();
+
+  if (mType == eLeaf) {
+    // Drill down to first leaf
+    while ((result = GetFirstChild(parent))) {
+      parent = result;
+    }
+  } else if (mType == ePreOrder) {
+    result = GetFirstChild(parent);
+    if (result)
+      parent = result;
+  }
+
+  if (parent != getCurrent()) {
+    result = parent;
+  } else {
+    while (parent) {
+      result = GetNextSibling(parent);
+      if (result) {
+        if (mType != ePreOrder) {
+          parent = result;
+          while ((result = GetFirstChild(parent))) {
+            parent = result;
+          }
+          result = parent;
+        }
+        break;
+      }
+      else {
+        result = GetParentFrameNotPopup(parent);
+        if (!result || IsRootFrame(result) ||
+            (mLockScroll && result->GetType() == nsGkAtoms::scrollFrame)) {
+          result = nullptr;
+          break;
+        }
+        if (mType == ePostOrder)
+          break;
+        parent = result;
+      }
+    }
+  }
+
+  setCurrent(result);
+  if (!result) {
+    setOffEdge(1);
+    setLast(parent);
+  }
+}
+
+void
+nsFrameIterator::Prev()
+{
+  // recursive-oid method to get prev frame
+  nsIFrame *result = nullptr;
+  nsIFrame *parent = getCurrent();
+  if (!parent)
+    parent = getLast();
+
+  if (mType == eLeaf) {
+    // Drill down to last leaf
+    while ((result = GetLastChild(parent))) {
+      parent = result;
+    }
+  } else if (mType == ePostOrder) {
+    result = GetLastChild(parent);
+    if (result)
+      parent = result;
+  }
+  
+  if (parent != getCurrent()) {
+    result = parent;
+  } else {
+    while (parent) {
+      result = GetPrevSibling(parent);
+      if (result) {
+        if (mType != ePostOrder) {
+          parent = result;
+          while ((result = GetLastChild(parent))) {
+            parent = result;
+          }
+          result = parent;
+        }
+        break;
+      } else {
+        result = GetParentFrameNotPopup(parent);
+        if (!result || IsRootFrame(result) ||
+            (mLockScroll && result->GetType() == nsGkAtoms::scrollFrame)) {
+          result = nullptr;
+          break;
+        }
+        if (mType == ePreOrder)
+          break;
+        parent = result;
+      }
+    }
+  }
+
+  setCurrent(result);
+  if (!result) {
+    setOffEdge(-1);
+    setLast(parent);
+  }
+}
+
+nsIFrame*
+nsFrameIterator::GetParentFrame(nsIFrame* aFrame)
+{
+  if (mFollowOOFs)
+    aFrame = GetPlaceholderFrame(aFrame);
+  if (aFrame)
+    return aFrame->GetParent();
+  
+  return nullptr;
+}
+
+nsIFrame*
+nsFrameIterator::GetParentFrameNotPopup(nsIFrame* aFrame)
+{
+  if (mFollowOOFs)
+    aFrame = GetPlaceholderFrame(aFrame);
+  if (aFrame) {
+    nsIFrame* parent = aFrame->GetParent();
+    if (!IsPopupFrame(parent))
+      return parent;
+  }
+    
+  return nullptr;
+}
+
+nsIFrame*
+nsFrameIterator::GetFirstChild(nsIFrame* aFrame)
+{
+  nsIFrame* result = GetFirstChildInner(aFrame);
+  if (mLockScroll && result && result->GetType() == nsGkAtoms::scrollFrame)
+    return nullptr;
+  if (result && mFollowOOFs) {
+    result = nsPlaceholderFrame::GetRealFrameFor(result);
+    
+    if (IsPopupFrame(result))
+      result = GetNextSibling(result);
+  }
+  return result;
+}
+
+nsIFrame*
+nsFrameIterator::GetLastChild(nsIFrame* aFrame)
+{
+  nsIFrame* result = GetLastChildInner(aFrame);
+  if (mLockScroll && result && result->GetType() == nsGkAtoms::scrollFrame)
+    return nullptr;
+  if (result && mFollowOOFs) {
+    result = nsPlaceholderFrame::GetRealFrameFor(result);
+    
+    if (IsPopupFrame(result))
+      result = GetPrevSibling(result);
+  }
+  return result;
+}
+
+nsIFrame*
+nsFrameIterator::GetNextSibling(nsIFrame* aFrame)
+{
+  nsIFrame* result = nullptr;
+  if (mFollowOOFs)
+    aFrame = GetPlaceholderFrame(aFrame);
+  if (aFrame) {
+    result = GetNextSiblingInner(aFrame);
+    if (result && mFollowOOFs)
+      result = nsPlaceholderFrame::GetRealFrameFor(result);
+  }
+
+  if (mFollowOOFs && IsPopupFrame(result))
+    result = GetNextSibling(result);
+
+  return result;
+}
+
+nsIFrame*
+nsFrameIterator::GetPrevSibling(nsIFrame* aFrame)
+{
+  nsIFrame* result = nullptr;
+  if (mFollowOOFs)
+    aFrame = GetPlaceholderFrame(aFrame);
+  if (aFrame) {
+    result = GetPrevSiblingInner(aFrame);
+    if (result && mFollowOOFs)
+      result = nsPlaceholderFrame::GetRealFrameFor(result);
+  }
+
+  if (mFollowOOFs && IsPopupFrame(result))
+    result = GetPrevSibling(result);
+
+  return result;
+}
+
+nsIFrame*
+nsFrameIterator::GetFirstChildInner(nsIFrame* aFrame) {
+  return aFrame->GetFirstPrincipalChild();
+}
+
+nsIFrame*
+nsFrameIterator::GetLastChildInner(nsIFrame* aFrame) {
+  return aFrame->PrincipalChildList().LastChild();
+}
+
+nsIFrame*
+nsFrameIterator::GetNextSiblingInner(nsIFrame* aFrame) {
+  return aFrame->GetNextSibling();
+}
+
+nsIFrame*
+nsFrameIterator::GetPrevSiblingInner(nsIFrame* aFrame) {
+  return aFrame->GetPrevSibling();
+}
+
+
+nsIFrame*
+nsFrameIterator::GetPlaceholderFrame(nsIFrame* aFrame)
+{
+  nsIFrame* result = aFrame;
+  nsIPresShell *presShell = mPresContext->GetPresShell();
+  if (presShell) {
+    nsIFrame* placeholder = presShell->GetPlaceholderFrameFor(aFrame);
+    if (placeholder)
+      result = placeholder;
+  }
+
+  if (result != aFrame)
+    result = GetPlaceholderFrame(result);
+
+  return result;
+}
+
+bool
+nsFrameIterator::IsPopupFrame(nsIFrame* aFrame)
+{
+  return (aFrame &&
+          aFrame->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_POPUP);
+}
+
+// nsVisualIterator implementation
+
+nsIFrame*
+nsVisualIterator::GetFirstChildInner(nsIFrame* aFrame) {
+  return aFrame->PrincipalChildList().GetNextVisualFor(nullptr);
+}
+
+nsIFrame*
+nsVisualIterator::GetLastChildInner(nsIFrame* aFrame) {
+  return aFrame->PrincipalChildList().GetPrevVisualFor(nullptr);
+}
+
+nsIFrame*
+nsVisualIterator::GetNextSiblingInner(nsIFrame* aFrame) {
+  nsIFrame* parent = GetParentFrame(aFrame);
+  if (!parent)
+    return nullptr;
+  return parent->PrincipalChildList().GetNextVisualFor(aFrame);
+}
+
+nsIFrame*
+nsVisualIterator::GetPrevSiblingInner(nsIFrame* aFrame) {
+  nsIFrame* parent = GetParentFrame(aFrame);
+  if (!parent)
+    return nullptr;
+  return parent->PrincipalChildList().GetPrevVisualFor(aFrame);
+}
new file mode 100644
--- /dev/null
+++ b/layout/base/nsFrameTraversal.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef NSFRAMETRAVERSAL_H
+#define NSFRAMETRAVERSAL_H
+
+#include "nsIFrame.h"
+#include "nsIFrameTraversal.h"
+
+nsresult NS_NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
+                              nsPresContext* aPresContext,
+                              nsIFrame *aStart,
+                              nsIteratorType aType,
+                              bool aVisual,
+                              bool aLockInScrollView,
+                              bool aFollowOOFs);
+
+nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult);
+
+class nsFrameTraversal : public nsIFrameTraversal
+{
+public:
+  nsFrameTraversal();
+  virtual ~nsFrameTraversal();
+
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
+                               nsPresContext* aPresContext,
+                               nsIFrame *aStart,
+                               PRInt32 aType,
+                               bool aVisual,
+                               bool aLockInScrollView,
+                               bool aFollowOOFs);
+};
+
+#endif //NSFRAMETRAVERSAL_H
new file mode 100644
--- /dev/null
+++ b/layout/base/nsIFrameTraversal.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef NSIFRAMETRAVERSAL_H
+#define NSIFRAMETRAVERSAL_H
+
+#include "nsISupports.h"
+#include "nsIFrame.h"
+
+#define NS_IFRAMEENUMERATOR_IID \
+{ 0x7c633f5d, 0x91eb, 0x494e, \
+  { 0xa1, 0x40, 0x17, 0x46, 0x17, 0x4c, 0x23, 0xd3 } }
+
+class nsIFrameEnumerator : public nsISupports
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFRAMEENUMERATOR_IID)
+
+  virtual void First() = 0;
+  virtual void Next() = 0;
+  virtual nsIFrame* CurrentItem() = 0;
+  virtual bool IsDone() = 0;
+
+  virtual void Last() = 0;
+  virtual void Prev() = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIFrameEnumerator, NS_IFRAMEENUMERATOR_IID)
+
+enum nsIteratorType {
+  eLeaf,
+  ePreOrder,
+  ePostOrder
+};
+
+// {9d469828-9bf2-4151-a385-05f30219221b}
+#define NS_IFRAMETRAVERSAL_IID \
+{ 0x9d469828, 0x9bf2, 0x4151, { 0xa3, 0x85, 0x05, 0xf3, 0x02, 0x19, 0x22, 0x1b } }
+
+class nsIFrameTraversal : public nsISupports
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFRAMETRAVERSAL_IID)
+
+  /**
+   * Create a frame iterator with the specified properties.
+   * @param aEnumerator [out] the created iterator
+   * @param aPresContext [in]
+   * @param aStart [in] the frame to start iterating from
+   * @param aType [in] the type of the iterator: leaf, pre-order, or post-order
+   * @param aVisual [in] whether the iterator should traverse frames in visual
+   *        bidi order
+   * @param aLockInScrollView [in] whether to stop iterating when exiting a
+   *        scroll view
+   * @param aFollowOOFs [in] whether the iterator should follow out-of-flows.
+   *        If true, when reaching a placeholder frame while going down will get
+   *        the real frame. Going back up will go on past the placeholder,
+   *        so the placeholders are logically part of the frame tree.
+   */
+  NS_IMETHOD NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
+                               nsPresContext* aPresContext,
+                               nsIFrame *aStart,
+                               PRInt32 aType,
+                               bool aVisual,
+                               bool aLockInScrollView,
+                               bool aFollowOOFs) = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIFrameTraversal, NS_IFRAMETRAVERSAL_IID)
+
+#endif //NSIFRAMETRAVERSAL_H
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -272,19 +272,30 @@ public:
 
   nsIDocument* GetDocument() const { return mDocument; }
 
   nsPresContext* GetPresContext() const { return mPresContext; }
 
   nsIViewManager* GetViewManager() const { return mViewManager; }
 
 #ifdef ACCESSIBILITY
-  void SetAccDocument(DocAccessible* aAccDocument)
+  /**
+   * Return the document accessible for this pres shell if there is one.
+   */
+  DocAccessible* GetDocAccessible() const
   {
-    mAccDocument = aAccDocument;
+    return mDocAccessible;
+  }
+
+  /**
+   * Set the document accessible for this pres shell.
+   */
+  void SetDocAccessible(DocAccessible* aDocAccessible)
+  {
+    mDocAccessible = aDocAccessible;
   }
 #endif
 
 #ifdef _IMPL_NS_LAYOUT
   nsStyleSet* StyleSet() const { return mStyleSet; }
 
   nsCSSFrameConstructor* FrameConstructor() const { return mFrameConstructor; }
 
@@ -1366,17 +1377,17 @@ protected:
   nsPresArena               mFrameArena;
   nsFrameSelection*         mSelection;
   // Pointer into mFrameConstructor - this is purely so that FrameManager() and
   // GetRootFrame() can be inlined:
   nsFrameManagerBase*       mFrameManager;
   nsWeakPtr                 mForwardingContainer;
   nsRefreshDriver*          mHiddenInvalidationObserverRefreshDriver;
 #ifdef ACCESSIBILITY
-  DocAccessible* mAccDocument;
+  DocAccessible* mDocAccessible;
 #endif
 
 #ifdef DEBUG
   nsIFrame*                 mDrawEventTargetFrame;
   // Ensure that every allocation from the PresArena is eventually freed.
   uint32_t                  mPresArenaAllocCount;
 #endif
 
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -126,51 +126,51 @@ static ContentMap& GetContentMap() {
     sContentMap = new ContentMap();
     sContentMap->Init();
   }
   return *sContentMap;
 }
 
 // When the pref "layout.css.flexbox.enabled" changes, this function is invoked
 // to let us update kDisplayKTable, to selectively disable or restore the
-// entries for "-moz-flex" and "-moz-inline-flex" in that table.
+// entries for "flex" and "inline-flex" in that table.
 #ifdef MOZ_FLEXBOX
 static int
 FlexboxEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
 {
   MOZ_ASSERT(strncmp(aPrefName, FLEXBOX_ENABLED_PREF_NAME,
                      NS_ARRAY_LENGTH(FLEXBOX_ENABLED_PREF_NAME)) == 0,
              "We only registered this callback for a single pref, so it "
              "should only be called for that pref");
 
   bool isFlexboxEnabled =
     Preferences::GetBool(FLEXBOX_ENABLED_PREF_NAME, false);
 
   if (!sAreFlexKeywordIndicesInitialized) {
-    // First run: find the position of "-moz-flex" and "-moz-inline-flex" in
+    // First run: find the position of "flex" and "inline-flex" in
     // kDisplayKTable.
     sIndexOfFlexInDisplayTable =
-      nsCSSProps::FindIndexOfKeyword(eCSSKeyword__moz_flex,
+      nsCSSProps::FindIndexOfKeyword(eCSSKeyword_flex,
                                      nsCSSProps::kDisplayKTable);
     sIndexOfInlineFlexInDisplayTable =
-      nsCSSProps::FindIndexOfKeyword(eCSSKeyword__moz_inline_flex,
+      nsCSSProps::FindIndexOfKeyword(eCSSKeyword_inline_flex,
                                      nsCSSProps::kDisplayKTable);
 
     sAreFlexKeywordIndicesInitialized = true;
   }
 
   // OK -- now, stomp on or restore the "flex" entries in kDisplayKTable,
   // depending on whether the flexbox pref is enabled vs. disabled.
   if (sIndexOfFlexInDisplayTable >= 0) {
     nsCSSProps::kDisplayKTable[sIndexOfFlexInDisplayTable] =
-      isFlexboxEnabled ? eCSSKeyword__moz_flex : eCSSKeyword_UNKNOWN;
+      isFlexboxEnabled ? eCSSKeyword_flex : eCSSKeyword_UNKNOWN;
   }
   if (sIndexOfInlineFlexInDisplayTable >= 0) {
     nsCSSProps::kDisplayKTable[sIndexOfInlineFlexInDisplayTable] =
-      isFlexboxEnabled ? eCSSKeyword__moz_inline_flex : eCSSKeyword_UNKNOWN;
+      isFlexboxEnabled ? eCSSKeyword_inline_flex : eCSSKeyword_UNKNOWN;
   }
 
   return 0;
 }
 #endif // MOZ_FLEXBOX
 
 bool
 nsLayoutUtils::HasAnimationsForCompositor(nsIContent* aContent,
@@ -2550,36 +2550,66 @@ nsLayoutUtils::IntrinsicForContainer(nsR
         !(styleMinHeight.GetUnit() == eStyleUnit_Auto || 
           (styleMinHeight.GetUnit() == eStyleUnit_Coord &&
            styleMinHeight.GetCoordValue() == 0)) ||
         styleMaxHeight.GetUnit() != eStyleUnit_None) {
 
       nsSize ratio = aFrame->GetIntrinsicRatio();
 
       if (ratio.height != 0) {
+        nscoord heightTakenByBoxSizing = 0;
+        switch (boxSizing) {
+        case NS_STYLE_BOX_SIZING_BORDER: {
+          const nsStyleBorder* styleBorder = aFrame->GetStyleBorder();
+          heightTakenByBoxSizing +=
+            styleBorder->GetComputedBorder().TopBottom();
+          // fall through
+        }
+        case NS_STYLE_BOX_SIZING_PADDING: {
+          const nsStylePadding* stylePadding = aFrame->GetStylePadding();
+          nscoord pad;
+          if (GetAbsoluteCoord(stylePadding->mPadding.GetTop(), pad) ||
+              GetPercentHeight(stylePadding->mPadding.GetTop(), aFrame, pad)) {
+            heightTakenByBoxSizing += pad;
+          }
+          if (GetAbsoluteCoord(stylePadding->mPadding.GetBottom(), pad) ||
+              GetPercentHeight(stylePadding->mPadding.GetBottom(), aFrame, pad)) {
+            heightTakenByBoxSizing += pad;
+          }
+          // fall through
+        }
+        case NS_STYLE_BOX_SIZING_CONTENT:
+        default:
+          break;
+        }
 
         nscoord h;
         if (GetAbsoluteCoord(styleHeight, h) ||
             GetPercentHeight(styleHeight, aFrame, h)) {
+          h = NS_MAX(0, h - heightTakenByBoxSizing);
           result =
             NSToCoordRound(h * (float(ratio.width) / float(ratio.height)));
         }
 
         if (GetAbsoluteCoord(styleMaxHeight, h) ||
             GetPercentHeight(styleMaxHeight, aFrame, h)) {
-          h = NSToCoordRound(h * (float(ratio.width) / float(ratio.height)));
-          if (h < result)
-            result = h;
+          h = NS_MAX(0, h - heightTakenByBoxSizing);
+          nscoord maxHeight =
+            NSToCoordRound(h * (float(ratio.width) / float(ratio.height)));
+          if (maxHeight < result)
+            result = maxHeight;
         }
 
         if (GetAbsoluteCoord(styleMinHeight, h) ||
             GetPercentHeight(styleMinHeight, aFrame, h)) {
-          h = NSToCoordRound(h * (float(ratio.width) / float(ratio.height)));
-          if (h > result)
-            result = h;
+          h = NS_MAX(0, h - heightTakenByBoxSizing);
+          nscoord minHeight =
+            NSToCoordRound(h * (float(ratio.width) / float(ratio.height)));
+          if (minHeight > result)
+            result = minHeight;
         }
       }
     }
   }
 
   if (aFrame->GetType() == nsGkAtoms::tableFrame) {
     // Tables can't shrink smaller than their intrinsic minimum width,
     // no matter what.
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -932,24 +932,24 @@ PresShell::Destroy()
     mReflowCountMgr = nullptr;
   }
 #endif
 
   if (mHaveShutDown)
     return;
 
 #ifdef ACCESSIBILITY
-  if (mAccDocument) {
+  if (mDocAccessible) {
 #ifdef DEBUG
     if (a11y::logging::IsEnabled(a11y::logging::eDocDestroy))
       a11y::logging::DocDestroy("presshell destroyed", mDocument);
 #endif
 
-    mAccDocument->Shutdown();
-    mAccDocument = nullptr;
+    mDocAccessible->Shutdown();
+    mDocAccessible = nullptr;
   }
 #endif // ACCESSIBILITY
 
   MaybeReleaseCapturingContent();
 
   if (gKeyDownTarget && gKeyDownTarget->OwnerDoc() == mDocument) {
     NS_RELEASE(gKeyDownTarget);
   }
@@ -3743,17 +3743,17 @@ PresShell::FlushPendingNotifications(moz
     "Content",
     "ContentAndNotify",
     "Style",
     "InterruptibleLayout",
     "Layout",
     "Display"
   };
   // Make sure that we don't miss things added to mozFlushType!
-  MOZ_ASSERT(aType <= ArrayLength(flushTypeNames));
+  MOZ_ASSERT(static_cast<uint32_t>(aType) <= ArrayLength(flushTypeNames));
 
   SAMPLE_LABEL_PRINTF("layout", "Flush", "(Flush_%s)",
                       flushTypeNames[aType - 1]);
 #endif
 
 #ifdef ACCESSIBILITY
 #ifdef DEBUG
   nsAccessibilityService* accService = GetAccService();
--- a/layout/base/nsStyleSheetService.cpp
+++ b/layout/base/nsStyleSheetService.cpp
@@ -14,31 +14,55 @@
 #include "nsContentCID.h"
 #include "nsCOMPtr.h"
 #include "nsIServiceManager.h"
 #include "nsICategoryManager.h"
 #include "nsISupportsPrimitives.h"
 #include "nsNetUtil.h"
 #include "nsIObserverService.h"
 #include "nsLayoutStatics.h"
+#include "nsIMemoryReporter.h"
+
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(LayoutStyleSheetServiceMallocSizeOf,
+                                     "layout/style-sheet-service")
+
+static int64_t
+GetStyleSheetServiceSize()
+{
+  return nsStyleSheetService::SizeOfIncludingThis(
+           LayoutStyleSheetServiceMallocSizeOf);
+}
+
+NS_MEMORY_REPORTER_IMPLEMENT(StyleSheetService,
+  "explicit/layout/style-sheet-service",
+  KIND_HEAP,
+  nsIMemoryReporter::UNITS_BYTES,
+  GetStyleSheetServiceSize,
+  "Memory used for style sheets held by the style sheet service.")
 
 nsStyleSheetService *nsStyleSheetService::gInstance = nullptr;
 
 nsStyleSheetService::nsStyleSheetService()
 {
   PR_STATIC_ASSERT(0 == AGENT_SHEET && 1 == USER_SHEET);
   NS_ASSERTION(!gInstance, "Someone is using CreateInstance instead of GetService");
   gInstance = this;
   nsLayoutStatics::AddRef();
+
+  mReporter = new NS_MEMORY_REPORTER_NAME(StyleSheetService);
+  (void)::NS_RegisterMemoryReporter(mReporter);
 }
 
 nsStyleSheetService::~nsStyleSheetService()
 {
   gInstance = nullptr;
   nsLayoutStatics::Release();
+
+  (void)::NS_UnregisterMemoryReporter(mReporter);
+  mReporter = nullptr;
 }
 
 NS_IMPL_ISUPPORTS1(nsStyleSheetService, nsIStyleSheetService)
 
 void
 nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager  *aManager,
                                             const char          *aCategory,
                                             nsISimpleEnumerator *aEnumerator,
@@ -168,18 +192,49 @@ nsStyleSheetService::UnregisterSheet(nsI
 {
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET || aSheetType == USER_SHEET);
   NS_ENSURE_ARG_POINTER(sheetURI);
 
   int32_t foundIndex = FindSheetByURI(mSheets[aSheetType], sheetURI);
   NS_ENSURE_TRUE(foundIndex >= 0, NS_ERROR_INVALID_ARG);
   nsCOMPtr<nsIStyleSheet> sheet = mSheets[aSheetType][foundIndex];
   mSheets[aSheetType].RemoveObjectAt(foundIndex);
-  
+
   const char* message = (aSheetType == AGENT_SHEET) ?
       "agent-sheet-removed" : "user-sheet-removed";
   nsCOMPtr<nsIObserverService> serv =
     mozilla::services::GetObserverService();
   if (serv)
     serv->NotifyObservers(sheet, message, nullptr);
 
   return NS_OK;
 }
+
+size_t
+nsStyleSheetService::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
+{
+  if (!nsStyleSheetService::gInstance) {
+    return 0;
+  }
+
+  return nsStyleSheetService::gInstance->
+      SizeOfIncludingThisHelper(aMallocSizeOf);
+}
+
+static size_t
+SizeOfElementIncludingThis(nsIStyleSheet* aElement,
+                           nsMallocSizeOfFun aMallocSizeOf, void *aData)
+{
+    return aElement->SizeOfIncludingThis(aMallocSizeOf);
+}
+
+size_t
+nsStyleSheetService::SizeOfIncludingThisHelper(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  size_t n = aMallocSizeOf(this);
+  n += mSheets[AGENT_SHEET].SizeOfExcludingThis(SizeOfElementIncludingThis,
+                                                aMallocSizeOf);
+  n += mSheets[USER_SHEET].SizeOfExcludingThis(SizeOfElementIncludingThis,
+                                               aMallocSizeOf);
+  return n;
+}
+
+
--- a/layout/base/nsStyleSheetService.h
+++ b/layout/base/nsStyleSheetService.h
@@ -17,43 +17,51 @@ class nsISimpleEnumerator;
 class nsICategoryManager;
 
 #define NS_STYLESHEETSERVICE_CID \
 {0xfcca6f83, 0x9f7d, 0x44e4, {0xa7, 0x4b, 0xb5, 0x94, 0x33, 0xe6, 0xc8, 0xc3}}
 
 #define NS_STYLESHEETSERVICE_CONTRACTID \
   "@mozilla.org/content/style-sheet-service;1"
 
+class nsIMemoryReporter;
+
 class nsStyleSheetService MOZ_FINAL : public nsIStyleSheetService
 {
  public:
   nsStyleSheetService() NS_HIDDEN;
   ~nsStyleSheetService() NS_HIDDEN;
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTYLESHEETSERVICE
 
   NS_HIDDEN_(nsresult) Init();
 
   nsCOMArray<nsIStyleSheet>* AgentStyleSheets() { return &mSheets[AGENT_SHEET]; }
   nsCOMArray<nsIStyleSheet>* UserStyleSheets() { return &mSheets[USER_SHEET]; }
 
+  static size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
+
   static nsStyleSheetService *gInstance;
 
  private:
 
   NS_HIDDEN_(void) RegisterFromEnumerator(nsICategoryManager  *aManager,
                                           const char          *aCategory,
                                           nsISimpleEnumerator *aEnumerator,
                                           uint32_t             aSheetType);
 
   NS_HIDDEN_(int32_t) FindSheetByURI(const nsCOMArray<nsIStyleSheet> &sheets,
                                      nsIURI *sheetURI);
 
   // Like LoadAndRegisterSheet, but doesn't notify.  If successful, the
   // new sheet will be the last sheet in mSheets[aSheetType].
   NS_HIDDEN_(nsresult) LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
                                                     uint32_t aSheetType);
-  
+
+  size_t SizeOfIncludingThisHelper(nsMallocSizeOfFun aMallocSizeOf) const;
+
   nsCOMArray<nsIStyleSheet> mSheets[2];
+
+  nsIMemoryReporter* mReporter;
 };
 
 #endif
--- a/layout/build/nsLayoutCID.h
+++ b/layout/build/nsLayoutCID.h
@@ -1,16 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsLayoutCID_h__
 #define nsLayoutCID_h__
 
+// {1691E1F4-EE41-11d4-9885-00C04FA0CF4B}
+#define NS_FRAMETRAVERSAL_CID \
+{ 0x1691e1f4, 0xee41, 0x11d4, { 0x98, 0x85, 0x0, 0xc0, 0x4f, 0xa0, 0xcf, 0x4b } }
+
 /* a6cf90f9-15b3-11d2-932e-00805f8add32 */
 #define NS_LAYOUT_DEBUGGER_CID \
  { 0xa6cf90f9, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
 
 /* a6cf90d7-15b3-11d2-932e-00805f8add32 */
 #define NS_FRAME_UTIL_CID \
  { 0xa6cf90d5, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
 
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -40,16 +40,17 @@
 #include "nsCaret.h"
 #include "nsPlainTextSerializer.h"
 #include "nsXMLContentSerializer.h"
 #include "nsXHTMLContentSerializer.h"
 #include "nsRuleNode.h"
 #include "nsContentAreaDragDrop.h"
 #include "nsContentList.h"
 #include "nsBox.h"
+#include "nsIFrameTraversal.h"
 #include "nsLayoutCID.h"
 #inc