Merge last PGO-green changeset of mozilla-inbound to mozilla-central
authorEd Morley <emorley@mozilla.com>
Fri, 12 Oct 2012 11:59:59 +0100
changeset 110176 83e8792a147ad42739c9bfc661dc3e503444951e
parent 110083 b1775e08bb167b0d05bab35747cb7fa7d86077d7 (current diff)
parent 110175 bb55953508db0a3d86fa8f7937cedafbe28e16bb (diff)
child 110177 cfbf2d4218c825b2d9c17eb6398913c2d294cb57
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
browser/components/privatebrowsing/test/browser/Makefile.in
browser/components/privatebrowsing/test/browser/browser_console_clear.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent_page.html
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_crh.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_fastswitch.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_findbar.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_import.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page.html
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page2.html
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page1.html
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page2.html
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_newwindow_stopcmd.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_openLocationLastURL.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_openlocation.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_pageinfo.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placestitle.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupblocker.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupmode.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_searchbar.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_sslsite_transition.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_theming.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarfocus.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle_page.html
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js
browser/components/privatebrowsing/test/browser/ctxmenu-image.png
browser/components/privatebrowsing/test/browser/ctxmenu.html
browser/components/privatebrowsing/test/browser/head.js
browser/components/privatebrowsing/test/browser/popup.html
browser/components/privatebrowsing/test/browser/staller.sjs
browser/components/privatebrowsing/test/browser/title.sjs
content/base/src/nsStubImageDecoderObserver.cpp
content/base/src/nsStubImageDecoderObserver.h
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
layout/base/nsDisplayList.cpp
layout/reftests/flexbox/flexbox-align-self-horiz-1.xhtml
mobile/android/base/android-sync-files.mk
mobile/android/sync/README.txt
mobile/android/sync/android-drawable-hdpi-resources.mn
mobile/android/sync/android-drawable-ldpi-resources.mn
mobile/android/sync/android-drawable-mdpi-resources.mn
mobile/android/sync/android-drawable-resources.mn
mobile/android/sync/android-layout-resources.mn
mobile/android/sync/android-values-resources.mn
mobile/android/sync/java-sources.mn
mobile/android/sync/java-third-party-sources.mn
mobile/android/sync/manifests/SyncAndroidManifest_activities.xml.in
mobile/android/sync/manifests/SyncAndroidManifest_permissions.xml.in
mobile/android/sync/manifests/SyncAndroidManifest_services.xml.in
mobile/android/sync/preprocess-sources.mn
mobile/android/sync/strings.xml.in
--- a/accessible/src/base/Logging.cpp
+++ b/accessible/src/base/Logging.cpp
@@ -157,23 +157,27 @@ LogDocState(nsIDocument* aDocumentNode)
       break;
   }
 
   printf("doc state: %s", docState);
   printf(", %sinitial", aDocumentNode->IsInitialDocument() ? "" : "not ");
   printf(", %sshowing", aDocumentNode->IsShowing() ? "" : "not ");
   printf(", %svisible", aDocumentNode->IsVisible() ? "" : "not ");
   printf(", %sactive", aDocumentNode->IsActive() ? "" : "not ");
+  printf(", %sresource", aDocumentNode->IsResourceDoc() ? "" : "not ");
+  printf(", has %srole content",
+         nsCoreUtils::GetRoleContent(aDocumentNode) ? "" : "no ");
 }
 
 static void
 LogPresShell(nsIDocument* aDocumentNode)
 {
   nsIPresShell* ps = aDocumentNode->GetShell();
-  printf("presshell: %p", static_cast<void*>(ps));
+  printf("presshell: %p, is %s destroying", static_cast<void*>(ps),
+         (ps->IsDestroying() ? "" : "not"));
   nsIScrollableFrame *sf = ps ?
     ps->GetRootScrollFrameAsScrollableExternal() : nullptr;
   printf(", root scroll frame: %p", static_cast<void*>(sf));
 }
 
 static void
 LogDocLoadGroup(nsIDocument* aDocumentNode)
 {
@@ -421,21 +425,21 @@ logging::DocLoad(const char* aMsg, nsIDo
 }
 
 void
 logging::DocCompleteLoad(DocAccessible* aDocument, bool aIsLoadEventTarget)
 {
   MsgBegin(sDocLoadTitle, "document loaded *completely*");
 
   printf("    DOM document: %p, acc document: %p\n",
-         static_cast<void*>(aDocument->GetDocumentNode()),
+         static_cast<void*>(aDocument->DocumentNode()),
          static_cast<void*>(aDocument));
 
   printf("    ");
-  LogDocURI(aDocument->GetDocumentNode());
+  LogDocURI(aDocument->DocumentNode());
   printf("\n");
 
   printf("    ");
   LogDocAccState(aDocument);
   printf("\n");
 
   printf("    document is load event target: %s\n",
          (aIsLoadEventTarget ? "true" : "false"));
@@ -526,17 +530,17 @@ void
 logging::FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
                                  nsISupports* aTargetThing)
 {
   MsgBegin(sFocusTitle, aMsg);
 
   if (aTargetThing) {
     nsCOMPtr<nsINode> targetNode(do_QueryInterface(aTargetThing));
     if (targetNode)
-      Node(aTargetDescr, targetNode);
+      AccessibleNNode(aTargetDescr, targetNode);
     else
       printf("    %s: %p, window\n", aTargetDescr,
              static_cast<void*>(aTargetThing));
   }
 
   MsgEnd();
 }
 
@@ -651,17 +655,17 @@ void
 logging::Address(const char* aDescr, Accessible* aAcc)
 {
   if (!aAcc->IsDoc()) {
     printf("    %s accessible: %p, node: %p\n", aDescr,
            static_cast<void*>(aAcc), static_cast<void*>(aAcc->GetNode()));
   }
 
   DocAccessible* doc = aAcc->Document();
-  nsIDocument* docNode = aAcc->GetDocumentNode();
+  nsIDocument* docNode = doc->DocumentNode();
   printf("    document: %p, node: %p\n",
          static_cast<void*>(doc), static_cast<void*>(docNode));
 
   printf("    ");
   LogDocURI(docNode);
   printf("\n");
 }
 
@@ -705,16 +709,28 @@ logging::Node(const char* aDescr, nsINod
   if (idAtom)
     idAtom->ToUTF8String(id);
 
   printf("%s: %p, %s@id='%s', idx in parent: %d\n",
          aDescr, static_cast<void*>(elm), tag.get(), id.get(), idxInParent);
 }
 
 void
+logging::Document(DocAccessible* aDocument)
+{
+  printf("    Document: %p, document node: %p\n",
+         static_cast<void*>(aDocument),
+         static_cast<void*>(aDocument->DocumentNode()));
+
+  printf("    Document ");
+  LogDocURI(aDocument->DocumentNode());
+  printf("\n");
+}
+
+void
 logging::AccessibleNNode(const char* aDescr, Accessible* aAccessible)
 {
   printf("    %s: %p; ", aDescr, static_cast<void*>(aAccessible));
   if (!aAccessible)
     return;
 
   nsAutoString role;
   GetAccService()->GetStringRole(aAccessible->Role(), role);
@@ -723,42 +739,45 @@ logging::AccessibleNNode(const char* aDe
 
   printf("role: %s, name: '%s';\n", NS_ConvertUTF16toUTF8(role).get(),
          NS_ConvertUTF16toUTF8(name).get());
 
   nsAutoCString nodeDescr(aDescr);
   nodeDescr.AppendLiteral(" node");
   Node(nodeDescr.get(), aAccessible->GetNode());
 
-  printf("    Document: %p, document node: %p\n",
-         static_cast<void*>(aAccessible->Document()),
-         static_cast<void*>(aAccessible->GetDocumentNode()));
-
-  printf("    Document ");
-  LogDocURI(static_cast<nsIDocument*>(aAccessible->GetDocumentNode()));
-  printf("\n");
+  Document(aAccessible->Document());
 }
 
 void
 logging::AccessibleNNode(const char* aDescr, nsINode* aNode)
 {
   DocAccessible* document =
     GetAccService()->GetDocAccessible(aNode->OwnerDoc());
 
   if (document) {
     Accessible* accessible = document->GetAccessible(aNode);
     if (accessible) {
       AccessibleNNode(aDescr, accessible);
       return;
     }
   }
 
-  nsAutoCString nodeDescr("Not accessible ");
+  nsAutoCString nodeDescr("[not accessible] ");
   nodeDescr.Append(aDescr);
   Node(nodeDescr.get(), aNode);
+
+  if (document) {
+    Document(document);
+    return;
+  }
+
+  printf("    [contained by not accessible document]:\n");
+  LogDocInfo(aNode->OwnerDoc(), document);
+  printf("\n");
 }
 
 void
 logging::DOMEvent(const char* aDescr, nsINode* aOrigTarget,
                   const nsAString& aEventType)
 {
   logging::MsgBegin("DOMEvents", "event '%s' %s",
                     NS_ConvertUTF16toUTF8(aEventType).get(), aDescr);
--- a/accessible/src/base/Logging.h
+++ b/accessible/src/base/Logging.h
@@ -146,16 +146,21 @@ void Text(const char* aText);
 void Address(const char* aDescr, Accessible* aAcc);
 
 /**
  * Log the DOM node info as message entry.
  */
 void Node(const char* aDescr, nsINode* aNode);
 
 /**
+ * Log the document accessible info as message entry.
+ */
+void Document(DocAccessible* aDocument);
+
+/**
  * Log the accessible and its DOM node as a message entry.
  */
 void AccessibleNNode(const char* aDescr, Accessible* aAccessible);
 void AccessibleNNode(const char* aDescr, nsINode* aNode);
 
 /**
  * Log the DOM event.
  */
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -238,18 +238,18 @@ NotificationController::WillRefresh(mozi
 
   // Bind hanging child documents.
   uint32_t hangingDocCnt = mHangingChildDocuments.Length();
   for (uint32_t idx = 0; idx < hangingDocCnt; idx++) {
     DocAccessible* childDoc = mHangingChildDocuments[idx];
     if (childDoc->IsDefunct())
       continue;
 
-    nsIContent* ownerContent = mDocument->GetDocumentNode()->
-      FindContentForSubDocument(childDoc->GetDocumentNode());
+    nsIContent* ownerContent = mDocument->DocumentNode()->
+      FindContentForSubDocument(childDoc->DocumentNode());
     if (ownerContent) {
       Accessible* outerDocAcc = mDocument->GetAccessible(ownerContent);
       if (outerDocAcc && outerDocAcc->AppendChild(childDoc)) {
         if (mDocument->AppendChildDocument(childDoc))
           continue;
 
         outerDocAcc->RemoveChild(childDoc);
       }
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -106,22 +106,16 @@ nsAccessNode::GetFrame() const
 }
 
 nsINode*
 nsAccessNode::GetNode() const
 {
   return mContent;
 }
 
-nsIDocument*
-nsAccessNode::GetDocumentNode() const
-{
-  return mContent ? mContent->OwnerDoc() : nullptr;
-}
-
 void
 nsAccessNode::Language(nsAString& aLanguage)
 {
   aLanguage.Truncate();
 
   if (!mDoc)
     return;
 
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -59,17 +59,16 @@ public:
    * Return frame for the given access node object.
    */
   virtual nsIFrame* GetFrame() const;
   /**
    * Return DOM node associated with the accessible.
    */
   virtual nsINode* GetNode() const;
   nsIContent* GetContent() const { return mContent; }
-  virtual nsIDocument* GetDocumentNode() const;
 
   /**
    * Return node type information of DOM node associated with the accessible.
    */
   bool IsContent() const
   {
     return GetNode() && GetNode()->IsNodeOfType(nsINode::eCONTENT);
   }
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -891,17 +891,17 @@ nsAccessibilityService::GetOrCreateAcces
   }
 
   // We have a content node.
   if (!aNode->IsInDoc()) {
     NS_WARNING("Creating accessible for node with no document");
     return nullptr;
   }
 
-  if (aNode->OwnerDoc() != aDoc->GetDocumentNode()) {
+  if (aNode->OwnerDoc() != aDoc->DocumentNode()) {
     NS_ERROR("Creating accessible for wrong document");
     return nullptr;
   }
 
   if (!aNode->IsContent())
     return nullptr;
 
   nsIContent* content = aNode->AsContent();
--- a/accessible/src/generic/DocAccessible.h
+++ b/accessible/src/generic/DocAccessible.h
@@ -78,17 +78,17 @@ public:
   // nsIDocumentObserver
   NS_DECL_NSIDOCUMENTOBSERVER
 
   // nsAccessNode
   virtual void Init();
   virtual void Shutdown();
   virtual nsIFrame* GetFrame() const;
   virtual nsINode* GetNode() const { return mDocument; }
-  virtual nsIDocument* GetDocumentNode() const { return mDocument; }
+  nsIDocument* DocumentNode() const { return mDocument; }
 
   // Accessible
   virtual mozilla::a11y::ENameValueFlag Name(nsString& aName);
   virtual void Description(nsString& aDescription);
   virtual Accessible* FocusedChild();
   virtual mozilla::a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual uint64_t NativeInteractiveState() const;
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -1480,17 +1480,17 @@ HyperTextAccessible::GetEditor() const
 
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mContent);
   nsCOMPtr<nsIEditingSession> editingSession(do_GetInterface(docShellTreeItem));
   if (!editingSession)
     return nullptr; // No editing session interface
 
   nsCOMPtr<nsIEditor> editor;
-  nsIDocument* docNode = mDoc->GetDocumentNode();
+  nsIDocument* docNode = mDoc->DocumentNode();
   editingSession->GetEditorForWindow(docNode->GetWindow(),
                                      getter_AddRefs(editor));
   return editor.forget();
 }
 
 /**
   * =================== Caret & Selection ======================
   */
@@ -1526,17 +1526,17 @@ HyperTextAccessible::SetSelectionRange(i
   // not focusable. That happens when selection is set within hypertext
   // accessible.
   if (isFocusable)
     return NS_OK;
 
   nsFocusManager* DOMFocusManager = nsFocusManager::GetFocusManager();
   if (DOMFocusManager) {
     NS_ENSURE_TRUE(mDoc, NS_ERROR_FAILURE);
-    nsIDocument* docNode = mDoc->GetDocumentNode();
+    nsIDocument* docNode = mDoc->DocumentNode();
     NS_ENSURE_TRUE(docNode, NS_ERROR_FAILURE);
     nsCOMPtr<nsPIDOMWindow> window = docNode->GetWindow();
     nsCOMPtr<nsIDOMElement> result;
     DOMFocusManager->MoveFocus(window, nullptr, nsIFocusManager::MOVEFOCUS_CARET,
                                nsIFocusManager::FLAG_BYMOVEFOCUS, getter_AddRefs(result));
   }
 
   return NS_OK;
--- a/accessible/src/generic/OuterDocAccessible.cpp
+++ b/accessible/src/generic/OuterDocAccessible.cpp
@@ -128,17 +128,17 @@ OuterDocAccessible::Shutdown()
     logging::OuterDocDestroy(this);
 #endif
 
   Accessible* childAcc = mChildren.SafeElementAt(0, nullptr);
   if (childAcc) {
 #ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eDocDestroy)) {
       logging::DocDestroy("outerdoc's child document shutdown",
-                          childAcc->GetDocumentNode());
+                          childAcc->AsDoc()->DocumentNode());
     }
 #endif
     childAcc->Shutdown();
   }
 
   AccessibleWrap::Shutdown();
 }
 
@@ -172,17 +172,17 @@ OuterDocAccessible::AppendChild(Accessib
     mChildren[0]->Shutdown();
 
   if (!AccessibleWrap::AppendChild(aAccessible))
     return false;
 
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocCreate)) {
     logging::DocCreate("append document to outerdoc",
-                       aAccessible->GetDocumentNode());
+                       aAccessible->AsDoc()->DocumentNode());
     logging::Address("outerdoc", this);
   }
 #endif
 
   return true;
 }
 
 bool
@@ -191,18 +191,18 @@ OuterDocAccessible::RemoveChild(Accessib
   Accessible* child = mChildren.SafeElementAt(0, nullptr);
   if (child != aAccessible) {
     NS_ERROR("Wrong child to remove!");
     return false;
   }
 
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocDestroy)) {
-    logging::DocDestroy("remove document from outerdoc", child->GetDocumentNode(),
-                        child->AsDoc());
+    logging::DocDestroy("remove document from outerdoc",
+                        child->AsDoc()->DocumentNode(), child->AsDoc());
     logging::Address("outerdoc", this);
   }
 #endif
 
   bool wasRemoved = AccessibleWrap::RemoveChild(child);
 
   NS_ASSERTION(!mChildren.Length(),
                "This child document of outerdoc accessible wasn't removed!");
--- a/accessible/src/msaa/AccessibleWrap.cpp
+++ b/accessible/src/msaa/AccessibleWrap.cpp
@@ -161,17 +161,17 @@ AccessibleWrap::get_accParent( IDispatch
     return CO_E_OBJNOTCONNECTED;
 
   DocAccessible* doc = AsDoc();
   if (doc) {
     // Return window system accessible object for root document and tab document
     // accessibles.
     if (!doc->ParentDocument() ||
         nsWinUtils::IsWindowEmulationStarted() &&
-        nsCoreUtils::IsTabDocument(doc->GetDocumentNode())) {
+        nsCoreUtils::IsTabDocument(doc->DocumentNode())) {
       HWND hwnd = static_cast<HWND>(doc->GetNativeWindow());
       if (hwnd && SUCCEEDED(::AccessibleObjectFromWindow(hwnd, OBJID_WINDOW,
                                                          IID_IAccessible,
                                                          (void**)ppdispParent))) {
         return S_OK;
       }
     }
   }
--- a/accessible/src/msaa/RootAccessibleWrap.cpp
+++ b/accessible/src/msaa/RootAccessibleWrap.cpp
@@ -30,17 +30,17 @@ RootAccessibleWrap::~RootAccessibleWrap(
 
 ////////////////////////////////////////////////////////////////////////////////
 // RootAccessible
 
 void
 RootAccessibleWrap::DocumentActivated(DocAccessible* aDocument)
 {
   if (Compatibility::IsDolphin() &&
-      nsCoreUtils::IsTabDocument(aDocument->GetDocumentNode())) {
+      nsCoreUtils::IsTabDocument(aDocument->DocumentNode())) {
     uint32_t count = mChildDocuments.Length();
     for (uint32_t idx = 0; idx < count; idx++) {
       DocAccessible* childDoc = mChildDocuments[idx];
       HWND childDocHWND = static_cast<HWND>(childDoc->GetNativeWindow());
       if (childDoc != aDocument)
         nsWinUtils::HideNativeWindow(childDocHWND);
       else
         nsWinUtils::ShowNativeWindow(childDocHWND);
--- a/b2g/build.mk
+++ b/b2g/build.mk
@@ -13,19 +13,17 @@ endif
 endif
 
 TIERS += app
 
 ifdef MOZ_EXTENSIONS
 tier_app_dirs += extensions
 endif
 
-ifdef MOZ_SERVICES_SYNC
 tier_app_dirs += services
-endif
 
 tier_app_dirs += \
   $(MOZ_BRANDING_DIRECTORY) \
   b2g \
   $(NULL)
 
 
 installer: 
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -12,17 +12,17 @@ MOZ_UA_OS_AGNOSTIC=1
 
 MOZ_B2G_VERSION=1.0.0
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
-MOZ_SERVICES_SYNC=
+MOZ_SERVICES_COMMON=1
 
 MOZ_WEBSMS_BACKEND=1
 MOZ_DISABLE_DOMCRYPTO=1
 MOZ_APP_STATIC_INI=1
 
 if test "$OS_TARGET" = "Android"; then
 MOZ_CAPTURE=1
 MOZ_RAW=1
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -354,16 +354,18 @@
 @BINPATH@/components/nsPrivateBrowsingService.js
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsTryToClose.manifest
 @BINPATH@/components/nsTryToClose.js
 @BINPATH@/components/passwordmgr.manifest
 @BINPATH@/components/nsLoginInfo.js
 @BINPATH@/components/nsLoginManager.js
 @BINPATH@/components/nsLoginManagerPrompter.js
+@BINPATH@/components/SiteSpecificUserAgent.js
+@BINPATH@/components/SiteSpecificUserAgent.manifest
 @BINPATH@/components/storage-Legacy.js
 @BINPATH@/components/storage-mozStorage.js
 @BINPATH@/components/crypto-SDR.js
 @BINPATH@/components/jsconsole-clhandler.manifest
 @BINPATH@/components/jsconsole-clhandler.js
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -477,17 +477,19 @@
     </menupopup>
   </menu>
 
             <menu id="tools-menu"
                   label="&toolsMenu.label;"
                   accesskey="&toolsMenu.accesskey;">
               <menupopup id="menu_ToolsPopup"
 #ifdef MOZ_SERVICES_SYNC
-                         onpopupshowing="gSyncUI.updateUI();"
+                         onpopupshowing="gSyncUI.updateUI(); SocialMenu.populate();"
+#else
+                         onpopupshowing="SocialMenu.populate();"
 #endif
                          >
               <menuitem id="menu_search"
                         class="show-only-for-keyboard"
                         label="&search.label;"
                         accesskey="&search.accesskey;"
                         key="key_search"
                         command="Tools:Search"/>
@@ -502,16 +504,21 @@
                         label="&addons.label;"
                         accesskey="&addons.accesskey;"
                         key="key_openAddons"
                         command="Tools:Addons"/>
               <menuitem id="menu_socialToggle"
                         type="checkbox"
                         autocheck="false"
                         command="Social:Toggle"/>
+              <menu id="menu_socialAmbientMenu"
+                    class="show-only-for-keyboard"
+                    command="Social:Toggle">
+                <menupopup id="menu_socialAmbientMenuPopup"/>
+              </menu>
 #ifdef MOZ_SERVICES_SYNC
               <!-- only one of sync-setup or sync-menu will be showing at once -->
               <menuitem id="sync-setup"
                         label="&syncSetup.label;"
                         accesskey="&syncSetup.accesskey;"
                         observes="sync-setup-state"
                         oncommand="gSyncUI.openSetup()"/>
               <menuitem id="sync-syncnowitem"
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -57,16 +57,17 @@ let SocialUI = {
           SocialFlyout.unload();
         } catch (e) {
           Components.utils.reportError(e);
           throw e;
         }
         break;
       case "social:ambient-notification-changed":
         SocialToolbar.updateButton();
+        SocialMenu.updateMenu();
         break;
       case "social:profile-changed":
         SocialToolbar.updateProfile();
         SocialShareButton.updateProfileInfo();
         SocialChatBar.update();
         break;
       case "nsPref:changed":
         SocialSidebar.updateSidebar();
@@ -102,17 +103,17 @@ let SocialUI = {
 
   updateToggleCommand: function SocialUI_updateToggleCommand() {
     let toggleCommand = this.toggleCommand;
     toggleCommand.setAttribute("checked", Services.prefs.getBoolPref("social.enabled"));
 
     // FIXME: bug 772808: menu items don't inherit the "hidden" state properly,
     // need to update them manually.
     // This should just be: toggleCommand.hidden = !Social.active;
-    for (let id of ["appmenu_socialToggle", "menu_socialToggle"]) {
+    for (let id of ["appmenu_socialToggle", "menu_socialToggle", "menu_socialAmbientMenu"]) {
       let el = document.getElementById(id);
       if (!el)
         continue;
 
       if (Social.active)
         el.removeAttribute("hidden");
       else
         el.setAttribute("hidden", "true");
@@ -579,16 +580,41 @@ let SocialShareButton = {
       shareButton.removeAttribute("shared");
       shareButton.setAttribute("tooltiptext", this.promptMessages['shareTooltip']);
       imageURL = this.promptImages["share"]
     }
     shareButton.style.backgroundImage = 'url("' + encodeURI(imageURL) + '")';
   }
 };
 
+var SocialMenu = {
+  populate: function SocialMenu_populate() {
+    // This menu is only accessible through keyboard navigation.
+    let submenu = document.getElementById("menu_socialAmbientMenuPopup");
+    while (submenu.hasChildNodes())
+      submenu.removeChild(submenu.firstChild);
+    let provider = Social.provider;
+    if (Social.active && provider) {
+      let iconNames = Object.keys(provider.ambientNotificationIcons);
+      for (let name of iconNames) {
+        let icon = provider.ambientNotificationIcons[name];
+        if (!icon.label || !icon.menuURL)
+          continue;
+        let menuitem = document.createElement("menuitem");
+        menuitem.setAttribute("label", icon.label);
+        menuitem.addEventListener("command", function() {
+          openUILinkIn(icon.menuURL, "tab");
+        }, false);
+        submenu.appendChild(menuitem);
+      }
+    }
+    document.getElementById("menu_socialAmbientMenu").hidden = !submenu.querySelector("menuitem");
+  }
+};
+
 var SocialToolbar = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function SocialToolbar_init() {
     this.button.setAttribute("image", Social.provider.iconURL);
     this.updateButton();
     this.updateProfile();
     this._dynamicResizer = new DynamicResizeWatcher();
   },
@@ -712,16 +738,19 @@ var SocialToolbar = {
       let image, label;
       if (stack) {
         image = document.getElementById(imageId);
         label = document.getElementById(labelId);
       } else {
         let box = document.createElement("box");
         box.classList.add("toolbarbutton-1");
         box.setAttribute("id", iconId);
+        // Use the accessibility menuitem label as tooltiptext.
+        if (icon.label)
+          box.setAttribute("tooltiptext", icon.label);
         box.addEventListener("mousedown", function (e) {
           if (e.button == 0)
             SocialToolbar.showAmbientPopup(box);
         }, false);
         box.setAttribute("notificationFrameId", notificationFrameId);
         stack = document.createElement("stack");
         stack.setAttribute("id", stackId);
         stack.classList.add("social-notification-icon-stack");
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7063,19 +7063,16 @@ function getNavToolbox() gNavToolbox;
 # We define a new gPrivateBrowsingUI object, as the per-window PB implementation
 # is completely different to the global PB one.  Specifically, the per-window
 # PB implementation does not expose many APIs on the gPrivateBrowsingUI object,
 # and only uses it as a way to initialize and uninitialize private browsing
 # windows.  While we could use #ifdefs all around the global PB mode code to
 # make it work in both modes, the amount of duplicated code is small and the
 # code is much more readable this way.
 let gPrivateBrowsingUI = {
-  _inited: false,
-  _initCallbacks: [],
-
   init: function PBUI_init() {
     // Do nothing for normal windows
     if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
       return;
     }
 
     // Disable the Clear Recent History... menu item when in PB mode
     // temporary fix until bug 463607 is fixed
@@ -7086,83 +7083,48 @@ let gPrivateBrowsingUI = {
       let docElement = document.documentElement;
       docElement.setAttribute("title",
         docElement.getAttribute("title_privatebrowsing"));
       docElement.setAttribute("titlemodifier",
         docElement.getAttribute("titlemodifier_privatebrowsing"));
       docElement.setAttribute("privatebrowsingmode", "temporary");
       gBrowser.updateTitlebar();
     }
-
-    this._inited = true;
-
-    this._initCallbacks.forEach(function (callback) callback.apply());
-    this._initCallbacks = [];
-  },
-
-  get autoStarted() {
-    return false; // auto-started PB not supported for now
-  },
-
-  get initialized() {
-    return this._inited;
-  },
-
-  addInitializationCallback: function PBUI_addInitializationCallback(aCallback) {
-    if (this._inited)
-      return;
-
-    this._initCallbacks.push(aCallback);
   }
 };
 
 #else
 
 let gPrivateBrowsingUI = {
   _privateBrowsingService: null,
   _searchBarValue: null,
   _findBarValue: null,
   _inited: false,
-  _initCallbacks: [],
 
   init: function PBUI_init() {
     Services.obs.addObserver(this, "private-browsing", false);
     Services.obs.addObserver(this, "private-browsing-transition-complete", false);
 
     this._privateBrowsingService = Cc["@mozilla.org/privatebrowsing;1"].
                                    getService(Ci.nsIPrivateBrowsingService);
 
     if (this.privateBrowsingEnabled)
       this.onEnterPrivateBrowsing(true);
 
     this._inited = true;
-
-    this._initCallbacks.forEach(function (callback) callback.apply());
-    this._initCallbacks = [];
   },
 
   uninit: function PBUI_unint() {
     if (!this._inited)
       return;
 
     Services.obs.removeObserver(this, "private-browsing");
     Services.obs.removeObserver(this, "private-browsing-transition-complete");
   },
 
-  get initialized() {
-    return this._inited;
-  },
-
-  addInitializationCallback: function PBUI_addInitializationCallback(aCallback) {
-    if (this._inited)
-      return;
-
-    this._initCallbacks.push(aCallback);
-  },
-
   get _disableUIOnToggle() {
     if (this._privateBrowsingService.autoStarted)
       return false;
 
     try {
       return !gPrefService.getBoolPref("browser.privatebrowsing.keep_current_session");
     }
     catch (e) {
@@ -7355,20 +7317,16 @@ let gPrivateBrowsingUI = {
     if (!this.privateBrowsingEnabled)
       if (!this._shouldEnter())
         return;
 
     this._privateBrowsingService.privateBrowsingEnabled =
       !this.privateBrowsingEnabled;
   },
 
-  get autoStarted() {
-    return this._privateBrowsingService.autoStarted;
-  },
-
   get privateBrowsingEnabled() {
     return this._privateBrowsingService.privateBrowsingEnabled;
   }
 };
 
 #endif
 
 
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -831,18 +831,21 @@
       <method name="updateCurrentBrowser">
         <parameter name="aForceUpdate"/>
         <body>
           <![CDATA[
             var newBrowser = this.getBrowserAtIndex(this.tabContainer.selectedIndex);
             if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
               return;
 
-            if (!aForceUpdate)
+            if (!aForceUpdate) {
               TelemetryStopwatch.start("FX_TAB_SWITCH_UPDATE_MS");
+              window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils)
+                                                             .beginTabSwitch();
+            }
 
             var oldTab = this.mCurrentTab;
 
             // Preview mode should not reset the owner
             if (!this._previewMode && oldTab != this.selectedTab)
               oldTab.owner = null;
 
             if (this._lastRelatedTab) {
--- a/browser/base/content/test/browser_social_toolbar.js
+++ b/browser/base/content/test/browser_social_toolbar.js
@@ -28,37 +28,75 @@ var tests = {
     // check dom values
     let portrait = document.getElementById("social-statusarea-user-portrait").getAttribute("src");
     is(profile.portrait, portrait, "portrait is set");
     let userButton = document.getElementById("social-statusarea-username");
     ok(!userButton.hidden, "username is visible");
     is(userButton.value, profile.userName, "username is set");
     next();
   },
+  testNoAmbientNotificationsIsNoKeyboardMenu: function(next) {
+    // The menu bar isn't as easy to instrument on Mac.
+    if (navigator.platform.contains("Mac")) {
+      info("Skipping checking the menubar on Mac OS");
+      next();
+    }
+
+    // Test that keyboard accessible menuitem doesn't exist when no ambient icons specified.
+    let toolsPopup = document.getElementById("menu_ToolsPopup");
+    toolsPopup.addEventListener("popupshown", function ontoolspopupshownNoAmbient() {
+      toolsPopup.removeEventListener("popupshown", ontoolspopupshownNoAmbient);
+      let socialToggleMore = document.getElementById("menu_socialAmbientMenu");
+      ok(socialToggleMore, "Keyboard accessible social menu should exist");
+      is(socialToggleMore.hidden, true, "Menu should be hidden when no ambient notifications.");
+      toolsPopup.hidePopup();
+      next();
+    }, false);
+    document.getElementById("menu_ToolsPopup").openPopup();
+  },
   testAmbientNotifications: function(next) {
     let ambience = {
       name: "testIcon",
       iconURL: "https://example.com/browser/browser/base/content/test/moz.png",
       contentPanel: "about:blank",
-      counter: 42
+      counter: 42,
+      label: "Test Ambient 1",
+      menuURL: "https://example.com/testAmbient1"
     };
     Social.provider.setAmbientNotification(ambience);
 
     let statusIcon = document.querySelector("#social-toolbar-item > box");
     waitForCondition(function() {
       statusIcon = document.querySelector("#social-toolbar-item > box");
       return !!statusIcon;
     }, function () {
       let statusIconLabel = statusIcon.querySelector("label");
       is(statusIconLabel.value, "42", "status value is correct");
 
       ambience.counter = 0;
       Social.provider.setAmbientNotification(ambience);
       is(statusIconLabel.value, "", "status value is correct");
-      next();
+
+      // The menu bar isn't as easy to instrument on Mac.
+      if (navigator.platform.contains("Mac"))
+        next();
+
+      // Test that keyboard accessible menuitem was added.
+      let toolsPopup = document.getElementById("menu_ToolsPopup");
+      toolsPopup.addEventListener("popupshown", function ontoolspopupshownAmbient() {
+        toolsPopup.removeEventListener("popupshown", ontoolspopupshownAmbient);
+        let socialToggleMore = document.getElementById("menu_socialAmbientMenu");
+        ok(socialToggleMore, "Keyboard accessible social menu should exist");
+        is(socialToggleMore.hidden, false, "Menu is visible when ambient notifications have label & menuURL");
+        let menuitem = socialToggleMore.querySelector("menuitem");
+        is(menuitem.getAttribute("label"), "Test Ambient 1", "Keyboard accessible ambient menuitem should have specified label");
+        toolsPopup.hidePopup();
+        next();
+      }, false);
+      document.getElementById("menu_ToolsPopup").openPopup();
     }, "statusIcon was never found");
   },
   testProfileUnset: function(next) {
     Social.provider.updateUserProfile({});
     // check dom values
     let userButton = document.getElementById("social-statusarea-username");
     ok(userButton.hidden, "username is not visible");
     let ambientIcons = document.querySelectorAll("#social-toolbar-item > box");
--- a/browser/base/content/test/head.js
+++ b/browser/base/content/test/head.js
@@ -127,16 +127,17 @@ function runSocialTestWithProvider(manif
   let oldProvider;
   SocialService.addProvider(manifest, function(provider) {
     info("runSocialTestWithProvider: provider added");
     oldProvider = Social.provider;
     Social.provider = provider;
 
     // Now that we've set the UI's provider, enable the social functionality
     Services.prefs.setBoolPref("social.enabled", true);
+    Services.prefs.setBoolPref("social.active", true);
 
     // Need to re-call providerReady since it is actually called before the test
     // framework is loaded and the provider state won't be set in the browser yet.
     SocialUI._providerReady();
 
     registerCleanupFunction(function () {
       // if one test happens to fail, it is likely finishSocialTest will not
       // be called, causing most future social tests to also fail as they
@@ -144,16 +145,17 @@ function runSocialTestWithProvider(manif
       // around that by also attempting to remove the test provider.
       try {
         SocialService.removeProvider(provider.origin, finish);
       } catch (ex) {
         ;
       }
       Social.provider = oldProvider;
       Services.prefs.clearUserPref("social.enabled");
+      Services.prefs.clearUserPref("social.active");
     });
 
     function finishSocialTest() {
       SocialService.removeProvider(provider.origin, finish);
     }
     callback(finishSocialTest);
   });
 }
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -8,24 +8,19 @@ Components.utils.import("resource://gre/
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () {
   const PREF = "browser.newtab.url";
   const TOPIC = "private-browsing-transition-complete";
 
   function getNewTabPageURL() {
-    if (("gPrivateBrowsingUI" in window) &&
-        !Services.prefs.prefHasUserValue(PREF)) {
-      // gPrivateBrowsingUI may not be initialized yet, in that case we'll
-      // update BROWSER_NEW_TAB_URL when it gets initialized.
-      if (!gPrivateBrowsingUI.initialized)
-        gPrivateBrowsingUI.addInitializationCallback(update);
-      else if (PrivateBrowsingUtils.isWindowPrivate(window) &&
-               !gPrivateBrowsingUI.autoStarted)
+    if (!Services.prefs.prefHasUserValue(PREF)) {
+      if (PrivateBrowsingUtils.isWindowPrivate(window) &&
+          !PrivateBrowsingUtils.permanentPrivateBrowsing)
         return "about:privatebrowsing";
     }
     return Services.prefs.getCharPref(PREF) || "about:blank";
   }
 
   function update() {
     BROWSER_NEW_TAB_URL = getNewTabPageURL();
   }
--- a/browser/components/feeds/src/nsFeedSniffer.cpp
+++ b/browser/components/feeds/src/nsFeedSniffer.cpp
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsFeedSniffer.h"
 
-#include "prmem.h"
 
 #include "nsNetCID.h"
 #include "nsXPCOM.h"
 #include "nsCOMPtr.h"
 #include "nsStringStream.h"
 
 #include "nsBrowserCompsCID.h"
 
--- a/browser/components/privatebrowsing/test/Makefile.in
+++ b/browser/components/privatebrowsing/test/Makefile.in
@@ -7,14 +7,21 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= test_privatebrowsing
 
+# Most xpcshell PB tests use the global PB service, which means that we should
+# not attempt to run them in regular builds.  We should look at the list and
+# decide which ones of them should be ported to the browser/perwindow suite
+# in the future.
+
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
 XPCSHELL_TESTS	= unit
+endif
 
 DIRS +=	browser \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/components/privatebrowsing/test/browser/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/Makefile.in
@@ -5,70 +5,28 @@
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-MOCHITEST_BROWSER_FILES =  \
-		head.js \
-		browser_console_clear.js \
-		browser_privatebrowsing_certexceptionsui.js \
-		browser_privatebrowsing_commandline_toggle.js \
-		browser_privatebrowsing_concurrent.js \
-		browser_privatebrowsing_concurrent_page.html \
-		browser_privatebrowsing_crh.js \
-		browser_privatebrowsing_fastswitch.js \
-		browser_privatebrowsing_findbar.js \
-		browser_privatebrowsing_forgetthissite.js \
-		browser_privatebrowsing_geoprompt.js \
-		browser_privatebrowsing_geoprompt_page.html \
-		browser_privatebrowsing_import.js \
-		browser_privatebrowsing_lastpbcontextexited.js \
-		browser_privatebrowsing_localStorage.js \
-		browser_privatebrowsing_localStorage_before_after.js \
-		browser_privatebrowsing_localStorage_before_after_page.html \
-		browser_privatebrowsing_localStorage_before_after_page2.html \
-		browser_privatebrowsing_localStorage_page1.html \
-		browser_privatebrowsing_localStorage_page2.html \
-		browser_privatebrowsing_newwindow_stopcmd.js \
-		browser_privatebrowsing_opendir.js \
-		browser_privatebrowsing_openlocation.js \
-		browser_privatebrowsing_openLocationLastURL.js \
-		browser_privatebrowsing_pageinfo.js \
-		browser_privatebrowsing_placestitle.js \
-		browser_privatebrowsing_popupblocker.js \
-		browser_privatebrowsing_popupmode.js \
-		browser_privatebrowsing_protocolhandler.js \
-		browser_privatebrowsing_protocolhandler_page.html \
-		browser_privatebrowsing_searchbar.js \
-		browser_privatebrowsing_sslsite_transition.js \
-		browser_privatebrowsing_theming.js \
-		browser_privatebrowsing_transition.js \
-		browser_privatebrowsing_ui.js \
-		browser_privatebrowsing_urlbarfocus.js \
-		browser_privatebrowsing_urlbarundo.js \
-		browser_privatebrowsing_viewsource.js \
-		browser_privatebrowsing_windowtitle.js \
-		browser_privatebrowsing_windowtitle_page.html \
-		browser_privatebrowsing_zoom.js \
-		browser_privatebrowsing_zoomrestore.js \
-		ctxmenu.html \
-		ctxmenu-image.png \
-		popup.html \
-		staller.sjs \
-		title.sjs \
-		$(NULL)
+MODULE		= test_privatebrowsing
 
-# Disabled until bug 564934 is fixed:
-#		browser_privatebrowsing_downloadmonitor.js \
+# We have three category of browser-chrome tests:
+#  global: these tests focus on the global PB service implementation.
+#  perwindow: these tests focus on the per-window PB implementation.
+#  obsolete: these tests focus on the global mode, but the functionality
+#            that they are testing is specific to the global mode, and
+#            will never have a per-window counterpart.
+#
+# As a transition plan, we have divided the existing tests into the
+# global and obsolete categories, and we'll then focus on rewriting the
+# global tests to test the per-window mode.
 
-# Turn off private browsing tests that perma-timeout on Linux.
-ifneq (Linux,$(OS_ARCH))
-MOCHITEST_BROWSER_FILES += \
-		browser_privatebrowsing_beforeunload.js \
-		browser_privatebrowsing_cookieacceptdialog.js \
-		$(NULL)
+ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
+DIRS += perwindow
+else
+DIRS += global obsolete
 endif
 
 include $(topsrcdir)/config/rules.mk
copy from browser/components/privatebrowsing/test/browser/Makefile.in
copy to browser/components/privatebrowsing/test/browser/global/Makefile.in
--- a/browser/components/privatebrowsing/test/browser/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/global/Makefile.in
@@ -7,68 +7,47 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_BROWSER_FILES =  \
 		head.js \
-		browser_console_clear.js \
 		browser_privatebrowsing_certexceptionsui.js \
-		browser_privatebrowsing_commandline_toggle.js \
-		browser_privatebrowsing_concurrent.js \
-		browser_privatebrowsing_concurrent_page.html \
 		browser_privatebrowsing_crh.js \
-		browser_privatebrowsing_fastswitch.js \
-		browser_privatebrowsing_findbar.js \
-		browser_privatebrowsing_forgetthissite.js \
 		browser_privatebrowsing_geoprompt.js \
 		browser_privatebrowsing_geoprompt_page.html \
-		browser_privatebrowsing_import.js \
-		browser_privatebrowsing_lastpbcontextexited.js \
 		browser_privatebrowsing_localStorage.js \
 		browser_privatebrowsing_localStorage_before_after.js \
 		browser_privatebrowsing_localStorage_before_after_page.html \
 		browser_privatebrowsing_localStorage_before_after_page2.html \
 		browser_privatebrowsing_localStorage_page1.html \
 		browser_privatebrowsing_localStorage_page2.html \
-		browser_privatebrowsing_newwindow_stopcmd.js \
 		browser_privatebrowsing_opendir.js \
 		browser_privatebrowsing_openlocation.js \
 		browser_privatebrowsing_openLocationLastURL.js \
-		browser_privatebrowsing_pageinfo.js \
 		browser_privatebrowsing_placestitle.js \
 		browser_privatebrowsing_popupblocker.js \
-		browser_privatebrowsing_popupmode.js \
 		browser_privatebrowsing_protocolhandler.js \
 		browser_privatebrowsing_protocolhandler_page.html \
-		browser_privatebrowsing_searchbar.js \
 		browser_privatebrowsing_sslsite_transition.js \
 		browser_privatebrowsing_theming.js \
-		browser_privatebrowsing_transition.js \
 		browser_privatebrowsing_ui.js \
 		browser_privatebrowsing_urlbarfocus.js \
-		browser_privatebrowsing_urlbarundo.js \
-		browser_privatebrowsing_viewsource.js \
 		browser_privatebrowsing_windowtitle.js \
 		browser_privatebrowsing_windowtitle_page.html \
 		browser_privatebrowsing_zoom.js \
 		browser_privatebrowsing_zoomrestore.js \
 		ctxmenu.html \
 		ctxmenu-image.png \
 		popup.html \
-		staller.sjs \
 		title.sjs \
 		$(NULL)
 
-# Disabled until bug 564934 is fixed:
-#		browser_privatebrowsing_downloadmonitor.js \
-
 # Turn off private browsing tests that perma-timeout on Linux.
 ifneq (Linux,$(OS_ARCH))
 MOCHITEST_BROWSER_FILES += \
-		browser_privatebrowsing_beforeunload.js \
 		browser_privatebrowsing_cookieacceptdialog.js \
 		$(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_certexceptionsui.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_cookieacceptdialog.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_crh.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_crh.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_geoprompt.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js
+++ b/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_geoprompt.js
@@ -6,17 +6,17 @@
 // control inside the private browsing mode.
 
 function test() {
   // initialization
   let pb = Cc["@mozilla.org/privatebrowsing;1"].
            getService(Ci.nsIPrivateBrowsingService);
 
   const testPageURL = "http://mochi.test:8888/browser/" +
-    "browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html";
+    "browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_geoprompt_page.html";
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function () {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
 
     let notification = PopupNotifications.getNotification("geolocation");
     ok(notification, "Notification should exist");
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_geoprompt_page.html
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_localStorage.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage.js
+++ b/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_localStorage.js
@@ -7,20 +7,20 @@ function test() {
            getService(Ci.nsIPrivateBrowsingService);
   waitForExplicitFinish();
   pb.privateBrowsingEnabled = true;
   let tab = gBrowser.selectedTab = gBrowser.addTab();
   let browser = gBrowser.selectedBrowser;
   browser.addEventListener('load', function() {
     browser.removeEventListener('load', arguments.callee, true);
     let tab2 = gBrowser.selectedTab = gBrowser.addTab();
-    browser.contentWindow.location = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/' +
+    browser.contentWindow.location = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/global/' +
                      'browser_privatebrowsing_localStorage_page2.html';
     browser.addEventListener('load', function() {
       browser.removeEventListener('load', arguments.callee, true);
       is(browser.contentWindow.document.title, '2', "localStorage should contain 2 items");
       pb.privateBrowsingEnabled = false;
       finish();
     }, true);
   }, true);
-  browser.loadURI('http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/' +
+  browser.loadURI('http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/global/' +
                   'browser_privatebrowsing_localStorage_page1.html');
 }
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_localStorage_before_after.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after.js
+++ b/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_localStorage_before_after.js
@@ -6,19 +6,19 @@
 // allow any data to leak due to cached values.
 
 // Step 1: Load browser_privatebrowsing_localStorage_before_after_page.html in a private tab, causing a storage
 //   item to exist. Close the tab.
 // Step 2: Load the same page in a non-private tab, ensuring that the storage instance reports only one item
 //   existing.
 
 function test() {
-  let prefix = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/';
+  let prefix = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/global/';
   waitForExplicitFinish();
-  
+
   // We wait for a GC to ensure that all previous PB docshells in this test suite are destroyed
   // so that the PB localStorage instance is clean.
   Components.utils.schedulePreciseGC(function() {
     let tab = gBrowser.selectedTab = gBrowser.addTab();
     let browser = gBrowser.selectedBrowser;
     browser.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing = true;
     browser.addEventListener('load', function() {
       browser.removeEventListener('load', arguments.callee, true);
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page.html
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_localStorage_before_after_page.html
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page2.html
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_localStorage_before_after_page2.html
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page1.html
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_localStorage_page1.html
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page2.html
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_localStorage_page2.html
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_openLocationLastURL.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_openLocationLastURL.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_opendir.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_openlocation.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_openlocation.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placestitle.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_placestitle.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placestitle.js
+++ b/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_placestitle.js
@@ -9,17 +9,17 @@ function test() {
   // initialization
   let pb = Cc["@mozilla.org/privatebrowsing;1"].
            getService(Ci.nsIPrivateBrowsingService);
   let cm = Cc["@mozilla.org/cookiemanager;1"].
            getService(Ci.nsICookieManager);
   waitForExplicitFinish();
   ignoreAllUncaughtExceptions();
 
-  const TEST_URL = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/title.sjs";
+  const TEST_URL = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/global/title.sjs";
 
   function waitForCleanup(aCallback) {
     // delete all cookies
     cm.removeAll();
     // delete all history items
     waitForClearHistory(aCallback);
   }
 
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupblocker.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_popupblocker.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupblocker.js
+++ b/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_popupblocker.js
@@ -8,17 +8,17 @@
 function test() {
   // initialization
   let pb = Cc["@mozilla.org/privatebrowsing;1"].
            getService(Ci.nsIPrivateBrowsingService);
 
   let oldPopupPolicy = gPrefService.getBoolPref("dom.disable_open_during_load");
   gPrefService.setBoolPref("dom.disable_open_during_load", true);
 
-  const TEST_URI = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/popup.html";
+  const TEST_URI = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/global/popup.html";
 
   waitForExplicitFinish();
 
   function testPopupBlockerMenuItem(expectedDisabled, callback) {
     gBrowser.addEventListener("DOMUpdatePageReport", function() {
       gBrowser.removeEventListener("DOMUpdatePageReport", arguments.callee, false);
       executeSoon(function() {
         let notification = gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked");
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_protocolhandler.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler.js
+++ b/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_protocolhandler.js
@@ -6,17 +6,17 @@
 // inside the private browsing mode.
 
 function test() {
   // initialization
   let pb = Cc["@mozilla.org/privatebrowsing;1"].
            getService(Ci.nsIPrivateBrowsingService);
 
   const testPageURL = "http://example.com/browser/" +
-    "browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html";
+    "browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_protocolhandler_page.html";
   waitForExplicitFinish();
 
   const notificationValue = "Protocol Registration: testprotocol";
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function () {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
 
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_protocolhandler_page.html
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_sslsite_transition.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_sslsite_transition.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_theming.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_theming.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_ui.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarfocus.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_urlbarfocus.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_windowtitle.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle.js
+++ b/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_windowtitle.js
@@ -7,17 +7,17 @@
 
 function test() {
   // initialization
   gPrefService.setBoolPref("browser.privatebrowsing.keep_current_session", true);
   let pb = Cc["@mozilla.org/privatebrowsing;1"].
            getService(Ci.nsIPrivateBrowsingService);
 
   const testPageURL = "http://mochi.test:8888/browser/" +
-    "browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle_page.html";
+    "browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_windowtitle_page.html";
   waitForExplicitFinish();
   requestLongerTimeout(2);
 
   // initialization of expected titles
   let test_title = "Test title";
   let app_name = document.documentElement.getAttribute("title");
   const isOSX = ("nsILocalFileMac" in Ci);
   let page_with_title;
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle_page.html
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_windowtitle_page.html
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_zoom.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js
rename to browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_zoomrestore.js
rename from browser/components/privatebrowsing/test/browser/ctxmenu-image.png
rename to browser/components/privatebrowsing/test/browser/global/ctxmenu-image.png
rename from browser/components/privatebrowsing/test/browser/ctxmenu.html
rename to browser/components/privatebrowsing/test/browser/global/ctxmenu.html
rename from browser/components/privatebrowsing/test/browser/head.js
rename to browser/components/privatebrowsing/test/browser/global/head.js
rename from browser/components/privatebrowsing/test/browser/popup.html
rename to browser/components/privatebrowsing/test/browser/global/popup.html
rename from browser/components/privatebrowsing/test/browser/title.sjs
rename to browser/components/privatebrowsing/test/browser/global/title.sjs
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/obsolete/Makefile.in
@@ -0,0 +1,41 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH		= @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MOCHITEST_BROWSER_FILES =  \
+		head.js \
+		browser_console_clear.js \
+		browser_privatebrowsing_commandline_toggle.js \
+		browser_privatebrowsing_fastswitch.js \
+		browser_privatebrowsing_findbar.js \
+		browser_privatebrowsing_forgetthissite.js \
+		browser_privatebrowsing_import.js \
+		browser_privatebrowsing_newwindow_stopcmd.js \
+		browser_privatebrowsing_pageinfo.js \
+		browser_privatebrowsing_popupmode.js \
+		browser_privatebrowsing_searchbar.js \
+		browser_privatebrowsing_transition.js \
+		browser_privatebrowsing_urlbarundo.js \
+		browser_privatebrowsing_viewsource.js \
+		staller.sjs \
+		$(NULL)
+
+# Disabled until bug 564934 is fixed:
+#		browser_privatebrowsing_downloadmonitor.js \
+
+# Turn off private browsing tests that perma-timeout on Linux.
+ifneq (Linux,$(OS_ARCH))
+MOCHITEST_BROWSER_FILES += \
+		browser_privatebrowsing_beforeunload.js \
+		$(NULL)
+endif
+
+include $(topsrcdir)/config/rules.mk
rename from browser/components/privatebrowsing/test/browser/browser_console_clear.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_console_clear.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_beforeunload.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_commandline_toggle.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_downloadmonitor.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js
+++ b/browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_downloadmonitor.js
@@ -110,17 +110,17 @@ function addDownload(dm, aParams)
     aParams.resultFileName = "download.result";
   if (!("targetFile" in aParams)) {
     let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
                  getService(Ci.nsIProperties);
     aParams.targetFile = dirSvc.get("ProfD", Ci.nsIFile);
     aParams.targetFile.append(aParams.resultFileName);
   }
   if (!("sourceURI" in aParams))
-    aParams.sourceURI = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/staller.sjs";
+    aParams.sourceURI = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/global/staller.sjs";
   if (!("downloadName" in aParams))
     aParams.downloadName = null;
   if (!("runBeforeStart" in aParams))
     aParams.runBeforeStart = function () {};
 
   const nsIWBP = Ci.nsIWebBrowserPersist;
   let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
                 .createInstance(Ci.nsIWebBrowserPersist);
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_fastswitch.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_fastswitch.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_findbar.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_findbar.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_forgetthissite.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_import.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_import.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_import.js
+++ b/browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_import.js
@@ -1,17 +1,15 @@
 /* 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/. */
 
 // This test makes sure that the "Import and Backup->Import From Another Browser"
 // menu item in the Places Organizer is disabled inside private browsing mode.
 
-// TEST_PATH=browser/components/privatebrowsing/test/browser/browser_privatebrowsing_import.js make -C $(OBJDIR) mochitest-browser-chrome
-
 let pb = Cc["@mozilla.org/privatebrowsing;1"].
          getService(Ci.nsIPrivateBrowsingService);
 
 function test() {
   waitForExplicitFinish();
   gPrefService.setBoolPref("browser.privatebrowsing.keep_current_session", true);
 
   // first test: open the library with PB disabled
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_newwindow_stopcmd.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_newwindow_stopcmd.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_pageinfo.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_pageinfo.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupmode.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_popupmode.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_searchbar.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_searchbar.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_transition.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_urlbarundo.js
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_viewsource.js
copy from browser/components/privatebrowsing/test/browser/head.js
copy to browser/components/privatebrowsing/test/browser/obsolete/head.js
--- a/browser/components/privatebrowsing/test/browser/head.js
+++ b/browser/components/privatebrowsing/test/browser/obsolete/head.js
@@ -18,23 +18,8 @@ registerCleanupFunction(function() {
  */
 function waitForClearHistory(aCallback) {
   Services.obs.addObserver(function observeCH(aSubject, aTopic, aData) {
     Services.obs.removeObserver(observeCH, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
     aCallback();
   }, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
   PlacesUtils.bhistory.removeAllPages();
 }
-
-/*
- * Function created to put a window in PB mode.
- * THIS IS DANGEROUS.  DO NOT DO THIS OUTSIDE OF TESTS!
- */
-function setPrivateWindow(aWindow, aEnable) {
-  return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIWebNavigation)
-                 .QueryInterface(Ci.nsIDocShellTreeItem)
-                 .treeOwner
-                 .QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIXULWindow)
-                 .docShell.QueryInterface(Ci.nsILoadContext)
-                 .usePrivateBrowsing = aEnable;
-} 
rename from browser/components/privatebrowsing/test/browser/staller.sjs
rename to browser/components/privatebrowsing/test/browser/obsolete/staller.sjs
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
@@ -0,0 +1,20 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH		= @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MOCHITEST_BROWSER_FILES =  \
+		head.js \
+		browser_privatebrowsing_concurrent.js \
+		browser_privatebrowsing_concurrent_page.html \
+		browser_privatebrowsing_lastpbcontextexited.js \
+		$(NULL)
+
+include $(topsrcdir)/config/rules.mk
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent.js
rename to browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_concurrent.js
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_concurrent.js
@@ -7,17 +7,17 @@
 // earlier private storage sessions aren't visible later.
 
 // Step 1: create new tab, load a page that sets test=value in non-private storage
 // Step 2: create a new tab, load a page that sets test2=value2 in private storage
 // Step 3: load a page in the tab from step 1 that checks the value of test2 is value2 and the total count in non-private storage is 1
 // Step 4: load a page in the tab from step 2 that checks the value of test is value and the total count in private storage is 1
 
 function test() {
-  let prefix = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent_page.html';
+  let prefix = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_concurrent_page.html';
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   let non_private_tab = gBrowser.selectedBrowser;
   non_private_tab.addEventListener('load', function() {
     non_private_tab.removeEventListener('load', arguments.callee, true);
     gBrowser.selectedTab = gBrowser.addTab();
     let private_tab = gBrowser.selectedBrowser;
     private_tab.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing = true;
@@ -65,9 +65,9 @@ function test() {
         }, true);
         private_tab.loadURI(prefix + '?action=get&name=test');
       }, true);
       non_private_tab.loadURI(prefix + '?action=get&name=test2');
     }, true);
     private_tab.loadURI(prefix + '?action=set&name=test2&value=value2');
   }, true);
   non_private_tab.loadURI(prefix + '?action=set&name=test&value=value&initial=true');
-}
\ No newline at end of file
+}
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent_page.html
rename to browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_concurrent_page.html
rename from browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
rename to browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_lastpbcontextexited.js
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/perwindow/head.js
@@ -0,0 +1,14 @@
+/*
+ * Function created to put a window in PB mode.
+ * THIS IS DANGEROUS.  DO NOT DO THIS OUTSIDE OF TESTS!
+ */
+function setPrivateWindow(aWindow, aEnable) {
+  return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsIDocShellTreeItem)
+                 .treeOwner
+                 .QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIXULWindow)
+                 .docShell.QueryInterface(Ci.nsILoadContext)
+                 .usePrivateBrowsing = aEnable;
+} 
--- a/browser/components/safebrowsing/content/test/Makefile.in
+++ b/browser/components/safebrowsing/content/test/Makefile.in
@@ -13,15 +13,16 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 # The browser chrome test for bug 415846 doesn't run on Mac because of its
 # bizarre special-and-unique snowflake of a help menu.
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _NON_MAC_BROWSER_TESTS = browser_bug415846.js
 endif
 
-_BROWSER_FILES = browser_bug400731.js \
+_BROWSER_FILES = head.js \
+                 browser_bug400731.js \
                  $(_NON_MAC_BROWSER_TESTS) \
     $(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
 
new file mode 100644
--- /dev/null
+++ b/browser/components/safebrowsing/content/test/head.js
@@ -0,0 +1,3 @@
+// Force SafeBrowsing to be initialized for the tests
+SafeBrowsing.init();
+
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -14,16 +14,18 @@ if test "$OS_ARCH" = "WINNT"; then
     MOZ_MAINTENANCE_SERVICE=1
   fi
 fi
 
 MOZ_STUB_INSTALLER=1
 MOZ_CHROME_FILE_FORMAT=omni
 MOZ_SAFE_BROWSING=1
 MOZ_SERVICES_AITC=1
+MOZ_SERVICES_COMMON=1
+MOZ_SERVICES_CRYPTO=1
 MOZ_SERVICES_NOTIFICATIONS=1
 MOZ_SERVICES_SYNC=1
 MOZ_APP_VERSION=$FIREFOX_VERSION
 MOZ_EXTENSIONS_DEFAULT=" gio"
 # MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
 # Changing MOZ_*BRANDING_DIRECTORY requires a clobber to ensure correct results,
 # because branding dependencies are broken.
 # MOZ_BRANDING_DIRECTORY is the default branding directory used when none is
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -340,16 +340,18 @@
 @BINPATH@/components/nsSetDefaultBrowser.js
 @BINPATH@/components/BrowserDownloads.manifest
 @BINPATH@/components/DownloadsStartup.js
 @BINPATH@/components/DownloadsUI.js
 @BINPATH@/components/BrowserPlaces.manifest
 @BINPATH@/components/BrowserPageThumbs.manifest
 @BINPATH@/components/nsPrivateBrowsingService.manifest
 @BINPATH@/components/nsPrivateBrowsingService.js
+@BINPATH@/components/SiteSpecificUserAgent.js
+@BINPATH@/components/SiteSpecificUserAgent.manifest
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsSearchService.js
 @BINPATH@/components/nsSearchSuggestions.js
 @BINPATH@/components/passwordmgr.manifest
 @BINPATH@/components/nsLoginInfo.js
 @BINPATH@/components/nsLoginManager.js
 @BINPATH@/components/nsLoginManagerPrompter.js
 @BINPATH@/components/storage-Legacy.js
--- a/browser/themes/pinstripe/downloads/downloads.css
+++ b/browser/themes/pinstripe/downloads/downloads.css
@@ -157,16 +157,17 @@ richlistitem[type="download"][state="1"]
   -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;
 }
 
 #downloads-indicator-anchor {
   min-width: 20px;
   min-height: 20px;
   /* Makes the outermost stack element positioned, so that its contents are
@@ -246,27 +247,27 @@ richlistitem[type="download"][state="1"]
 #downloads-indicator[notification]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
   animation-name: downloadsIndicatorNotificationLeft;
 }
 
 /*** Progress bar and text ***/
 
 #downloads-indicator-counter {
   height: 10px;
-  margin: 0;
+  margin: -3px 0 0;
   color: hsl(0,0%,30%);
   text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
   font-size: 10px;
   line-height: 10px;
   text-align: center;
 }
 
 #downloads-indicator-progress {
   width: 16px;
-  height: 6px;
+  height: 4px;
   min-width: 0;
   min-height: 0;
   margin-top: 1px;
   margin-bottom: 2px;
   border-radius: 2px;
   box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
 }
 
--- a/configure.in
+++ b/configure.in
@@ -1481,23 +1481,21 @@ if test "$GNU_CXX"; then
     # Turn on GNU-specific warnings:
     # -Wall - turn on a lot of warnings
     # -pedantic - this is turned on below
     # -Wpointer-arith - enabled with -pedantic, but good to have even if not
     # -Woverloaded-virtual - ???
     # -Werror=return-type - catches missing returns, zero false positives
     # -Wtype-limits - catches overflow bugs, few false positives
     # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
-    # -Werror=conversion-null - catches conversions between NULL and non-pointer types
     #
     _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual"
     MOZ_CXX_SUPPORTS_WARNING(-W, error=return-type, ac_cxx_has_werror_return_type)
     MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits)
     MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body)
-    MOZ_CXX_SUPPORTS_WARNING(-W, error=conversion-null, ac_cxx_has_werror_conversion_null)
 
     # Turn off the following warnings that -Wall/-pedantic turn on:
     # -Wno-ctor-dtor-privacy - ???
     # -Wno-overlength-strings - we exceed the minimum maximum length frequently 
     # -Wno-invalid-offsetof - we use offsetof on non-POD types frequently
     # -Wno-variadic-macros - ???
     #
     _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-ctor-dtor-privacy"
@@ -8235,16 +8233,28 @@ if test "$MOZ_PLACES"; then
 fi
 
 dnl Build Apps in the Cloud (AITC) if required
 AC_SUBST(MOZ_SERVICES_AITC)
 if test -n "$MOZ_SERVICES_AITC"; then
   AC_DEFINE(MOZ_SERVICES_AITC)
 fi
 
+dnl Build Common JS modules provided by services.
+AC_SUBST(MOZ_SERVICES_COMMON)
+if test -n "$MOZ_SERVICES_COMMON"; then
+  AC_DEFINE(MOZ_SERVICES_COMMON)
+fi
+
+dnl Build Services crypto component (used by Sync)
+AC_SUBST(MOZ_SERVICES_CRYPTO)
+if test -n "$MOZ_SERVICES_CRYPTO"; then
+  AC_DEFINE(MOZ_SERVICES_CRYPTO)
+fi
+
 dnl Build Notifications if required
 AC_SUBST(MOZ_SERVICES_NOTIFICATIONS)
 if test -n "$MOZ_SERVICES_NOTIFICATIONS"; then
   AC_DEFINE(MOZ_SERVICES_NOTIFICATIONS)
 fi
 
 dnl Build Sync Services if required
 AC_SUBST(MOZ_SERVICES_SYNC)
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -569,31 +569,39 @@ NS_IMETHODIMP nsImageLoadingContent::For
 
 NS_IMETHODIMP
 nsImageLoadingContent::BlockOnload(imgIRequest* aRequest)
 {
   if (aRequest != mCurrentRequest) {
     return NS_OK;
   }
 
+  NS_ASSERTION(!(mCurrentRequestFlags & REQUEST_BLOCKS_ONLOAD),
+               "Double BlockOnload!?");
+  mCurrentRequestFlags |= REQUEST_BLOCKS_ONLOAD;
+
   nsIDocument* doc = GetOurCurrentDoc();
   if (doc) {
     doc->BlockOnload();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsImageLoadingContent::UnblockOnload(imgIRequest* aRequest)
 {
   if (aRequest != mCurrentRequest) {
     return NS_OK;
   }
 
+  NS_ASSERTION(mCurrentRequestFlags & REQUEST_BLOCKS_ONLOAD,
+               "Double UnblockOnload!?");
+  mCurrentRequestFlags &= ~REQUEST_BLOCKS_ONLOAD;
+
   nsIDocument* doc = GetOurCurrentDoc();
   if (doc) {
     doc->UnblockOnload(false);
   }
 
   return NS_OK;
 }
 
@@ -1162,16 +1170,19 @@ nsImageLoadingContent::BindToTree(nsIDoc
   // below code won't think they're being called from JS.
   nsCxPusher pusher;
   pusher.PushNull();
 
   if (mCurrentRequestFlags & REQUEST_SHOULD_BE_TRACKED)
     aDocument->AddImage(mCurrentRequest);
   if (mPendingRequestFlags & REQUEST_SHOULD_BE_TRACKED)
     aDocument->AddImage(mPendingRequest);
+
+  if (mCurrentRequestFlags & REQUEST_BLOCKS_ONLOAD)
+    aDocument->BlockOnload();
 }
 
 void
 nsImageLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   // We may be leaving the document, so if our image is tracked, untrack it.
   nsCOMPtr<nsIDocument> doc = GetOurCurrentDoc();
   if (!doc)
@@ -1181,16 +1192,19 @@ nsImageLoadingContent::UnbindFromTree(bo
   // below code won't think they're being called from JS.
   nsCxPusher pusher;
   pusher.PushNull();
 
   if (mCurrentRequestFlags & REQUEST_SHOULD_BE_TRACKED)
     doc->RemoveImage(mCurrentRequest);
   if (mPendingRequestFlags & REQUEST_SHOULD_BE_TRACKED)
     doc->RemoveImage(mPendingRequest);
+
+  if (mCurrentRequestFlags & REQUEST_BLOCKS_ONLOAD)
+    doc->UnblockOnload(false);
 }
 
 nsresult
 nsImageLoadingContent::TrackImage(imgIRequest* aImage)
 {
   if (!aImage)
     return NS_OK;
 
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -320,17 +320,19 @@ protected:
   uint32_t mCurrentRequestFlags;
   uint32_t mPendingRequestFlags;
 
   enum {
     // Set if the request needs 
     REQUEST_NEEDS_ANIMATION_RESET = 0x00000001U,
     // Set if the request should be tracked.  This is true if the request is
     // not tracked iff this node is not in the document.
-    REQUEST_SHOULD_BE_TRACKED = 0x00000002U
+    REQUEST_SHOULD_BE_TRACKED = 0x00000002U,
+    // Set if the request is blocking onload.
+    REQUEST_BLOCKS_ONLOAD = 0x00000004U
   };
 
   // If the image was blocked or if there was an error loading, it's nice to
   // still keep track of what the URI was despite not having an imgIRequest.
   // We only maintain this in those situations (in the common case, this is
   // always null).
   nsCOMPtr<nsIURI>      mCurrentURI;
 
--- a/content/base/src/nsMappedAttributes.cpp
+++ b/content/base/src/nsMappedAttributes.cpp
@@ -6,17 +6,16 @@
 /*
  * A unique per-element set of attributes that is used as an
  * nsIStyleRule; used to implement presentational attributes.
  */
 
 #include "nsMappedAttributes.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsRuleWalker.h"
-#include "prmem.h"
 #include "mozilla/HashFunctions.h"
 
 using namespace mozilla;
 
 nsMappedAttributes::nsMappedAttributes(nsHTMLStyleSheet* aSheet,
                                        nsMapRuleToAttributesFunc aMapRuleFunc)
   : mAttrCount(0),
     mSheet(aSheet),
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -3821,19 +3821,21 @@ nsXMLHttpRequest::GetInterface(const nsI
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Verify that it's ok to prompt for credentials here, per spec
     // http://xhr.spec.whatwg.org/#the-send%28%29-method
     bool showPrompt = true;
 
     // If authentication fails, XMLHttpRequest origin and
     // the request URL are same origin, ...
+    /* Disabled - bug: 799540
     if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
       showPrompt = false;
     }
+    */
 
     // ... Authorization is not in the list of author request headers, ...
     if (showPrompt) {
       for (uint32_t i = 0, len = mModifiedRequestHeaders.Length(); i < len; ++i) {
         if (mModifiedRequestHeaders[i].header.
               LowerCaseEqualsLiteral("authorization")) {
           showPrompt = false;
           break;
--- a/content/base/test/bug282547.sjs
+++ b/content/base/test/bug282547.sjs
@@ -1,5 +1,9 @@
 function handleRequest(request, response)
 {
   response.setStatusLine(null, 401, "Unauthorized");
+
   response.setHeader("WWW-Authenticate", "basic realm=\"restricted\"", false);
+
+  response.setHeader("Access-Control-Allow-Origin", "*", false);
+  response.setHeader("Access-Control-Allow-Credentials", "true", false);
 }
--- a/content/base/test/test_bug282547.html
+++ b/content/base/test/test_bug282547.html
@@ -60,20 +60,36 @@ function xhr_auth_header_async() {
       ok(xhr.status == 401, "Status 401");
       runTests();
     }
   }
 
   xhr.send(null);
 }
 
+function xhr_crossorigin_sync() {
+  var xhr = new XMLHttpRequest();
+  xhr.open('GET', 'http://example.com/tests/content/base/test/bug282547.sjs', true);
+  xhr.withCredentials = true;
+
+  xhr.onreadystatechange = function() {
+    if (xhr.readyState == 4) {
+      ok(xhr.status == 401, "Status 401");
+      runTests();
+    }
+  }
+
+  xhr.send(null);
+}
+
 var tests = [ xhr_userpass_sync,
               xhr_userpass_async,
               xhr_auth_header_sync,
-              xhr_auth_header_async ];
+              xhr_auth_header_async,
+              /* Disabled: bug799540 xhr_crossorigin_sync */ ];
 function runTests() {
   if (!tests.length) {
     SimpleTest.finish();
     return;
   }
 
   var test = tests.shift();
   test();
--- a/content/canvas/Makefile.in
+++ b/content/canvas/Makefile.in
@@ -7,12 +7,12 @@ DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 PARALLEL_DIRS	= public src
 
-TOOLS_DIRS += test
+TEST_DIRS += test
 
 include $(topsrcdir)/config/rules.mk
 
--- a/content/canvas/src/CanvasUtils.cpp
+++ b/content/canvas/src/CanvasUtils.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdlib.h>
 #include <stdarg.h>
 
-#include "prmem.h"
 #include "prprf.h"
 
 #include "nsIServiceManager.h"
 
 #include "nsIConsoleService.h"
 #include "nsIDOMCanvasRenderingContext2D.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsHTMLCanvasElement.h"
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -56,16 +56,28 @@
 #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;
+
 class nsIPropertyBag;
 
 namespace mozilla {
 
 class WebGLTexture;
 class WebGLBuffer;
 class WebGLProgram;
 class WebGLShader;
--- a/content/canvas/src/WebGLElementArrayCache.cpp
+++ b/content/canvas/src/WebGLElementArrayCache.cpp
@@ -141,63 +141,62 @@ public:
   WebGLElementArrayCacheTree(WebGLElementArrayCache& p)
     : mParent(p)
     , mNumLeaves(0)
     , mInvalidated(false)
     , mFirstInvalidatedLeaf(0)
     , mLastInvalidatedLeaf(0)
   {
     ResizeToParentSize();
-    Invalidate(0, mParent.ByteSize() - 1);
   }
 
   T GlobalMaximum() const {
     MOZ_ASSERT(!mInvalidated);
     return mTreeData[1];
   }
 
   // returns the index of the parent node; if treeIndex=1 (the root node),
   // the return value is 0.
   static size_t ParentNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex);
+    MOZ_ASSERT(treeIndex > 1);
     return treeIndex >> 1;
   }
 
   static bool IsRightNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex);
+    MOZ_ASSERT(treeIndex > 1);
     return treeIndex & 1;
   }
 
   static bool IsLeftNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex);
+    MOZ_ASSERT(treeIndex > 1);
     return !IsRightNode(treeIndex);
   }
 
   static size_t SiblingNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex);
+    MOZ_ASSERT(treeIndex > 1);
     return treeIndex ^ 1;
   }
 
   static size_t LeftChildNode(size_t treeIndex) {
     MOZ_ASSERT(treeIndex);
     return treeIndex << 1;
   }
 
   static size_t RightChildNode(size_t treeIndex) {
     MOZ_ASSERT(treeIndex);
     return SiblingNode(LeftChildNode(treeIndex));
   }
 
   static size_t LeftNeighborNode(size_t treeIndex, size_t distance = 1) {
-    MOZ_ASSERT(treeIndex);
+    MOZ_ASSERT(treeIndex > 1);
     return treeIndex - distance;
   }
 
   static size_t RightNeighborNode(size_t treeIndex, size_t distance = 1) {
-    MOZ_ASSERT(treeIndex);
+    MOZ_ASSERT(treeIndex > 1);
     return treeIndex + distance;
   }
 
   size_t LeafForElement(size_t element) {
     size_t leaf = element / sElementsPerLeaf;
     MOZ_ASSERT(leaf < mNumLeaves);
     return leaf;
   }
@@ -282,20 +281,28 @@ public:
     return result;
   }
 
   bool ResizeToParentSize()
   {
     size_t numberOfElements = mParent.ByteSize() / sizeof(T);
     size_t requiredNumLeaves = (numberOfElements + sElementsPerLeaf - 1) / sElementsPerLeaf;
 
+    size_t oldNumLeaves = mNumLeaves;
     mNumLeaves = NextPowerOfTwo(requiredNumLeaves);
+    Invalidate(0, mParent.ByteSize() - 1);
 
     // see class comment for why we the tree storage size is 2 * mNumLeaves
-    return mTreeData.SetLength(2 * mNumLeaves);
+    if (!mTreeData.SetLength(2 * mNumLeaves)) {
+      return false;
+    }
+    if (mNumLeaves != oldNumLeaves) {
+      memset(mTreeData.Elements(), 0, mTreeData.Length() * sizeof(mTreeData[0]));
+    }
+    return true;
   }
 
   void Invalidate(size_t firstByte, size_t lastByte);
 
   void Update();
 
   size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
   {
@@ -375,33 +382,28 @@ void WebGLElementArrayCacheTree<T>::Upda
       }
       mTreeData[treeIndex] = m;
       treeIndex++;
     }
   }
 
   // Step #2: propagate the values up the tree. This is simply a matter of walking up
   // the tree and setting each node to the max of its two children.
-  while (true) {
-
-    // fast-exit case where only one node is invalidated at the current level
-    if (firstTreeIndex == lastTreeIndex) {
-      size_t firstTreeIndexParent = ParentNode(firstTreeIndex);
-      while (firstTreeIndexParent) {
-        mTreeData[firstTreeIndexParent] = NS_MAX(mTreeData[firstTreeIndex], mTreeData[SiblingNode(firstTreeIndex)]);
-        firstTreeIndex = firstTreeIndexParent;
-        firstTreeIndexParent = ParentNode(firstTreeIndex);
-      }
-      break;
-    }
+  while (firstTreeIndex > 1) {
 
     // move up 1 level
     firstTreeIndex = ParentNode(firstTreeIndex);
     lastTreeIndex = ParentNode(lastTreeIndex);
 
+    // fast-exit case where only one node is invalidated at the current level
+    if (firstTreeIndex == lastTreeIndex) {
+      mTreeData[firstTreeIndex] = NS_MAX(mTreeData[LeftChildNode(firstTreeIndex)], mTreeData[RightChildNode(firstTreeIndex)]);
+      continue;
+    }
+
     // initialize local iteration variables: child and parent.
     size_t child = LeftChildNode(firstTreeIndex);
     size_t parent = firstTreeIndex;
 
     // the unrolling makes this look more complicated than it is; the plain non-unrolled
     // version is in the second while loop below
     const int unrollSize = 8;
     while (RightNeighborNode(parent, unrollSize - 1) <= lastTreeIndex)
--- a/content/canvas/src/WebGLElementArrayCache.h
+++ b/content/canvas/src/WebGLElementArrayCache.h
@@ -60,17 +60,17 @@ private:
   template<typename T>
   const T* Elements() const { return static_cast<const T*>(mUntypedData); }
   template<typename T>
   T* Elements() { return static_cast<T*>(mUntypedData); }
 
   void InvalidateTrees(size_t firstByte, size_t lastByte);
 
   template<typename T>
-  friend class WebGLElementArrayCacheTree;
+  friend struct WebGLElementArrayCacheTree;
   template<typename T>
   friend struct TreeForType;
 
   void* mUntypedData;
   size_t mByteSize;
   WebGLElementArrayCacheTree<uint8_t>* mUint8Tree;
   WebGLElementArrayCacheTree<uint16_t>* mUint16Tree;
 };
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -3,17 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 #include "nsIDOMXULElement.h"
 
-#include "prmem.h"
 #include "prenv.h"
 
 #include "nsIServiceManager.h"
 #include "nsMathUtils.h"
 
 #include "nsContentUtils.h"
 
 #include "nsIDocument.h"
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 #include "nsCanvasRenderingContext2DAzure.h"
 
 #include "nsIDOMXULElement.h"
 
-#include "prmem.h"
 #include "prenv.h"
 
 #include "nsIServiceManager.h"
 #include "nsMathUtils.h"
 
 #include "nsContentUtils.h"
 
 #include "nsIDocument.h"
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -5,17 +5,17 @@
 
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = @relativesrcdir@
 DIRS		+= webgl crossorigin
 
-TOOLS_DIRS += compiled
+# TEST_DIRS += compiled
 
 include $(DEPTH)/config/autoconf.mk
 MOCHITEST_FILES = \
 	test_canvas.html \
 	image_transparent50.png \
 	image_redtransparent.png \
 	image_yellow.png \
 	image_anim-poster-gr.png \
--- a/content/canvas/test/compiled/TestWebGLElementArrayCache.cpp
+++ b/content/canvas/test/compiled/TestWebGLElementArrayCache.cpp
@@ -26,24 +26,21 @@ void VerifyImplFunction(bool condition, 
   }
 }
 
 #define VERIFY(condition) \
     VerifyImplFunction((condition), __FILE__, __LINE__)
 
 void MakeRandomVector(nsTArray<uint8_t>& a, size_t size) {
   a.SetLength(size);
-  // only the most-significant bits of rand() are reasonably random
-  // 16 here is arbitrary, may fail on platforms where RAND_MAX is low,
-  // but guarded by an assertion.
-  enum { bitsToIgnore = 16 };
-  MOZ_STATIC_ASSERT((unsigned int)(RAND_MAX) >> (8 + bitsToIgnore),
-                    "Didn't expect RAND_MAX to be so low");
+  // only the most-significant bits of rand() are reasonably random.
+  // RAND_MAX can be as low as 0x7fff, and we need 8 bits for the result, so we can only
+  // ignore the 7 least significant bits.
   for (size_t i = 0; i < size; i++)
-    a[i] = static_cast<uint8_t>((unsigned int)(rand()) >> bitsToIgnore);
+    a[i] = static_cast<uint8_t>((unsigned int)(rand()) >> 7);
 }
 
 template<typename T>
 T RandomInteger(T a, T b)
 {
   T result(a + rand() % (b - a + 1));
   return result;
 }
--- a/content/canvas/test/test_bug764125.html
+++ b/content/canvas/test/test_bug764125.html
@@ -23,14 +23,14 @@ where only one tranform ought to be appl
 
 var c = document.createElement("canvas");
 
 var ctx = c.getContext("2d");
 ctx.translate(50, 0);
 ctx.rect(50, 0, 20, 20);
 ctx.translate(0, 50);
 ok(ctx.isPointInPath(60, 10) === false, "ctx.isPointInPath(60, 10) === false");
-ok(ctx.isPointInPath(110, 10) === true, "ctx.isPointInPath(110, 10) === true");
+// ok(ctx.isPointInPath(110, 10) === true, "ctx.isPointInPath(110, 10) === true"); // reenable me ASAP!
 ok(ctx.isPointInPath(110, 60) === false, "ctx.isPointInPath(110, 60) === false");
 </script>
 </pre>
 </body>
 </html>
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -13374,20 +13374,20 @@ ok(ctx.isPointInPath(50, 10) === true, "
 function test_2d_path_isPointInPath_transform_1() {
 
 var canvas = document.getElementById('c409');
 var ctx = canvas.getContext('2d');
 
 ctx.translate(50, 0);
 ctx.rect(0, 0, 20, 20);
 ok(ctx.isPointInPath(-40, 10) === false, "ctx.isPointInPath(-40, 10) === false");
-ok(ctx.isPointInPath(10, 10) === false, "ctx.isPointInPath(10, 10) === false");
+// ok(ctx.isPointInPath(10, 10) === false, "ctx.isPointInPath(10, 10) === false"); // reenable me ASAP!
 ok(ctx.isPointInPath(49, 10) === false, "ctx.isPointInPath(49, 10) === false");
-ok(ctx.isPointInPath(51, 10) === true, "ctx.isPointInPath(51, 10) === true");
-ok(ctx.isPointInPath(69, 10) === true, "ctx.isPointInPath(69, 10) === true");
+// ok(ctx.isPointInPath(51, 10) === true, "ctx.isPointInPath(51, 10) === true"); // reenable me ASAP!
+// ok(ctx.isPointInPath(69, 10) === true, "ctx.isPointInPath(69, 10) === true"); // reenable me ASAP!
 ok(ctx.isPointInPath(71, 10) === false, "ctx.isPointInPath(71, 10) === false");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.path.isPointInPath.transform.2.html ]]] -->
 
@@ -13399,20 +13399,20 @@ ok(ctx.isPointInPath(71, 10) === false, 
 function test_2d_path_isPointInPath_transform_2() {
 
 var canvas = document.getElementById('c410');
 var ctx = canvas.getContext('2d');
 
 ctx.rect(50, 0, 20, 20);
 ctx.translate(50, 0);
 ok(ctx.isPointInPath(-40, 10) === false, "ctx.isPointInPath(-40, 10) === false");
-ok(ctx.isPointInPath(10, 10) === false, "ctx.isPointInPath(10, 10) === false");
+// ok(ctx.isPointInPath(10, 10) === false, "ctx.isPointInPath(10, 10) === false"); // reenable me ASAP!
 ok(ctx.isPointInPath(49, 10) === false, "ctx.isPointInPath(49, 10) === false");
-ok(ctx.isPointInPath(51, 10) === true, "ctx.isPointInPath(51, 10) === true");
-ok(ctx.isPointInPath(69, 10) === true, "ctx.isPointInPath(69, 10) === true");
+// ok(ctx.isPointInPath(51, 10) === true, "ctx.isPointInPath(51, 10) === true"); // reenable me ASAP!
+// ok(ctx.isPointInPath(69, 10) === true, "ctx.isPointInPath(69, 10) === true"); // reenable me ASAP!
 ok(ctx.isPointInPath(71, 10) === false, "ctx.isPointInPath(71, 10) === false");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.path.isPointInPath.transform.3.html ]]] -->
 
@@ -13424,20 +13424,20 @@ ok(ctx.isPointInPath(71, 10) === false, 
 function test_2d_path_isPointInPath_transform_3() {
 
 var canvas = document.getElementById('c411');
 var ctx = canvas.getContext('2d');
 
 ctx.scale(-1, 1);
 ctx.rect(-70, 0, 20, 20);
 ok(ctx.isPointInPath(-40, 10) === false, "ctx.isPointInPath(-40, 10) === false");
-ok(ctx.isPointInPath(10, 10) === false, "ctx.isPointInPath(10, 10) === false");
+// ok(ctx.isPointInPath(10, 10) === false, "ctx.isPointInPath(10, 10) === false"); // reenable me ASAP!
 ok(ctx.isPointInPath(49, 10) === false, "ctx.isPointInPath(49, 10) === false");
-ok(ctx.isPointInPath(51, 10) === true, "ctx.isPointInPath(51, 10) === true");
-ok(ctx.isPointInPath(69, 10) === true, "ctx.isPointInPath(69, 10) === true");
+// ok(ctx.isPointInPath(51, 10) === true, "ctx.isPointInPath(51, 10) === true"); // reenable me ASAP!
+// ok(ctx.isPointInPath(69, 10) === true, "ctx.isPointInPath(69, 10) === true"); // reenable me ASAP!
 ok(ctx.isPointInPath(71, 10) === false, "ctx.isPointInPath(71, 10) === false");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.path.isPointInPath.unclosed.html ]]] -->
 
@@ -23522,17 +23522,17 @@ function runTests() {
   ok(false, "unexpected exception thrown in: test_2d_path_isPointInPath_outside");
  }
  try {
   test_2d_path_isPointInPath_subpath();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_path_isPointInPath_subpath");
  }
  try {
-  test_2d_path_isPointInPath_transform_1();
+   test_2d_path_isPointInPath_transform_1();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_path_isPointInPath_transform_1");
  }
  try {
   test_2d_path_isPointInPath_transform_2();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_path_isPointInPath_transform_2");
  }
--- a/content/canvas/test/webgl/conformance/buffers/00_test_list.txt
+++ b/content/canvas/test/webgl/conformance/buffers/00_test_list.txt
@@ -1,8 +1,8 @@
 buffer-bind-test.html
 buffer-data-array-buffer.html
 index-validation-copies-indices.html
 index-validation-crash-with-buffer-sub-data.html
 index-validation-verifies-too-many-indices.html
 index-validation-with-resized-buffer.html
-index-validation.html
+#index-validation.html # reenable me ASAP!
 
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -14,17 +14,16 @@
 #include "nsDOMEvent.h"
 #include "nsEventStateManager.h"
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsIDocument.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
-#include "prmem.h"
 #include "nsGkAtoms.h"
 #include "nsMutationEvent.h"
 #include "nsContentUtils.h"
 #include "nsIURI.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScriptError.h"
 #include "mozilla/Preferences.h"
 #include "nsJSUtils.h"
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -14,17 +14,16 @@
 #include "nsDOMEvent.h"
 #include "nsEventListenerManager.h"
 #include "nsCaret.h"
 #include "nsIDOMEventListener.h"
 #include "nsITextControlFrame.h"
 #include "nsGkAtoms.h"
 #include "nsPIDOMWindow.h"
 #include "nsIJSEventListener.h"
-#include "prmem.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptRuntime.h"
 #include "nsLayoutUtils.h"
 #include "nsINameSpaceManager.h"
 #include "nsIContent.h"
 #include "mozilla/dom/Element.h"
 #include "nsIFrame.h"
 #include "nsIView.h"
new file mode 100644
--- /dev/null
+++ b/content/html/content/crashtests/798802-1.html
@@ -0,0 +1,18 @@
+<html>
+  <head>
+    <script>
+      onload = function() {
+        var canvas2d = document.createElement('canvas')
+        canvas2d.setAttribute('width', 0)
+        document.body.appendChild(canvas2d)
+        var ctx2d = canvas2d.getContext('2d')
+        ctx2d.fillStyle = 'black'
+        var gl = document.createElement('canvas').getContext('experimental-webgl')
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d)
+        ctx2d.fillRect(0, 0, 1, 1)
+      }
+    </script>
+  </head>
+  <body>
+  </body>
+</html>
--- a/content/html/content/crashtests/crashtests.list
+++ b/content/html/content/crashtests/crashtests.list
@@ -36,8 +36,9 @@ load 682460.html
 load 673853.html
 load 738744.xhtml
 load 741250.xhtml
 load 795221-1.html
 load 795221-2.html
 load 795221-3.html
 load 795221-4.html
 load 795221-5.xml
+load 798802-1.html
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsHTMLCanvasElement.h"
 #include "nsAttrValueInlines.h"
 
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "nsNetUtil.h"
-#include "prmem.h"
 #include "nsDOMFile.h"
 
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsIDOMCanvasRenderingContext2D.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
@@ -832,17 +831,17 @@ nsHTMLCanvasElement::InvalidateCanvasCon
   // We don't need to flush anything here; if there's no frame or if
   // we plan to reframe we don't need to invalidate it anyway.
   nsIFrame *frame = GetPrimaryFrame();
   if (!frame)
     return;
 
   frame->MarkLayersActive(nsChangeHint(0));
 
-  Layer* layer;
+  Layer* layer = nullptr;
   if (damageRect) {
     nsIntSize size = GetWidthHeight();
     if (size.width != 0 && size.height != 0) {
 
       gfxRect realRect(*damageRect);
       realRect.RoundOut();
 
       // then make it a nsRect
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -2130,22 +2130,22 @@ nsHTMLMediaElement::IsWebMType(const nsA
   }
 
   return false;
 }
 #endif
 
 #if defined(MOZ_GSTREAMER) || defined(MOZ_WIDGET_GONK)
 char const *const nsHTMLMediaElement::gH264Codecs[7] = {
-  "avc1.42E01E",
-  "avc1.42001E",
-  "avc1.58A01E",
-  "avc1.4D401E",
-  "avc1.64001E",
-  "mp4a.40.2",
+  "avc1.42E01E",  // H.264 Constrained Baseline Profile Level 3.0
+  "avc1.42001E",  // H.264 Baseline Profile Level 3.0
+  "avc1.58A01E",  // H.264 Extended Profile Level 3.0
+  "avc1.4D401E",  // H.264 Main Profile Level 3.0
+  "avc1.64001E",  // H.264 High Profile Level 3.0
+  "mp4a.40.2",    // AAC-LC
   nullptr
 };
 #endif
 
 #ifdef MOZ_GSTREAMER
 const char nsHTMLMediaElement::gH264Types[3][16] = {
   "video/mp4",
   "video/3gpp",
--- a/content/html/content/src/nsHTMLVideoElement.cpp
+++ b/content/html/content/src/nsHTMLVideoElement.cpp
@@ -11,17 +11,16 @@
 #include "nsHTMLVideoElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsSize.h"
 #include "nsError.h"
 #include "nsNodeInfoManager.h"
 #include "plbase64.h"
 #include "nsNetUtil.h"
-#include "prmem.h"
 #include "nsXPCOMStrings.h"
 #include "prlock.h"
 #include "nsThreadUtils.h"
 #include "ImageContainer.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -105,17 +105,16 @@
 #include "nsIDOMJSWindow.h"
 #include "nsSandboxFlags.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define NS_MAX_DOCUMENT_WRITE_DEPTH 20
 
-#include "prmem.h"
 #include "prtime.h"
 
 // Find/Search Includes
 const int32_t kForward  = 0;
 const int32_t kBackward = 1;
 
 //#define DEBUG_charset
 
--- a/content/media/nsBuiltinDecoderStateMachine.h
+++ b/content/media/nsBuiltinDecoderStateMachine.h
@@ -71,17 +71,16 @@ During playback the audio thread will be
 monitor) if the audio queue is empty. Otherwise it constantly pops
 audio data off the queue and plays it with a blocking write to the audio
 hardware (via nsAudioStream and libsydneyaudio).
 
 */
 #if !defined(nsBuiltinDecoderStateMachine_h__)
 #define nsBuiltinDecoderStateMachine_h__
 
-#include "prmem.h"
 #include "nsThreadUtils.h"
 #include "nsBuiltinDecoder.h"
 #include "nsBuiltinDecoderReader.h"
 #include "nsAudioAvailableEventManager.h"
 #include "nsHTMLMediaElement.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "nsITimer.h"
 #include "AudioSegment.h"
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -15,16 +15,21 @@ MODULE		= dom
 LIBRARY_NAME	= jsdombase_s
 LIBXUL_LIBRARY	= 1
 FORCE_STATIC_LIB = 1
 
 DIRS = \
   test \
   $(NULL)
 
+EXTRA_COMPONENTS = \
+  SiteSpecificUserAgent.js \
+  SiteSpecificUserAgent.manifest \
+  $(NULL)
+
 EXTRA_PP_COMPONENTS = \
   ConsoleAPI.js \
   ConsoleAPI.manifest \
   $(NULL)
 
 EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
   $(NULL)
 
@@ -34,16 +39,17 @@ EXTRA_JS_MODULES += \
   ObjectWrapper.jsm \
   $(NULL)
 
 XPIDLSRCS = \
   nsIDOMDOMError.idl \
   nsIDOMDOMRequest.idl \
   nsIEntropyCollector.idl \
   nsIScriptChannel.idl \
+  nsISiteSpecificUserAgent.idl \
   $(NULL)
 
 EXPORTS = \
   nsDOMCID.h \
   nsDOMClassInfoClasses.h \
   nsDOMClassInfoID.h \
   nsDOMJSUtils.h \
   nsDOMScriptObjectHolder.h \
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -28,16 +28,17 @@
 #include "BatteryManager.h"
 #include "PowerManager.h"
 #include "nsIDOMWakeLock.h"
 #include "nsIPowerManagerService.h"
 #include "SmsManager.h"
 #include "nsISmsService.h"
 #include "mozilla/Hal.h"
 #include "nsIWebNavigation.h"
+#include "nsISiteSpecificUserAgent.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
 #include "Connection.h"
 #ifdef MOZ_B2G_RIL
 #include "MobileConnection.h"
 #endif
 #include "nsIIdleObserver.h"
 #include "nsIPermissionManager.h"
@@ -229,17 +230,40 @@ Navigator::GetWindow()
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigator
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetUserAgent(nsAString& aUserAgent)
 {
-  return NS_GetNavigatorUserAgent(aUserAgent);
+  nsresult rv = NS_GetNavigatorUserAgent(aUserAgent);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+  if (!win || !win->GetDocShell()) {
+    return NS_OK;
+  }
+
+  nsIDocument* doc = win->GetExtantDoc();
+  if (!doc) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIURI> codebaseURI;
+  doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
+  if (!codebaseURI) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsISiteSpecificUserAgent> siteSpecificUA =
+    do_GetService("@mozilla.org/dom/site-specific-user-agent;1");
+  NS_ENSURE_TRUE(siteSpecificUA, NS_OK);
+
+  return siteSpecificUA->GetUserAgentForURI(codebaseURI, aUserAgent);
 }
 
 NS_IMETHODIMP
 Navigator::GetAppCodeName(nsAString& aAppCodeName)
 {
   nsresult rv;
 
   nsCOMPtr<nsIHttpProtocolHandler>
new file mode 100644
--- /dev/null
+++ b/dom/base/SiteSpecificUserAgent.js
@@ -0,0 +1,27 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const Cu = Components.utils;
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/UserAgentOverrides.jsm");
+
+const DEFAULT_UA = Cc["@mozilla.org/network/protocol;1?name=http"]
+                     .getService(Ci.nsIHttpProtocolHandler)
+                     .userAgent;
+
+function SiteSpecificUserAgent() {}
+
+SiteSpecificUserAgent.prototype = {
+  getUserAgentForURI: function ssua_getUserAgentForURI(aURI) {
+    return UserAgentOverrides.getOverrideForURI(aURI) || DEFAULT_UA;
+  },
+
+  classID: Components.ID("{506c680f-3d1c-4954-b351-2c80afbc37d3}"),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISiteSpecificUserAgent])
+};
+
+let NSGetFactory = XPCOMUtils.generateNSGetFactory([SiteSpecificUserAgent]);
new file mode 100644
--- /dev/null
+++ b/dom/base/SiteSpecificUserAgent.manifest
@@ -0,0 +1,2 @@
+component {506c680f-3d1c-4954-b351-2c80afbc37d3} SiteSpecificUserAgent.js
+contract @mozilla.org/dom/site-specific-user-agent;1 {506c680f-3d1c-4954-b351-2c80afbc37d3}
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2127,16 +2127,36 @@ nsDOMWindowUtils::StopFrameTimeRecording
     for (uint32_t i = 0; i < *frameCount; i++) {
       (*frames)[i] = frameTimes[i];
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDOMWindowUtils::BeginTabSwitch()
+{
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  if (!widget)
+    return NS_ERROR_FAILURE;
+
+  LayerManager *mgr = widget->GetLayerManager();
+  if (!mgr)
+    return NS_ERROR_FAILURE;
+
+  mgr->BeginTabSwitch();
+
+  return NS_OK;
+}
+
 static bool
 ComputeAnimationValue(nsCSSProperty aProperty,
                       Element* aElement,
                       const nsAString& aInput,
                       nsStyleAnimation::Value& aOutput)
 {
 
   if (!nsStyleAnimation::ComputeValue(aProperty, aElement, aInput,
new file mode 100644
--- /dev/null
+++ b/dom/base/nsISiteSpecificUserAgent.idl
@@ -0,0 +1,25 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsIURI;
+
+/**
+ * nsISiteSpecificUserAgent provides you with site-specific User Agent strings.
+ */
+
+[scriptable, uuid(604a64af-9809-4c2f-a91d-f6ebfa21f6cb)]
+interface nsISiteSpecificUserAgent : nsISupports
+{
+  /**
+   * Get the User Agent string for a given URI.
+   *
+   * @param aURI is the URI of the page the UA string is used for.
+   *
+   * @returns the User Agent string for the given URI. If no override applies,
+   * the default User Agent string is used.
+   */
+  AString getUserAgentForURI(in nsIURI aURI);
+};
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -12,19 +12,16 @@
 #include "nsIWebNavigation.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIURIFixup.h"
 #include "nsIURL.h"
 #include "nsIJARURI.h"
 #include "nsIIOService.h"
 #include "nsIServiceManager.h"
 #include "nsNetUtil.h"
-#include "plstr.h"
-#include "prprf.h"
-#include "prmem.h"
 #include "nsCOMPtr.h"
 #include "nsEscape.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIJSContextStack.h"
--- a/dom/camera/GonkCameraControl.h
+++ b/dom/camera/GonkCameraControl.h
@@ -13,17 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef DOM_CAMERA_GONKCAMERACONTROL_H
 #define DOM_CAMERA_GONKCAMERACONTROL_H
 
 #include "base/basictypes.h"
-#include "prtypes.h"
 #include "prrwlock.h"
 #include "nsIDOMCameraManager.h"
 #include "DOMCameraControl.h"
 #include "CameraControlImpl.h"
 #include "CameraCommon.h"
 #include "GonkRecorder.h"
 
 namespace mozilla {
--- a/dom/fm/DOMFMRadioParent.jsm
+++ b/dom/fm/DOMFMRadioParent.jsm
@@ -58,16 +58,19 @@ XPCOMUtils.defineLazyGetter(this, "FMRad
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
                                    "@mozilla.org/settingsService;1",
                                    "nsISettingsService");
 
 let EXPORTED_SYMBOLS = ["DOMFMRadioParent"];
 
 let DOMFMRadioParent = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                         Ci.nsISettingsServiceCallback]),
+
   _initialized: false,
 
   /* Indicates if the FM radio is currently enabled */
   _isEnabled: false,
 
   /* Indicates if the FM radio is currently being enabled */
   _enabling: false,
 
--- a/dom/fm/FMRadio.cpp
+++ b/dom/fm/FMRadio.cpp
@@ -139,24 +139,26 @@ NS_IMETHODIMP FMRadio::Enable(nsIFMRadio
   audioManager->SetFmRadioAudioEnabled(true);
 
   return NS_OK;
 }
 
 /* void disableRadio (); */
 NS_IMETHODIMP FMRadio::Disable()
 {
+  // Fix Bug 796733. 
+  // DisableFMRadio should be called before SetFmRadioAudioEnabled to prevent
+  // the annoying beep sound.
+  DisableFMRadio();
+  
   nsCOMPtr<nsIAudioManager> audioManager =
     do_GetService(NS_AUDIOMANAGER_CONTRACTID);
   NS_ENSURE_TRUE(audioManager, NS_OK);
 
   audioManager->SetFmRadioAudioEnabled(false);
-
-  DisableFMRadio();
-
   return NS_OK;
 }
 
 /* void cancelSeek */
 NS_IMETHODIMP FMRadio::CancelSeek()
 {
   CancelFMRadioSeek();
   return NS_OK;
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -35,17 +35,17 @@ interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMTouch;
 interface nsIDOMClientRect;
 interface nsIURI;
 
-[scriptable, uuid(f5b9883b-2ab9-426c-8fc1-7296cb6bc1d2)]
+[scriptable, uuid(d0b58b1b-58fa-49a0-8e4d-a3693bc65ebd)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1046,16 +1046,22 @@ interface nsIDOMWindowUtils : nsISupport
    * error if there is no widget associated with this window.
    */
   readonly attribute AString layerManagerType;
 
   void startFrameTimeRecording();
   void stopFrameTimeRecording([optional] out unsigned long frameCount,
                               [retval, array, size_is(frameCount)] out float frameTime);
   /**
+   * Signals that we're begining to tab switch. This is used by painting code to
+   * determine total tab switch time.
+   */
+  void beginTabSwitch();
+
+  /**
    * The DPI of the display
    */
   readonly attribute float displayDPI;
 
   /**
    * Return the outer window with the given ID, if any.  Can return null.
    */
   nsIDOMWindow getOuterWindowWithId(in unsigned long long aOuterWindowID);
--- a/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
+++ b/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
@@ -1,125 +1,15 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
-#include "nsIVariant.idl"
 
-interface nsIDOMElement;
-interface nsIDOMHTMLCanvasElement;
-interface nsIPropertyBag;
-
-// XXX should we comment out these typedefs in the C++ header?
-
-typedef unsigned long  WebGLenum;
-typedef boolean        WebGLboolean;
-typedef unsigned long  WebGLbitfield;
-typedef long           WebGLint;
-typedef long           WebGLsizei;
-typedef long long      WebGLsizeiptr;
-typedef long long      WebGLintptr;
-typedef unsigned long  WebGLuint;
-typedef float          WebGLfloat;
-typedef float          WebGLclampf;
-
-%{C++
-// for jsval
-#include "jsapi.h"
-
-namespace mozilla {
-namespace dom {
-class Element;
-} // namespace dom
-} // namespace mozilla
-
-/* Avoid conflict with WinAPI */
-#undef NO_ERROR
-%}
-
-[ptr] native WebGLJSObjectPtr (JSObject);
-[ptr] native Element (mozilla::dom::Element);
-
-//
-// OpenGL object wrappers
-//
-
-/* Base class for all WebGL extensions, and for those without
- * any additional tokens/methods.
- */
-[scriptable, builtinclass, uuid(70814f32-a5c5-4b95-83d5-ac653bac3316)]
-interface nsIWebGLExtension : nsISupports
-{
-};
-
-/* Classes that extend on nsIWebGLExtension and provide
- * extra tokens, functions, etc.
- */
-[scriptable, builtinclass, uuid(3de3dfd9-864a-4e4c-989b-2977eaa80b7b)]
-interface nsIWebGLExtensionStandardDerivatives : nsIWebGLExtension
-{
-  //
-  //  CONSTANTS
-  //
-
-  /* Fragment shader hint */
-  const WebGLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES   = 0x8B8B;
-};
-
-[scriptable, builtinclass, uuid(b0afc2eb-0895-4509-98de-5c383d160694)]
-interface nsIWebGLExtensionLoseContext : nsIWebGLExtension
-{
-  void loseContext();
-  void restoreContext();
-};
-
-[scriptable, builtinclass, uuid(73bfb64d-94bd-4a7a-9eab-6b6d32e57aa0)]
-interface nsIWebGLExtensionTextureFilterAnisotropic : nsIWebGLExtension
-{
-  const WebGLenum TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
-  const WebGLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
-};
-
-[scriptable, builtinclass, uuid(a1508b6f-f2ab-44cf-bbb4-3cfb339e1e8a)]
-interface nsIWebGLExtensionCompressedTextureS3TC : nsIWebGLExtension
-{
-    /* Compressed Texture Formats */
-    const WebGLenum COMPRESSED_RGB_S3TC_DXT1_EXT        = 0x83F0;
-    const WebGLenum COMPRESSED_RGBA_S3TC_DXT1_EXT       = 0x83F1;
-    const WebGLenum COMPRESSED_RGBA_S3TC_DXT3_EXT       = 0x83F2;
-    const WebGLenum COMPRESSED_RGBA_S3TC_DXT5_EXT       = 0x83F3;
-};
-
-[scriptable, builtinclass, uuid(9592637f-ee3b-4c42-8329-5c9ad47411c1)]
-interface nsIWebGLExtensionCompressedTextureATC : nsIWebGLExtension
-{
-    /* Compressed Texture Formats */
-    const WebGLenum COMPRESSED_RGB_ATC_WEBGL                     = 0x8C92;
-    const WebGLenum COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL     = 0x8C93;
-    const WebGLenum COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;
-};
-
-[scriptable, builtinclass, uuid(c33aa5a1-035c-4dfa-b240-df71395ad0f8)]
-interface nsIWebGLExtensionCompressedTexturePVRTC : nsIWebGLExtension
-{
-    /* Compressed Texture Formats */
-    const WebGLenum COMPRESSED_RGB_PVRTC_4BPPV1  = 0x8C00;
-    const WebGLenum COMPRESSED_RGB_PVRTC_2BPPV1  = 0x8C01;
-    const WebGLenum COMPRESSED_RGBA_PVRTC_4BPPV1 = 0x8C02;
-    const WebGLenum COMPRESSED_RGBA_PVRTC_2BPPV1 = 0x8C03;
-};
-
-[scriptable, builtinclass, uuid(ef36f000-c1b2-11e1-afa7-0800200c9a66)]
-interface nsIWebGLExtensionDepthTexture : nsIWebGLExtension
-{
-  const WebGLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
-};
-
-[builtinclass, uuid(a1fdfb76-6a08-4a1a-b0c9-d92ef3357cb9)]
+[builtinclass, uuid(f1a2fd3a-c6ac-4ee2-a700-5d285d5e3fff)]
 interface nsIDOMWebGLRenderingContext : nsISupports
 {
   // get an underlying GL parameter, without any WebGL intervention.
   // Most useful for querying GL_VENDOR/GL_RENDERER for identifying
   // the underlying renderer to the user.
-  [noscript] DOMString mozGetUnderlyingParamString(in WebGLenum pname);
+  [noscript] DOMString mozGetUnderlyingParamString(in unsigned long pname);
 };
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 /* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
 #include "mozilla/Util.h"
 
-#include "prtypes.h"
 #include "prmem.h"
 #include "prenv.h"
 #include "prclist.h"
 
 #include "jsfriendapi.h"
 
 #include "nsPluginHost.h"
 #include "nsNPAPIPlugin.h"
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -2,17 +2,16 @@
 // vim:set ts=2 sts=2 sw=2 et cin:
 /* 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 nsPluginInstanceOwner_h_
 #define nsPluginInstanceOwner_h_
 
-#include "prtypes.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"
--- a/dom/plugins/base/nsPluginTags.h
+++ b/dom/plugins/base/nsPluginTags.h
@@ -2,17 +2,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsPluginTags_h_
 #define nsPluginTags_h_
 
 #include "nscore.h"
-#include "prtypes.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsIPluginTag.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsISupportsArray.h"
 #include "nsITimer.h"
 #include "nsIDOMMimeType.h"
--- a/dom/plugins/test/testplugin/nptest.cpp
+++ b/dom/plugins/test/testplugin/nptest.cpp
@@ -3273,17 +3273,17 @@ hangPlugin(NPObject* npobj, const NPVari
 bool
 getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
                  NPVariant* result)
 {
   NPP npp = static_cast<TestNPObject*>(npobj)->npp;
   InstanceData* id = static_cast<InstanceData*>(npp->pdata);
   string sel = pluginGetClipboardText(id);
 
-  uint32 len = sel.size();
+  uint32_t len = sel.size();
   char* selCopy = static_cast<char*>(NPN_MemAlloc(1 + len));
   if (!selCopy)
     return false;
 
   memcpy(selCopy, sel.c_str(), len);
   selCopy[len] = '\0';
 
   STRINGN_TO_NPVARIANT(selCopy, len, *result);
--- a/dom/plugins/test/testplugin/nptest.h
+++ b/dom/plugins/test/testplugin/nptest.h
@@ -34,17 +34,16 @@
 #ifndef nptest_h_
 #define nptest_h_
 
 #include "mozilla-config.h"
 
 #include "npapi.h"
 #include "npfunctions.h"
 #include "npruntime.h"
-#include "prtypes.h"
 #include "mozilla/StandardInteger.h"
 #include <string>
 #include <sstream>
 
 typedef enum  {
   DM_DEFAULT,
   DM_SOLID_COLOR
 } DrawMode;
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/marionette/manifest.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+b2g = true
+browser = false
+qemu = true
+
+[test_geolocation.js]
+gps = true
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/marionette/test_geolocation.js
@@ -0,0 +1,104 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 10000;
+
+let geolocation = window.navigator.geolocation;
+ok(geolocation);
+
+var target = Object();
+var wpid;
+
+/**
+ * Grant special power to get the geolocation
+ */
+SpecialPowers.addPermission("geolocation", true, document);
+
+/**
+ * Helper that compares the geolocation against the web API.
+ */
+function verifyLocation(callback, expectedLocation) {
+  geolocation.getCurrentPosition(function(position) {
+    log("Expected location: " + expectedLocation.latitude + " " + expectedLocation.longitude);
+    log("Current location: " + position.coords.latitude + " " + position.coords.longitude);
+    is(expectedLocation.latitude, position.coords.latitude);
+    is(expectedLocation.longitude, position.coords.longitude);
+  });
+  window.setTimeout(callback, 0);
+}
+
+/**
+ * Test story begins here.
+ */
+function setup() {
+  log("Providing initial setup: set geographic position watcher.");
+
+  wpid = geolocation.watchPosition(function(position) {
+    log("Position changes has found.");    
+    log("Watch: Target location: " + target.latitude + " " + target.longitude);
+    log("Watch: Current location: " + position.coords.latitude + " " + position.coords.longitude);
+    is(target.latitude, position.coords.latitude, "Latitude isn't match!");
+    is(target.longitude, position.coords.longitude, "Longitude isn't match!");
+  });
+
+  target.latitude  = 0;
+  target.longitude = 0;
+
+  cmd = "geo fix " + target.longitude + " " + target.latitude;
+
+  runEmulatorCmd(cmd, function(result) {
+    log("Geolocation setting status: " + result);
+    verifyLocation(movePosition_1, target);
+  });
+
+}
+
+function movePosition_1() {
+  log("Geolocation changes. Move to Position 1.");
+
+  target.latitude  = 25;
+  target.longitude = 121.56499833333334;
+
+  cmd = "geo fix " + target.longitude + " " + target.latitude;
+
+  runEmulatorCmd(cmd, function(result) {
+    log("Geolocation setting status: " + result);
+    verifyLocation(movePosition_2, target);
+  });
+}
+
+function movePosition_2() {
+  log("Geolocation changes to a negative longitude. Move to Position 2.");
+
+  target.latitude  = 37.393;
+  target.longitude = -122.08199833333335;
+
+  cmd = "geo fix " + target.longitude + " " + target.latitude;
+
+  runEmulatorCmd(cmd, function(result) {
+    log("Geolocation setting status: " + result);
+    verifyLocation(movePosition_3, target);
+  });
+}
+
+function movePosition_3() {
+  log("Geolocation changes with WatchPosition. Move to Position 3.");
+
+  target.latitude  = -22;
+  target.longitude = -43;
+
+  cmd = "geo fix " + target.longitude + " " + target.latitude;
+
+  runEmulatorCmd(cmd, function(result) {
+    log("Geolocation setting status: " + result);
+    verifyLocation(cleanup, target);
+  });
+}
+
+function cleanup() {
+  geolocation.clearWatch(wpid);
+  SpecialPowers.removePermission("geolocation", document);
+  finish();
+}
+
+setup();
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -83,50 +83,47 @@ var interfaceNamesInGlobalScope =
     "XULContainerItemElement",
     "HTMLTableCaptionElement",
     "SVGRect",
     "IDBCursor",
     "History",
     "HTMLTableRowElement",
     "NodeFilter",
     "ClientRectList",
-    "WebGLExtensionLoseContext",
     "CanvasRenderingContext2D",
     "SVGPathSegLinetoVerticalRel",
     "MozAlarmsManager",
     "MozPowerManager",
     "SVGElement",
     "GeoPositionError",
     "XPathEvaluator",
     "NodeIterator",
     "MozNavigatorNetwork",
     "CryptoDialogs",
     "SVGLocatable",
     "XULElement",
     "CSSRuleList",
     "SVGMarkerElement",
     "Rect",
     "SVGPathElement",
-    "WebGLUniformLocation",
     "SVGUseElement",
     "SVGAnimatedPoints",
     "DeviceAcceleration",
     "DOMError",
     "SVGAnimateMotionElement",
     "HTMLMeterElement",
     "SmartCardEvent",
     "CSSValueList",
     "ValidityState",
     "HTMLAppletElement",
     "Touch",
     "Controllers",
     "AnimationEvent",
     "NavigatorDesktopNotification",
     "LoadStatus",
-    "WebGLBuffer",
     "MediaQueryList",
     "Contact",
     "MediaQueryListListener",
     "DesktopNotificationCenter",
     "PluginArray",
     "XULSelectControlElement",
     "TimeRanges",
     "ImageData",
@@ -170,17 +167,16 @@ var interfaceNamesInGlobalScope =
     "HTMLDataListElement",
     "XPathResult",
     "XMLDocument",
     "DocumentType",
     "NamedNodeMap",
     "DeviceProximityEvent",
     "XULLabeledControlElement",
     "MozWakeLock",
-    "WebGLFramebuffer",
     "MozConnection",
     "WebGLRenderingContext",
     "JSON",
     "ClientRect",
     "GetUserMediaSuccessCallback",
     "CommandEvent",
     "HTMLDocument",
     "DeviceOrientationEvent",
@@ -258,18 +254,16 @@ var interfaceNamesInGlobalScope =
     "DOMException",
     "MozSmsMessage",
     "SVGFESpecularLightingElement",
     "StorageObsolete",
     "ContactManager",
     "NSXPathExpression",
     "SVGLineElement",
     "SVGPathSegArcRel",
-    "WebGLExtension",
-    "WebGLExtensionDepthTexture",
     "XSLTProcessor",
     "SVGPathSegLinetoVerticalAbs",
     "SVGPathSegLinetoRel",
     "HTMLImageElement",
     "MozSmsEvent",
     "CustomEvent",
     "XMLHttpRequestUpload",
     "SVGFEFuncBElement",
@@ -284,28 +278,22 @@ var interfaceNamesInGlobalScope =
     "DesktopNotification",
     "KeyEvent",
     "HTMLAreaElement",
     "XULLabelElement",
     "FormData",
     "IDBDatabase",
     "CSSPrimitiveValue",
     "SVGStopElement",
-    "WebGLExtensionCompressedTextureS3TC",
-    "WebGLExtensionCompressedTextureATC",
-    "WebGLExtensionCompressedTexturePVRTC",
     "XULCommandEvent",
     "HTMLMediaElement",
     "SVGPathSegLinetoHorizontalAbs",
     "SVGAnimatedRect",
     "SVGTextContentElement",
-    "WebGLRenderbuffer",
     "TreeColumn",
-    "WebGLExtensionStandardDerivatives",
-    "WebGLShaderPrecisionFormat",
     "XPathNamespace",
     "FontFace",
     "SVGPathSegCurvetoCubicSmoothRel",
     "HTMLMapElement",
     "SVGImageElement",
     "HTMLMetaElement",
     "NotifyPaintEvent",
     "XULTreeElement",
@@ -326,24 +314,22 @@ var interfaceNamesInGlobalScope =
     "SVGFEPointLightElement",
     "ModalContentWindow",
     "Crypto",
     "StorageManager",
     "SVGAngle",
     "Navigator",
     "SVGPathSegCurvetoQuadraticSmoothAbs",
     "HTMLButtonElement",
-    "WebGLProgram",
     "SVGPointList",
     "SVGFEColorMatrixElement",
     "USSDReceivedEvent",
     "SettingsManager",
     "DeviceRotationRate",
     "HTMLAudioElement",
-    "WebGLTexture",
     "SVGFEDistantLightElement",
     "HTMLOListElement",
     "ProcessingInstruction",
     "CSSUnknownRule",
     "SVGComponentTransferFunctionElement",
     "SVGEvent",
     "SVGPathSegLinetoHorizontalRel",
     "SVGAnimatedNumber",
@@ -368,17 +354,16 @@ var interfaceNamesInGlobalScope =
     "IDBFactory",
     "SVGFilterPrimitiveStandardAttributes",
     "CSSImportRule",
     "SVGPathSegClosePath",
     "HTMLTableCellElement",
     "WindowUtils",
     "SVGAnimatedNumberList",
     "WindowCollection",
-    "WebGLExtensionTextureFilterAnisotropic",
     "SVGPathSegMovetoRel",
     "ChromeWindow",
     "Comment",
     "HTMLSourceElement",
     "SVGStringList",
     "Storage",
     "HTMLModElement",
     "PaintRequest",
@@ -425,17 +410,16 @@ var interfaceNamesInGlobalScope =
     "SVGTransform",
     "SVGTextPositioningElement",
     "ContactFindOptions",
     "SVGFEMergeElement",
     "FileRequest",
     "SVGDefsElement",
     "Element",
     "HTMLBaseElement",
-    "WebGLShader",
     "GeoPositionErrorCallback",
     "HTMLVideoElement",
     "MozSettingsEvent",
     "SVGAnimatedPathData",
     "SVGUnitTypes",
     "SVGTests",
     "RGBColor",
     "HTMLLabelElement",
@@ -515,17 +499,16 @@ var interfaceNamesInGlobalScope =
     "HTMLScriptElement",
     "SVGPathSegCurvetoCubicAbs",
     "HTMLLIElement",
     "SVGClipPathElement",
     "NavigatorGeolocation",
     "HTMLParagraphElement",
     "EventTarget",
     "File",
-    "WebGLActiveInfo",
     "SVGGradientElement",
     "ContactTelField",
     "ContactField",
     "SVGFitToViewBox",
     "SVGAElement",
     "NavigatorCamera",
     "CameraControl",
     "CameraCapabilities",
--- a/dom/webidl/WebGLRenderingContext.webidl
+++ b/dom/webidl/WebGLRenderingContext.webidl
@@ -771,54 +771,62 @@ interface WebGLContextEvent : Event {
 // EventInit is defined in the DOM4 specification.
 /*dictionary WebGLContextEventInit : EventInit {
     DOMString statusMessage;
     };*/
 
 
 // specific extension interfaces
 
+[NoInterfaceObject]
 interface WebGLExtensionStandardDerivatives {
     const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
 };
 
+[NoInterfaceObject]
 interface WebGLExtensionLoseContext {
     void loseContext();
     void restoreContext();
 };
 
+[NoInterfaceObject]
 interface WebGLExtensionTextureFilterAnisotropic
 {
     const GLenum TEXTURE_MAX_ANISOTROPY_EXT     = 0x84FE;
     const GLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
 };
 
+[NoInterfaceObject]
 interface WebGLExtensionCompressedTextureS3TC
 {
     const GLenum COMPRESSED_RGB_S3TC_DXT1_EXT  = 0x83F0;
     const GLenum COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
     const GLenum COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
     const GLenum COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
 };
 
+[NoInterfaceObject]
 interface WebGLExtensionCompressedTextureATC
 {
     const GLenum COMPRESSED_RGB_ATC_WEBGL                     = 0x8C92;
     const GLenum COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL     = 0x8C93;
     const GLenum COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;
 };
 
+[NoInterfaceObject]
 interface WebGLExtensionCompressedTexturePVRTC
 {
     const GLenum COMPRESSED_RGB_PVRTC_4BPPV1  = 0x8C00;
     const GLenum COMPRESSED_RGB_PVRTC_2BPPV1  = 0x8C01;
     const GLenum COMPRESSED_RGBA_PVRTC_4BPPV1 = 0x8C02;
     const GLenum COMPRESSED_RGBA_PVRTC_2BPPV1 = 0x8C03;
 };
 
+[NoInterfaceObject]
 interface WebGLExtensionDepthTexture
 {
     const GLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
 };
 
+[NoInterfaceObject]
 interface WebGLExtensionTextureFloat
 {
 };
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=78: */
 /* 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 <string.h>
 
+#include "mozilla/Base64.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Selection.h"
 #include "mozilla/Util.h"
 #include "nsAString.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
@@ -84,18 +85,16 @@
 #include "nsStringIterator.h"
 #include "nsSubstringTuple.h"
 #include "nsTextEditRules.h"
 #include "nsTextEditUtils.h"
 #include "nsTreeSanitizer.h"
 #include "nsWSRunObject.h"
 #include "nsXPCOM.h"
 #include "nscore.h"
-#include "plbase64.h"
-#include "prmem.h"
 
 class nsIAtom;
 class nsILoadContext;
 class nsISupports;
 
 using namespace mozilla;
 
 const PRUnichar nbsp = 160;
@@ -1223,33 +1222,33 @@ nsresult nsHTMLEditor::InsertObject(cons
 
     nsCString imageData;
     rv = NS_ConsumeStream(imageStream, UINT32_MAX, imageData);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = imageStream->Close();
     NS_ENSURE_SUCCESS(rv, rv);
 
-    char * base64 = PL_Base64Encode(imageData.get(), imageData.Length(), nullptr);
-    NS_ENSURE_TRUE(base64, NS_ERROR_OUT_OF_MEMORY);
+    nsAutoCString data64;
+    rv = Base64Encode(imageData, data64);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoString stuffToPaste;
     stuffToPaste.AssignLiteral("<IMG src=\"data:");
     AppendUTF8toUTF16(type, stuffToPaste);
     stuffToPaste.AppendLiteral(";base64,");
-    AppendUTF8toUTF16(base64, stuffToPaste);
+    AppendUTF8toUTF16(data64, stuffToPaste);
     stuffToPaste.AppendLiteral("\" alt=\"\" >");
     nsAutoEditBatch beginBatching(this);
     rv = DoInsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(), 
                                  NS_LITERAL_STRING(kFileMime),
                                  aSourceDoc,
                                  aDestinationNode, aDestOffset,
                                  aDoDeleteSelection,
                                  aIsSafe);
-    PR_Free(base64);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable, 
                                                    nsIDOMDocument *aSourceDoc,
                                                    const nsAString & aContextStr,
--- a/embedding/components/printingui/src/win/nsPrintDialogUtil.cpp
+++ b/embedding/components/printingui/src/win/nsPrintDialogUtil.cpp
@@ -15,17 +15,16 @@ To Build This:
 
 WIN_LIBS=                                       \
         winspool.lib                           \
         comctl32.lib                           \
         comdlg32.lib
 
 ---------------------------------------------------------------------- */
 
-#include "prmem.h"
 #include "plstr.h"
 #include <windows.h>
 #include <tchar.h>
 
 #include <unknwn.h>
 #include <commdlg.h>
 
 #include "nsIWebBrowserPrint.h"
--- a/extensions/universalchardet/src/xpcom/nsUdetXPCOMWrapper.cpp
+++ b/extensions/universalchardet/src/xpcom/nsUdetXPCOMWrapper.cpp
@@ -8,18 +8,16 @@
 #include "nsUniversalDetector.h"
 #include "nsUdetXPCOMWrapper.h"
 #include "nsCharSetProber.h" // for DumpStatus
 
 #include "nsUniversalCharDetDll.h"
 //---- for XPCOM
 #include "nsIFactory.h"
 #include "nsISupports.h"
-#include "pratom.h"
-#include "prmem.h"
 #include "nsCOMPtr.h"
 
 static NS_DEFINE_CID(kUniversalDetectorCID, NS_UNIVERSAL_DETECTOR_CID);
 static NS_DEFINE_CID(kUniversalStringDetectorCID, NS_UNIVERSAL_STRING_DETECTOR_CID);
 
 //---------------------------------------------------------------------
 nsXPCOMDetector:: nsXPCOMDetector(uint32_t aLanguageFilter)
  : nsUniversalDetector(aLanguageFilter)
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -2,16 +2,17 @@
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/PLayers.h"
 #include "mozilla/layers/ShadowLayers.h"
+#include "mozilla/Telemetry.h"
 
 #include "ImageLayers.h"
 #include "ImageContainer.h"
 #include "Layers.h"
 #include "gfxPlatform.h"
 #include "ReadbackLayer.h"
 #include "gfxUtils.h"
 #include "nsPrintfCString.h"
@@ -871,28 +872,37 @@ LayerManager::StartFrameTimeRecording()
 void
 LayerManager::PostPresent()
 {
   if (!mLastFrameTime.IsNull()) {
     TimeStamp now = TimeStamp::Now();
     mFrameTimes.AppendElement((now - mLastFrameTime).ToMilliseconds());
     mLastFrameTime = now;
   }
+  if (!mTabSwitchStart.IsNull()) {
+    Telemetry::Accumulate(Telemetry::FX_TAB_SWITCH_TOTAL_MS,
+                          uint32_t((TimeStamp::Now() - mTabSwitchStart).ToMilliseconds()));
+    mTabSwitchStart = TimeStamp();
+  }
 }
 
 nsTArray<float>
 LayerManager::StopFrameTimeRecording()
 {
   mLastFrameTime = TimeStamp();
   nsTArray<float> result = mFrameTimes;
   mFrameTimes.Clear();
   return result;
 }
 
-
+void
+LayerManager::BeginTabSwitch()
+{
+  mTabSwitchStart = TimeStamp::Now();
+}
 
 #ifdef MOZ_LAYERS_HAVE_LOG
 
 static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer);
 
 #ifdef MOZ_DUMP_PAINTING
 template <typename T>
 void WriteSnapshotLinkToDumpFile(T* aObj, FILE* aFile)
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -463,16 +463,18 @@ public:
    */
   void LogSelf(const char* aPrefix="");
 
   void StartFrameTimeRecording();
   nsTArray<float> StopFrameTimeRecording();
 
   void PostPresent();
 
+  void BeginTabSwitch();
+
   static bool IsLogEnabled();
   static PRLogModuleInfo* GetLog() { return sLog; }
 
   bool IsCompositingCheap(LayersBackend aBackend)
   { return LAYERS_BASIC != aBackend; }
 
   virtual bool IsCompositingCheap() { return true; }
 
@@ -490,16 +492,17 @@ protected:
 
   static void InitLog();
   static PRLogModuleInfo* sLog;
   uint64_t mId;
   bool mInTransaction;
 private:
   TimeStamp mLastFrameTime;
   nsTArray<float> mFrameTimes;
+  TimeStamp mTabSwitchStart;
 };
 
 class ThebesLayer;
 typedef InfallibleTArray<Animation> AnimationArray;
 
 struct AnimData {
   InfallibleTArray<nsStyleAnimation::Value> mStartValues;
   InfallibleTArray<nsStyleAnimation::Value> mEndValues;
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -585,16 +585,17 @@ BasicLayerManager::EndTransactionInterna
         PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
       }
       // If we're not retained, then don't composite means do nothing at all.
     } else {
       PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
       if (mWidget) {
         FlashWidgetUpdateArea(mTarget);
       }
+      LayerManager::PostPresent();
     }
 
     if (!mTransactionIncomplete) {
       // Clear out target if we have a complete transaction.
       mTarget = nullptr;
     }
   }
 
--- a/gfx/thebes/gfxCoreTextShaper.cpp
+++ b/gfx/thebes/gfxCoreTextShaper.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Util.h"
 
 #include "nsAlgorithm.h"
-#include "prmem.h"
 #include "nsString.h"
 #include "nsBidiUtils.h"
 
 #include "gfxTypes.h"
 
 #include "nsPromiseFlatString.h"
 
 #include "gfxContext.h"
--- a/gfx/thebes/gfxGraphiteShaper.cpp
+++ b/gfx/thebes/gfxGraphiteShaper.cpp
@@ -1,14 +1,13 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "prmem.h"
 #include "nsString.h"
 #include "nsBidiUtils.h"
 #include "nsMathUtils.h"
 
 #include "gfxTypes.h"
 
 #include "gfxContext.h"
 #include "gfxPlatform.h"
--- a/gfx/thebes/gfxHarfBuzzShaper.cpp
+++ b/gfx/thebes/gfxHarfBuzzShaper.cpp
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsAlgorithm.h"
-#include "prmem.h"
 #include "nsString.h"
 #include "nsBidiUtils.h"
 #include "nsMathUtils.h"
 
 #include "gfxTypes.h"
 
 #include "gfxContext.h"
 #include "gfxPlatform.h"
--- a/gfx/thebes/gfxImageSurface.cpp
+++ b/gfx/thebes/gfxImageSurface.cpp
@@ -1,14 +1,13 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "prmem.h"
 
 #include "gfxAlphaRecovery.h"
 #include "gfxImageSurface.h"
 
 #include "cairo.h"
 #include "mozilla/gfx/2D.h"
 #include "gfx2DGlue.h"
 
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -34,17 +34,16 @@ For further information, please contact 
 
 CompuServe Incorporated maintains a mailing list with all those individuals and
 organizations who wish to receive copies of this document when it is corrected
 or revised. This service is offered free of charge; please provide us with your
 mailing address.
 */
 
 #include <stddef.h>
-#include "prmem.h"
 
 #include "nsGIFDecoder2.h"
 #include "nsIInputStream.h"
 #include "imgIContainerObserver.h"
 #include "RasterImage.h"
 
 #include "gfxColor.h"
 #include "gfxPlatform.h"
--- a/image/encoders/bmp/nsBMPEncoder.cpp
+++ b/image/encoders/bmp/nsBMPEncoder.cpp
@@ -1,16 +1,15 @@
 /* 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 "nsCRT.h"
 #include "EndianMacros.h"
 #include "nsBMPEncoder.h"
-#include "prmem.h"
 #include "prprf.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 #include "nsAutoPtr.h"
 
 using namespace mozilla;
 
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsBMPEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
--- a/image/encoders/ico/nsICOEncoder.cpp
+++ b/image/encoders/ico/nsICOEncoder.cpp
@@ -2,17 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsCRT.h"
 #include "EndianMacros.h"
 #include "nsBMPEncoder.h"
 #include "nsPNGEncoder.h"
 #include "nsICOEncoder.h"
-#include "prmem.h"
 #include "prprf.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::image;
 
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsICOEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
--- a/image/encoders/jpeg/nsJPEGEncoder.cpp
+++ b/image/encoders/jpeg/nsJPEGEncoder.cpp
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsJPEGEncoder.h"
-#include "prmem.h"
 #include "prprf.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 #include "gfxColor.h"
 
 #include <setjmp.h>
 #include "jerror.h"
 
@@ -30,17 +29,17 @@ nsJPEGEncoder::nsJPEGEncoder() : mFinish
                                  mCallbackTarget(nullptr), mNotifyThreshold(0),
                                  mReentrantMonitor("nsJPEGEncoder.mReentrantMonitor")
 {
 }
 
 nsJPEGEncoder::~nsJPEGEncoder()
 {
   if (mImageBuffer) {
-    PR_Free(mImageBuffer);
+    moz_free(mImageBuffer);
     mImageBuffer = nullptr;
   }
 }
 
 
 // nsJPEGEncoder::InitFromData
 //
 //    One output option is supported: "quality=X" where X is an integer in the
@@ -221,17 +220,17 @@ NS_IMETHODIMP nsJPEGEncoder::EndImageEnc
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 /* void close (); */
 NS_IMETHODIMP nsJPEGEncoder::Close()
 {
   if (mImageBuffer != nullptr) {
-    PR_Free(mImageBuffer);
+    moz_free(mImageBuffer);
     mImageBuffer = nullptr;
     mImageBufferSize = 0;
     mImageBufferUsed = 0;
     mImageBufferReadPoint = 0;
   }
   return NS_OK;
 }
 
@@ -368,17 +367,17 @@ nsJPEGEncoder::ConvertRGBARow(const uint
 
 void // static
 nsJPEGEncoder::initDestination(jpeg_compress_struct* cinfo)
 {
   nsJPEGEncoder* that = static_cast<nsJPEGEncoder*>(cinfo->client_data);
   NS_ASSERTION(! that->mImageBuffer, "Image buffer already initialized");
 
   that->mImageBufferSize = 8192;
-  that->mImageBuffer = (uint8_t*)PR_Malloc(that->mImageBufferSize);
+  that->mImageBuffer = (uint8_t*)moz_malloc(that->mImageBufferSize);
   that->mImageBufferUsed = 0;
 
   cinfo->dest->next_output_byte = that->mImageBuffer;
   cinfo->dest->free_in_buffer = that->mImageBufferSize;
 }
 
 
 // nsJPEGEncoder::emptyOutputBuffer
@@ -402,21 +401,21 @@ nsJPEGEncoder::emptyOutputBuffer(jpeg_co
   // that nobody is trying to read from the buffer we are destroying
   ReentrantMonitorAutoEnter autoEnter(that->mReentrantMonitor);
 
   that->mImageBufferUsed = that->mImageBufferSize;
 
   // expand buffer, just double size each time
   that->mImageBufferSize *= 2;
 
-  uint8_t* newBuf = (uint8_t*)PR_Realloc(that->mImageBuffer,
-                                         that->mImageBufferSize);
+  uint8_t* newBuf = (uint8_t*)moz_realloc(that->mImageBuffer,
+                                          that->mImageBufferSize);
   if (! newBuf) {
     // can't resize, just zero (this will keep us from writing more)
-    PR_Free(that->mImageBuffer);
+    moz_free(that->mImageBuffer);
     that->mImageBuffer = nullptr;
     that->mImageBufferSize = 0;
     that->mImageBufferUsed = 0;
 
     // This seems to be the only way to do errors through the JPEG library.  We
     // pass an nsresult masquerading as an int, which works because the
     // setjmp() caller casts it back.
     longjmp(((encoder_error_mgr*)(cinfo->err))->setjmp_buffer,
--- a/image/encoders/png/nsPNGEncoder.cpp
+++ b/image/encoders/png/nsPNGEncoder.cpp
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsCRT.h"
 #include "nsPNGEncoder.h"
-#include "prmem.h"
 #include "prprf.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 
 using namespace mozilla;
 
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsPNGEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
 
@@ -23,17 +22,17 @@ nsPNGEncoder::nsPNGEncoder() : mPNG(null
                                mCallbackTarget(nullptr), mNotifyThreshold(0),
                                mReentrantMonitor("nsPNGEncoder.mReentrantMonitor")
 {
 }
 
 nsPNGEncoder::~nsPNGEncoder()
 {
   if (mImageBuffer) {
-    PR_Free(mImageBuffer);
+    moz_free(mImageBuffer);
     mImageBuffer = nullptr;
   }
   // don't leak if EndImageEncode wasn't called
   if (mPNG)
     png_destroy_write_struct(&mPNG, &mPNGinfo);
 }
 
 // nsPNGEncoder::InitFromData
@@ -128,17 +127,17 @@ NS_IMETHODIMP nsPNGEncoder::StartImageEn
     png_destroy_write_struct(&mPNG, &mPNGinfo);
     return NS_ERROR_FAILURE;
   }
 
   // Set up to read the data into our image buffer, start out with an 8K
   // estimated size. Note: we don't have to worry about freeing this data
   // in this function. It will be freed on object destruction.
   mImageBufferSize = 8192;
-  mImageBuffer = (uint8_t*)PR_Malloc(mImageBufferSize);
+  mImageBuffer = (uint8_t*)moz_malloc(mImageBufferSize);
   if (!mImageBuffer) {
     png_destroy_write_struct(&mPNG, &mPNGinfo);
     return NS_ERROR_OUT_OF_MEMORY;
   }
   mImageBufferUsed = 0;
 
   // set our callback for libpng to give us the data
   png_set_write_fn(mPNG, this, WriteCallback, nullptr);
@@ -477,17 +476,17 @@ nsPNGEncoder::ParseOptions(const nsAStri
   return NS_OK;
 }
 
 
 /* void close (); */
 NS_IMETHODIMP nsPNGEncoder::Close()
 {
   if (mImageBuffer != nullptr) {
-    PR_Free(mImageBuffer);
+    moz_free(mImageBuffer);
     mImageBuffer = nullptr;
     mImageBufferSize = 0;
     mImageBufferUsed = 0;
     mImageBufferReadPoint = 0;
   }
   return NS_OK;
 }
 
@@ -674,21 +673,21 @@ nsPNGEncoder::WriteCallback(png_structp 
 
   if (that->mImageBufferUsed + size > that->mImageBufferSize) {
     // When we're reallocing the buffer we need to take the lock to ensure
     // that nobody is trying to read from the buffer we are destroying
     ReentrantMonitorAutoEnter autoEnter(that->mReentrantMonitor);
 
     // expand buffer, just double each time
     that->mImageBufferSize *= 2;
-    uint8_t* newBuf = (uint8_t*)PR_Realloc(that->mImageBuffer,
-                                           that->mImageBufferSize);
+    uint8_t* newBuf = (uint8_t*)moz_realloc(that->mImageBuffer,
+                                            that->mImageBufferSize);
     if (! newBuf) {
       // can't resize, just zero (this will keep us from writing more)
-      PR_Free(that->mImageBuffer);
+      moz_free(that->mImageBuffer);
       that->mImageBuffer = nullptr;
       that->mImageBufferSize = 0;
       that->mImageBufferUsed = 0;
       return;
     }
     that->mImageBuffer = newBuf;
   }
   memcpy(&that->mImageBuffer[that->mImageBufferUsed], data, size);
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -10,17 +10,16 @@
 #include "nsError.h"
 #include "Decoder.h"
 #include "imgIDecoderObserver.h"
 #include "RasterImage.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsAutoPtr.h"
 #include "nsStringStream.h"
-#include "prmem.h"
 #include "prenv.h"
 #include "ImageContainer.h"
 #include "Layers.h"
 
 #include "nsPNGDecoder.h"
 #include "nsGIFDecoder2.h"
 #include "nsJPEGDecoder.h"
 #include "nsBMPDecoder.h"
--- a/image/src/imgFrame.cpp
+++ b/image/src/imgFrame.cpp
@@ -4,17 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "imgFrame.h"
 #include "DiscardTracker.h"
 
 #include <limits.h>
 
-#include "prmem.h"
 #include "prenv.h"
 
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
 
 static bool gDisableOptimize = false;
 
 #include "cairo.h"
@@ -127,17 +126,18 @@ imgFrame::imgFrame() :
       gDisableOptimize = true;
     }
     hasCheckedOptimize = true;
   }
 }
 
 imgFrame::~imgFrame()
 {
-  PR_FREEIF(mPalettedImageData);
+  moz_free(mPalettedImageData);
+  mPalettedImageData = nullptr;
 #ifdef USE_WIN_SURFACE
   if (mIsDDBSurface) {
       gTotalDDBs--;
       gTotalDDBSize -= mSize.width * mSize.height * 4;
   }
 #endif
 
   if (mInformedDiscardTracker) {
--- a/image/src/imgRequest.cpp
+++ b/image/src/imgRequest.cpp
@@ -195,17 +195,17 @@ void imgRequest::AddProxy(imgRequestProx
     mImage->ResetAnimation();
   }
 
   proxy->SetPrincipal(mPrincipal);
 
   mObservers.AppendElementUnlessExists(proxy);
 }
 
-nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, bool aNotify)
+nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus)
 {
   LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy", "proxy", proxy);
 
   // This will remove our animation consumers, so after removing
   // this proxy, we don't end up without proxies with observers, but still
   // have animation consumers.
   proxy->ClearAnimationConsumers();
 
@@ -215,17 +215,17 @@ nsresult imgRequest::RemoveProxy(imgRequ
   }
 
   // Let the status tracker do its thing before we potentially call Cancel()
   // below, because Cancel() may result in OnStopRequest being called back
   // before Cancel() returns, leaving the image in a different state then the
   // one it was in at this point.
 
   imgStatusTracker& statusTracker = GetStatusTracker();
-  statusTracker.EmulateRequestFinished(proxy, aStatus, !aNotify);
+  statusTracker.EmulateRequestFinished(proxy, aStatus);
 
   if (mObservers.IsEmpty()) {
     // If we have no observers, there's nothing holding us alive. If we haven't
     // been cancelled and thus removed from the cache, tell the image loader so
     // we can be evicted from the cache.
     if (mCacheEntry) {
       NS_ABORT_IF_FALSE(mURI, "Removing last observer without key uri.");
 
--- a/image/src/imgRequest.h
+++ b/image/src/imgRequest.h
@@ -62,18 +62,17 @@ public:
                 imgCacheEntry *aCacheEntry,
                 void *aLoadId,
                 nsIPrincipal* aLoadingPrincipal,
                 int32_t aCORSMode);
 
   // Callers must call imgRequestProxy::Notify later.
   void AddProxy(imgRequestProxy *proxy);
 
-  // aNotify==false still sends OnStopRequest.
-  nsresult RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, bool aNotify);
+  nsresult RemoveProxy(imgRequestProxy *proxy, nsresult aStatus);
 
   void SniffMimeType(const char *buf, uint32_t len, nsACString& newType);
 
   // Cancel, but also ensure that all work done in Init() is undone. Call this
   // only when the channel has failed to open, and so calling Cancel() on it
   // won't be sufficient.
   void CancelAndAbort(nsresult aStatus);
 
--- a/image/src/imgRequestProxy.cpp
+++ b/image/src/imgRequestProxy.cpp
@@ -78,21 +78,18 @@ imgRequestProxy::~imgRequestProxy()
   if (mOwner) {
     if (!mCanceled) {
       mCanceled = true;
 
       /* Call RemoveProxy with a successful status.  This will keep the
          channel, if still downloading data, from being canceled if 'this' is
          the last observer.  This allows the image to continue to download and
          be cached even if no one is using it currently.
-         
-         Passing false to aNotify means that we will still get
-         OnStopRequest, if needed.
        */
-      mOwner->RemoveProxy(this, NS_OK, false);
+      mOwner->RemoveProxy(this, NS_OK);
     }
   }
 }
 
 nsresult imgRequestProxy::Init(imgRequest* request, nsILoadGroup* aLoadGroup, Image* aImage,
                                nsIURI* aURI, imgIDecoderObserver* aObserver)
 {
   NS_PRECONDITION(!mOwner && !mListener, "imgRequestProxy is already initialized");
@@ -155,19 +152,17 @@ nsresult imgRequestProxy::ChangeOwner(im
   // Were we decoded before?
   bool wasDecoded = false;
   if (mImage &&
       (mImage->GetStatusTracker().GetImageStatus() &
        imgIRequest::STATUS_FRAME_COMPLETE)) {
     wasDecoded = true;
   }
 
-  // Passing false to aNotify means that mListener will still get
-  // OnStopRequest, if needed.
-  mOwner->RemoveProxy(this, NS_IMAGELIB_CHANGING_OWNER, false);
+  mOwner->RemoveProxy(this, NS_IMAGELIB_CHANGING_OWNER);
 
   // If we had animation requests, restore them here. Note that we
   // do this *after* RemoveProxy, which clears out animation consumers
   // (see bug 601723).
   for (uint32_t i = 0; i < oldAnimationConsumers; i++)
     IncrementAnimationConsumers();
 
   mOwner = aNewOwner;
@@ -251,20 +246,19 @@ NS_IMETHODIMP imgRequestProxy::Cancel(ns
 
   nsCOMPtr<nsIRunnable> ev = new imgCancelRunnable(this, status);
   return NS_DispatchToCurrentThread(ev);
 }
 
 void
 imgRequestProxy::DoCancel(nsresult status)
 {
-  // Passing false to aNotify means that mListener will still get
-  // OnStopRequest, if needed.
-  if (mOwner)
-    mOwner->RemoveProxy(this, status, false);
+  if (mOwner) {
+    mOwner->RemoveProxy(this, status);
+  }
 
   NullOutListener();
 }
 
 /* void cancelAndForgetObserver (in nsresult aStatus); */
 NS_IMETHODIMP imgRequestProxy::CancelAndForgetObserver(nsresult aStatus)
 {
   // If mCanceled is true but mListener is non-null, that means
@@ -279,20 +273,19 @@ NS_IMETHODIMP imgRequestProxy::CancelAnd
   LOG_SCOPE(gImgLog, "imgRequestProxy::CancelAndForgetObserver");
 
   mCanceled = true;
 
   // Now cheat and make sure our removal from loadgroup happens async
   bool oldIsInLoadGroup = mIsInLoadGroup;
   mIsInLoadGroup = false;
 
-  // Passing false to aNotify means that mListener will still get
-  // OnStopRequest, if needed.
-  if (mOwner)
-    mOwner->RemoveProxy(this, aStatus, false);
+  if (mOwner) {
+    mOwner->RemoveProxy(this, aStatus);
+  }
 
   mIsInLoadGroup = oldIsInLoadGroup;
 
   if (mIsInLoadGroup) {
     nsCOMPtr<nsIRunnable> ev =
       NS_NewRunnableMethod(this, &imgRequestProxy::DoRemoveFromLoadGroup);
     NS_DispatchToCurrentThread(ev);
   }
--- a/image/src/imgStatusTracker.cpp
+++ b/image/src/imgStatusTracker.cpp
@@ -245,32 +245,21 @@ imgStatusTracker::SyncNotify(imgRequestP
 
   if (mState & stateRequestStopped) {
     proxy->OnStopDecode(GetResultFromImageStatus(mImageStatus), nullptr);
     proxy->OnStopRequest(mHadLastPart);
   }
 }
 
 void
-imgStatusTracker::EmulateRequestFinished(imgRequestProxy* aProxy, nsresult aStatus,
-                                                bool aOnlySendStopRequest)
+imgStatusTracker::EmulateRequestFinished(imgRequestProxy* aProxy,
+                                         nsresult aStatus)
 {
   nsCOMPtr<imgIRequest> kungFuDeathGrip(aProxy);
 
-  if (!aOnlySendStopRequest) {
-    // The "real" OnStopDecode - fix this with bug 505385.
-    if (!(mState & stateDecodeStopped)) {
-      aProxy->OnStopContainer(mImage);
-    }
-
-    if (!(mState & stateRequestStopped)) {
-      aProxy->OnStopDecode(aStatus, nullptr);
-    }
-  }
-
   if (mState & stateBlockingOnload) {
     aProxy->UnblockOnload();
   }
 
   if (!(mState & stateRequestStopped)) {
     aProxy->OnStopRequest(true);
   }
 }
--- a/image/src/imgStatusTracker.h
+++ b/image/src/imgStatusTracker.h
@@ -75,22 +75,20 @@ public:
   void NotifyCurrentState(imgRequestProxy* proxy);
 
   // "Replay" all of the notifications that would have to happen to put us in
   // the state we're currently in.
   // Only use this if you're already servicing an asynchronous call (e.g.
   // OnStartRequest).
   void SyncNotify(imgRequestProxy* proxy);
 
-  // Send all notifications that would be necessary to make |proxy| believe the
-  // request is finished downloading and decoding.
-  // If aOnlySendStopRequest is true, we will only send OnStopRequest, and then
-  // only if that is necessary.
-  void EmulateRequestFinished(imgRequestProxy* proxy, nsresult aStatus,
-                              bool aOnlySendStopRequest);
+  // Send some notifications that would be necessary to make |proxy| believe
+  // the request is finished downloading and decoding.  We only send
+  // OnStopRequest and UnblockOnload, and only if necessary.
+  void EmulateRequestFinished(imgRequestProxy* proxy, nsresult aStatus);
 
   // Returns whether we are in the process of loading; that is, whether we have
   // not received OnStopRequest.
   bool IsLoading() const;
 
   // Get the current image status (as in imgIRequest).
   uint32_t GetImageStatus() const;
 
--- a/intl/locale/src/mac/nsDateTimeFormatMac.cpp
+++ b/intl/locale/src/mac/nsDateTimeFormatMac.cpp
@@ -7,17 +7,16 @@
 #include "nsIServiceManager.h"
 #include "nsDateTimeFormatMac.h"
 #include <CoreFoundation/CFDateFormatter.h>
 #include "nsIComponentManager.h"
 #include "nsLocaleCID.h"
 #include "nsILocaleService.h"
 #include "nsCRT.h"
 #include "plstr.h"
-#include "prmem.h"
 #include "nsUnicharUtils.h"
 #include "nsTArray.h"
 
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsDateTimeFormatMac, nsIDateTimeFormat)
 
 nsresult nsDateTimeFormatMac::Initialize(nsILocale* locale)
 {
--- a/intl/locale/src/windows/nsDateTimeFormatWin.cpp
+++ b/intl/locale/src/windows/nsDateTimeFormatWin.cpp
@@ -7,17 +7,16 @@
 #include "nsIServiceManager.h"
 #include "nsIComponentManager.h"
 #include "nsLocaleCID.h"
 #include "nsILocaleService.h"
 #include "nsWin32Locale.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsCOMPtr.h"
-#include "prmem.h"
 
 
 #define NSDATETIMEFORMAT_BUFFER_LEN  80
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsDateTimeFormatWin, nsIDateTimeFormat)
 
 
 // init this interface to a specified locale
--- a/intl/lwbrk/src/nsSemanticUnitScanner.cpp
+++ b/intl/lwbrk/src/nsSemanticUnitScanner.cpp
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsSemanticUnitScanner.h"
-#include "prmem.h"
 
 NS_IMPL_ISUPPORTS1(nsSemanticUnitScanner, nsISemanticUnitScanner)
 
 nsSemanticUnitScanner::nsSemanticUnitScanner() : nsSampleWordBreaker()
 {
   /* member initializers and constructor code */
 }
 
--- a/intl/uconv/src/nsCharsetConverterManager.cpp
+++ b/intl/uconv/src/nsCharsetConverterManager.cpp
@@ -8,17 +8,16 @@
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsCharsetAlias.h"
 #include "nsIServiceManager.h"
 #include "nsICategoryManager.h"
 #include "nsICharsetConverterManager.h"
 #include "nsEncoderDecoderUtils.h"
 #include "nsIStringBundle.h"
-#include "prmem.h"
 #include "nsCRT.h"
 #include "nsTArray.h"
 #include "nsStringEnumerator.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Services.h"
 
 #include "nsXPCOM.h"
 #include "nsComponentManagerUtils.h"
--- a/intl/uconv/src/nsTextToSubURI.cpp
+++ b/intl/uconv/src/nsTextToSubURI.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "nsString.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsICharsetConverterManager.h"
 #include "nsReadableUtils.h"
 #include "nsITextToSubURI.h"
 #include "nsIServiceManager.h"
 #include "nsEscape.h"
-#include "prmem.h"
 #include "nsTextToSubURI.h"
 #include "nsCRT.h"
 
 static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
 
 nsTextToSubURI::nsTextToSubURI()
 {
 }
--- a/intl/uconv/src/nsUTF8ConverterService.cpp
+++ b/intl/uconv/src/nsUTF8ConverterService.cpp
@@ -4,17 +4,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "nsString.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsICharsetConverterManager.h"
 #include "nsReadableUtils.h"
 #include "nsIServiceManager.h"
-#include "prmem.h"
 #include "nsUTF8ConverterService.h"
 #include "nsEscape.h"
 #include "nsAutoPtr.h"
 
 NS_IMPL_ISUPPORTS1(nsUTF8ConverterService, nsIUTF8ConverterService)
 
 static nsresult 
 ToUTF8(const nsACString &aString, const char *aCharset,
--- a/intl/uconv/tests/nsTestUConv.cpp
+++ b/intl/uconv/tests/nsTestUConv.cpp
@@ -6,17 +6,16 @@
 #include <stdio.h>
 #include <string.h>
 #include "nsXPCOM.h"
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsISupports.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIPlatformCharset.h"
-#include "prmem.h"
 #include "nsReadableUtils.h"
 
 
 static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
 static NS_DEFINE_CID(kPlatformCharsetCID, NS_PLATFORMCHARSET_CID);
 
 /**
  * Test program for the Unicode Converters.
--- a/js/public/HashTable.h
+++ b/js/public/HashTable.h
@@ -383,26 +383,26 @@ class HashTable : private AllocPolicy
 
     ~HashTable()
     {
         if (table)
             destroyTable(*this, table, capacity());
     }
 
   private:
-    static HashNumber hash1(HashNumber hash0, uint32_t shift) {
-        return hash0 >> shift;
+    HashNumber hash1(HashNumber hash0) const {
+        return hash0 >> hashShift;
     }
 
     struct DoubleHash {
         HashNumber h2;
         HashNumber sizeMask;
     };
 
-    DoubleHash hash2(HashNumber curKeyHash, uint32_t hashShift) const {
+    DoubleHash hash2(HashNumber curKeyHash) const {
         unsigned sizeLog2 = sHashBits - hashShift;
         DoubleHash dh = {
             ((curKeyHash << sizeLog2) >> hashShift) | 1,
             (HashNumber(1) << sizeLog2) - 1
         };
         return dh;
     }
 
@@ -428,33 +428,33 @@ class HashTable : private AllocPolicy
     {
         JS_ASSERT(isLiveHash(keyHash));
         JS_ASSERT(!(keyHash & sCollisionBit));
         JS_ASSERT(collisionBit == 0 || collisionBit == sCollisionBit);
         JS_ASSERT(table);
         METER(stats.searches++);
 
         /* Compute the primary hash address. */
-        HashNumber h1 = hash1(keyHash, hashShift);
+        HashNumber h1 = hash1(keyHash);
         Entry *entry = &table[h1];
 
         /* Miss: return space for a new entry. */
         if (entry->isFree()) {
             METER(stats.misses++);
             return *entry;
         }
 
         /* Hit: return entry. */
         if (entry->matchHash(keyHash) && match(*entry, l)) {
             METER(stats.hits++);
             return *entry;
         }
 
         /* Collision: double hash. */
-        DoubleHash dh = hash2(keyHash, hashShift);
+        DoubleHash dh = hash2(keyHash);
 
         /* Save the first removed entry pointer so we can recycle later. */
         Entry *firstRemoved = NULL;
 
         while(true) {
             if (JS_UNLIKELY(entry->isRemoved())) {
                 if (!firstRemoved)
                     firstRemoved = entry;
@@ -490,27 +490,27 @@ class HashTable : private AllocPolicy
     {
         JS_ASSERT(!(keyHash & sCollisionBit));
         JS_ASSERT(table);
         METER(stats.searches++);
 
         /* N.B. the |keyHash| has already been distributed. */
 
         /* Compute the primary hash address. */
-        HashNumber h1 = hash1(keyHash, hashShift);
+        HashNumber h1 = hash1(keyHash);
         Entry *entry = &table[h1];
 
         /* Miss: return space for a new entry. */
         if (!entry->isLive()) {
             METER(stats.misses++);
             return *entry;
         }
 
         /* Collision: double hash. */
-        DoubleHash dh = hash2(keyHash, hashShift);
+        DoubleHash dh = hash2(keyHash);
 
         while(true) {
             JS_ASSERT(!entry->isRemoved());
             entry->setCollision();
 
             METER(stats.steps++);
             h1 = applyDoubleHash(h1, dh);
 
@@ -627,18 +627,18 @@ class HashTable : private AllocPolicy
             Entry *src = &table[i];
 
             if (!src->isLive() || src->hasCollision()) {
                 ++i;
                 continue;
             }
 
             HashNumber keyHash = src->getKeyHash();
-            HashNumber h1 = hash1(keyHash, hashShift);
-            DoubleHash dh = hash2(keyHash, hashShift);
+            HashNumber h1 = hash1(keyHash);
+            DoubleHash dh = hash2(keyHash);
             Entry *tgt = &table[h1];
             while (true) {
                 if (!tgt->hasCollision()) {
                     Swap(*src, *tgt);
                     tgt->setCollision();
                     break;
                 }
 
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -5939,23 +5939,19 @@ IonBuilder::jsop_getprop(HandlePropertyN
 
         // If the cache is known to access getters, then enable generation of
         // getter stubs and set its result type to value.
         if (accessGetter)
             load->setAllowGetters();
 
         ins = load;
     } else if (obj->type() == MIRType_Value && unaryTypes.inTypes->objectOrSentinel()) {
-        // Fallibly unwrap the object and IC the result.
-        MUnbox *unbox = MUnbox::New(obj, MIRType_Object, MUnbox::Fallible);
-        current->add(unbox);
-
         spew("GETPROP is object-or-sentinel");
 
-        MGetPropertyCache *load = MGetPropertyCache::New(unbox, name);
+        MGetPropertyCache *load = MGetPropertyCache::New(obj, name);
         load->setResultType(rvalType);
         if (accessGetter)
             load->setAllowGetters();
 
         ins = load;
     } else {
         ins = MCallGetProperty::New(obj, name);
     }
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -46,17 +46,16 @@
 #include "nsDOMFile.h"
 #include "jsprf.h"
 #include "nsJSPrincipals.h"
 // For reporting errors with the console service
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIStorageStream.h"
 #include "nsIStringStream.h"
-#include "prmem.h"
 #if defined(XP_WIN)
 #include "nsILocalFileWin.h"
 #endif
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "nsIResProtocolHandler.h"
 #include "nsContentUtils.h"
 #include "WrapperFactory.h"
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -128,17 +128,16 @@
 #include "nsXPTCUtils.h"
 #include "xptinfo.h"
 #include "XPCForwards.h"
 #include "XPCLog.h"
 #include "xpccomponents.h"
 #include "xpcexception.h"
 #include "xpcjsid.h"
 #include "prlong.h"
-#include "prmem.h"
 #include "prenv.h"
 #include "prclist.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsXPIDLString.h"
 #include "nsAutoJSValHolder.h"
 
 #include "js/HashTable.h"
--- a/js/xpconnect/tests/chrome/Makefile.in
+++ b/js/xpconnect/tests/chrome/Makefile.in
@@ -36,16 +36,17 @@ MOCHITEST_CHROME_FILES = \
 		test_bug743843.xul \
 		test_bug760076.xul \
 		test_bug760109.xul \
 		test_bug763343.xul \
 		test_bug771429.xul \
 		test_bug773962.xul \
 		test_bug793433.xul \
 		test_bug795275.xul \
+		test_bug799348.xul \
 		test_APIExposer.xul \
 		test_chrometoSource.xul \
 		outoflinexulscript.js \
 		subscript.js \
 		test_cows.xul \
 		test_documentdomain.xul \
 		test_doublewrappedcompartments.xul \
 		test_evalInSandbox.xul \
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_bug799348.xul
@@ -0,0 +1,50 @@
+<?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=799348
+-->
+<window title="Mozilla Bug 799348"
+        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=799348"
+     target="_blank">Mozilla Bug 799348</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test for Bug 799348 **/
+  SimpleTest.waitForExplicitFinish();
+  Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+  Components.utils.import("resource://gre/modules/Services.jsm");
+  gCalledOnload = false;
+  var myObserver = {
+    QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]),
+    observe: function(win, topic, data) {
+      if (topic == "domwindowopened") {
+        ok(!gCalledOnload, "domwindowopened notification fired before onload");
+        win.addEventListener("load", function(evt) {
+          gCalledOnload = true;
+          win.close();
+        }, false);
+      } else if (topic == "domwindowclosed") {
+        ok(gCalledOnload, "should have called onload");
+        Services.ww.unregisterNotification(myObserver);
+        SimpleTest.finish();
+      }
+      else {
+        ok(false, "unknown topic");
+      }
+    }
+  };
+  Services.ww.registerNotification(myObserver);
+
+
+  ]]>
+  </script>
+  <iframe id="frame" type="content" src="http://test1.example.org/tests/js/xpconnect/tests/mochitest/file_bug799348.html" />
+</window>
--- a/js/xpconnect/tests/mochitest/Makefile.in
+++ b/js/xpconnect/tests/mochitest/Makefile.in
@@ -64,16 +64,17 @@ MOCHITEST_FILES =	bug500931_helper.html 
 		file_bug760131.html \
 		test_bug764389.html \
 		test_bug772288.html \
 		test_bug781476.html \
 		file_bug781476.html \
 		test_bug789713.html \
 		file_bug795275.html \
 		file_bug795275.xml \
+		file_bug799348.html \
 		file_nodelists.html \
 		file_exnstack.html \
 		file_expandosharing.html \
 		file_empty.html \
 		file_documentdomain.html \
 		test_lookupMethod.html \
 		file_bug738244.html \
 		file_mozMatchesSelector.html \
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/mochitest/file_bug799348.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script>
+  var foo = window.open('file_empty.html', '', 'width=550, height=420, status=no, resizable=yes, scrollbars=yes, toolbar=no, left=945, top=225');
+</script>
+</head>
+<body>
+</body>
+</html>
+
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -26,99 +26,188 @@
 #include "mozilla/gfx/Tools.h"
 
 #include "nsAnimationManager.h"
 #include "nsTransitionManager.h"
 
 #ifdef DEBUG
 #include <stdio.h>
 //#define DEBUG_INVALIDATIONS
+//#define DEBUG_DISPLAY_ITEM_DATA
 #endif
 
 using namespace mozilla::layers;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 
-FrameLayerBuilder::DisplayItemData::DisplayItemData(Layer* aLayer, uint32_t aKey, LayerState aLayerState, uint32_t aGeneration)
-  : mLayer(aLayer)
+FrameLayerBuilder::DisplayItemData::DisplayItemData(LayerManagerData* aParent, nsIFrame* aFrame, uint32_t aKey, 
+                                                    Layer* aLayer, LayerState aLayerState, uint32_t aGeneration)
+
+  : mParent(aParent)
+  , mLayer(aLayer)
   , mDisplayItemKey(aKey)
   , mContainerLayerGeneration(aGeneration)
   , mLayerState(aLayerState)
   , mUsed(false)
-{}
+  , mCopiedInto(nullptr)
+{
+  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::CopyInto(DisplayItemData* aOther)
+{
+  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;
+}
+
+void
+FrameLayerBuilder::DisplayItemData::RemoveFrameData(nsIFrame* aSkip /* = nullptr */)
+{
+  for (uint32_t i = 0; i < mFrameList.Length(); i++) {
+    nsIFrame* frame = mFrameList[i];
+    if (frame == aSkip) {
+      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;
   }
-  
+
   nsAutoTArray<nsIFrame*,4> mergedFrames;
   aOther->GetMergedFrames(&mergedFrames);
   for (uint32_t i = 0; i < mergedFrames.Length(); ++i) {
     if (!copy.RemoveElement(mergedFrames[i])) {
       return false;
     }
   }
 
   return copy.IsEmpty();
 }
 
 /**
  * This is the userdata we associate with a layer manager.
  */
 class LayerManagerData : public LayerUserData {
 public:
-  LayerManagerData() :
-    mInvalidateAllLayers(false)
+  LayerManagerData(LayerManager *aManager)
+    : mLayerManager(aManager)
+    , mParent(nullptr)
+    , mInvalidateAllLayers(false)
   {
     MOZ_COUNT_CTOR(LayerManagerData);
-    mFramesWithLayers.Init();
+    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.
-    mFramesWithLayers.EnumerateEntries(
-        FrameLayerBuilder::RemoveDisplayItemDataForFrame, this);
+    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 += "  ";
+    mDisplayItems.EnumerateEntries(
+        FrameLayerBuilder::DumpDisplayItemDataForFrame, (void*)prefix.get());
+  }
+#endif
 
   /**
    * Tracks which frames have layers associated with them.
    */
-  nsTHashtable<FrameLayerBuilder::DisplayItemDataEntry> mFramesWithLayers;
+  LayerManager *mLayerManager;
+  LayerManagerData *mParent;
+  nsTHashtable<nsRefPtrHashKey<FrameLayerBuilder::DisplayItemData> > mDisplayItems;
   bool mInvalidateAllLayers;
 };
 
 /* static */ void
 FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame)
 {
   FrameProperties props = aFrame->Properties();
   props.Delete(LayerManagerDataProperty());
-  props.Delete(LayerManagerSecondaryDataProperty());
 }
 
 namespace {
 
 // a global cache of image containers used for mask layers
 static MaskLayerImageCache* gMaskLayerImageCache = nullptr;
 
 static inline MaskLayerImageCache* GetMaskLayerImageCache()
@@ -400,17 +489,18 @@ protected:
   /**
    * If aItem used to belong to a ThebesLayer, invalidates the area of
    * aItem in that layer. If aNewLayer is a ThebesLayer, invalidates the area of
    * aItem in that layer.
    */
   void InvalidateForLayerChange(nsDisplayItem* aItem, 
                                 Layer* aNewLayer,
                                 const FrameLayerBuilder::Clip& aClip,
-                                const nsPoint& aTopLeft);
+                                const nsPoint& aTopLeft,
+                                nsDisplayItemGeometry *aGeometry);
   /**
    * Try to determine whether the ThebesLayer at aThebesLayerIndex
    * has a single opaque color behind it, over the entire bounds of its visible
    * region.
    * If successful, return that color, otherwise return NS_RGBA(0,0,0,0).
    */
   nscolor FindOpaqueBackgroundColorFor(int32_t aThebesLayerIndex);
   /**
@@ -573,26 +663,16 @@ struct MaskLayerUserData : public LayerU
   nsRefPtr<const MaskLayerImageCache::MaskLayerImageKey> mImageKey;
   // properties of the mask layer; the mask layer may be re-used if these
   // remain unchanged.
   nsTArray<FrameLayerBuilder::Clip::RoundedRect> mRoundedClipRects;
   // scale from the masked layer which is applied to the mask
   float mScaleX, mScaleY;
 };
 
-/*
- * User data to track the owning frame of a layer during construction.
- */
-struct LayerOwnerUserData : public LayerUserData
-{
-  LayerOwnerUserData(nsIFrame* aOwnerFrame) : mOwnerFrame(aOwnerFrame) {}
-
-  nsIFrame* mOwnerFrame;
-};
-
 /**
  * The address of gThebesDisplayItemLayerUserData is used as the user
  * data key for ThebesLayers created by FrameLayerBuilder.
  * It identifies ThebesLayers used to draw non-layer content, which are
  * therefore eligible for recycling. We want display items to be able to
  * create their own dedicated ThebesLayers in BuildLayer, if necessary,
  * and we wouldn't want to accidentally recycle those.
  * The user data is a ThebesDisplayItemLayerUserData.
@@ -617,22 +697,16 @@ uint8_t gImageLayerUserData;
  */
 uint8_t gLayerManagerUserData;
 /**
  * The address of gMaskLayerUserData is used as the user
  * data key for mask layers managed by FrameLayerBuilder.
  * The user data is a MaskLayerUserData.
  */
 uint8_t gMaskLayerUserData;
-/**
- * The address of gLayerOwnerUserData is used as the user
- * data key for a Layer's owner frame during layer-building.
- * The user data is a LayerOwnerUserData.
- */
-uint8_t gLayerOwnerUserData;
 
 /**
   * Helper functions for getting user data and casting it to the correct type.
   * aLayer is the layer where the user data is stored.
   */
 MaskLayerUserData* GetMaskLayerUserData(Layer* aLayer)
 {
   return static_cast<MaskLayerUserData*>(aLayer->GetUserData(&gMaskLayerUserData));
@@ -641,71 +715,16 @@ MaskLayerUserData* GetMaskLayerUserData(
 ThebesDisplayItemLayerUserData* GetThebesDisplayItemLayerUserData(Layer* aLayer)
 {
   return static_cast<ThebesDisplayItemLayerUserData*>(
     aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
 }
 
 } // anonymous namespace
 
-uint8_t gLayerManagerSecondary;
-
-bool FrameLayerBuilder::sWidgetManagerSecondary = false;
-
-/* static */ const FramePropertyDescriptor* 
-FrameLayerBuilder::GetDescriptorForManager(LayerManager* aManager)
-{
-  bool secondary = sWidgetManagerSecondary;
-  if (aManager) {
-    secondary = !!static_cast<LayerManagerSecondary*>(aManager->GetUserData(&gLayerManagerSecondary));
-  }
-
-  return secondary ? LayerManagerSecondaryDataProperty() : LayerManagerDataProperty();
-}
-
-LayerManagerData*
-FrameLayerBuilder::GetManagerData(nsIFrame* aFrame, LayerManager* aManager)
-{
-  FrameProperties props = aFrame->Properties();
-  return static_cast<LayerManagerData*>(props.Get(GetDescriptorForManager(aManager)));
-}
-
-void
-FrameLayerBuilder::SetManagerData(nsIFrame* aFrame, LayerManagerData* aData)
-{
-  FrameProperties props = aFrame->Properties();
-  const FramePropertyDescriptor* desc = GetDescriptorForManager(nullptr);
-
-  props.Remove(desc);
-  if (aData) {
-    props.Set(desc, aData);
-  }
-}
-
-void
-FrameLayerBuilder::ClearManagerData(nsIFrame* aFrame)
-{
-  SetManagerData(aFrame, nullptr);
-}
-
-void
-FrameLayerBuilder::ClearManagerData(nsIFrame* aFrame, LayerManagerData* aData)
-{
-  NS_ABORT_IF_FALSE(aData, "Must have a widget manager to check for manager data!");
-
-  FrameProperties props = aFrame->Properties();
-  if (aData == static_cast<LayerManagerData*>(props.Get(LayerManagerDataProperty()))) {
-    props.Remove(LayerManagerDataProperty());
-    return;
-  }
-  if (aData == static_cast<LayerManagerData*>(props.Get(LayerManagerSecondaryDataProperty()))) {
-    props.Remove(LayerManagerSecondaryDataProperty());
-    return;
-  }
-}
 /* static */ void
 FrameLayerBuilder::Shutdown()
 {
   if (gMaskLayerImageCache) {
     delete gMaskLayerImageCache;
     gMaskLayerImageCache = nullptr;
   }
 }
@@ -716,27 +735,16 @@ FrameLayerBuilder::Init(nsDisplayListBui
   mDisplayListBuilder = aBuilder;
   mRootPresContext = aBuilder->RootReferenceFrame()->PresContext()->GetRootPresContext();
   if (mRootPresContext) {
     mInitialDOMGeneration = mRootPresContext->GetDOMGeneration();
   }
   aManager->SetUserData(&gLayerManagerLayerBuilder, this);
 }
 
-bool
-FrameLayerBuilder::DisplayItemDataEntry::HasNonEmptyContainerLayer()
-{
-  for (uint32_t i = 0; i < mData.Length(); ++i) {
-    if (mData[i]->mLayer->GetType() == Layer::TYPE_CONTAINER &&
-        mData[i]->mLayerState != LAYER_ACTIVE_EMPTY)
-      return true;
-  }
-  return false;
-}
-
 void
 FrameLayerBuilder::FlashPaint(gfxContext *aContext)
 {
   static bool sPaintFlashingEnabled;
   static bool sPaintFlashingPrefCached = false;
 
   if (!sPaintFlashingPrefCached) {
     sPaintFlashingPrefCached = true;
@@ -748,30 +756,31 @@ FrameLayerBuilder::FlashPaint(gfxContext
     float r = float(rand()) / RAND_MAX;
     float g = float(rand()) / RAND_MAX;
     float b = float(rand()) / RAND_MAX;
     aContext->SetColor(gfxRGBA(r, g, b, 0.2));
     aContext->Paint();
   }
 }
 
-nsTArray<nsRefPtr<FrameLayerBuilder::DisplayItemData> >*
-FrameLayerBuilder::GetDisplayItemDataArrayForFrame(nsIFrame* aFrame)
+FrameLayerBuilder::DisplayItemData*
+FrameLayerBuilder::GetDisplayItemData(nsIFrame* aFrame, uint32_t aKey)
 {
-  LayerManagerData* data = static_cast<LayerManagerData*>
-    (mRetainingManager->GetUserData(&gLayerManagerUserData));
-  if (!data) {
-    return nullptr;
+  nsTArray<DisplayItemData*> *array = 
+    reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(LayerManagerDataProperty()));
+  if (array) {
+    for (uint32_t i = 0; i < array->Length(); i++) {
+      DisplayItemData* item = array->ElementAt(i);
+      if (item->mDisplayItemKey == aKey &&
+          item->mLayer->Manager() == mRetainingManager) {
+        return item;
+      }
+    }
   }
-
-  DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(aFrame);
-  if (!entry)
-    return nullptr;
-
-  return &entry->mData;
+  return nullptr;
 }
 
 nsACString&
 AppendToString(nsACString& s, const nsIntRect& r,
                const char* pfx="", const char* sfx="")
 {
   s += pfx;
   s += nsPrintfCString(
@@ -839,75 +848,90 @@ GetTranslationForThebesLayer(ThebesLayer
  * 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
  * 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 nsIFrame* sDestroyedFrame = NULL;
 
 /* static */ void
 FrameLayerBuilder::RemoveFrameFromLayerManager(nsIFrame* aFrame,
                                                void* aPropertyValue)
 {
-  LayerManagerData *data = reinterpret_cast<LayerManagerData*>(aPropertyValue);
-
-  DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(aFrame);
-  for (uint32_t i = 0; i < entry->mData.Length(); ++i) {
-    ThebesLayer* t = entry->mData[i]->mLayer->AsThebesLayer();
+  sDestroyedFrame = aFrame;
+  nsTArray<DisplayItemData*> *array = 
+    reinterpret_cast<nsTArray<DisplayItemData*>*>(aPropertyValue);
+
+  // Hold a reference to all the items so that they don't get
+  // deleted from under us.
+  nsTArray<nsRefPtr<DisplayItemData> > arrayCopy;
+  for (uint32_t i = 0; i < array->Length(); ++i) {
+    arrayCopy.AppendElement(array->ElementAt(i));
+  }
+
+#ifdef DEBUG_DISPLAY_ITEM_DATA
+  if (array->Length()) {
+    LayerManagerData *rootData = array->ElementAt(0)->mParent;
+    while (rootData->mParent) {
+      rootData = rootData->mParent;
+    }
+    printf("Removing frame %p - dumping display data\n", aFrame);
+    rootData->Dump();
+  }
+#endif
+
+  for (uint32_t i = 0; i < array->Length(); ++i) {
+    DisplayItemData* data = array->ElementAt(i);
+
+    ThebesLayer* t = data->mLayer->AsThebesLayer();
     if (t) {
-      ThebesDisplayItemLayerUserData* data =
+      ThebesDisplayItemLayerUserData* thebesData =
           static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
-      if (data) {
-        nsRegion old = entry->mData[i]->mGeometry->ComputeInvalidationRegion();
-        nsIntRegion rgn = old.ScaleToOutsidePixels(data->mXScale, data->mYScale, data->mAppUnitsPerDevPixel);
+      if (thebesData) {
+        nsRegion old = data->mGeometry->ComputeInvalidationRegion();
+        nsIntRegion rgn = old.ScaleToOutsidePixels(thebesData->mXScale, thebesData->mYScale, thebesData->mAppUnitsPerDevPixel);
         rgn.MoveBy(-GetTranslationForThebesLayer(t));
-        data->mRegionToInvalidate.Or(data->mRegionToInvalidate, rgn);
+        thebesData->mRegionToInvalidate.Or(thebesData->mRegionToInvalidate, rgn);
       }
     }
+
+    data->RemoveFrameData(aFrame);
+    data->mParent->mDisplayItems.RemoveEntry(data);
   }
 
-  sDestroyedFrame = aFrame;
-  data->mFramesWithLayers.RemoveEntry(aFrame);
+  arrayCopy.Clear();
+  delete array;
   sDestroyedFrame = NULL;
 }
 
 void
 FrameLayerBuilder::DidBeginRetainedLayerTransaction(LayerManager* aManager)
 {
   mRetainingManager = aManager;
   LayerManagerData* data = static_cast<LayerManagerData*>
     (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     mInvalidateAllLayers = data->mInvalidateAllLayers;
   } else {
-    data = new LayerManagerData();
+    data = new LayerManagerData(aManager);
     aManager->SetUserData(&gLayerManagerUserData, data);
   }
 }
 
 void
 FrameLayerBuilder::StoreOptimizedLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey, Layer* aImage)
 {
-  DisplayItemDataEntry *entry = mNewDisplayItemData.GetEntry(aFrame);
+  DisplayItemKey key(aFrame, aDisplayItemKey);
+  DisplayItemHashData *entry = mNewDisplayItemData.GetEntry(key);
   if (!entry)
     return;
 
-  nsTArray<nsRefPtr<DisplayItemData> > *array = &entry->mData;
-  if (!array)
-    return;
-
-  for (uint32_t i = 0; i < array->Length(); ++i) {
-    if (array->ElementAt(i)->mDisplayItemKey == aDisplayItemKey) {
-      array->ElementAt(i)->mOptLayer = aImage;
-      return;
-    }
-  }
+  entry->mData->mOptLayer = aImage;
 }
 
 void
 FrameLayerBuilder::DidEndTransaction()
 {
   GetMaskLayerImageCache()->Sweep();
 }
 
@@ -918,17 +942,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->mFramesWithLayers.EnumerateEntries(UpdateDisplayItemDataForFrame, this);
+  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->mInvalidateAllLayers = false;
 }
 
@@ -938,330 +962,252 @@ struct ProcessRemovedDisplayItemsData
     : mLayer(aLayer)
     , mLayerBuilder(aLayerBuilder)
   {}
 
   Layer *mLayer;
   FrameLayerBuilder *mLayerBuilder;
 };
 
+
 /* static */ PLDHashOperator
-FrameLayerBuilder::ProcessRemovedDisplayItems(DisplayItemDataEntry* aEntry,
+FrameLayerBuilder::ProcessRemovedDisplayItems(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                               void* aUserArg)
 {
   ProcessRemovedDisplayItemsData *userData =
     static_cast<ProcessRemovedDisplayItemsData*>(aUserArg);
   Layer* layer = userData->mLayer;
   FrameLayerBuilder* layerBuilder = userData->mLayerBuilder;
-  for (uint32_t i = 0; i < aEntry->mData.Length(); ++i) {
-    DisplayItemData* item = aEntry->mData[i];
-    ThebesLayer* t = item->mLayer->AsThebesLayer();
-    if (!item->mUsed && t && item->mLayer == layer) {
+
+  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, aEntry->GetKey(), t);
+    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));
-    }
+    ThebesDisplayItemLayerUserData* data =
+        static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
+    InvalidatePostTransformRegion(t,
+        item->mGeometry->ComputeInvalidationRegion().
+          ScaleToOutsidePixels(data->mXScale, data->mYScale, data->mAppUnitsPerDevPixel),
+        layerBuilder->GetLastPaintOffset(t));
   }
   return PL_DHASH_NEXT;
 }
 
 /* static */ PLDHashOperator
-FrameLayerBuilder::UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
+FrameLayerBuilder::UpdateDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                                  void* aUserArg)
 {
   FrameLayerBuilder* builder = static_cast<FrameLayerBuilder*>(aUserArg);
-  nsIFrame* f = aEntry->GetKey();
-  DisplayItemDataEntry* newDisplayItems =
-    builder ? builder->mNewDisplayItemData.GetEntry(f) : nullptr;
-
-  LayerManagerData* managerData = static_cast<LayerManagerData*>
-    (builder->GetRetainingLayerManager()->GetUserData(&gLayerManagerUserData));
-  LayerManagerData* data = GetManagerData(f);
-  if (!newDisplayItems || newDisplayItems->mData.IsEmpty()) {
-    // This frame was visible, but isn't anymore.
-    if (newDisplayItems) {
-      builder->mNewDisplayItemData.RawRemoveEntry(newDisplayItems);
-    }
-    if (data == managerData) {
-      ClearManagerData(f);
-    }
+  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)) {
+    // 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;
   }
 
-  SetManagerData(f, managerData);
-
-  // Steal the list of display item layers and invalid region
-  aEntry->mData.SwapElements(newDisplayItems->mData);
+  // 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);
+  }
   return PL_DHASH_NEXT;
 }
   
 /* static */ PLDHashOperator 
-FrameLayerBuilder::RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
+FrameLayerBuilder::RemoveDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                                  void* aClosure)
 {
-  LayerManagerData* managerData = static_cast<LayerManagerData*>(aClosure);
-  nsIFrame* f = aEntry->GetKey();
+  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.
-  if (f != sDestroyedFrame) {
-    ClearManagerData(f, managerData);
+  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);
+  
+  const char *layerState;
+  switch (data->mLayerState) {
+    case LAYER_NONE:
+      layerState = "LAYER_NONE"; break;
+    case LAYER_INACTIVE:
+      layerState = "LAYER_INACTIVE"; break;
+    case LAYER_ACTIVE:
+      layerState = "LAYER_ACTIVE"; break;
+    case LAYER_ACTIVE_FORCE:
+      layerState = "LAYER_ACTIVE_FORCE"; break;
+    case LAYER_ACTIVE_EMPTY:
+      layerState = "LAYER_ACTIVE_EMPTY"; break;
+    case LAYER_SVG_EFFECTS:
+      layerState = "LAYER_SVG_EFFECTS"; break;
   }
-  return PL_DHASH_REMOVE;
+  uint32_t mask = (1 << nsDisplayItem::TYPE_BITS) - 1;
+
+  nsAutoCString str;
+  str += prefix;
+  str += nsPrintfCString("Frame %p ", data->mFrameList[0]);
+  str += nsDisplayItem::DisplayItemTypeName(static_cast<nsDisplayItem::Type>(data->mDisplayItemKey & mask));
+  if ((data->mDisplayItemKey >> nsDisplayItem::TYPE_BITS)) {
+    str += nsPrintfCString("(%i)", data->mDisplayItemKey >> nsDisplayItem::TYPE_BITS);
+  }
+  str += nsPrintfCString(", %s, Layer %p", layerState, data->mLayer.get());
+  if (data->mOptLayer) {
+    str += nsPrintfCString(", OptLayer %p", data->mOptLayer.get());
+  }
+  if (data->mInactiveManager) {
+    str += nsPrintfCString(", InactiveLayerManager %p", data->mInactiveManager.get());
+  }
+  str += "\n";
+
+  printf("%s", str.get());
+    
+  if (data->mInactiveManager) {
+    prefix += "  ";
+    printf("%sDumping inactive layer info:\n", prefix.get());
+    LayerManagerData* lmd = static_cast<LayerManagerData*>
+      (data->mInactiveManager->GetUserData(&gLayerManagerUserData));
+    lmd->Dump(prefix.get());
+  }
+#endif
+  return PL_DHASH_NEXT;
 }
 
 /* static */ PLDHashOperator
-FrameLayerBuilder::StoreNewDisplayItemData(DisplayItemDataEntry* aEntry,
+FrameLayerBuilder::StoreNewDisplayItemData(DisplayItemHashData* aEntry,
                                            void* aUserArg)
 {
   LayerManagerData* data = static_cast<LayerManagerData*>(aUserArg);
-  nsIFrame* f = aEntry->GetKey();
+  const DisplayItemKey& key = aEntry->GetKey();
 
   // Remember that this frame has display items in retained layers
-  NS_ASSERTION(!data->mFramesWithLayers.GetEntry(f),
-               "We shouldn't get here if we're already in mFramesWithLayers");
-  DisplayItemDataEntry *newEntry = data->mFramesWithLayers.PutEntry(f);
-
-  newEntry->mData.SwapElements(aEntry->mData);
-  // Remove any old layer manager data for this frame. We don't destroy it
-  // because we don't want it to call the frame destroyed function.
-  // When a frame has multiple layer managers (main, inactive, svg), we
-  // only need to store the outermost one since that will be enough to
-  // invalidate the entire region covered by all the children.
-  SetManagerData(f, data);
+  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;
 }
 
-/**
- * Attempts to find the LayerManagerData for the widget manager
- * for the given frame, nullptr otherwise.
- */
-static LayerManagerData*
-GetDefaultLayerManagerDataForFrame(nsIFrame* aFrame)
-{
-  FrameProperties props = aFrame->Properties();
-  return static_cast<LayerManagerData*>(props.Get(FrameLayerBuilder::LayerManagerDataProperty()));
-}
-
-static LayerManagerData*
-GetSecondaryLayerManagerDataForFrame(nsIFrame* aFrame)
-{
-  FrameProperties props = aFrame->Properties();
-  return static_cast<LayerManagerData*>(props.Get(FrameLayerBuilder::LayerManagerSecondaryDataProperty()));
-}
-
-/* static */ FrameLayerBuilder::DisplayItemData*
-FrameLayerBuilder::GetDisplayItemDataForManager(nsIFrame* aFrame,
-                                                uint32_t aDisplayItemKey,
-                                                LayerManagerData* aData)
-{
-  DisplayItemDataEntry *entry = aData->mFramesWithLayers.GetEntry(aFrame);
-  if (!entry) {
-    return nullptr;
-  }
-
-  for (uint32_t i = 0; i < entry->mData.Length(); ++i) {
-    if (entry->mData[i]->mDisplayItemKey == aDisplayItemKey) {
-      return entry->mData[i];
-    }
-  }
-  
-  return nullptr;
-}
-
-/* static */ FrameLayerBuilder::DisplayItemData*
-FrameLayerBuilder::GetDisplayItemDataForManager(nsIFrame* aFrame, 
-                                                uint32_t aDisplayItemKey, 
-                                                LayerManager* aManager)
-{
-  LayerManagerData *data = 
-    static_cast<LayerManagerData*>(aManager->GetUserData(&gLayerManagerUserData));
-  
-  if (!data) {
-    return nullptr;
-  }
-
-  return GetDisplayItemDataForManager(aFrame, aDisplayItemKey, data);
-}
-
 /* static */ FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem, 
                                                 LayerManager* aManager)
 {
-  DisplayItemData* data = 
-    GetDisplayItemDataForManager(aItem->GetUnderlyingFrame(), 
-                                 aItem->GetPerFrameKey(), 
-                                 aManager);
-  if (data) {
-    return data->FrameListMatches(aItem) ? data : nullptr;
-  }
-
-  nsAutoTArray<nsIFrame*,4> mergedFrames;
-  aItem->GetMergedFrames(&mergedFrames);
-  for (uint32_t i = 0; i < mergedFrames.Length(); ++i) {
-    data = 
-      GetDisplayItemDataForManager(mergedFrames[i], 
-                                   aItem->GetPerFrameKey(), 
-                                   aManager);
-    if (data) {
-      return data->FrameListMatches(aItem) ? data : nullptr;
+  nsTArray<DisplayItemData*> *array = 
+    reinterpret_cast<nsTArray<DisplayItemData*>*>(aItem->GetUnderlyingFrame()->Properties().Get(LayerManagerDataProperty()));
+  if (array) {
+    for (uint32_t i = 0; i < array->Length(); i++) {
+      DisplayItemData* item = array->ElementAt(i);
+      if (item->mDisplayItemKey == aItem->GetPerFrameKey() &&
+          item->mLayer->Manager() == aManager &&
+          item->FrameListMatches(aItem)) {
+        return item;
+      }
     }
   }
   return nullptr;
 }
 
-/* static */ FrameLayerBuilder::DisplayItemData*
-FrameLayerBuilder::GetDisplayItemDataForManager(nsIFrame* aFrame, 
-                                                uint32_t aDisplayItemKey)
-{
-  LayerManagerData *data = GetDefaultLayerManagerDataForFrame(aFrame);
-  
-  if (!data) {
-    return nullptr;
-  }
-  
-  return GetDisplayItemDataForManager(aFrame, aDisplayItemKey, data);
-}
-
-bool
-FrameLayerBuilder::HasRetainedLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey, LayerManager* aManager)
-{
-  DisplayItemData* data = GetDisplayItemDataForManager(aFrame, aDisplayItemKey, aManager);
-  if (data) {
-    Layer* layer = data->mLayer;
-    if (layer->Manager()->GetUserData(&gLayerManagerUserData)) {
-      // All layer managers with our user data are retained layer managers
-      return true;
-    }
-  }
-  return false;
-}
-
 bool
 FrameLayerBuilder::HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
 {
-  LayerManagerData* data = GetDefaultLayerManagerDataForFrame(aFrame);
-  if (data && GetDisplayItemDataForManager(aFrame, aDisplayItemKey, data)) {
-    return true;
-  }
-  data = GetSecondaryLayerManagerDataForFrame(aFrame);
-  if (data && GetDisplayItemDataForManager(aFrame, aDisplayItemKey, data)) {
-    return true;
+  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) {
+        return true;
+      }
+    }
   }
   return false;
 }
 
 FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey)
 {
   // If we need to build a new layer tree, then just refuse to recycle
   // anything.
   if (!mRetainingManager || mInvalidateAllLayers)
     return nullptr;
 
-  nsTArray<nsRefPtr<DisplayItemData> > *array = GetDisplayItemDataArrayForFrame(aFrame);
-  if (!array)
-    return nullptr;
-
-  for (uint32_t i = 0; i < array->Length(); ++i) {
-    if (array->ElementAt(i)->mDisplayItemKey == aDisplayItemKey) {
-      Layer* layer = array->ElementAt(i)->mLayer;
-      if (layer->Manager() == mRetainingManager) {
-        return array->ElementAt(i);
-      }
-    }
+  DisplayItemData *data = GetDisplayItemData(aFrame, aDisplayItemKey);
+
+  if (data && data->mLayer->Manager() == mRetainingManager) {
+    return data;
   }
   return nullptr;
 }
 
 Layer*
 FrameLayerBuilder::GetOldLayerFor(nsDisplayItem* aItem, nsDisplayItemGeometry** aOldGeometry, Clip** aOldClip)
 {
   uint32_t key = aItem->GetPerFrameKey();
   nsIFrame* frame = aItem->GetUnderlyingFrame();
 
   if (frame) {
     DisplayItemData* oldData = GetOldLayerForFrame(frame, key);
-    if (oldData) {
-      if (aOldGeometry) {
-        *aOldGeometry = oldData->mGeometry.get();
-      }
-      if (aOldClip) {
-        *aOldClip = &oldData->mClip;
-      }
-      return oldData->mLayer;
-    }
-  }
-
-  nsAutoTArray<nsIFrame*,4> mergedFrames;
-  aItem->GetMergedFrames(&mergedFrames);
-  for (uint32_t i = 0; i < mergedFrames.Length(); ++i) {
-    DisplayItemData* oldData = GetOldLayerForFrame(mergedFrames[i], key);
-    if (oldData) {
+    if (oldData && oldData->FrameListMatches(aItem)) {
       if (aOldGeometry) {
         *aOldGeometry = oldData->mGeometry.get();
       }
       if (aOldClip) {
         *aOldClip = &oldData->mClip;
       }
       return oldData->mLayer;
     }
   }
 
   return nullptr;
 } 
 
 /* static */ Layer*
 FrameLayerBuilder::GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
 {
-  LayerManagerData* data = GetManagerData(aFrame);
-  if (!data) {
+  nsTArray<DisplayItemData*> *array = 
+    reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(LayerManagerDataProperty()));
+
+  if (!array) {
     return nullptr;
   }
-  DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(aFrame);
-  if (!entry)
-    return nullptr;
-
-  nsTArray<nsRefPtr<DisplayItemData> > *array = &entry->mData;
-  if (!array)
-    return nullptr;
-
-  for (uint32_t i = 0; i < array->Length(); ++i) {
-    if (array->ElementAt(i)->mDisplayItemKey == aDisplayItemKey) {
-      return array->ElementAt(i)->mLayer;
+
+  for (uint32_t i = 0; i < array->Length(); i++) {
+    DisplayItemData *data = array->ElementAt(i);
+
+    if (data->mDisplayItemKey == aDisplayItemKey) {
+      return data->mLayer; 
     }
   }
   return nullptr;
 }
 
-LayerManager*
-FrameLayerBuilder::GetInactiveLayerManagerFor(nsDisplayItem* aItem)
-{
-  nsTArray<nsRefPtr<FrameLayerBuilder::DisplayItemData> > *array = GetDisplayItemDataArrayForFrame(aItem->GetUnderlyingFrame());
-  NS_ASSERTION(array, "We need an array here!. Really, we do.");
-
-  nsRefPtr<LayerManager> tempManager;
-  for (uint32_t i = 0; i < array->Length(); ++i) {
-    if (array->ElementAt(i)->mDisplayItemKey == aItem->GetPerFrameKey()) {
-      NS_ASSERTION(array->ElementAt(i)->mInactiveManager, "Must already have one of these");
-      return array->ElementAt(i)->mInactiveManager;
-      
-    }
-  }
-  NS_ERROR("Failed to find data for display item");
-  return NULL;
-}
-
 already_AddRefed<ColorLayer>
 ContainerState::CreateOrRecycleColorLayer(ThebesLayer *aThebes)
 {
   ThebesDisplayItemLayerUserData* data = 
       static_cast<ThebesDisplayItemLayerUserData*>(aThebes->GetUserData(&gThebesDisplayItemLayerUserData));
   nsRefPtr<ColorLayer> layer = data->mColorLayer;
   if (layer) {
     layer->SetClipRect(nullptr);
@@ -2054,16 +2000,20 @@ PaintInactiveLayer(nsDisplayListBuilder*
  * of ContainerState::Finish.
  */
 void
 ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
                                     FrameLayerBuilder::Clip& aClip,
                                     uint32_t aFlags)
 {
   SAMPLE_LABEL("ContainerState", "ProcessDisplayItems");
+
+  const nsIFrame* lastActiveScrolledRoot = nullptr;
+  nsPoint topLeft;
+
   for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) {
     nsDisplayItem::Type type = item->GetType();
     if (type == nsDisplayItem::TYPE_CLIP ||
         type == nsDisplayItem::TYPE_CLIP_ROUNDED_RECT) {
       FrameLayerBuilder::Clip childClip(aClip, item);
       ProcessDisplayItems(*item->GetList(), childClip, aFlags);
       continue;
     }
@@ -2084,30 +2034,34 @@ ContainerState::ProcessDisplayItems(cons
     mBounds.UnionRect(mBounds, itemContent);
     itemVisibleRect.IntersectRect(itemVisibleRect, itemDrawRect);
 
     LayerState layerState = item->GetLayerState(mBuilder, mManager, mParameters);
 
     bool isFixed;
     bool forceInactive;
     const nsIFrame* activeScrolledRoot;
-    nsPoint topLeft;
     if (aFlags & NO_COMPONENT_ALPHA) {
       // When NO_COMPONENT_ALPHA is set, items will be flattened onto the
       // reference frame. In this case, force the active scrolled root to
       // that frame.
       forceInactive = true;
       activeScrolledRoot = mContainerReferenceFrame;
       topLeft = nsPoint(0, 0);
       isFixed = mBuilder->IsFixedItem(item, nullptr, activeScrolledRoot);
     } else {
       forceInactive = false;
       isFixed = mBuilder->IsFixedItem(item, &activeScrolledRoot);
-      topLeft = activeScrolledRoot->GetOffsetToCrossDoc(mContainerReferenceFrame);
+      if (activeScrolledRoot != lastActiveScrolledRoot) {
+        lastActiveScrolledRoot = activeScrolledRoot;
+        topLeft = activeScrolledRoot->GetOffsetToCrossDoc(mContainerReferenceFrame);
+      }
     }
+  
+    nsAutoPtr<nsDisplayItemGeometry> geometry(item->AllocateGeometry(mBuilder));
 
     // Assign the item to a layer
     if (layerState == LAYER_ACTIVE_FORCE ||
         (!forceInactive &&
          (layerState == LAYER_ACTIVE_EMPTY ||
           layerState == LAYER_ACTIVE))) {
 
       // LAYER_ACTIVE_EMPTY means the layer is created just for its metadata.
@@ -2116,24 +2070,24 @@ ContainerState::ProcessDisplayItems(cons
                    itemVisibleRect.IsEmpty(),
                    "State is LAYER_ACTIVE_EMPTY but visible rect is not.");
 
       // 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);
+        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);
+        InvalidateForLayerChange(item, ownLayer, aClip, topLeft, geometry);
         continue;
       }
 
       nsRect invalid;
       if (item->IsInvalid(invalid)) {
         ownLayer->SetInvalidRectToVisibleRegion();
       }
 
@@ -2181,81 +2135,83 @@ 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);
+      InvalidateForLayerChange(item, ownLayer, aClip, topLeft, geometry);
 
       mNewChildLayers.AppendElement(ownLayer);
       mLayerBuilder->AddLayerDisplayItem(ownLayer, item, 
                                          aClip, layerState, 
-                                         topLeft, nullptr);
+                                         topLeft, nullptr,
+                                         geometry);
     } else {
       ThebesLayerData* data =
         FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, aClip,
                            activeScrolledRoot, topLeft);
 
       data->mLayer->SetIsFixedPosition(isFixed);
 
-      InvalidateForLayerChange(item, data->mLayer, aClip, topLeft);
+      InvalidateForLayerChange(item, data->mLayer, aClip, topLeft, geometry);
 
       mLayerBuilder->AddThebesDisplayItem(data->mLayer, item, aClip,
                                           mContainerFrame,
-                                          layerState, topLeft);
+                                          layerState, topLeft,
+                                          geometry);
 
       // check to see if the new item has rounded rect clips in common with
       // other items in the layer
       data->UpdateCommonClipCount(aClip);
     }
   }
 }
 
 void
 ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, 
                                          Layer* aNewLayer,
                                          const FrameLayerBuilder::Clip& aClip,
-                                         const nsPoint& aTopLeft)
+                                         const nsPoint& aTopLeft,
+                                         nsDisplayItemGeometry *aGeometry)
 {
   NS_ASSERTION(aItem->GetUnderlyingFrame(),
                "Display items that render using Thebes must have a frame");
   NS_ASSERTION(aItem->GetPerFrameKey(),
                "Display items that render using Thebes must have a key");
   nsDisplayItemGeometry *oldGeometry = NULL;
   FrameLayerBuilder::Clip* oldClip = NULL;
-  nsAutoPtr<nsDisplayItemGeometry> geometry(aItem->AllocateGeometry(mBuilder));
   Layer* oldLayer = mLayerBuilder->GetOldLayerFor(aItem, &oldGeometry, &oldClip);
   if (aNewLayer != oldLayer && oldLayer) {
     // The item has changed layers.
     // Invalidate the old bounds in the old layer and new bounds in the new layer.
     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(), f, t, aNewLayer);
+      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),
           mLayerBuilder->GetLastPaintOffset(t));
     }
     if (aNewLayer) {
       ThebesLayer* newThebesLayer = aNewLayer->AsThebesLayer();
       if (newThebesLayer) {
         ThebesDisplayItemLayerUserData* data =
             static_cast<ThebesDisplayItemLayerUserData*>(newThebesLayer->GetUserData(&gThebesDisplayItemLayerUserData));
         InvalidatePostTransformRegion(newThebesLayer,
-            geometry->ComputeInvalidationRegion().
+            aGeometry->ComputeInvalidationRegion().
               ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
             GetTranslationForThebesLayer(newThebesLayer));
       }
     }
     return;
   } 
   if (!aNewLayer) {
     return;
@@ -2271,41 +2227,41 @@ ContainerState::InvalidateForLayerChange
   // 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;
   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 = geometry->ComputeInvalidationRegion();
+    combined = aGeometry->ComputeInvalidationRegion();
 #ifdef DEBUG_INVALIDATIONS
-    printf("Display item type %s(%p) added to layer %p!\n", aItem->Name(), f, aNewLayer);
+    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(geometry->ComputeInvalidationRegion(), oldGeometry->ComputeInvalidationRegion());
+    combined.Or(aGeometry->ComputeInvalidationRegion(), oldGeometry->ComputeInvalidationRegion());
 #ifdef DEBUG_INVALIDATIONS
-    printf("Display item type %s(%p) (in layer %p) belongs to an invalidated frame!\n", aItem->Name(), f, aNewLayer);
+    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, geometry->ComputeInvalidationRegion(),
+                                           aClip, aGeometry->ComputeInvalidationRegion(),
                                            &combined);
 
     // Add in any rect that the frame specified
     combined = combined.Or(combined, invalid);
 #ifdef DEBUG_INVALIDATIONS
     if (!combined.IsEmpty()) {
-      printf("Display item type %s(%p) (in layer %p) changed geometry!\n", aItem->Name(), f, aNewLayer);
+      printf("Display item type %s(%p) (in layer %p) changed geometry!\n", aItem->Name(), aItem->GetUnderlyingFrame(), aNewLayer);
     }
 #endif
   }
   if (!combined.IsEmpty()) {
     InvalidatePostTransformRegion(newThebesLayer,
         combined.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
         GetTranslationForThebesLayer(newThebesLayer));
   }
@@ -2324,42 +2280,46 @@ FrameLayerBuilder::NeedToInvalidateFixed
   NS_ASSERTION(referenceFrame == nsLayoutUtils::GetDisplayRootFrame(referenceFrame),
                "Reference frame must be a display root for us to use the layer manager");
   nsIWidget* window = referenceFrame->GetNearestWidget();
   if (window) {
     layerManager = window->GetLayerManager();
   }
 
   if (layerManager) {
-    return !HasRetainedLayerFor(aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey(), layerManager);
+    DisplayItemData* data = GetDisplayItemDataForManager(aItem, layerManager);
+    if (data) {
+      return false;
+    }
   }
 
   return true;
 }
 
 void
 FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
                                         nsDisplayItem* aItem,
                                         const Clip& aClip,
                                         nsIFrame* aContainerLayerFrame,
                                         LayerState aLayerState,
-                                        const nsPoint& aTopLeft)
+                                        const nsPoint& aTopLeft,
+                                        nsAutoPtr<nsDisplayItemGeometry> aGeometry)
 {
   nsRefPtr<LayerManager> tempManager;
   if (aLayerState != LAYER_NONE) {
     DisplayItemData *data = GetDisplayItemDataForManager(aItem, aLayer->Manager());
     if (data) {
       tempManager = data->mInactiveManager;
     }
     if (!tempManager) {
       tempManager = new BasicLayerManager();
     }
   }
 
-  AddLayerDisplayItem(aLayer, aItem, aClip, aLayerState, aTopLeft, tempManager);
+  AddLayerDisplayItem(aLayer, aItem, aClip, aLayerState, aTopLeft, tempManager, aGeometry);
 
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
   if (entry) {
     entry->mContainerLayerFrame = aContainerLayerFrame;
     if (entry->mContainerLayerGeneration == 0) {
       entry->mContainerLayerGeneration = mContainerLayerGeneration;
     }
     NS_ASSERTION(aItem->GetUnderlyingFrame(), "Must have frame");
@@ -2380,20 +2340,27 @@ FrameLayerBuilder::AddThebesDisplayItem(
       if (!layer) {
         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.
-      nsRefPtr<DisplayItemData> data = 
-        new DisplayItemData(layer, aItem->GetPerFrameKey(), 
-                            LAYER_ACTIVE, mContainerLayerGeneration);
-      layerBuilder->StoreDataForFrame(aItem->GetUnderlyingFrame(), data);
+      if (mRetainingManager) {
+        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);
+      }
 
       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) {
@@ -2413,25 +2380,41 @@ FrameLayerBuilder::AddThebesDisplayItem(
     ClippedDisplayItem* cdi =
       entry->mItems.AppendElement(ClippedDisplayItem(aItem, aClip,
                                                      mContainerLayerGeneration));
     cdi->mInactiveLayer = tempManager;
   }
 }
 
 void
-FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame, DisplayItemData* aData)
+FrameLayerBuilder::StoreDataForFrame(nsDisplayItem* aItem, DisplayItemData* aData)
 {
-  DisplayItemDataEntry *entry = mNewDisplayItemData.GetEntry(aFrame);
+  DisplayItemKey key(aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey());
+  DisplayItemHashData *entry = mNewDisplayItemData.GetEntry(key);
   if (entry) {
     return;
   }
-  entry = mNewDisplayItemData.PutEntry(aFrame);
+  entry = mNewDisplayItemData.PutEntry(key);
   if (entry) {
-    entry->mData.AppendElement(aData);
+    entry->mData = aData;
+    entry->mContainerLayerGeneration = mContainerLayerGeneration;
+  }
+  
+  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);
+    }
   }
 }
 
 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.
@@ -2445,54 +2428,39 @@ FrameLayerBuilder::ClippedDisplayItem::~
 }
 
 void
 FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
                                        nsDisplayItem* aItem,
                                        const Clip& aClip,
                                        LayerState aLayerState,
                                        const nsPoint& aTopLeft,
-                                       LayerManager* aManager)
+                                       LayerManager* aManager,
+                                       nsAutoPtr<nsDisplayItemGeometry> aGeometry)
 {
   if (aLayer->Manager() != mRetainingManager)
     return;
-    
+
+  LayerManagerData* lmd = static_cast<LayerManagerData*>
+    (aLayer->Manager()->GetUserData(&gLayerManagerUserData));
   nsRefPtr<DisplayItemData> data = 
-    new DisplayItemData(aLayer, aItem->GetPerFrameKey(), aLayerState, mContainerLayerGeneration);
+    new DisplayItemData(lmd, aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey(), 
+                        aLayer, aLayerState, mContainerLayerGeneration);
     
   ThebesLayer *t = aLayer->AsThebesLayer();
   if (t) {
-    data->mGeometry = aItem->AllocateGeometry(mDisplayListBuilder);
+    data->mGeometry = aGeometry;
     data->mClip = aClip;
   }
   data->mInactiveManager = aManager;
 
-  DisplayItemDataEntry* entry = 
-    mNewDisplayItemData.PutEntry(aItem->GetUnderlyingFrame());
-  if (entry) {
-    entry->mContainerLayerGeneration = mContainerLayerGeneration;
-    entry->mData.AppendElement(data);
-    data->AddFrame(aItem->GetUnderlyingFrame());
-  }
-
-#if 0
-  nsAutoTArray<nsIFrame*,4> mergedFrames;
-  aItem->GetMergedFrames(&mergedFrames);
-  for (uint32_t i = 0; i < mergedFrames.Length(); ++i) {
-    entry = mNewDisplayItemData.PutEntry(mergedFrames[i]);
-    if (entry) {
-      entry->mContainerLayerGeneration = mContainerLayerGeneration;
-      entry->mData.AppendElement(data);
-      data->AddFrame(mergedFrames[i]);
-    }
-  }
-#endif
-  
+  StoreDataForFrame(aItem, data);
+
   DisplayItemData* oldData = GetDisplayItemDataForManager(aItem, mRetainingManager);
-  if (oldData && oldData->FrameListMatches(aItem)) {
+  if (oldData) {
     oldData->mUsed = true;
   }
 }
 
 nsIntPoint
 FrameLayerBuilder::GetLastPaintOffset(ThebesLayer* aLayer)
 {
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
@@ -2562,31 +2530,31 @@ ContainerState::CollectOldLayers()
 }
 
 void
 ContainerState::Finish(uint32_t* aTextContentFlags, LayerManagerData* aData)
 {
   while (!mThebesLayerDataStack.IsEmpty()) {
     PopThebesLayerData();
   }
-
+    
   uint32_t textContentFlags = 0;
 
   // Make sure that current/existing layers are added to the parent and are
   // in the correct order.
   Layer* layer = nullptr;
   for (uint32_t i = 0; i < mNewChildLayers.Length(); ++i) {
     Layer* prevChild = i == 0 ? nullptr : mNewChildLayers[i - 1].get();
     layer = mNewChildLayers[i];
-      
+  
     if (aData) {
       ProcessRemovedDisplayItemsData data(layer, mLayerBuilder);
-      aData->mFramesWithLayers.EnumerateEntries(FrameLayerBuilder::ProcessRemovedDisplayItems, &data);
-    }
-
+      aData->mDisplayItems.EnumerateEntries(FrameLayerBuilder::ProcessRemovedDisplayItems, &data);
+    } 
+      
     if (!layer->GetVisibleRegion().IsEmpty()) {
       textContentFlags |= layer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA;
     }
 
     if (!layer->GetParent()) {
       // This is not currently a child of the container, so just add it
       // now.
       mContainerLayer->InsertAfter(layer, prevChild);
@@ -2706,31 +2674,24 @@ ChooseScaleAndSetTransform(FrameLayerBui
   }
   if (isRetained && (!canDraw2D || transform2d.HasNonIntegerTranslation())) {
     result.mDisableSubpixelAntialiasingInDescendants = true;
   }
   return result;
 }
 
 /* static */ PLDHashOperator
-FrameLayerBuilder::RestoreDisplayItemData(DisplayItemDataEntry* aEntry, void* aUserArg)
+FrameLayerBuilder::RestoreDisplayItemData(DisplayItemHashData* aEntry, void* aUserArg)
 {
   uint32_t *generation = static_cast<uint32_t*>(aUserArg);
 
   if (aEntry->mContainerLayerGeneration >= *generation) {
     return PL_DHASH_REMOVE;
   }
 
-  for (uint32_t i = 0; i < aEntry->mData.Length(); i++) {
-    if (aEntry->mData[i]->mContainerLayerGeneration >= *generation) {
-      aEntry->mData.TruncateLength(i);
-      return PL_DHASH_NEXT;
-    }
-  }
-
   return PL_DHASH_NEXT;
 }
 
 /* static */ PLDHashOperator
 FrameLayerBuilder::RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry, void* aUserArg)
 {
   uint32_t *generation = static_cast<uint32_t*>(aUserArg);
 
@@ -2759,16 +2720,20 @@ 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) {
@@ -2798,22 +2763,16 @@ FrameLayerBuilder::BuildContainerLayerFo
   }
   if (!containerLayer) {
     // No suitable existing layer was found.
     containerLayer = aManager->CreateContainerLayer();
     if (!containerLayer)
       return nullptr;
   }
 
-  // This layer is owned by this frame for this building phase, don't let
-  // it be found by another frame due to its old underlying frame or merged
-  // frames. This flag will be cleared in FrameLayerBuilder::DidEndTransaction
-  containerLayer->SetUserData(&gLayerOwnerUserData,
-                              new LayerOwnerUserData(aContainerFrame));
-
   LayerState state = aContainerItem ? aContainerItem->GetLayerState(aBuilder, aManager, aParameters) : LAYER_ACTIVE;
 
   if (aContainerItem && state == LAYER_ACTIVE_EMPTY) {
     // Empty layers only have metadata and should never have display items. We
     // early exit because later, invalidation will walk up the frame tree to
     // determine which thebes layer gets invalidated. Since an empty layer
     // should never have anything to paint, it should never be invalidated.
     NS_ASSERTION(aChildren.IsEmpty(), "Should have no children");
@@ -2824,38 +2783,50 @@ FrameLayerBuilder::BuildContainerLayerFo
     ChooseScaleAndSetTransform(this, aBuilder, aContainerFrame, aTransform, aParameters,
                                containerLayer, state);
 
   uint32_t oldGeneration = mContainerLayerGeneration;
   mContainerLayerGeneration = ++mMaxContainerLayerGeneration;
 
   nsRefPtr<RefCountedRegion> thebesLayerInvalidRegion = nullptr;
   if (mRetainingManager) {
-    nsRefPtr<DisplayItemData> data =
-      new  DisplayItemData(containerLayer, containerDisplayItemKey,
-                           LAYER_ACTIVE, mContainerLayerGeneration);
-
-    DisplayItemDataEntry* entry = mNewDisplayItemData.PutEntry(aContainerFrame);
+    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.AppendElement(data);
-      data->AddFrame(aContainerFrame);
+      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);
+      }
+    }
   }
 
   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;
-  
-  LayerManagerData* data = static_cast<LayerManagerData*>
-    (aManager->GetUserData(&gLayerManagerUserData));
   while (true) {
     ContainerState state(aBuilder, aManager, aManager->GetLayerBuilder(),
                          aContainerFrame, aContainerItem,
                          containerLayer, scaleParameters);
     
     Clip clip;
     state.ProcessDisplayItems(aChildren, clip, stateFlags);
 
@@ -2935,48 +2906,50 @@ FrameLayerBuilder::InvalidateAllLayers(L
   if (data) {
     data->mInvalidateAllLayers = true;
   }
 }
 
 /* static */ void
 FrameLayerBuilder::InvalidateAllLayersForFrame(nsIFrame *aFrame)
 {
-  LayerManagerData* data = GetDefaultLayerManagerDataForFrame(aFrame);
-  if (data) {
-    data->mInvalidateAllLayers = true;
-  }
-  data = GetSecondaryLayerManagerDataForFrame(aFrame);
-  if (data) {
-    data->mInvalidateAllLayers = true;
+  nsTArray<DisplayItemData*> *array = 
+    reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(LayerManagerDataProperty()));
+  if (array) {
+    for (uint32_t i = 0; i < array->Length(); i++) {
+      array->ElementAt(i)->mParent->mInvalidateAllLayers = true;
+    }
   }
 }
 
 /* static */
 Layer*
 FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey)
 {
   //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
 
-  DisplayItemData *data = GetDisplayItemDataForManager(aFrame, aDisplayItemKey);
-  if (!data) {
-    return nullptr;
-  }
-
-  if (data->mOptLayer) {
-    return data->mOptLayer;
-  }
-
-  Layer* layer = data->mLayer;
-  if (!layer->HasUserData(&gColorLayerUserData) &&
-      !layer->HasUserData(&gImageLayerUserData) &&
-      !layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
-    return layer;
+  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;
+        }
+
+        Layer* layer = array->ElementAt(i)->mLayer;
+        if (!layer->HasUserData(&gColorLayerUserData) &&
+            !layer->HasUserData(&gImageLayerUserData) &&
+            !layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
+          return layer;
+        }
+      }
+    }
   }
   return nullptr;
 }
 
 static gfxSize
 PredictScaleForContent(nsIFrame* aFrame, nsIFrame* aAncestorWithScale,
                        const gfxSize& aScale)
 {
@@ -2992,29 +2965,28 @@ PredictScaleForContent(nsIFrame* aFrame,
 }
 
 gfxSize
 FrameLayerBuilder::GetThebesLayerScaleForFrame(nsIFrame* aFrame)
 {
   nsIFrame* last;
   for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
     last = f;
-    LayerManagerData *data = GetDefaultLayerManagerDataForFrame(f);
-    if (!data)
+  
+    nsTArray<DisplayItemData*> *array = 
+      reinterpret_cast<nsTArray<DisplayItemData*>*>(aFrame->Properties().Get(LayerManagerDataProperty()));
+    if (!array) {
       continue;
-    DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(f);
-    // Some frames with NS_FRAME_HAS_CONTAINER_LAYER may not have display items.
-    // In particular the root frame probably doesn't!
-    if (!entry)
-      continue;
-    nsTArray<nsRefPtr<DisplayItemData> >* array = &entry->mData;
-    for (uint32_t i = 0; i < array->Length(); ++i) {
+    }
+
+    for (uint32_t i = 0; i < array->Length(); i++) {
       Layer* layer = array->ElementAt(i)->mLayer;
       ContainerLayer* container = layer->AsContainerLayer();
-      if (!container) {
+      if (!container ||
+          !layer->Manager()->IsWidgetLayerManager()) {
         continue;
       }
       for (Layer* l = container->GetFirstChild(); l; l = l->GetNextSibling()) {
         ThebesDisplayItemLayerUserData* data =
             static_cast<ThebesDisplayItemLayerUserData*>
               (l->GetUserData(&gThebesDisplayItemLayerUserData));
         if (data) {
           return PredictScaleForContent(aFrame, f, gfxSize(data->mXScale, data->mYScale));
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -39,21 +39,16 @@ enum LayerState {
   // when the layer has rounded rect clips.
   LAYER_ACTIVE_FORCE,
   // Special layer that is metadata only.
   LAYER_ACTIVE_EMPTY,
   // Inactive style layer for rendering SVG effects.
   LAYER_SVG_EFFECTS
 };
 
-extern uint8_t gLayerManagerSecondary;
-
-class LayerManagerSecondary : public layers::LayerUserData {
-};
-
 class RefCountedRegion : public RefCounted<RefCountedRegion> {
 public:
   RefCountedRegion() : mIsInfinite(false) {}
   nsRegion mRegion;
   bool mIsInfinite;
 };
 
 /**
@@ -269,90 +264,50 @@ public:
    * then this is the temporary layer manager to draw with.
    */
   struct Clip;
   void AddLayerDisplayItem(Layer* aLayer,
                            nsDisplayItem* aItem,
                            const Clip& aClip,
                            LayerState aLayerState,
                            const nsPoint& aTopLeft,
-                           LayerManager* aManager = nullptr);
+                           LayerManager* aManager,
+                           nsAutoPtr<nsDisplayItemGeometry> aGeometry);
 
   /**
    * Record aItem as a display item that is rendered by the ThebesLayer
    * aLayer, with aClipRect, where aContainerLayerFrame is the frame
    * for the container layer this ThebesItem belongs to.
    * aItem must have an underlying frame.
    * @param aTopLeft offset from active scrolled root to reference frame
    */
   void AddThebesDisplayItem(ThebesLayer* aLayer,
                             nsDisplayItem* aItem,
                             const Clip& aClip,
                             nsIFrame* aContainerLayerFrame,
                             LayerState aLayerState,
-                            const nsPoint& aTopLeft);
-
-  /**
-   * Set the current top-level LayerManager for the widget being
-   * painted.
-   */
-  static void SetWidgetLayerManager(LayerManager* aManager)
-  {
-    LayerManagerSecondary* secondary = 
-      static_cast<LayerManagerSecondary*>(aManager->GetUserData(&gLayerManagerSecondary));
-    sWidgetManagerSecondary = !!secondary;
-  }
+                            const nsPoint& aTopLeft,
+                            nsAutoPtr<nsDisplayItemGeometry> aGeometry);
 
   /**
    * Gets the frame property descriptor for the given manager, or for the current
    * widget layer manager if nullptr is passed.
    */
   static const FramePropertyDescriptor* GetDescriptorForManager(LayerManager* aManager);
 
   /**
-   * Get the LayerManagerData for a given frame and layer manager. If no layer manager
-   * is passed, then the current widget layer manager is used.
-   */
-  static LayerManagerData* GetManagerData(nsIFrame* aFrame, LayerManager* aManager = nullptr);
-
-  /**
-   * Set the LayerManagerData for a given frame and current widget layer manager.
-   * This replaces any existing data for the same frame/layer manager pair.
-   */
-  static void SetManagerData(nsIFrame* aFrame, LayerManagerData* aData);
-
-  /**
-   * Clears the current LayerManagerData for the given frame and current widget
-   * layer manager.
-   */
-  static void ClearManagerData(nsIFrame* aFrame);
-
-  /**
-   * Clears any references to the given LayerManagerData for the given frame
-   * and belonging to any layer manager.
-   */
-  static void ClearManagerData(nsIFrame* aFrame, LayerManagerData* aData);
-
-  /**
    * Calls GetOldLayerForFrame on the underlying frame of the display item,
    * and each subsequent merged frame if no layer is found for the underlying
    * frame.
    */
   Layer* GetOldLayerFor(nsDisplayItem* aItem, nsDisplayItemGeometry** aOldGeometry = nullptr, Clip** aOldClip = nullptr);
 
   static Layer* GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey);
 
   /**
-   * If the display item was previously drawn as an inactive layer,
-   * then return the layer manager used for the inactive transaction.
-   * Returns nullptr if no manager could be found.
-   */
-  LayerManager* GetInactiveLayerManagerFor(nsDisplayItem* aItem);
-
-  /**
    * Try to determine whether the ThebesLayer aLayer paints an opaque
    * single color everywhere it's visible in aRect.
    * If successful, return that color, otherwise return NS_RGBA(0,0,0,0).
    */
   nscolor FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder,
                                   ThebesLayer* aLayer, const nsRect& aRect);
 
   /**
@@ -369,27 +324,16 @@ public:
    * document.
    * Returns false if it doesn't need to be repainted because the layer system
    * is ensuring its fixed-ness for us.
    */
   static bool NeedToInvalidateFixedDisplayItem(nsDisplayListBuilder* aBuilder,
                                                  nsDisplayItem* aItem);
 
   /**
-   * Returns true if the given display item was rendered directly
-   * into a retained layer.
-   * Returns false if it was rendered into a temporary layer manager and then
-   * into a retained layer.
-   *
-   * Since display items can belong to multiple retained LayerManagers, we need to
-   * specify which LayerManager to check.
-   */
-  static bool HasRetainedLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey, LayerManager* aManager);
-
-  /**
    * Returns true if the given display item was rendered during the previous
    * paint. Returns false otherwise.
    */
   static bool HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey);
 
   /**
    * Save transform that was in aLayer when we last painted, and the position
    * of the active scrolled root frame. It must be an integer
@@ -511,124 +455,178 @@ public:
     bool operator!=(const Clip& aOther) const {
       return !(*this == aOther);
     }
   };
   
   NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty,
                                                RemoveFrameFromLayerManager)
 
-  NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerSecondaryDataProperty,
-                                               RemoveFrameFromLayerManager)
-
 protected:
   /**
-   * We store an array of these for each frame that is associated with
-   * one or more retained layers. Each DisplayItemData records the layer
-   * used to render one of the frame's display items.
+   * 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.
+   *
+   * 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.
+   */
+  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(Layer* aLayer, uint32_t aKey, LayerState aLayerState, uint32_t aGeneration);
-    DisplayItemData()
-      : mUsed(false)
-    {}
+
+    DisplayItemData(LayerManagerData* aParent, nsIFrame* aFrame, uint32_t aKey, Layer* aLayer, LayerState aLayerState, uint32_t aGeneration);
     DisplayItemData(DisplayItemData &toCopy);
     ~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
+     */
+    void RemoveFrameData(nsIFrame* aSkip = nullptr);
+
     bool FrameListMatches(nsDisplayItem* aOther);
+    bool FrameListMatches(DisplayItemData* aOther);
 
+    /**
+     * Copies the contents of this item into aDest and
+     * leaves this item invalid.
+     */
+    void CopyInto(DisplayItemData* aDest);
+
+    LayerManagerData* mParent;
     nsRefPtr<Layer> mLayer;
     nsRefPtr<Layer> mOptLayer;
     nsRefPtr<LayerManager> mInactiveManager;
-    nsAutoTArray<nsIFrame*, 2> mFrameList;
+    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.
      */
     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
    * display item for the frame, find the layer that was last used to
    * render that display item. Returns null if there is no such layer.
    * This could be a dedicated layer for the display item, or a ThebesLayer
    * that renders many display items.
    */
   DisplayItemData* GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey);
 
   /**
-   * We accumulate DisplayItemData elements in a hashtable during
-   * the paint process, one per visible display item.
-   * There is one hashtable per layer manager, and one entry
-   * per frame. This is the hashentry for that hashtable.
-   */
-  class DisplayItemDataEntry : public nsPtrHashKey<nsIFrame> {
-  public:
-    DisplayItemDataEntry(const nsIFrame *key)
-      : nsPtrHashKey<nsIFrame>(key)
-    { 
-      MOZ_COUNT_CTOR(DisplayItemDataEntry); 
-    }
-    DisplayItemDataEntry(DisplayItemDataEntry &toCopy)
-      : nsPtrHashKey<nsIFrame>(toCopy.mKey)
-    {
-      MOZ_COUNT_CTOR(DisplayItemDataEntry);
-      // This isn't actually a copy-constructor; notice that it steals toCopy's
-      // array and invalid region.  Be careful.
-      mData.SwapElements(toCopy.mData);
-      mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
-    }
-    ~DisplayItemDataEntry() { MOZ_COUNT_DTOR(DisplayItemDataEntry); }
-
-    bool HasNonEmptyContainerLayer();
-
-    nsAutoTArray<nsRefPtr<DisplayItemData>, 1> mData;
-    uint32_t mContainerLayerGeneration;
-
-    enum { ALLOW_MEMMOVE = false };
-  };
-
-  // LayerManagerData needs to see DisplayItemDataEntry.
-  friend class LayerManagerData;
-
-  /**
    * Stores DisplayItemData associated with aFrame, stores the data in
    * mNewDisplayItemData.
    */
-  void StoreDataForFrame(nsIFrame* aFrame, DisplayItemData* data);
+  void StoreDataForFrame(nsDisplayItem* aItem, DisplayItemData* data);
 
   // 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.
    *
    * Note that the pointer returned here is only valid so long as you don't
    * poke the LayerManagerData's mFramesWithLayers hashtable.
    */
-  nsTArray<nsRefPtr<DisplayItemData> >* GetDisplayItemDataArrayForFrame(nsIFrame *aFrame);
+  DisplayItemData* GetDisplayItemData(nsIFrame *aFrame, uint32_t aKey);
 
   /*
    * Get the DisplayItemData associated with this frame / display item pair,
    * using the LayerManager instead of FrameLayerBuilder.
    */
   static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, 
                                                        uint32_t aDisplayItemKey, 
                                                        LayerManager* aManager);
@@ -639,19 +637,21 @@ protected:
                                                        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(DisplayItemDataEntry* aEntry,
+  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
    * DrawThebesLayer callback can figure out which items to draw for the
    * ThebesLayer.
@@ -715,29 +715,28 @@ public:
    * Get the ThebesLayerItemsEntry object associated with aLayer in this
    * FrameLayerBuilder
    */
   ThebesLayerItemsEntry* GetThebesLayerItemsEntry(ThebesLayer* aLayer)
   {
     return mThebesLayerItems.GetEntry(aLayer);
   }
 
-  static PLDHashOperator ProcessRemovedDisplayItems(DisplayItemDataEntry* aEntry,
+  static PLDHashOperator ProcessRemovedDisplayItems(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                                     void* aUserArg);
 protected:
   void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer,
                                                     bool aRemoveThebesItems,
                                                     bool aRemoveOwnerData);
 
-  static void SetAndClearInvalidRegion(DisplayItemDataEntry* aEntry);
-  static PLDHashOperator UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
+  static PLDHashOperator UpdateDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry,
                                                        void* aUserArg);
-  static PLDHashOperator StoreNewDisplayItemData(DisplayItemDataEntry* aEntry,
+  static PLDHashOperator StoreNewDisplayItemData(DisplayItemHashData* aEntry,
                                                  void* aUserArg);
-  static PLDHashOperator RestoreDisplayItemData(DisplayItemDataEntry* aEntry,
+  static PLDHashOperator RestoreDisplayItemData(DisplayItemHashData* 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
@@ -758,17 +757,17 @@ protected:
   /**
    * 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<DisplayItemDataEntry>  mNewDisplayItemData;
+  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.
    */
@@ -781,19 +780,13 @@ protected:
   /**
    * Indicates that the entire layer tree should be rerendered
    * during this paint.
    */
   bool                                mInvalidateAllLayers;
 
   uint32_t                            mContainerLayerGeneration;
   uint32_t                            mMaxContainerLayerGeneration;
-
-  /**
-   * True if the current top-level LayerManager for the widget being
-   * painted is marked as being a 'secondary' LayerManager.
-   */
-  static bool                         sWidgetManagerSecondary;
 };
 
 }
 
 #endif /* FRAMELAYERBUILDER_H_ */
--- a/layout/base/Makefile.in
+++ b/layout/base/Makefile.in
@@ -32,16 +32,17 @@ EXPORTS		= \
 		nsArenaMemoryStats.h \
 		nsBidi.h \
 		nsBidiPresUtils.h \
 		nsCaret.h \
 		nsCSSFrameConstructor.h \
 		nsChangeHint.h \
 		nsCompatibility.h \
 		nsDisplayItemTypes.h \
+		nsDisplayItemTypesList.h \
 		nsDisplayList.h \
 		nsDisplayListInvalidation.h \
 		nsFrameManager.h \
 		nsFrameManagerBase.h \
 		nsFrameIterator.h \
 		nsILayoutDebugger.h \
 		nsILayoutHistoryState.h \
 		nsIPercentHeightObserver.h  \
--- a/layout/base/nsDisplayItemTypes.h
+++ b/layout/base/nsDisplayItemTypes.h
@@ -7,114 +7,35 @@
 
 /**
  * It's useful to be able to dynamically check the type of certain items.
  * Every subclass of nsDisplayItem must have a new type added here for the purposes
  * of easy comparison and matching of items in different display lists.
  * 
  * This is #included inside nsDisplayItem.
  */
+
+
 enum Type {
-  TYPE_ALT_FEEDBACK = 1,
-  TYPE_BACKGROUND,
-  TYPE_BORDER,
-  TYPE_BOX_SHADOW_OUTER,
-  TYPE_BOX_SHADOW_INNER,
-  TYPE_BULLET,
-  TYPE_BUTTON_BORDER_BACKGROUND,
-  TYPE_BUTTON_BOX_SHADOW_OUTER,
-  TYPE_BUTTON_FOREGROUND,
-  TYPE_CANVAS,
-  TYPE_CANVAS_BACKGROUND,
-  TYPE_CANVAS_FOCUS,
-  TYPE_CARET,
-  TYPE_CHECKED_CHECKBOX,
-  TYPE_CHECKED_RADIOBUTTON,
-  TYPE_CLIP,
-  TYPE_CLIP_ROUNDED_RECT,
-  TYPE_COLUMN_RULE,
-  TYPE_COMBOBOX_FOCUS,
-  TYPE_EVENT_RECEIVER,
-  TYPE_FIELDSET_BORDER_BACKGROUND,
-  TYPE_FIXED_POSITION,
-  TYPE_FORCEPAINTONSCROLL,
-  TYPE_FRAMESET_BORDER,
-  TYPE_FRAMESET_BLANK,
-  TYPE_HEADER_FOOTER,
-  TYPE_IMAGE,
-  TYPE_LIST_FOCUS,
-  TYPE_OPACITY,
-  TYPE_OPTION_EVENT_GRABBER,
-  TYPE_OUTLINE,
-  TYPE_OWN_LAYER,
-  TYPE_PAGE_CONTENT,
-  TYPE_PAGE_SEQUENCE,
-  TYPE_PLUGIN,
-  TYPE_PLUGIN_READBACK,
-  TYPE_PLUGIN_VIDEO,
-  TYPE_PRINT_PLUGIN,
-  TYPE_REMOTE,
-  TYPE_REMOTE_SHADOW,
-  TYPE_SCROLL_LAYER,
-  TYPE_SCROLL_INFO_LAYER,
-  TYPE_SELECTION_OVERLAY,
-  TYPE_SOLID_COLOR,
-  TYPE_SVG_EFFECTS,
-  TYPE_SVG_GLYPHS,
-  TYPE_SVG_OUTER_SVG,
-  TYPE_SVG_PATH_GEOMETRY,
-  TYPE_TABLE_CELL_BACKGROUND,
-  TYPE_TABLE_CELL_SELECTION,
-  TYPE_TABLE_ROW_BACKGROUND,
-  TYPE_TABLE_ROW_GROUP_BACKGROUND,
-  TYPE_TABLE_BORDER_BACKGROUND,
-  TYPE_TEXT,
-  TYPE_TEXT_DECORATION,
-  TYPE_TEXT_OVERFLOW,
-  TYPE_TEXT_SHADOW,
-  TYPE_TRANSFORM,
-  TYPE_VIDEO,
-  TYPE_WRAP_LIST,
-  TYPE_ZOOM,
-  TYPE_EXCLUDE_GLASS_FRAME,
+  TYPE_ZERO = 0, /** Spacer so that the first item starts at 1 */
 
-#if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
-  TYPE_REFLOW_COUNT,
-#endif
-
-#ifdef MOZ_XUL
-  TYPE_XUL_EVENT_REDIRECTOR,
-  TYPE_XUL_GROUP_BACKGROUND,
-  TYPE_XUL_IMAGE,
-  TYPE_XUL_TEXT_BOX,
-  TYPE_XUL_TREE_BODY,
-  TYPE_XUL_TREE_COL_SPLITTER_TARGET,
-#ifdef DEBUG_LAYOUT
-  TYPE_XUL_DEBUG,
-#endif
-#endif
-
-  TYPE_MATHML_BAR,
-  TYPE_MATHML_CHAR_BACKGROUND,
-  TYPE_MATHML_CHAR_FOREGROUND,
-  TYPE_MATHML_ERROR,
-  TYPE_MATHML_MENCLOSE_NOTATION,
-  TYPE_MATHML_SELECTION_RECT,
-  TYPE_MATHML_SLASH,
-#ifdef DEBUG
-  TYPE_MATHML_BOUNDING_METRICS,
-  TYPE_MATHML_CHAR_DEBUG,
-#endif
-
-#ifdef DEBUG
-  TYPE_DEBUG_BORDER,
-  TYPE_DEBUG_IMAGE_MAP,
-  TYPE_DEBUG_PLACEHOLDER,
-  TYPE_EVENT_TARGET_BORDER,
-#endif
+#define DECLARE_DISPLAY_ITEM_TYPE(name) TYPE_##name,
+#include "nsDisplayItemTypesList.h"
+#undef DECLARE_DISPLAY_ITEM_TYPE
 
   TYPE_MAX
 };
 
 enum {
   // Number of bits needed to represent all types
   TYPE_BITS = 8
 };
+
+static const char* DisplayItemTypeName(Type aType)
+{
+  switch (aType) {
+#define DECLARE_DISPLAY_ITEM_TYPE(name) case TYPE_##name: return #name;
+#include "nsDisplayItemTypesList.h"
+#undef DECLARE_DISPLAY_ITEM_TYPE
+
+    default: return "TYPE_UNKNOWN";
+  }
+}
new file mode 100644
--- /dev/null
+++ b/layout/base/nsDisplayItemTypesList.h
@@ -0,0 +1,95 @@
+DECLARE_DISPLAY_ITEM_TYPE(ALT_FEEDBACK)
+DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(BORDER)
+DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_OUTER)
+DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_INNER)
+DECLARE_DISPLAY_ITEM_TYPE(BULLET)
+DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BORDER_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BOX_SHADOW_OUTER)
+DECLARE_DISPLAY_ITEM_TYPE(BUTTON_FOREGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(CANVAS)
+DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(CANVAS_FOCUS)
+DECLARE_DISPLAY_ITEM_TYPE(CARET)
+DECLARE_DISPLAY_ITEM_TYPE(CHECKED_CHECKBOX)
+DECLARE_DISPLAY_ITEM_TYPE(CHECKED_RADIOBUTTON)
+DECLARE_DISPLAY_ITEM_TYPE(CLIP)
+DECLARE_DISPLAY_ITEM_TYPE(CLIP_ROUNDED_RECT)
+DECLARE_DISPLAY_ITEM_TYPE(COLUMN_RULE)
+DECLARE_DISPLAY_ITEM_TYPE(COMBOBOX_FOCUS)
+DECLARE_DISPLAY_ITEM_TYPE(EVENT_RECEIVER)
+DECLARE_DISPLAY_ITEM_TYPE(FIELDSET_BORDER_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(FIXED_POSITION)
+DECLARE_DISPLAY_ITEM_TYPE(FORCEPAINTONSCROLL)
+DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BORDER)
+DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BLANK)
+DECLARE_DISPLAY_ITEM_TYPE(HEADER_FOOTER)
+DECLARE_DISPLAY_ITEM_TYPE(IMAGE)
+DECLARE_DISPLAY_ITEM_TYPE(LIST_FOCUS)
+DECLARE_DISPLAY_ITEM_TYPE(OPACITY)
+DECLARE_DISPLAY_ITEM_TYPE(OPTION_EVENT_GRABBER)
+DECLARE_DISPLAY_ITEM_TYPE(OUTLINE)
+DECLARE_DISPLAY_ITEM_TYPE(OWN_LAYER)
+DECLARE_DISPLAY_ITEM_TYPE(PAGE_CONTENT)
+DECLARE_DISPLAY_ITEM_TYPE(PAGE_SEQUENCE)
+DECLARE_DISPLAY_ITEM_TYPE(PLUGIN)
+DECLARE_DISPLAY_ITEM_TYPE(PLUGIN_READBACK)
+DECLARE_DISPLAY_ITEM_TYPE(PLUGIN_VIDEO)
+DECLARE_DISPLAY_ITEM_TYPE(PRINT_PLUGIN)
+DECLARE_DISPLAY_ITEM_TYPE(REMOTE)
+DECLARE_DISPLAY_ITEM_TYPE(REMOTE_SHADOW)
+DECLARE_DISPLAY_ITEM_TYPE(SCROLL_LAYER)
+DECLARE_DISPLAY_ITEM_TYPE(SCROLL_INFO_LAYER)
+DECLARE_DISPLAY_ITEM_TYPE(SELECTION_OVERLAY)
+DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR)
+DECLARE_DISPLAY_ITEM_TYPE(SVG_EFFECTS)
+DECLARE_DISPLAY_ITEM_TYPE(SVG_GLYPHS)
+DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG)
+DECLARE_DISPLAY_ITEM_TYPE(SVG_PATH_GEOMETRY)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_GROUP_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(TEXT)
+DECLARE_DISPLAY_ITEM_TYPE(TEXT_DECORATION)
+DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW)
+DECLARE_DISPLAY_ITEM_TYPE(TEXT_SHADOW)
+DECLARE_DISPLAY_ITEM_TYPE(TRANSFORM)
+DECLARE_DISPLAY_ITEM_TYPE(VIDEO)
+DECLARE_DISPLAY_ITEM_TYPE(WRAP_LIST)
+DECLARE_DISPLAY_ITEM_TYPE(ZOOM)
+DECLARE_DISPLAY_ITEM_TYPE(EXCLUDE_GLASS_FRAME)
+
+#if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
+DECLARE_DISPLAY_ITEM_TYPE(REFLOW_COUNT)
+#endif
+
+#ifdef MOZ_XUL
+DECLARE_DISPLAY_ITEM_TYPE(XUL_EVENT_REDIRECTOR)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_GROUP_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_IMAGE)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_TEXT_BOX)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_TREE_BODY)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_TREE_COL_SPLITTER_TARGET)
+#ifdef DEBUG_LAYOUT
+DECLARE_DISPLAY_ITEM_TYPE(XUL_DEBUG)
+#endif
+#endif
+
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_BAR)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_CHAR_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_CHAR_FOREGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_ERROR)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_MENCLOSE_NOTATION)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_SELECTION_RECT)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_SLASH)
+#ifdef DEBUG
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_BOUNDING_METRICS)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_CHAR_DEBUG)
+
+DECLARE_DISPLAY_ITEM_TYPE(DEBUG_BORDER)
+DECLARE_DISPLAY_ITEM_TYPE(DEBUG_IMAGE_MAP)
+DECLARE_DISPLAY_ITEM_TYPE(DEBUG_PLACEHOLDER)
+DECLARE_DISPLAY_ITEM_TYPE(EVENT_TARGET_BORDER)
+#endif
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -992,17 +992,16 @@ void nsDisplayList::PaintForFrame(nsDisp
     view = rootReferenceFrame->GetView();
     NS_ASSERTION(rootReferenceFrame == nsLayoutUtils::GetDisplayRootFrame(rootReferenceFrame),
                  "Reference frame must be a display root for us to use the layer manager");
     nsIWidget* window = rootReferenceFrame->GetNearestWidget();
     if (window) {
       layerManager = window->GetLayerManager(&allowRetaining);
       if (layerManager) {
         doBeginTransaction = !(aFlags & PAINT_EXISTING_TRANSACTION);
-        FrameLayerBuilder::SetWidgetLayerManager(layerManager);
         widgetTransaction = true;
       }
     }
   }
   if (!layerManager) {
     if (!aCtx) {
       NS_WARNING("Nowhere to paint into");
       return;
@@ -1019,17 +1018,17 @@ void nsDisplayList::PaintForFrame(nsDisp
 
   if (doBeginTransaction) {
     if (aCtx) {
       layerManager->BeginTransactionWithTarget(aCtx->ThebesContext());
     } else {
       layerManager->BeginTransaction();
     }
   }
-  if (allowRetaining) {
+  if (widgetTransaction) {
     layerBuilder->DidBeginRetainedLayerTransaction(layerManager);
   }
 
   nsPresContext* presContext = aForFrame->PresContext();
   nsIPresShell* presShell = presContext->GetPresShell();
 
   NotifySubDocInvalidationFunc computeInvalidFunc =
     presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -658,17 +658,17 @@ public:
   nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
     : mFrame(aFrame)
 #ifdef MOZ_DUMP_PAINTING
     , mPainted(false)
 #endif
   {
     if (aFrame) {
       mReferenceFrame = aBuilder->FindReferenceFrameFor(aFrame);
-      mToReferenceFrame = aFrame->GetOffsetToCrossDoc(mReferenceFrame);
+      mToReferenceFrame = aBuilder->ToReferenceFrame(aFrame);
     }
   }
   nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                 const nsIFrame* aReferenceFrame,
                 const nsPoint& aToReferenceFrame)
     : mFrame(aFrame)
     , mReferenceFrame(aReferenceFrame)
     , mToReferenceFrame(aToReferenceFrame)
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -37,17 +37,16 @@
 #include "nsAnimationManager.h"
 #include "nsINameSpaceManager.h"  // for Pref-related rule management (bugs 22963,20760,31816)
 #include "nsIServiceManager.h"
 #include "nsFrame.h"
 #include "nsViewManager.h"
 #include "nsView.h"
 #include "nsCRTGlue.h"
 #include "prlog.h"
-#include "prmem.h"
 #include "prprf.h"
 #include "prinrval.h"
 #include "nsTArray.h"
 #include "nsCOMArray.h"
 #include "nsHashtable.h"
 #include "nsContainerFrame.h"
 #include "nsDOMEvent.h"
 #include "nsHTMLParts.h"
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -693,17 +693,18 @@ FlexItem::FlexItem(nsIFrame* aChildFrame
                    "Someone else tried to resolve our auto margin");
       }
     }
   }
 #endif // DEBUG
 
   // Resolve "align-self: auto" to parent's "align-items" value.
   if (mAlignSelf == NS_STYLE_ALIGN_SELF_AUTO) {
-    mAlignSelf = mFrame->GetParent()->GetStylePosition()->mAlignItems;
+    mAlignSelf =
+      mFrame->GetStyleContext()->GetParent()->GetStylePosition()->mAlignItems;
   }
 
   // If the flex item's inline axis is the same as the cross axis, then
   // 'align-self:baseline' is identical to 'flex-start'. If that's the case, we
   // just directly convert our align-self value here, so that we don't have to
   // handle this with special cases elsewhere.
   // Moreover: for the time being (until we support writing-modes),
   // all inline axes are horizontal -- so we can just check if the cross axis
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -15,17 +15,16 @@
 #include "nsWidgetsCID.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMDragEvent.h"
 #include "nsPluginHost.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
-#include "prmem.h"
 #include "nsGkAtoms.h"
 #include "nsIAppShell.h"
 #include "nsIDocument.h"
 #include "nsINodeInfo.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsIPluginInstanceOwner.h"
 #include "nsNPAPIPluginInstance.h"
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -656,17 +656,17 @@ nsSimplePageSequenceFrame::PrePrintNextP
 
         // Start the rendering process.
         nsWeakFrame weakFrame = this;
         canvas->DispatchPrintCallback(aCallback);
         NS_ENSURE_STATE(weakFrame.IsAlive());
       }
     }
   }
-  int32_t doneCounter = 0;
+  uint32_t doneCounter = 0;
   for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0 ; i--) {
     nsHTMLCanvasElement* canvas = mCurrentCanvasList[i];
 
     if (canvas->IsPrintCallbackDone()) {
       doneCounter++;
     }
   }
   // If all canvas have finished rendering, return true, otherwise false.
--- a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1-ref.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1-ref.xhtml
@@ -38,30 +38,26 @@
         font-size: 12px;
       }
 
       .lime   { background: lime;   }
       .yellow { background: yellow; }
       .orange { background: orange; }
       .pink   { background: pink;   }
       .aqua   { background: aqua;   }
-      .violet { background: violet; }
       .tan    { background: tan;    }
    </style>
   </head>
   <body>
     <div class="flexbox">
       <div class="lime">blk_1line</div
       ><table cellspacing="0" cellpadding="0"
               class="yellow">blk<br/>2lines</table
       ><div class="orange"><span class="super">super</span></div
       ><div class="pink"><span class="sub">sub</span></div
       ><table cellspacing="0" cellpadding="0"
               class="aqua big">big<br/>text<br/>3lines</table
-      ><table class="violet" border="1">
-        <tr><td>tr1</td></tr>
-        <tr><td>tr2</td></tr></table
       ><table class="tan" cellspacing="0" cellpadding="0">
         <i>ital<br/>ic</i>
       </table>
     </div>
   </body>
 </html>
--- a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1.xhtml
@@ -38,26 +38,22 @@
         font-size: 12px;
       }
 
       .lime   { background: lime;   }
       .yellow { background: yellow; }
       .orange { background: orange; }
       .pink   { background: pink;   }
       .aqua   { background: aqua;   }
-      .violet { background: violet; }
       .tan    { background: tan;    }
    </style>
   </head>
   <body>
     <div class="flexbox">
       <div class="lime">blk_1line</div>
       <div class="yellow">blk<br/>2lines</div>
       <div class="orange"><span class="super">super</span></div>
       <div class="pink"><span class="sub">sub</span></div>
       <div class="aqua big">big<br/>text<br/>3lines</div>
-      <table class="violet" border="1">
-        <tr><td>tr1</td></tr>
-        <tr><td>tr2</td></tr></table>
       <i class="tan">ital<br/>ic</i>
     </div>
   </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-4-ref.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!-- Reference case for behavior of the 'baseline' value for align-items and
+     align-self.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <style>
+      div.flexbox {
+        display: block;
+        border: 1px dashed blue;
+        font: 14px sans-serif;
+      }
+
+      div   { display: inline-block; }
+      table {
+        display: inline-table;
+        margin: 1px; /* to fix fuzziness from text overlapping table border */
+      }
+
+      .lime { background: lime; }
+      .pink { background: pink; }
+      .aqua { background: aqua; }
+   </style>
+  </head>
+  <body>
+    <div class="flexbox">
+      <div class="lime">text</div
+      ><table class="pink" border="1">
+        <tr><td>tr1</td></tr>
+        <tr><td>tr2</td></tr>
+      </table>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-4.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!-- Testcase for behavior of the 'baseline' value for align-items (and
+     align-self, implicitly). This test baseline-aligns a <table>.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <style>
+      div.flexbox {
+        display: -moz-flex;
+        -moz-align-items: baseline;
+        border: 1px dashed blue;
+        font: 14px sans-serif;
+      }
+
+      table {
+        margin: 1px; /* to fix fuzziness from text overlapping table border */
+      }
+
+      .lime { background: lime; }
+      .pink { background: pink; }
+      .aqua { background: aqua; }
+   </style>
+  </head>
+  <body>
+    <div class="flexbox">
+      <div class="lime">text</div>
+      <table class="pink" border="1">
+        <tr><td>tr1</td></tr>
+        <tr><td>tr2</td></tr>
+      </table>
+    </div>
+  </body>
+</html>
rename from layout/reftests/flexbox/flexbox-align-self-horiz-1.xhtml
rename to layout/reftests/flexbox/flexbox-align-self-horiz-1-block.xhtml
copy from layout/reftests/flexbox/flexbox-align-self-horiz-1.xhtml
copy to layout/reftests/flexbox/flexbox-align-self-horiz-1-table.xhtml
--- a/layout/reftests/flexbox/flexbox-align-self-horiz-1.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-horiz-1-table.xhtml
@@ -20,17 +20,18 @@
            -moz-initial) will end up taking this value from us: */
         -moz-align-items: center;
 
         /* Any children whose align-self is 'inherit' will end up
            inheriting this value from us: */
         -moz-align-self: flex-end;
       }
 
-      .flexbox > div {
+      .flexbox > * {
+        display: table;
         width: 40px;
       }
 
       .big {
         height: 100px;
         font-size: 20px;
         line-height: 20px;
       }
@@ -50,16 +51,17 @@
       }
       .baseline {
         background: teal;
         -moz-align-self: baseline;
       }
       .stretch {
         background: pink;
         -moz-align-self: stretch;
+        display: block; /* XXXdholbert Hackaround for bug 799725 */
       }
       .auto {
         background: yellow;
         -moz-align-self: auto;
       }
       .unspecified {
         background: lightgreen;
       }
--- a/layout/reftests/flexbox/reftest.list
+++ b/layout/reftests/flexbox/reftest.list
@@ -5,17 +5,26 @@ test-pref(layout.css.flexbox.enabled,fal
 test-pref(layout.css.flexbox.enabled,true) == flexbox-pref-1.xhtml flexbox-pref-1-enabled-ref.xhtml
 
 # Tests for cross-axis alignment (align-self / align-items properties)
 test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-baseline-horiz-1.xhtml  flexbox-align-self-baseline-horiz-1-ref.xhtml
 fails test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-baseline-horiz-2.xhtml  flexbox-align-self-baseline-horiz-2-ref.xhtml # bug 793456, and possibly others
 # This one fails on windows R (but not Ru, strangely). On Windows R, the
 # single-line <label> flex item has a different background size in test vs. ref
 random-if(winWidget) test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-baseline-horiz-3.xhtml  flexbox-align-self-baseline-horiz-3-ref.xhtml # XXXdholbert investigate
-test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-horiz-1.xhtml  flexbox-align-self-horiz-1-ref.xhtml
+# XXXdholbert This test needs the flexbox pref to be enabled _at startup time_
+# (when we parse ua.css) in order to pass -- so it'll fail until we enable the
+# flexbox pref by default (bug 783409):
+fails == flexbox-align-self-baseline-horiz-4.xhtml flexbox-align-self-baseline-horiz-4-ref.xhtml
+
+test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-horiz-1-block.xhtml  flexbox-align-self-horiz-1-ref.xhtml
+# XXXdholbert This test needs the flexbox pref to be enabled _at startup time_
+# (when we parse ua.css) in order to pass -- so it'll fail until we enable the
+# flexbox pref by default (bug 783409):
+fails == flexbox-align-self-horiz-1-table.xhtml  flexbox-align-self-horiz-1-ref.xhtml
 test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-horiz-2.xhtml  flexbox-align-self-horiz-2-ref.xhtml
 test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-horiz-3.xhtml  flexbox-align-self-horiz-3-ref.xhtml
 test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-horiz-4.xhtml  flexbox-align-self-horiz-4-ref.xhtml
 pref(layout.css.flexbox.enabled,true) == flexbox-align-self-horiz-5.xhtml  flexbox-align-self-horiz-5-ref.xhtml
 test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-vert-1.xhtml  flexbox-align-self-vert-1-ref.xhtml
 test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-vert-2.xhtml  flexbox-align-self-vert-2-ref.xhtml
 test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-vert-3.xhtml  flexbox-align-self-vert-3-ref.xhtml
 test-pref(layout.css.flexbox.enabled,true) == flexbox-align-self-vert-4.xhtml  flexbox-align-self-vert-4-ref.xhtml
--- a/layout/style/test/Makefile.in
+++ b/layout/style/test/Makefile.in
@@ -196,16 +196,20 @@ MOCHITEST_FILES +=	\
 		test_flexbox_align_self_auto.html \
 		file_flexbox_flex_grow_and_shrink.html \
 		test_flexbox_flex_grow_and_shrink.html \
 		file_flexbox_flex_shorthand.html \
 		test_flexbox_flex_shorthand.html \
 		file_flexbox_layout.html \
 		test_flexbox_layout.html \
 		flexbox_layout_testcases.js \
+		file_flexbox_order.html \
+		test_flexbox_order.html \
+		file_flexbox_order_table.html \
+		test_flexbox_order_table.html \
 		$(NULL)
 endif
 
 _VISITED_REFTEST_FILES = \
 		$(shell find $(topsrcdir)/layout/reftests/css-visited/ -name '*.html' -o -name '*.xhtml') \
 		$(topsrcdir)/layout/reftests/svg/pseudo-classes-02.svg \
 		$(topsrcdir)/layout/reftests/svg/pseudo-classes-02-ref.svg \
 		$(topsrcdir)/layout/reftests/svg/as-image/lime100x100.svg \
new file mode 100644
--- /dev/null
+++ b/layout/style/test/file_flexbox_order.html
@@ -0,0 +1,189 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+  <style type="text/css">
+
+    div.ref {
+      display: none;
+      height: 30px;
+    }
+
+    refA, refB, refC {
+      display: block;
+      float: left;
+    }
+
+    div#a, refA {
+      background: lightgreen;
+      width: 20px;
+      height: 30px;
+    }
+    div#b, refB {
+      background: orange;
+      width: 30px;
+      height: 30px;
+    }
+    div#c, refC {
+      background: blue;
+      width: 50px;
+      height: 30px;
+    }
+    div#flexContainer {
+      display: -moz-flex;
+      width: 100px;
+      height: 30px;
+    }
+    div#flexContainerParent {
+      display: none;
+    }
+  </style>
+</head>
+<body>
+<div id="display">
+
+  <!-- Reference cases (display:none; only shown during initRefSnapshots) -->
+  <div id="references">
+    <div class="ref" id="abc"><refA></refA><refB></refB><refC></refC></div>
+    <div class="ref" id="acb"><refA></refA><refC></refC><refB></refB></div>
+    <div class="ref" id="bac"><refB></refB><refA></refA><refC></refC></div>
+    <div class="ref" id="bca"><refB></refB><refC></refC><refA></refA></div>
+    <div class="ref" id="cab"><refC></refC><refA></refA><refB></refB></div>
+    <div class="ref" id="cba"><refC></refC><refB></refB><refA></refA></div>
+  </div>
+
+  <div id="flexContainerParent">
+    <!-- The flex container that we'll be testing
+         (its  parent is display:none initially) -->
+    <div id="flexContainer">
+      <div id="a"></div>
+      <div id="b"></div>
+      <div id="c"></div>
+    </div>
+  </div>
+
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+"use strict";
+
+/* This testcase ensures that we honor the "order" property when ordering
+ * flex items within a flex container.
+ *
+ * Note: The items in this testcase don't overlap, so this testcase does _not_
+ * test paint ordering.  It only tests horizontal ordering in a flex container.
+ */
+
+// Use "is()", "ok()", and "todo()" from parent document.
+var is = parent.is;
+var ok = parent.ok;
+var todo = parent.todo;
+
+// DATA
+// ----
+
+// This will store snapshots of our reference divs
+var gRefSnapshots = {};
+
+// These are the sets of 'order' values that we'll test.
+// The first three values in each array are the 'order' values that we'll
+// assign to elements a, b, and c (respectively).  The final value in each
+// array is the ID of the expected reference rendering.
+var gOrderTestcases = [
+  // The 6 basic permutations:
+  [ 1, 2, 3, "abc"],
+  [ 1, 3, 2, "acb"],
+  [ 2, 1, 3, "bac"],
+  [ 2, 3, 1, "cab"],
+  [ 3, 1, 2, "bca"],
+  [ 3, 2, 1, "cba"],
+
+  // Test negative values
+  [ 1, -5, -2, "bca"],
+  [ -50, 0, -2, "acb"],
+
+  // Non-integers should be ignored.
+  // (So, they'll leave their div with the initial 'order' value, which is 0.)
+  [ 1,   1.5, 2,   "bac"],
+  [ 2.5, 3.4, 1,   "abc"],
+  [ 0.5, 1,   1.5, "acb"],
+
+  // Decimal values that happen to be equal to integers (e.g. "3.0") are still
+  // <numbers>, and are _not_ <integers>.
+  //  Source: http://www.w3.org/TR/CSS21/syndata.html#value-def-integer
+  // (So, they'll leave their div with the initial 'order' value, which is 0.)
+  // (NOTE: We have to use quotes around "3.0" and "2.0" to be sure JS doesn't
+  // coerce them into integers before we get a chance to set them in CSS.)
+  [ "3.0", "2.0", "1.0", "abc"],
+  [ 3, "2.0", 1, "bca"],
+];
+
+// FUNCTIONS
+// ---------
+
+function initRefSnapshots() {
+  var refIds = ["abc", "acb", "bac", "bca", "cab", "cba"];
+  refIds.forEach(function(aRefId) {
+    var elem = document.getElementById(aRefId);
+    elem.style.display = "block";
+    gRefSnapshots[aRefId] = snapshotWindow(window, false);
+    elem.style.display = "";
+  });
+}
+
+function complainIfSnapshotsDiffer(aSnap1, aSnap2, aMsg) {
+  var compareResult = compareSnapshots(aSnap1, aSnap2, true);
+  ok(compareResult[0], "flex container rendering should match expected (" + aMsg +")");
+  if (!compareResult[0]) {
+    todo(false, "TESTCASE: " + compareResult[1]);
+    todo(false, "REFERENCE: "+ compareResult[2]);
+  }
+}
+
+function runOrderTestcase(aOrderTestcase) {
+  // Sanity-check
+  ok(Array.isArray(aOrderTestcase), "expecting testcase to be an array");
+  is(aOrderTestcase.length, 4, "expecting testcase to have 4 elements");
+
+  document.getElementById("a").style.MozOrder = aOrderTestcase[0];
+  document.getElementById("b").style.MozOrder = aOrderTestcase[1];
+  document.getElementById("c").style.MozOrder = aOrderTestcase[2];
+
+  var snapshot = snapshotWindow(window, false);
+  complainIfSnapshotsDiffer(snapshot, gRefSnapshots[aOrderTestcase[3]],
+                            aOrderTestcase);
+
+  // Clean up
+  document.getElementById("a").style.MozOrder = "";
+  document.getElementById("b").style.MozOrder = "";
+  document.getElementById("c").style.MozOrder = "";
+}
+
+// Main Function
+function main() {
+  initRefSnapshots();
+
+  // un-hide the flex container's parent
+  var flexContainerParent = document.getElementById("flexContainerParent");
+  flexContainerParent.style.display = "block";
+
+  // Initial sanity-check: should be in expected document order
+  var initialSnapshot = snapshotWindow(window, false);
+  complainIfSnapshotsDiffer(initialSnapshot, gRefSnapshots["abc"],
+                            "initial flex container rendering, no 'order' value yet");
+
+  // OK, now we run our tests
+  gOrderTestcases.forEach(runOrderTestcase);
+
+  // Re-hide the flex container at the end
+  flexContainerParent.style.display = "";
+
+  parent.finish();
+}
+
+main();
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/style/test/file_flexbox_order_table.html
@@ -0,0 +1,193 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+  <style type="text/css">
+
+    div.ref {
+      display: none;
+      height: 30px;
+    }
+
+    refA, refB, refC {
+      display: block;
+      float: left;
+    }
+
+    div#a, div#b, div#c {
+      display: table;
+    }
+
+    div#a, refA {
+      background: lightgreen;
+      width: 20px;
+      height: 30px;
+    }
+    div#b, refB {
+      background: orange;
+      width: 30px;
+      height: 30px;
+    }
+    div#c, refC {
+      background: blue;
+      width: 50px;
+      height: 30px;
+    }
+    div#flexContainer {
+      display: -moz-flex;
+      width: 100px;
+      height: 30px;
+    }
+    div#flexContainerParent {
+      display: none;
+    }
+  </style>
+</head>
+<body>
+<div id="display">
+
+  <!-- Reference cases (display:none; only shown during initRefSnapshots) -->
+  <div id="references">
+    <div class="ref" id="abc"><refA></refA><refB></refB><refC></refC></div>
+    <div class="ref" id="acb"><refA></refA><refC></refC><refB></refB></div>
+    <div class="ref" id="bac"><refB></refB><refA></refA><refC></refC></div>
+    <div class="ref" id="bca"><refB></refB><refC></refC><refA></refA></div>
+    <div class="ref" id="cab"><refC></refC><refA></refA><refB></refB></div>
+    <div class="ref" id="cba"><refC></refC><refB></refB><refA></refA></div>
+  </div>
+
+  <div id="flexContainerParent">
+    <!-- The flex container that we'll be testing
+         (its  parent is display:none initially) -->
+    <div id="flexContainer">
+      <div id="a"></div>
+      <div id="b"></div>
+      <div id="c"></div>
+    </div>
+  </div>
+
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+"use strict";
+
+/* This testcase ensures that we honor the "order" property when ordering
+ * tables as flex items within a flex container.
+ *
+ * Note: The items in this testcase don't overlap, so this testcase does _not_
+ * test paint ordering.  It only tests horizontal ordering in a flex container.
+ */
+
+// Use "is()", "ok()", and "todo()" from parent document.
+var is = parent.is;
+var ok = parent.ok;
+var todo = parent.todo;
+
+// DATA
+// ----
+
+// This will store snapshots of our reference divs
+var gRefSnapshots = {};
+
+// These are the sets of 'order' values that we'll test.
+// The first three values in each array are the 'order' values that we'll
+// assign to elements a, b, and c (respectively).  The final value in each
+// array is the ID of the expected reference rendering.
+var gOrderTestcases = [
+  // The 6 basic permutations:
+  [ 1, 2, 3, "abc"],
+  [ 1, 3, 2, "acb"],
+  [ 2, 1, 3, "bac"],
+  [ 2, 3, 1, "cab"],
+  [ 3, 1, 2, "bca"],
+  [ 3, 2, 1, "cba"],
+
+  // Test negative values
+  [ 1, -5, -2, "bca"],
+  [ -50, 0, -2, "acb"],
+
+  // Non-integers should be ignored.
+  // (So, they'll leave their div with the initial 'order' value, which is 0.)
+  [ 1,   1.5, 2,   "bac"],
+  [ 2.5, 3.4, 1,   "abc"],
+  [ 0.5, 1,   1.5, "acb"],
+
+  // Decimal values that happen to be equal to integers (e.g. "3.0") are still
+  // <numbers>, and are _not_ <integers>.
+  //  Source: http://www.w3.org/TR/CSS21/syndata.html#value-def-integer
+  // (So, they'll leave their div with the initial 'order' value, which is 0.)
+  // (NOTE: We have to use quotes around "3.0" and "2.0" to be sure JS doesn't
+  // coerce them into integers before we get a chance to set them in CSS.)
+  [ "3.0", "2.0", "1.0", "abc"],
+  [ 3, "2.0", 1, "bca"],
+];
+
+// FUNCTIONS
+// ---------
+
+function initRefSnapshots() {
+  var refIds = ["abc", "acb", "bac", "bca", "cab", "cba"];
+  refIds.forEach(function(aRefId) {
+    var elem = document.getElementById(aRefId);
+    elem.style.display = "block";
+    gRefSnapshots[aRefId] = snapshotWindow(window, false);
+    elem.style.display = "";
+  });
+}
+
+function complainIfSnapshotsDiffer(aSnap1, aSnap2, aMsg) {
+  var compareResult = compareSnapshots(aSnap1, aSnap2, true);
+  ok(compareResult[0], "flex container rendering should match expected (" + aMsg +")");
+  if (!compareResult[0]) {
+    todo(false, "TESTCASE: " + compareResult[1]);
+    todo(false, "REFERENCE: "+ compareResult[2]);
+  }
+}
+
+function runOrderTestcase(aOrderTestcase) {
+  // Sanity-check
+  ok(Array.isArray(aOrderTestcase), "expecting testcase to be an array");
+  is(aOrderTestcase.length, 4, "expecting testcase to have 4 elements");
+
+  document.getElementById("a").style.MozOrder = aOrderTestcase[0];
+  document.getElementById("b").style.MozOrder = aOrderTestcase[1];
+  document.getElementById("c").style.MozOrder = aOrderTestcase[2];
+
+  var snapshot = snapshotWindow(window, false);
+  complainIfSnapshotsDiffer(snapshot, gRefSnapshots[aOrderTestcase[3]],
+                            aOrderTestcase);
+
+  // Clean up
+  document.getElementById("a").style.MozOrder = "";
+  document.getElementById("b").style.MozOrder = "";
+  document.getElementById("c").style.MozOrder = "";
+}
+
+// Main Function
+function main() {
+  initRefSnapshots();
+
+  // un-hide the flex container's parent
+  var flexContainerParent = document.getElementById("flexContainerParent");
+  flexContainerParent.style.display = "block";
+
+  // Initial sanity-check: should be in expected document order
+  var initialSnapshot = snapshotWindow(window, false);
+  complainIfSnapshotsDiffer(initialSnapshot, gRefSnapshots["abc"],
+                            "initial flex container rendering, no 'order' value yet");
+
+  // OK, now we run our tests
+  gOrderTestcases.forEach(runOrderTestcase);
+
+  // Re-hide the flex container at the end
+  flexContainerParent.style.display = "";
+
+  parent.finish();
+}
+
+main();
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_flexbox_order.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=666041
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 666041</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=666041">Mozilla Bug 666041</a>
+<div id="display">
+  <iframe id="iframe" style="height: 100px; width: 200px"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+"use strict";
+
+/** Test for Bug 666041 **/
+
+/*
+ * This mochitest runs in an iframe so that we can selectively turn on the
+ * flexbox about:config pref before its document is instantiated.
+ *
+ * See the iframe's source ("file_flexbox_order.html") for the actual
+ * test code and for more documentation.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+ok(!SpecialPowers.getBoolPref("layout.css.flexbox.enabled"),
+   "expecting flexbox pref to be disabled by default");
+
+SpecialPowers.setBoolPref("layout.css.flexbox.enabled", true);
+document.getElementById("iframe").src = "file_flexbox_order.html";
+
+function finish() {
+  SpecialPowers.clearUserPref("layout.css.flexbox.enabled");
+  SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_flexbox_order_table.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=799775
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 799775</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=799775">Mozilla Bug 799775</a>
+<div id="display">
+  <iframe id="iframe" style="height: 100px; width: 200px"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+"use strict";
+
+/** Test for Bug 799775 **/
+
+/*
+ * This mochitest runs in an iframe so that we can selectively turn on the
+ * flexbox about:config pref before its document is instantiated.
+ *
+ * See the iframe's source ("file_flexbox_order_table.html") for the actual
+ * test code and for more documentation.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+if(SpecialPowers.getBoolPref("layout.css.flexbox.enabled")) {
+  document.getElementById("iframe").src = "file_flexbox_order_table.html";
+} else {
+  todo(false,
+       "Finishing early -- flexbox pref is disabled, and this test only " +
+       "works if the pref is enabled at startup-time, when ua.css is parsed");
+  finish();
+}
+
+function finish() {
+  SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
--- a/layout/style/ua.css
+++ b/layout/style/ua.css
@@ -37,16 +37,17 @@
   bottom: inherit;
   left: inherit;
   z-index: inherit;
   page-break-before: inherit;
   page-break-after: inherit;
   vertical-align: inherit; /* needed for inline-table */
   line-height: inherit; /* needed for vertical-align on inline-table */
   -moz-align-self: inherit; /* needed for "align-self: auto" to work on table */
+  -moz-order: inherit; /* needed for "order" to work on table flex items */
   /* Bug 722777 */
   -moz-transform: inherit;
   -moz-transform-origin: inherit;
   /* Bug 724750 */
   -moz-backface-visibility: inherit;
 }
 
 *|*::-moz-table-row {
--- a/media/mtransport/third_party/nICEr/nicer.gyp
+++ b/media/mtransport/third_party/nICEr/nicer.gyp
@@ -127,17 +127,16 @@
 	      'R_DEFINED_INT8=int64_t',
 	      'R_DEFINED_UINT8=uint64_t',
           ],
           
           'conditions' : [
               ## Mac
               [ 'OS == "mac"', {
                 'cflags_mozilla': [
-                    '-Werror',
                     '-Wall',
                     '-Wno-parentheses',
                     '-Wno-strict-prototypes',
                     '-Wmissing-prototypes',
                  ],
                  'defines' : [
                      'DARWIN',
                      'HAVE_LIBM=1',
@@ -178,17 +177,16 @@
 		     '../nrappkit/src/port/win32/include'
 		 ],
               }],
 
               
               ## Linux
               [ 'OS == "linux"', {
                 'cflags': [
-                    '-Werror',
                     '-Wall',
                     '-Wno-parentheses',
                     '-Wno-strict-prototypes',
                     '-Wmissing-prototypes',
                  ],
                  'defines' : [
                      'LINUX',
                      'HAVE_LIBM=1',
--- a/media/mtransport/third_party/nrappkit/nrappkit.gyp
+++ b/media/mtransport/third_party/nrappkit/nrappkit.gyp
@@ -145,17 +145,16 @@
 	      'R_DEFINED_INT8=int64_t',
 	      'R_DEFINED_UINT8=uint64_t',
           ],
           
           'conditions' : [
               ## Mac
               [ 'OS == "mac"', {
                 'cflags_mozilla': [
-                    '-Werror',
                     '-Wall',
                     '-Wno-parentheses',
                     '-Wno-strict-prototypes',
                     '-Wmissing-prototypes',
                  ],
                  'defines' : [
                      'DARWIN',
                      'HAVE_LIBM=1',
@@ -195,17 +194,16 @@
               	      './src/port/win32/include/csi_platform.h',
 		 ],
               }],
 
               
               ## Linux
               [ 'OS == "linux"', {
                 'cflags': [
-                    '-Werror',
                     '-Wall',
                     '-Wno-parentheses',
                     '-Wno-strict-prototypes',
                     '-Wmissing-prototypes',
                  ],
                  'defines' : [
                      'LINUX',
                      'HAVE_LIBM=1',
--- a/media/omx-plugin/OmxPlugin.cpp
+++ b/media/omx-plugin/OmxPlugin.cpp
@@ -844,20 +844,22 @@ static void DestroyDecoder(Decoder *aDec
 }
 
 static bool Match(const char *aMimeChars, size_t aMimeLen, const char *aNeedle)
 {
   return !strncmp(aMimeChars, aNeedle, aMimeLen);
 }
 
 static const char* const gCodecs[] = {
-  "avc",
-  "mp3",
-  "mp4v",
-  "mp4a",
+  "avc1.42E01E",  // H.264 Constrained Baseline Profile Level 3.0
+  "avc1.42001E",  // H.264 Baseline Profile Level 3.0
+  "avc1.42001F",  // H.264 Baseline Profile Level 3.1
+  "avc1.4D401E",  // H.264 Main Profile Level 3.0
+  "avc1.4D401F",  // H.264 Main Profile Level 3.1
+  "mp4a.40.2",    // AAC-LC
   NULL
 };
 
 static bool CanDecode(const char *aMimeChars, size_t aMimeLen, const char* const**aCodecs)
 {
   if (!Match(aMimeChars, aMimeLen, "video/mp4") &&
       !Match(aMimeChars, aMimeLen, "audio/mp4") &&
       !Match(aMimeChars, aMimeLen, "audio/mpeg") &&
--- a/media/webrtc/signaling/signaling.gyp
+++ b/media/webrtc/signaling/signaling.gyp
@@ -179,17 +179,16 @@
             'SIP_OS_LINUX',
             '_GNU_SOURCE',
             'LINUX', 
             'GIPS_VER=3510', 
             'SECLIB_OPENSSL',
           ],
           
           'cflags_mozilla': [
-            '-Werror',
           ],
         }],
         ['OS=="win"', {
           'include_dirs': [
           ],		
           'defines': [
             'SIP_OS_WINDOWS',
             'WIN32', 
@@ -207,18 +206,16 @@
           ],
           'defines': [
             'SIP_OS_OSX',
             'OSX', 
             '_FORTIFY_SOURCE=2',
           ],
           
           'cflags_mozilla': [
-            '-Werror',
-            '-Wno-error=conversion'
           ],
         }],
       ],
     },
   
     #
     # SIPCC
     #
@@ -628,17 +625,16 @@
             'USE_TIMER_SELECT_BASED',
             'FULL_BUILD',
             'STUBBED_OUT',
             'USE_PRINTF'
             'LINUX',
           ],
 
           'cflags_mozilla': [
-            '-Werror',
           ],
         }],
         ['OS=="win"', {
           'include_dirs': [
           ],
           
           'sources': [
             # SIPSTACK
@@ -747,18 +743,16 @@
             'FULL_BUILD',
             'STUBBED_OUT',
             'USE_PRINTF',
             '_DARWIN_C_SOURCE',
             'NO_NSPR_10_SUPPORT',
           ],
           
           'cflags_mozilla': [
-            '-Werror',
-            '-Wno-error=conversion'
           ],
         }],
       ],
             
     },
   ],
 }
 
--- a/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
+++ b/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
@@ -436,16 +436,19 @@ def GenerateOutput(target_list, target_d
     top = topsrcdir
     src = abs_srcdir
   WriteMakefile(makefile_path, topdata, params['build_files'][0],
                 depth,
                 swapslashes(top),
                 swapslashes(src),
                 swapslashes(relative_srcdir))
   scriptname = topsrcdir_path(__file__)
+  if scriptname[-4:] in ('.pyc', '.pyo'):
+    scriptname = scriptname[:-1]
+
   # Reassemble a commandline from parts so that all the paths are correct
   commandline = [topsrcdir_path(sys.argv[0]),
                  "--format=mozmake",
                  "--depth=%s" % topsrcdir_path(options.depth),
                  "--generator-output=%s" % objdir_path(options.generator_output),
                  "--toplevel-dir=$(topsrcdir)",
                  #XXX: handle other generator_flags gracefully?
                  "-G OBJDIR=$(DEPTH)"] + \
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -599,32 +599,26 @@ pref("direct-texture.force.disabled", fa
 
 // show checkerboard pattern on android; we use background colour instead
 pref("gfx.show_checkerboard_pattern", true);
 
 // This fraction in 1000ths of velocity remains after every animation frame when the velocity is low.
 pref("ui.scrolling.friction_slow", -1);
 // This fraction in 1000ths of velocity remains after every animation frame when the velocity is high.
 pref("ui.scrolling.friction_fast", -1);
-// Below this velocity (in pixels per frame), the friction starts increasing from friction_fast
-// to friction_slow.
-pref("ui.scrolling.velocity_threshold", -1);
 // The maximum velocity change factor between events, per ms, in 1000ths.
 // Direction changes are excluded.
 pref("ui.scrolling.max_event_acceleration", -1);
 // The rate of deceleration when the surface has overscrolled, in 1000ths.
 pref("ui.scrolling.overscroll_decel_rate", -1);
 // The fraction of the surface which can be overscrolled before it must snap back, in 1000ths.
 pref("ui.scrolling.overscroll_snap_limit", -1);
 // The minimum amount of space that must be present for an axis to be considered scrollable,
 // in 1/1000ths of pixels.
 pref("ui.scrolling.min_scrollable_distance", -1);
-// A comma-separated list of float values in the range [0.0, 1.0) that are used as
-// interpolation frames for zoom animations.
-pref("ui.zooming.animation_frames", "");
 
 // Enable accessibility mode if platform accessibility is enabled.
 pref("accessibility.accessfu.activate", 2);
 // Enable explore by touch if it is enabled in the platform
 pref("accessibility.accessfu.explorebytouch", 2);
 
 // Mobile manages state by autodetection
 pref("network.manage-offline-status", true);
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -12,17 +12,18 @@
 
 #ifdef ARMV7_ONLY
     <supports-screens android:smallScreens="false" />
 #endif
 
     <uses-sdk android:minSdkVersion="8"
               android:targetSdkVersion="14"/>
 
-#include ../sync/manifests/SyncAndroidManifest_permissions.xml.in
+#include ../services/manifests/AnnouncementsAndroidManifest_permissions.xml.in
+#include ../services/manifests/SyncAndroidManifest_permissions.xml.in
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
     <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
     <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
@@ -164,17 +165,18 @@
                   android:process="@ANDROID_PACKAGE_NAME@Restarter"
                   android:theme="@style/Gecko">
           <intent-filter>
             <action android:name="org.mozilla.gecko.restart"/>
             <action android:name="org.mozilla.gecko.restart_update"/>
           </intent-filter>
         </activity>
 
-#include ../sync/manifests/SyncAndroidManifest_activities.xml.in
+#include ../services/manifests/AnnouncementsAndroidManifest_activities.xml.in
+#include ../services/manifests/SyncAndroidManifest_activities.xml.in
 
 #if MOZ_CRASHREPORTER
   <activity android:name="CrashReporter"
             android:label="@string/crash_reporter_title"
             android:icon="@drawable/crash_reporter"
             android:theme="@style/Gecko"
             android:excludeFromRecents="true">
           <intent-filter>
@@ -236,17 +238,18 @@
 
         <service
             android:exported="false"
             android:name="org.mozilla.gecko.updater.UpdateService"
             android:process="@MANGLED_ANDROID_PACKAGE_NAME@.UpdateService">
         </service>
 
 
-#include ../sync/manifests/SyncAndroidManifest_services.xml.in
+#include ../services/manifests/AnnouncementsAndroidManifest_services.xml.in
+#include ../services/manifests/SyncAndroidManifest_services.xml.in
     </application>
 
     <permission android:name="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"
                 android:protectionLevel="signature"/>
 
     <permission android:name="@ANDROID_PACKAGE_NAME@.permissions.PASSWORD_PROVIDER"
                 android:protectionLevel="signature"/>
 
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -129,16 +129,17 @@ abstract public class GeckoApp
         URL,        /* launched with a passed URL */
         PREFETCH,   /* launched with a passed URL that we prefetch */
         REDIRECTOR  /* launched with a passed URL in our redirect list */
     }
 
     public static final String ACTION_ALERT_CLICK   = "org.mozilla.gecko.ACTION_ALERT_CLICK";
     public static final String ACTION_ALERT_CLEAR   = "org.mozilla.gecko.ACTION_ALERT_CLEAR";
     public static final String ACTION_ALERT_CALLBACK = "org.mozilla.gecko.ACTION_ALERT_CALLBACK";
+    public static final String ACTION_ANNOUNCEMENTS_PREF = "org.mozilla.gecko.ANNOUNCEMENTS_PREF";
     public static final String ACTION_WEBAPP_PREFIX = "org.mozilla.gecko.WEBAPP";
     public static final String ACTION_DEBUG         = "org.mozilla.gecko.DEBUG";
     public static final String ACTION_BOOKMARK      = "org.mozilla.gecko.BOOKMARK";
     public static final String ACTION_LOAD          = "org.mozilla.gecko.LOAD";
     public static final String ACTION_INIT_PW       = "org.mozilla.gecko.INIT_PW";
     public static final String SAVED_STATE_TITLE         = "title";
     public static final String SAVED_STATE_IN_BACKGROUND = "inBackground";
     public static final String SAVED_STATE_PRIVATE_SESSION = "privateSession";
@@ -1740,16 +1741,22 @@ abstract public class GeckoApp
 
         GeckoAppShell.getHandler().postDelayed(new Runnable() {
             public void run() {
                 Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - pre checkLaunchState");
                 // Sync settings need Gecko to be loaded, so
                 // no hurry in starting this.
                 checkMigrateSync();
 
+                // Kick off our background service to fetch product announcements.
+                // We do this by invoking the broadcast receiver, which uses the
+                // system alarm infrastructure to perform tasks at intervals.
+                Log.d(LOGTAG, "Broadcasting announcements pref.");
+                GeckoPreferences.broadcastAnnouncementsPref(GeckoApp.mAppContext);
+
                 /*
                   XXXX see bug 635342
                    We want to disable this code if possible.  It is about 145ms in runtime
                 SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
                 String localeCode = settings.getString(getPackageName() + ".locale", "");
                 if (localeCode != null && localeCode.length() > 0)
                     GeckoAppShell.setSelectedLocale(localeCode);
                 */
--- a/mobile/android/base/GeckoPreferences.java
+++ b/mobile/android/base/GeckoPreferences.java
@@ -9,24 +9,27 @@ import org.mozilla.gecko.util.GeckoEvent
 
 import org.json.JSONArray;
 import org.json.JSONObject;
 
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.preference.CheckBoxPreference;
 import android.preference.EditTextPreference;
 import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceChangeListener;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceGroup;
+import android.preference.PreferenceManager;
 import android.preference.PreferenceScreen;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.Log;
 import android.view.MenuItem;
 import android.view.View;
@@ -45,16 +48,17 @@ public class GeckoPreferences
     private ArrayList<String> mPreferencesList;
     private PreferenceScreen mPreferenceScreen;
     private static boolean sIsCharEncodingEnabled = false;
     private static final String NON_PREF_PREFIX = "android.not_a_preference.";
 
     // These match keys in resources/xml/preferences.xml.in.
     public static String PREFS_MP_ENABLED         = "privacy.masterpassword.enabled";
     public static String PREFS_MENU_CHAR_ENCODING = "browser.menu.showCharacterEncoding";
+    public static String PREFS_ANNOUNCEMENTS_ENABLED = NON_PREF_PREFIX + "privacy.announcements.enabled";
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         addPreferencesFromResource(R.xml.preferences);
         registerEventListener("Sanitize:Finished");
     }
 
@@ -132,24 +136,85 @@ public class GeckoPreferences
     public static void setCharEncodingState(boolean enabled) {
         sIsCharEncodingEnabled = enabled;
     }
 
     public static boolean getCharEncodingState() {
         return sIsCharEncodingEnabled;
     }
 
+    /**
+     * Broadcast an intent with <code>pref</code>, <code>branch</code>, and
+     * <code>enabled</code> extras. This is intended to represent the
+     * notification of a preference value to observers.
+     */
+    public static void broadcastPrefAction(final Context context,
+                                           final String action,
+                                           final String pref,
+                                           final boolean value) {
+        final Intent intent = new Intent(action);
+        intent.setAction(action);
+        intent.putExtra("pref", pref);
+        intent.putExtra("branch", GeckoApp.PREFS_NAME);
+        intent.putExtra("enabled", value);
+        Log.d(LOGTAG, "Broadcast: " + action + ", " + pref + ", " + GeckoApp.PREFS_NAME + ", " + value);
+        context.sendBroadcast(intent);
+    }
+
+    /**
+     * Broadcast the provided value as the value of the
+     * <code>PREFS_ANNOUNCEMENTS_ENABLED</code> pref.
+     */
+    public static void broadcastAnnouncementsPref(final Context context, final boolean value) {
+        broadcastPrefAction(context,
+                            GeckoApp.ACTION_ANNOUNCEMENTS_PREF,
+                            PREFS_ANNOUNCEMENTS_ENABLED,
+                            value);
+    }
+
+    /**
+     * Broadcast the current value of the
+     * <code>PREFS_ANNOUNCEMENTS_ENABLED</code> pref.
+     */
+    public static void broadcastAnnouncementsPref(final Context context) {
+        broadcastPrefAction(context,
+                            GeckoApp.ACTION_ANNOUNCEMENTS_PREF,
+                            PREFS_ANNOUNCEMENTS_ENABLED,
+                            getBooleanPref(context, PREFS_ANNOUNCEMENTS_ENABLED, true));
+    }
+
+    /**
+     * Return the value of the named preference in the default preferences file.
+     *
+     * This corresponds to the storage that backs preferences.xml.
+     * @param context a <code>Context</code>; the
+     *                <code>PreferenceActivity</code> will suffice, but this
+     *                method is intended to be called from other contexts
+     *                within the application, not just this <code>Activity</code>.
+     * @param name    the name of the preference to retrieve.
+     * @param def     the default value to return if the preference is not present.
+     * @return        the value of the preference, or the default.
+     */
+    public static boolean getBooleanPref(final Context context, final String name, boolean def) {
+        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        return prefs.getBoolean(name, def);
+    }
+
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         String prefName = preference.getKey();
         if (prefName != null && prefName.equals(PREFS_MP_ENABLED)) {
             showDialog((Boolean) newValue ? DIALOG_CREATE_MASTER_PASSWORD : DIALOG_REMOVE_MASTER_PASSWORD);
             return false;
         } else if (prefName != null && prefName.equals(PREFS_MENU_CHAR_ENCODING)) {
             setCharEncodingState(((String) newValue).equals("true"));
+        } else if (prefName != null && prefName.equals(PREFS_ANNOUNCEMENTS_ENABLED)) {
+            // Send a broadcast intent to the product announcements service, either to start or
+            // to stop the repeated background checks.
+            broadcastAnnouncementsPref(GeckoApp.mAppContext, ((Boolean) newValue).booleanValue());
         }
 
         if (!TextUtils.isEmpty(prefName)) {
             PrefsHelper.setPref(prefName, newValue);
         }
         if (preference instanceof ListPreference) {
             // We need to find the entry for the new value
             int newIndex = ((ListPreference)preference).findIndexOfValue((String) newValue);
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -9,17 +9,17 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/ipc/app/defs.mk
 
 DIRS = locales
 
 DIST_FILES = package-name.txt
 
-include $(topsrcdir)/mobile/android/base/android-sync-files.mk
+include $(topsrcdir)/mobile/android/base/android-services-files.mk
 
 MOZGLUE_JAVA_FILES := \
   mozglue/DirectBufferAllocator.java \
   $(NULL)
 
 UTIL_JAVA_FILES := \
   ActivityResultHandler.java \
   ActivityResultHandlerMap.java \
@@ -279,17 +279,17 @@ GARBAGE += \
   res/values/strings.xml \
   R.java \
   $(FENNEC_PP_XML_FILES) \
   $(SYNC_PP_RES_XML) \
   package-name.txt \
   Manifest.java \
   $(NULL)
 
-GARBAGE_DIRS += classes db jars res sync
+GARBAGE_DIRS += classes db jars res sync services
 
 MOZ_ANDROID_SHARED_ID = "$(ANDROID_PACKAGE_NAME).sharedID"
 MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "$(ANDROID_PACKAGE_NAME)_sync"
 
 # Bug 567884 - Need a way to find appropriate icons during packaging
 ifeq ($(MOZ_APP_NAME),fennec)
 ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_48x48.png
 ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_72x72.png
@@ -1056,29 +1056,29 @@ PP_RES_XML= \
   $(NULL)
 
 # This is kinda awful; if any of the source files change, we remake them all.
 $(PP_RES_XML): $(patsubst res/%,$(srcdir)/resources/%.in,$(PP_RES_XML))
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
              $(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $(subst res,$(srcdir)/resources,$@).in > $@
 
 # AndroidManifest.xml includes these files, so they need to be marked as dependencies.
-SYNC_MANIFEST_FRAGMENTS = $(wildcard $(topsrcdir)/mobile/android/sync/manifests/*.in)
+SERVICES_MANIFEST_FRAGMENTS = $(wildcard $(topsrcdir)/mobile/android/services/manifests/*.in)
 
 android-tgts = \
   AndroidManifest.xml \
   $(FENNEC_PP_JAVA_FILES) \
   $(SYNC_PP_JAVA_FILES) \
   package-name.txt \
   $(NULL)
 
 android-preqs = \
   Makefile.in \
   $(call mkdir_deps,db,sync/repositories/android) \
-  $(SYNC_MANIFEST_FRAGMENTS) \
+  $(SERVICES_MANIFEST_FRAGMENTS) \
   WebAppManifestFragment.xml.in \
   WebAppsFragments.java \
   $(NULL)
 
 $(android-tgts): % : %.in $(android-preqs)
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
              $(AUTOMATION_PPARGS) -DOBJDIR="`pwd`" $(DEFINES) $(ACDEFINES) $< > $@
 
rename from mobile/android/base/android-sync-files.mk
rename to mobile/android/base/android-services-files.mk
--- a/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml.in
@@ -28,16 +28,17 @@
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
           android:icon="@drawable/ic_menu_desktop_mode_off"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
     <item android:id="@+id/private_browsing"
+          android:visible="false"
           android:title="@string/new_pb_tab"/>
 
     <item android:title="@string/tools"
           android:icon="@drawable/ic_menu_tools">
 
         <menu>
 
             <item android:id="@+id/save_as_pdf"
--- a/mobile/android/base/resources/menu-v11/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu-v11/browser_app_menu.xml.in
@@ -29,16 +29,17 @@
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
           android:icon="@drawable/ic_menu_desktop_mode_off"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
     <item android:id="@+id/private_browsing"
+          android:visible="false"
           android:title="@string/new_pb_tab"/>
 
     <item android:title="@string/tools"
           android:icon="@drawable/ic_menu_tools">
 
         <menu>
 
             <item android:id="@+id/save_as_pdf"
--- a/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml.in
@@ -29,16 +29,17 @@
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
           android:icon="@drawable/ic_menu_desktop_mode_off"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
     <item android:id="@+id/private_browsing"
+          android:visible="false"
           android:title="@string/new_pb_tab"/>
 
     <item android:title="@string/tools"
           android:icon="@drawable/ic_menu_tools">
 
         <menu>
 
             <item android:id="@+id/save_as_pdf"
--- a/mobile/android/base/resources/menu/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu/browser_app_menu.xml.in
@@ -28,16 +28,17 @@
     <item android:id="@+id/find_in_page"
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
     <item android:id="@+id/private_browsing"
+          android:visible="false"
           android:title="@string/new_pb_tab"/>
 
     <item android:id="@+id/addons"
           android:title="@string/addons"/>
 
     <item android:id="@+id/downloads"
           android:title="@string/downloads"/>
 
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -7,17 +7,17 @@
 <!DOCTYPE resources [
 #includesubst @BRANDPATH@
 #includesubst @STRINGSPATH@
 #includesubst @SYNCSTRINGSPATH@
 ]>
 #includesubst @BOOKMARKSPATH@
 <resources>
   <string name="moz_app_displayname">@MOZ_APP_DISPLAYNAME@</string>
-#include ../sync/strings.xml.in
+#include ../services/strings.xml.in
   <string name="splash_settingup">&splash_settingup;</string>
   <string name="splash_bookmarks_history">&splash_bookmarks_history;</string>
   <string name="no_space_to_start_error">&no_space_to_start_error;</string>
   <string name="error_loading_file">&error_loading_file;</string>
 
   <string name="awesomebar_all_pages_title">&awesomebar_all_pages_title;</string>
   <string name="awesomebar_bookmarks_title">&awesomebar_bookmarks_title;</string>
   <string name="awesomebar_history_title">&awesomebar_history_title;</string>
--- a/mobile/android/base/sync/GlobalConstants.java.in
+++ b/mobile/android/base/sync/GlobalConstants.java.in
@@ -5,20 +5,39 @@
 
 package org.mozilla.gecko.sync;
 
 /**
  * Preprocessed class for storing preprocessed values.
  */
 public class GlobalConstants {
   public static final String PRODUCT_NAME = "@MOZ_APP_DISPLAYNAME@";
-  public static final String SYNC_VERSION_STRING = "1.@MOZ_APP_VERSION@.0";
+  public static final String ANDROID_CPU_ARCH = "@ANDROID_CPU_ARCH@";
+
+  // One of 'beta', 'aurora', 'nightly', 'default'.
+  // If this is an official build, 'default' means 'release'.
+  // Otherwise, it means 'dev'.
+  public static final String MOZ_UPDATE_CHANNEL = "@MOZ_UPDATE_CHANNEL@";
+#ifdef MOZ_OFFICIAL_BRANDING
+  public static final boolean MOZ_OFFICIAL_BRANDING = true;
+#else
+  public static final boolean MOZ_OFFICIAL_BRANDING = false;
+#endif
 
-  public static final String USER_AGENT = "Firefox AndroidSync " + SYNC_VERSION_STRING +
-                                          " (" + PRODUCT_NAME + ")";
+  public static final String MOZ_APP_VERSION = "@MOZ_APP_VERSION@";
+  public static final String SYNC_MAJOR_VERSION  = "1";
+  public static final String SYNC_MINOR_VERSION  = "0";
+  public static final String SYNC_VERSION_STRING = SYNC_MAJOR_VERSION + "." +
+                                                   MOZ_APP_VERSION + "." +
+                                                   SYNC_MINOR_VERSION;
+
+  public static final String SYNC_USER_AGENT = "Firefox AndroidSync " +
+                                               SYNC_VERSION_STRING + " (" +
+                                               PRODUCT_NAME + ")";
+
   public static final String BROWSER_INTENT_PACKAGE = "@ANDROID_PACKAGE_NAME@";
   public static final String BROWSER_INTENT_CLASS = BROWSER_INTENT_PACKAGE + ".App";
 
   public static final String ACCOUNTTYPE_SYNC     = "@MOZ_ANDROID_SHARED_ACCOUNT_TYPE@";
 
   /**
    * Bug 790931: this signing-level permission protects broadcast intents that
    * should be received only by Firefox versions sharing the same Android
--- a/mobile/android/base/sync/net/SyncStorageRequest.java
+++ b/mobile/android/base/sync/net/SyncStorageRequest.java
@@ -126,17 +126,17 @@ public class SyncStorageRequest implemen
 
     @Override
     public void handleTransportException(GeneralSecurityException e) {
       this.request.delegate.handleRequestError(e);
     }
 
     @Override
     public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
-      client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, GlobalConstants.USER_AGENT);
+      client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, GlobalConstants.SYNC_USER_AGENT);
 
       // Clients can use their delegate interface to specify X-If-Unmodified-Since.
       String ifUnmodifiedSince = this.request.delegate.ifUnmodifiedSince();
       if (ifUnmodifiedSince != null) {
         Logger.debug(LOG_TAG, "Making request with X-If-Unmodified-Since = " + ifUnmodifiedSince);
         request.setHeader("x-if-unmodified-since", ifUnmodifiedSince);
       }
       if (request.getMethod().equalsIgnoreCase("DELETE")) {
--- a/mobile/android/base/sync/setup/auth/AuthenticateAccountStage.java
+++ b/mobile/android/base/sync/setup/auth/AuthenticateAccountStage.java
@@ -97,17 +97,17 @@ public class AuthenticateAccountStage im
     final BaseResource httpResource = new BaseResource(authRequestUrl);
     httpResource.delegate = new SyncResourceDelegate(httpResource) {
 
       @Override
       public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
         // Make reference to request, to abort if necessary.
         httpRequest = request;
         client.log.enableDebug(true);
-        request.setHeader(new BasicHeader("User-Agent", GlobalConstants.USER_AGENT));
+        request.setHeader(new BasicHeader("User-Agent", GlobalConstants.SYNC_USER_AGENT));
         // Host header is not set for some reason, so do it explicitly.
         try {
           URI authServerUri = new URI(authRequestUrl);
           request.setHeader(new BasicHeader("Host", authServerUri.getHost()));
         } catch (URISyntaxException e) {
           Logger.error(LOG_TAG, "Malformed uri, will be caught elsewhere.", e);
         }
         request.setHeader(new BasicHeader("Authorization", authHeader));
--- a/mobile/android/base/ui/Axis.java
+++ b/mobile/android/base/ui/Axis.java
@@ -22,17 +22,16 @@ import java.util.Map;
  * like displacement, velocity, viewport dimensions, etc. pertaining to
  * a particular axis.
  */
 abstract class Axis {
     private static final String LOGTAG = "GeckoAxis";
 
     private static final String PREF_SCROLLING_FRICTION_SLOW = "ui.scrolling.friction_slow";
     private static final String PREF_SCROLLING_FRICTION_FAST = "ui.scrolling.friction_fast";
-    private static final String PREF_SCROLLING_VELOCITY_THRESHOLD = "ui.scrolling.velocity_threshold";
     private static final String PREF_SCROLLING_MAX_EVENT_ACCELERATION = "ui.scrolling.max_event_acceleration";
     private static final String PREF_SCROLLING_OVERSCROLL_DECEL_RATE = "ui.scrolling.overscroll_decel_rate";
     private static final String PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT = "ui.scrolling.overscroll_snap_limit";
     private static final String PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE = "ui.scrolling.min_scrollable_distance";
 
     // This fraction of velocity remains after every animation frame when the velocity is low.
     private static float FRICTION_SLOW;
     // This fraction of velocity remains after every animation frame when the velocity is high.
@@ -62,17 +61,16 @@ abstract class Axis {
         Integer value = (prefs == null ? null : prefs.get(prefName));
         return (value == null || value < 0 ? defaultValue : value);
     }
 
     static void initPrefs() {
         JSONArray prefs = new JSONArray();
         prefs.put(PREF_SCROLLING_FRICTION_FAST);
         prefs.put(PREF_SCROLLING_FRICTION_SLOW);
-        prefs.put(PREF_SCROLLING_VELOCITY_THRESHOLD);
         prefs.put(PREF_SCROLLING_MAX_EVENT_ACCELERATION);
         prefs.put(PREF_SCROLLING_OVERSCROLL_DECEL_RATE);
         prefs.put(PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT);
         prefs.put(PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE);
 
         PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() {
             Map<String, Integer> mPrefs = new HashMap<String, Integer>();
 
@@ -81,36 +79,43 @@ abstract class Axis {
             }
 
             @Override public void finish() {
                 setPrefs(mPrefs);
             }
         });
     }
 
+    static final float MS_PER_FRAME = 4.0f;
+    private static final float FRAMERATE_MULTIPLIER = (1000f/60f) / MS_PER_FRAME;
+
+    //  The values we use for friction are based on a 16.6ms frame, adjust them to MS_PER_FRAME:
+    //  FRICTION^1 = FRICTION_ADJUSTED^(16/MS_PER_FRAME)
+    //  FRICTION_ADJUSTED = e ^ ((ln(FRICTION))/FRAMERATE_MULTIPLIER)
+    static float getFrameAdjustedFriction(float baseFriction) {
+        return (float)Math.pow(Math.E, (Math.log(baseFriction) / FRAMERATE_MULTIPLIER));
+    }
+
     static void setPrefs(Map<String, Integer> prefs) {
-        FRICTION_SLOW = getFloatPref(prefs, PREF_SCROLLING_FRICTION_SLOW, 850);
-        FRICTION_FAST = getFloatPref(prefs, PREF_SCROLLING_FRICTION_FAST, 970);
-        VELOCITY_THRESHOLD = getIntPref(prefs, PREF_SCROLLING_VELOCITY_THRESHOLD, 10);
+        FRICTION_SLOW = getFrameAdjustedFriction(getFloatPref(prefs, PREF_SCROLLING_FRICTION_SLOW, 850));
+        FRICTION_FAST = getFrameAdjustedFriction(getFloatPref(prefs, PREF_SCROLLING_FRICTION_FAST, 970));
+        VELOCITY_THRESHOLD = 10 / FRAMERATE_MULTIPLIER;
         MAX_EVENT_ACCELERATION = getFloatPref(prefs, PREF_SCROLLING_MAX_EVENT_ACCELERATION, 12);
-        OVERSCROLL_DECEL_RATE = getFloatPref(prefs, PREF_SCROLLING_OVERSCROLL_DECEL_RATE, 40);
+        OVERSCROLL_DECEL_RATE = getFrameAdjustedFriction(getFloatPref(prefs, PREF_SCROLLING_OVERSCROLL_DECEL_RATE, 40));
         SNAP_LIMIT = getFloatPref(prefs, PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT, 300);
         MIN_SCROLLABLE_DISTANCE = getFloatPref(prefs, PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE, 500);
         Log.i(LOGTAG, "Prefs: " + FRICTION_SLOW + "," + FRICTION_FAST + "," + VELOCITY_THRESHOLD + ","
                 + MAX_EVENT_ACCELERATION + "," + OVERSCROLL_DECEL_RATE + "," + SNAP_LIMIT + "," + MIN_SCROLLABLE_DISTANCE);
     }
 
     static {
         // set the scrolling parameters to default values on startup
         setPrefs(null);
     }
 
-    // The number of milliseconds per frame assuming 60 fps
-    private static final float MS_PER_FRAME = 1000.0f / 60.0f;
-
     private enum FlingStates {
         STOPPED,
         PANNING,
         FLINGING,
     }
 
     private enum Overscroll {
         NONE,
@@ -177,17 +182,17 @@ abstract class Axis {
     }
 
     void updateWithTouchAt(float pos, float timeDelta) {
         float newVelocity = (mTouchPos - pos) / timeDelta * MS_PER_FRAME;
 
         // If there's a direction change, or current velocity is very low,
         // allow setting of the velocity outright. Otherwise, use the current
         // velocity and a maximum change factor to set the new velocity.
-        boolean curVelocityIsLow = Math.abs(mVelocity) < 1.0f;
+        boolean curVelocityIsLow = Math.abs(mVelocity) < 1.0f / FRAMERATE_MULTIPLIER;
         boolean directionChange = (mVelocity > 0) != (newVelocity > 0);
         if (curVelocityIsLow || (directionChange && !FloatUtils.fuzzyEquals(newVelocity, 0.0f))) {
             mVelocity = newVelocity;
         } else {
             float maxChange = Math.abs(mVelocity * timeDelta * MAX_EVENT_ACCELERATION);
             mVelocity = Math.min(mVelocity + maxChange, Math.max(mVelocity - maxChange, newVelocity));
         }
 
--- a/mobile/android/base/ui/PanZoomController.java
+++ b/mobile/android/base/ui/PanZoomController.java
@@ -41,54 +41,32 @@ public class PanZoomController
     extends GestureDetector.SimpleOnGestureListener
     implements SimpleScaleGestureDetector.SimpleScaleGestureListener, GeckoEventListener
 {
     private static final String LOGTAG = "GeckoPanZoomController";
 
     private static String MESSAGE_ZOOM_RECT = "Browser:ZoomToRect";
     private static String MESSAGE_ZOOM_PAGE = "Browser:ZoomToPageWidth";
 
-    private static final String PREF_ZOOM_ANIMATION_FRAMES = "ui.zooming.animation_frames";
-
     // Animation stops if the velocity is below this value when overscrolled or panning.
     private static final float STOPPED_THRESHOLD = 4.0f;
 
     // Animation stops is the velocity is below this threshold when flinging.
     private static final float FLING_STOPPED_THRESHOLD = 0.1f;
 
     // The distance the user has to pan before we recognize it as such (e.g. to avoid 1-pixel pans
     // between the touch-down and touch-up of a click). In units of density-independent pixels.
     public static final float PAN_THRESHOLD = 1/16f * GeckoAppShell.getDpi();
 
     // Angle from axis within which we stay axis-locked
     private static final double AXIS_LOCK_ANGLE = Math.PI / 6.0; // 30 degrees
 
     // The maximum amount we allow you to zoom into a page
     private static final float MAX_ZOOM = 4.0f;
 
-    /* 16 precomputed frames of the _ease-out_ animation from the CSS Transitions specification. */
-    private static float[] ZOOM_ANIMATION_FRAMES = new float[] {
-        0.00000f,   /* 0 */
-        0.10211f,   /* 1 */
-        0.19864f,   /* 2 */
-        0.29043f,   /* 3 */
-        0.37816f,   /* 4 */
-        0.46155f,   /* 5 */
-        0.54054f,   /* 6 */
-        0.61496f,   /* 7 */
-        0.68467f,   /* 8 */
-        0.74910f,   /* 9 */
-        0.80794f,   /* 10 */
-        0.86069f,   /* 11 */
-        0.90651f,   /* 12 */
-        0.94471f,   /* 13 */
-        0.97401f,   /* 14 */
-        0.99309f,   /* 15 */
-    };
-
     private enum PanZoomState {
         NOTHING,        /* no touch-start events received */
         FLING,          /* all touches removed, but we're still scrolling page */
         TOUCHING,       /* one touch-start event received */
         PANNING_LOCKED, /* touch-start followed by move (i.e. panning with axis lock) */
         PANNING,        /* panning without axis lock */
         PANNING_HOLD,   /* in panning, but not moving.
                          * similar to TOUCHING but after starting a pan */
@@ -130,30 +108,32 @@ public class PanZoomController
         checkMainThread();
 
         setState(PanZoomState.NOTHING);
 
         mEventDispatcher = eventDispatcher;
         registerEventListener(MESSAGE_ZOOM_RECT);
         registerEventListener(MESSAGE_ZOOM_PAGE);
 
-        PrefsHelper.getPref(PREF_ZOOM_ANIMATION_FRAMES, new PrefsHelper.PrefHandlerBase() {
-            @Override public void prefValue(String pref, String value) {
-                setZoomAnimationFrames(value);
-            }
-        });
         Axis.initPrefs();
     }
 
     public void destroy() {
         unregisterEventListener(MESSAGE_ZOOM_RECT);
         unregisterEventListener(MESSAGE_ZOOM_PAGE);
         mSubscroller.destroy();
     }
 
+    private final static float easeOut(float t) {
+        // ease-out approx.
+        // -(t-1)^2+1
+        t = t-1;
+        return -t*t+1;
+    }
+
     private void registerEventListener(String event) {
         mEventDispatcher.registerEventListener(event, this);
     }
 
     private void unregisterEventListener(String event) {
         mEventDispatcher.unregisterEventListener(event, this);
     }
 
@@ -209,33 +189,16 @@ public class PanZoomController
                     }
                 });
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
-    private void setZoomAnimationFrames(String frames) {
-        try {
-            if (frames.length() > 0) {
-                StringTokenizer st = new StringTokenizer(frames, ",");
-                float[] values = new float[st.countTokens()];
-                for (int i = 0; i < values.length; i++) {
-                    values[i] = Float.parseFloat(st.nextToken());
-                }
-                ZOOM_ANIMATION_FRAMES = values;
-            }
-        } catch (NumberFormatException e) {
-            Log.e(LOGTAG, "Error setting zoom animation frames", e);
-        } finally {
-            Log.i(LOGTAG, "Zoom animation frames: " + Arrays.toString(ZOOM_ANIMATION_FRAMES));
-        }
-    }
-
     public boolean onTouchEvent(MotionEvent event) {
         switch (event.getAction() & MotionEvent.ACTION_MASK) {
         case MotionEvent.ACTION_DOWN:   return onTouchStart(event);
         case MotionEvent.ACTION_MOVE:   return onTouchMove(event);
         case MotionEvent.ACTION_UP:     return onTouchEnd(event);
         case MotionEvent.ACTION_CANCEL: return onTouchCancel(event);
         default:                        return false;
         }
@@ -574,17 +537,17 @@ public class PanZoomController
             stopAnimationTimer();
         }
 
         mAnimationTimer = new Timer("Animation Timer");
         mAnimationRunnable = runnable;
         mAnimationTimer.scheduleAtFixedRate(new TimerTask() {
             @Override
             public void run() { mTarget.post(runnable); }
-        }, 0, 1000L/60L);
+        }, 0, (int)Axis.MS_PER_FRAME);
     }
 
     /* Stops the fling or bounce animation. */
     private void stopAnimationTimer() {
         if (mAnimationTimer != null) {
             mAnimationTimer.cancel();
             mAnimationTimer = null;
         }
@@ -674,31 +637,31 @@ public class PanZoomController
              * out.
              */
             if (!(mState == PanZoomState.BOUNCE || mState == PanZoomState.ANIMATED_ZOOM)) {
                 finishAnimation();
                 return;
             }
 
             /* Perform the next frame of the bounce-back animation. */
-            if (mBounceFrame < ZOOM_ANIMATION_FRAMES.length) {
+            if (mBounceFrame < (int)(256f/Axis.MS_PER_FRAME)) {
                 advanceBounce();
                 return;
             }
 
             /* Finally, if there's nothing else to do, complete the animation and go to sleep. */
             finishBounce();
             finishAnimation();
             setState(PanZoomState.NOTHING);
         }
 
         /* Performs one frame of a bounce animation. */
         private void advanceBounce() {
             synchronized (mTarget.getLock()) {
-                float t = ZOOM_ANIMATION_FRAMES[mBounceFrame];
+                float t = easeOut(mBounceFrame * Axis.MS_PER_FRAME / 256f);
                 ViewportMetrics newMetrics = mBounceStartMetrics.interpolate(mBounceEndMetrics, t);
                 mTarget.setViewportMetrics(newMetrics);
                 mBounceFrame++;
             }
         }
 
         /* Concludes a bounce animation and snaps the viewport into place. */
         private void finishBounce() {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -817,20 +817,21 @@ var BrowserApp = {
     let webBrowserPrint = aBrowser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                                                 .getInterface(Ci.nsIWebBrowserPrint);
 
     let cancelable = {
       cancel: function (aReason) {
         webBrowserPrint.cancel();
       }
     }
+    let isPrivate = aBrowser.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing;
     let download = dm.addDownload(Ci.nsIDownloadManager.DOWNLOAD_TYPE_DOWNLOAD,
                                   aBrowser.currentURI,
                                   Services.io.newFileURI(file), "", mimeInfo,
-                                  Date.now() * 1000, null, cancelable);
+                                  Date.now() * 1000, null, cancelable, isPrivate);
 
     webBrowserPrint.print(printSettings, download);
   },
 
   getPreferences: function getPreferences(aPrefNames) {
     try {
       let json = JSON.parse(aPrefNames);
       let prefs = [];
@@ -3543,16 +3544,17 @@ var BrowserEventHandler = {
     BrowserApp.deck.addEventListener("touchstart", this, true);
     BrowserApp.deck.addEventListener("click", InputWidgetHelper, true);
     BrowserApp.deck.addEventListener("click", SelectHelper, true);
     document.addEventListener("MozMagnifyGestureStart", this, true);
     document.addEventListener("MozMagnifyGestureUpdate", this, true);
     document.addEventListener("MozMagnifyGesture", this, true);
 
     Services.prefs.addObserver("browser.zoom.reflowOnZoom", this, false);
+    this.updateReflozPref();
   },
 
   updateReflozPref: function() {
      this.mReflozPref = Services.prefs.getBoolPref("browser.zoom.reflowOnZoom");
   },
 
   handleEvent: function(aEvent) {
     if (aEvent.type && (aEvent.type === "MozMagnifyGesture" ||
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -265,16 +265,18 @@
 @BINPATH@/components/nsPrivateBrowsingService.js
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsSearchService.js
 @BINPATH@/components/nsSearchSuggestions.js
 @BINPATH@/components/passwordmgr.manifest
 @BINPATH@/components/nsLoginInfo.js
 @BINPATH@/components/nsLoginManager.js
 @BINPATH@/components/nsLoginManagerPrompter.js
+@BINPATH@/components/SiteSpecificUserAgent.js
+@BINPATH@/components/SiteSpecificUserAgent.manifest
 @BINPATH@/components/storage-Legacy.js
 @BINPATH@/components/storage-mozStorage.js
 @BINPATH@/components/crypto-SDR.js
 @BINPATH@/components/jsconsole-clhandler.manifest
 @BINPATH@/components/jsconsole-clhandler.js
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
rename from mobile/android/sync/README.txt
rename to mobile/android/services/README.txt
rename from mobile/android/sync/android-drawable-hdpi-resources.mn
rename to mobile/android/services/android-drawable-hdpi-resources.mn
rename from mobile/android/sync/android-drawable-ldpi-resources.mn
rename to mobile/android/services/android-drawable-ldpi-resources.mn
rename from mobile/android/sync/android-drawable-mdpi-resources.mn
rename to mobile/android/services/android-drawable-mdpi-resources.mn
rename from mobile/android/sync/android-drawable-resources.mn
rename to mobile/android/services/android-drawable-resources.mn
rename from mobile/android/sync/android-layout-resources.mn
rename to mobile/android/services/android-layout-resources.mn
rename from mobile/android/sync/android-values-resources.mn
rename to mobile/android/services/android-values-resources.mn
rename from mobile/android/sync/java-sources.mn
rename to mobile/android/services/java-sources.mn
rename from mobile/android/sync/java-third-party-sources.mn
rename to mobile/android/services/java-third-party-sources.mn
new file mode 100644
new file mode 100644
new file mode 100644
rename from mobile/android/sync/manifests/SyncAndroidManifest_activities.xml.in
rename to mobile/android/services/manifests/SyncAndroidManifest_activities.xml.in
rename from mobile/android/sync/manifests/SyncAndroidManifest_permissions.xml.in
rename to mobile/android/services/manifests/SyncAndroidManifest_permissions.xml.in
rename from mobile/android/sync/manifests/SyncAndroidManifest_services.xml.in
rename to mobile/android/services/manifests/SyncAndroidManifest_services.xml.in
rename from mobile/android/sync/preprocess-sources.mn
rename to mobile/android/services/preprocess-sources.mn
rename from mobile/android/sync/strings.xml.in
rename to mobile/android/services/strings.xml.in
--- a/mobile/xul/confvars.sh
+++ b/mobile/xul/confvars.sh
@@ -7,16 +7,19 @@ MOZ_APP_VENDOR=Mozilla
 
 MOZ_APP_VERSION=19.0a1
 
 MOZ_BRANDING_DIRECTORY=mobile/xul/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/xul/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
+
+MOZ_SERVICES_COMMON=1
+MOZ_SERVICES_CRYPTO=1
 MOZ_SERVICES_SYNC=1
 
 MOZ_DISABLE_DOMCRYPTO=1
 
 if test "$LIBXUL_SDK"; then
 MOZ_XULRUNNER=1
 else
 MOZ_XULRUNNER=
--- a/mobile/xul/installer/package-manifest.in
+++ b/mobile/xul/installer/package-manifest.in
@@ -324,16 +324,18 @@
 @BINPATH@/components/nsPrivateBrowsingService.js
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsSearchService.js
 @BINPATH@/components/nsSearchSuggestions.js
 @BINPATH@/components/passwordmgr.manifest
 @BINPATH@/components/nsLoginInfo.js
 @BINPATH@/components/nsLoginManager.js
 @BINPATH@/components/nsLoginManagerPrompter.js
+@BINPATH@/components/SiteSpecificUserAgent.js
+@BINPATH@/components/SiteSpecificUserAgent.manifest
 @BINPATH@/components/storage-Legacy.js
 @BINPATH@/components/storage-mozStorage.js
 @BINPATH@/components/crypto-SDR.js
 @BINPATH@/components/jsconsole-clhandler.manifest
 @BINPATH@/components/jsconsole-clhandler.js
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
--- a/modules/libjar/nsJAR.h
+++ b/modules/libjar/nsJAR.h
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #ifndef nsJAR_h__
 #define nsJAR_h__
 
 #include "nscore.h"
 #include "pratom.h"
-#include "prmem.h"
 #include "prio.h"
 #include "plstr.h"
 #include "prlog.h"
 #include "prtypes.h"
 #include "prinrval.h"
 
 #include "mozilla/Mutex.h"
 #include "nsIComponentManager.h"
--- a/modules/libjar/nsJARFactory.cpp
+++ b/modules/libjar/nsJARFactory.cpp
@@ -1,21 +1,16 @@
 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <string.h>
 
 #include "nscore.h"
-#include "pratom.h"
-#include "prmem.h"
-#include "prio.h"
-#include "plstr.h"
-#include "prlog.h"
 
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsCOMPtr.h"
 #include "mozilla/ModuleUtils.h"
 #include "nsIJARFactory.h"
 #include "nsJARProtocolHandler.h"
 #include "nsJARURI.h"
--- a/modules/libpref/src/nsPrefBranch.cpp
+++ b/modules/libpref/src/nsPrefBranch.cpp
@@ -12,20 +12,18 @@
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIDirectoryService.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsXPIDLString.h"
 #include "nsIStringBundle.h"
 #include "prefapi.h"
-#include "prmem.h"
 #include "pldhash.h"
 
-#include "plstr.h"
 #include "nsCRT.h"
 #include "mozilla/Services.h"
 
 #include "prefapi_private_data.h"
 
 // Definitions
 struct EnumerateData {
   const char  *parent;
--- a/modules/libpref/src/prefapi.cpp
+++ b/modules/libpref/src/prefapi.cpp
@@ -20,17 +20,16 @@
 #ifdef _WIN32
   #include "windows.h"
 #endif /* _WIN32 */
 
 #include "plstr.h"
 #include "pldhash.h"
 #include "plbase64.h"
 #include "prlog.h"
-#include "prmem.h"
 #include "prprf.h"
 #include "mozilla/dom/PContent.h"
 #include "nsQuickSort.h"
 #include "nsString.h"
 #include "nsPrintfCString.h"
 #include "prlink.h"
 
 #ifdef XP_OS2
--- a/netwerk/base/src/nsPreloadedStream.cpp
+++ b/netwerk/base/src/nsPreloadedStream.cpp
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsPreloadedStream.h"
 #include "nsIRunnable.h"
 
 #include "nsThreadUtils.h"
 #include "nsAlgorithm.h"
-#include "prmem.h"
    
 namespace mozilla {
 namespace net {
 
 NS_IMPL_THREADSAFE_ISUPPORTS2(nsPreloadedStream,
                               nsIInputStream,
                               nsIAsyncInputStream)
 
--- a/netwerk/base/src/nsProtocolProxyService.h
+++ b/netwerk/base/src/nsProtocolProxyService.h
@@ -15,17 +15,16 @@
 #include "nsIProtocolProxyFilter.h"
 #include "nsISystemProxySettings.h"
 #include "nsIProxyInfo.h"
 #include "nsIObserver.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsPACMan.h"
 #include "prtime.h"
-#include "prmem.h"
 #include "prio.h"
 #include "mozilla/Attributes.h"
 
 typedef nsDataHashtable<nsCStringHashKey, uint32_t> nsFailedProxyTable;
 
 class nsProxyInfo;
 struct nsProtocolInfo;
 
--- a/netwerk/base/src/nsSimpleURI.cpp
+++ b/netwerk/base/src/nsSimpleURI.cpp
@@ -5,17 +5,16 @@
 
 #include "IPCMessageUtils.h"
 
 #include "nsSimpleURI.h"
 #include "nscore.h"
 #include "nsCRT.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
-#include "prmem.h"
 #include "prprf.h"
 #include "nsURLHelper.h"
 #include "nsNetCID.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsEscape.h"
 #include "nsError.h"
 #include "nsIProgrammingLanguage.h"
--- a/netwerk/protocol/http/UserAgentOverrides.jsm
+++ b/netwerk/protocol/http/UserAgentOverrides.jsm
@@ -14,17 +14,19 @@ Components.utils.import("resource://gre/
 const PREF_OVERRIDES_ENABLED = "general.useragent.site_specific_overrides";
 const DEFAULT_UA = Cc["@mozilla.org/network/protocol;1?name=http"]
                      .getService(Ci.nsIHttpProtocolHandler)
                      .userAgent;
 
 var gPrefBranch;
 var gOverrides;
 var gInitialized = false;
-var gComplexOverrides = [];
+var gOverrideFunctions = [
+  function (aHttpChannel) UserAgentOverrides.getOverrideForURI(aHttpChannel.URI)
+];
 
 var UserAgentOverrides = {
   init: function uao_init() {
     if (gInitialized)
       return;
     gInitialized = true;
 
     gPrefBranch = Services.prefs.getBranch("general.useragent.override.");
@@ -33,17 +35,32 @@ var UserAgentOverrides = {
     Services.prefs.addObserver(PREF_OVERRIDES_ENABLED, buildOverrides, false);
 
     Services.obs.addObserver(HTTP_on_modify_request, "http-on-modify-request", false);
 
     buildOverrides();
   },
 
   addComplexOverride: function uao_addComplexOverride(callback) {
-    gComplexOverrides.push(callback);
+    gOverrideFunctions.push(callback);
+  },
+
+  getOverrideForURI: function uao_getOverrideForURI(aURI) {
+    if (!gInitialized)
+      return null;
+
+    let host = aURI.asciiHost;
+    for (let domain in gOverrides) {
+      if (host == domain ||
+          host.endsWith("." + domain)) {
+        return gOverrides[domain];
+      }
+    }
+
+    return null;
   },
 
   uninit: function uao_uninit() {
     if (!gInitialized)
       return;
     gInitialized = false;
 
     gPrefBranch.removeObserver("", buildOverrides);
@@ -71,26 +88,17 @@ function buildOverrides() {
     } else {
       gOverrides[domain] = override;
     }
   }
 }
 
 function HTTP_on_modify_request(aSubject, aTopic, aData) {
   let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
-  let host = channel.URI.asciiHost;
 
-  for (let domain in gOverrides) {
-    if (host == domain ||
-        host.endsWith("." + domain)) {
-      channel.setRequestHeader("User-Agent", gOverrides[domain], false);
-      return;
-    }
-  }
-
-  for (let callback of gComplexOverrides) {
+  for (let callback of gOverrideFunctions) {
     let modifiedUA = callback(channel, DEFAULT_UA);
     if (modifiedUA) {
       channel.setRequestHeader("User-Agent", modifiedUA, false);
       return;
     }
   }
 }
--- a/netwerk/protocol/http/nsHttpBasicAuth.cpp
+++ b/netwerk/protocol/http/nsHttpBasicAuth.cpp
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdlib.h>
 #include "nsHttp.h"
 #include "nsHttpBasicAuth.h"
 #include "plbase64.h"
 #include "plstr.h"
-#include "prmem.h"
 #include "nsString.h"
 
 //-----------------------------------------------------------------------------
 // nsHttpBasicAuth <public>
 //-----------------------------------------------------------------------------
 
 nsHttpBasicAuth::nsHttpBasicAuth()
 {
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -13,17 +13,16 @@
 #include "nsISocketTransportService.h"
 #include "nsISocketTransport.h"
 #include "nsIServiceManager.h"
 #include "nsISSLSocketControl.h"
 #include "nsStringStream.h"
 #include "netCore.h"
 #include "nsNetCID.h"
 #include "nsProxyRelease.h"
-#include "prmem.h"
 #include "nsPreloadedStream.h"
 #include "ASpdySession.h"
 #include "mozilla/Telemetry.h"
 #include "nsISupportsPriority.h"
 #include "nsHttpPipeline.h"
 
 #ifdef DEBUG
 // defined by the socket transport service while active
--- a/netwerk/protocol/http/nsHttpDigestAuth.cpp
+++ b/netwerk/protocol/http/nsHttpDigestAuth.cpp
@@ -14,17 +14,16 @@
 #include "nsIURI.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsEscape.h"
 #include "nsNetCID.h"
 #include "plbase64.h"
 #include "plstr.h"
 #include "prprf.h"
-#include "prmem.h"
 #include "nsCRT.h"
 
 //-----------------------------------------------------------------------------
 // nsHttpDigestAuth <public>
 //-----------------------------------------------------------------------------
 
 nsHttpDigestAuth::nsHttpDigestAuth()
 {}
--- a/netwerk/protocol/res/nsResProtocolHandler.cpp
+++ b/netwerk/protocol/res/nsResProtocolHandler.cpp
@@ -5,17 +5,16 @@
 
 #include "mozilla/chrome/RegistryMessageUtils.h"
 
 #include "nsResProtocolHandler.h"
 #include "nsIURL.h"
 #include "nsIIOService.h"
 #include "nsIServiceManager.h"
 #include "prenv.h"
-#include "prmem.h"
 #include "prprf.h"
 #include "nsXPIDLString.h"
 #include "nsIFile.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsNetUtil.h"
 #include "nsURLHelper.h"
 #include "nsEscape.h"
 
--- a/netwerk/system/win32/nsNotifyAddrListener.cpp
+++ b/netwerk/system/win32/nsNotifyAddrListener.cpp
@@ -8,17 +8,16 @@
 #include <windef.h>
 #include <winbase.h>
 #include <wingdi.h>
 #include <winuser.h>
 #include <ole2.h>
 #include <netcon.h>
 #include <objbase.h>
 #include <iprtrmib.h>
-#include "prmem.h"
 #include "plstr.h"
 #include "nsThreadUtils.h"
 #include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsNotifyAddrListener.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "mozilla/Services.h"
--- a/parser/htmlparser/src/CNavDTD.cpp
+++ b/parser/htmlparser/src/CNavDTD.cpp
@@ -22,17 +22,16 @@
 #include "nsHTMLTokenizer.h"
 #include "nsParserNode.h"
 #include "nsHTMLEntities.h"
 #include "nsLinebreakConverter.h"
 #include "nsIFormProcessor.h"
 #include "nsTArray.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
-#include "prmem.h"
 #include "nsIServiceManager.h"
 #include "nsParserConstants.h"
 
 using namespace mozilla;
 
 /*
  * Ignore kFontStyle and kPhrase tags when the stack is deep, bug 58917.
  */
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG
 #endif
 
 #include "nspr.h"
 #include "prlog.h"
-#include "prmem.h"
 
 #include "nsISecureBrowserUI.h"
 #include "nsSecureBrowserUIImpl.h"
 #include "nsCOMPtr.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIServiceManager.h"
 #include "nsIObserverService.h"
--- a/security/manager/ssl/src/nsCRLInfo.cpp
+++ b/security/manager/ssl/src/nsCRLInfo.cpp
@@ -1,13 +1,12 @@
 /* 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 "prmem.h"
 #include "prerror.h"
 #include "prprf.h"
 
 #include "nsCRLInfo.h"
 #include "nsIDateTimeFormat.h"
 #include "nsDateTimeFormatCID.h"
 #include "nsCOMPtr.h"
 #include "nsComponentManagerUtils.h"
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -13,17 +13,16 @@
 #include "nsPK11TokenDB.h"
 #include "nsThreadUtils.h"
 #include "nsIServiceManager.h"
 #include "nsIMemory.h"
 #include "nsAutoPtr.h"
 #include "nsAlgorithm.h"
 #include "nsCRT.h"
 #include "prprf.h"
-#include "prmem.h"
 #include "nsDOMCID.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMClassInfo.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptGlobalObject.h"
--- a/security/manager/ssl/src/nsNSSCertHelper.cpp
+++ b/security/manager/ssl/src/nsNSSCertHelper.cpp
@@ -1,13 +1,12 @@
 /* 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 "prmem.h"
 #include "prerror.h"
 #include "prprf.h"
 
 #include "nsNSSCertHelper.h"
 #include "nsCOMPtr.h"
 #include "nsNSSCertificate.h"
 #include "cert.h"
 #include "keyhi.h"
--- a/services/Makefile.in
+++ b/services/Makefile.in
@@ -5,17 +5,23 @@
 
 DEPTH     = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-PARALLEL_DIRS += common crypto
+ifdef MOZ_SERVICES_COMMON
+PARALLEL_DIRS += common
+endif
+
+ifdef MOZ_SERVICES_CRYPTO
+PARALLEL_DIRS += crypto
+endif
 
 ifdef MOZ_SERVICES_AITC
 PARALLEL_DIRS += aitc
 endif
 
 ifdef MOZ_SERVICES_NOTIFICATIONS
 PARALLEL_DIRS += notifications
 endif
--- a/services/makefiles.sh
+++ b/services/makefiles.sh
@@ -1,9 +1,8 @@
-#
 # 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/.
 
 add_makefiles "
   services/Makefile
   services/aitc/Makefile
   services/common/Makefile
--- a/startupcache/StartupCache.cpp
+++ b/startupcache/StartupCache.cpp
@@ -409,17 +409,17 @@ CacheCloseHelper(const nsACString& key, 
  * to make sure there isn't a write happening on another thread
  */
 void
 StartupCache::WriteToDisk() 
 {
   nsresult rv;
   mStartupWriteInitiated = true;
 
-  if (mTable.Count() == 0)
+  if (!mTable.IsInitialized() || mTable.Count() == 0)
     return;
 
   nsCOMPtr<nsIZipWriter> zipW = do_CreateInstance("@mozilla.org/zipwriter;1");
   if (!zipW)
     return;
 
   rv = zipW->Open(mFile, PR_RDWR | PR_CREATE_FILE);
   if (NS_FAILED(rv)) {
--- a/startupcache/StartupCacheModule.cpp
+++ b/startupcache/StartupCacheModule.cpp
@@ -1,21 +1,16 @@
 /* -*-  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 <string.h>
 
 #include "nscore.h"
-#include "pratom.h"
-#include "prmem.h"
-#include "prio.h"
-#include "plstr.h"
-#include "prlog.h"
 
 #include "nsID.h"
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsCOMPtr.h"
 #include "nsIModule.h"
 #include "mozilla/ModuleUtils.h"
 #include "mozilla/scache/StartupCache.h"
--- a/testing/marionette/client/marionette/tests/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit-tests.ini
@@ -11,11 +11,12 @@ b2g = true
 ; true if the test should be skipped
 skip = false
 
 ; webapi tests
 [include:../../../../../dom/telephony/test/marionette/manifest.ini]
 [include:../../../../../dom/battery/test/marionette/manifest.ini]
 [include:../../../../../dom/sms/tests/marionette/manifest.ini]
 [include:../../../../../dom/network/tests/marionette/manifest.ini]
+[include:../../../../../dom/system/gonk/tests/marionette/manifest.ini]
 
 ; marionette unit tests
 [include:unit/unit-tests.ini]
--- a/toolkit/components/console/content/consoleBindings.xml
+++ b/toolkit/components/console/content/consoleBindings.xml
@@ -408,22 +408,20 @@
 
   <binding id="error" extends="xul:box">
     <content>
       <xul:box class="console-row-internal-box" flex="1">
         <xul:box class="console-row-icon" align="center" xbl:inherits="selected">
           <xul:image class="console-icon" xbl:inherits="src,type"/>
         </xul:box>
         <xul:vbox class="console-row-content" xbl:inherits="selected" flex="1">
-          <xul:box class="console-row-time">
-            <xul:label class="label" xbl:inherits="value=time"/>
-          </xul:box>
           <xul:box class="console-row-msg" align="start">
             <xul:label class="label" xbl:inherits="value=typetext"/>
             <xul:description class="console-error-msg" xbl:inherits="xbl:text=msg" flex="1"/>
+            <xul:label class="label console-time" xbl:inherits="value=time"/>
           </xul:box>
           <xul:box class="console-row-file" xbl:inherits="hidden=hideSource">
             <xul:label class="label" value="&errFile.label;"/>
             <xul:box class="console-error-source" xbl:inherits="href,line"/>
             <xul:spacer flex="1"/>
             <xul:hbox class="lineNumberRow" xbl:inherits="line">
               <xul:label class="label" value="&errLine.label;"/>
               <xul:label class="label" xbl:inherits="value=line"/>
--- a/toolkit/components/filepicker/nsFileView.cpp
+++ b/toolkit/components/filepicker/nsFileView.cpp
@@ -8,17 +8,16 @@
 #include "mozilla/ModuleUtils.h"
 #include "nsITreeSelection.h"
 #include "nsITreeColumns.h"
 #include "nsITreeBoxObject.h"
 #include "nsIFile.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
-#include "prmem.h"
 #include "nsPrintfCString.h"
 #include "nsIDateTimeFormat.h"
 #include "nsDateTimeFormatCID.h"
 #include "nsQuickSort.h"
 #include "nsIAtom.h"
 #include "nsIAutoCompleteResult.h"
 #include "nsIAutoCompleteSearch.h"
 #include "nsISimpleEnumerator.h"
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1922,16 +1922,22 @@
     "description": "Firefox: Time taken by the tab closing animation in milliseconds"
   },
   "FX_TAB_SWITCH_UPDATE_MS": {
     "kind": "exponential",
     "high": "1000",
     "n_buckets": 20,
     "description": "Firefox: Time in ms spent updating UI in response to a tab switch"
   },
+  "FX_TAB_SWITCH_TOTAL_MS": {
+    "kind": "exponential",
+    "high": "1000",
+    "n_buckets": 20,
+    "description": "Firefox: Time in ms till a tab switch is complete including the first paint"
+  },
   "FX_KEYWORD_URL_USERSET": {
     "kind": "boolean",
     "description": "Firefox: keyword.URL has a user-set value"
   },
   "FX_IDENTITY_POPUP_OPEN_MS": {
     "kind": "exponential",
     "high": "1000",
     "n_buckets": 10,
--- a/toolkit/components/typeaheadfind/nsITypeAheadFind.idl
+++ b/toolkit/components/typeaheadfind/nsITypeAheadFind.idl
@@ -71,16 +71,18 @@ interface nsITypeAheadFind : nsISupports
 
   /* Find return codes */
   const unsigned short FIND_FOUND    = 0;
                                         // Successful find
   const unsigned short FIND_NOTFOUND = 1;
                                         // Unsuccessful find
   const unsigned short FIND_WRAPPED  = 2;
                                         // Successful find, but wrapped around
+  const unsigned short FIND_PENDING  = 3;
+                                        // Unknown status, find has not finished
 
 
   /*************************************************************************/
 
 };
 
 
 /*****************************************************************************/
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -383,20 +383,18 @@ nsTypeAheadFind::FindItNow(nsIPresShell 
       bool usesIndependentSelection;
       if (!IsRangeVisible(presShell, presContext, returnRange,
                           aIsFirstVisiblePreferred, false,
                           getter_AddRefs(mStartPointRange), 
                           &usesIndependentSelection) ||
           (aIsLinksOnly && !isInsideLink) ||
           (mStartLinksOnlyPref && aIsLinksOnly && !isStartingLink)) {
         // ------ Failure ------
-        // Start find again from here
-        returnRange->CloneRange(getter_AddRefs(mStartPointRange));
-
-        // Collapse to end
+        // mStartPointRange got updated to the right thing already,
+        // but we stil need to collapse it to the right end.
         mStartPointRange->Collapse(aFindPrev);
 
         continue;
       }
 
       // ------ Success! -------
       // Hide old selection (new one may be on a different controller)
       if (selection) {
@@ -1133,17 +1131,16 @@ nsTypeAheadFind::IsRangeVisible(nsIPresS
 
   if (frame) {
     nsCOMP