Merge mozilla-central to fx-team
authorPhil Ringnalda <philringnalda@gmail.com>
Fri, 19 Oct 2012 22:13:58 -0700
changeset 111015 0c34dd4742b6a0581009894955fb739693e6474e
parent 111014 f36f62550c6e2511a03c539b528cdc56ca02383f (current diff)
parent 110960 ff4af83233dc62a9423bfb0a3042a3c7f3eadd79 (diff)
child 111016 4957ebb0625a1f1390928b06f37bd90f9aace47d
child 111473 faa86d5b7b5660857b3f12c55e490ca4a8550c7c
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone19.0a1
Merge mozilla-central to fx-team
browser/base/content/browser-menubar.inc
browser/base/content/browser.js
browser/devtools/scratchpad/scratchpad.js
browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
intl/uconv/tests/unit/test_decode_x_mac_roman.js
intl/uconv/tests/unit/test_encode_x_mac_roman.js
layout/base/nsFrameIterator.cpp
layout/base/nsFrameIterator.h
mobile/android/base/sync/log/writers/SingleTagLogWriter.java
security/manager/tools/getHSTSPreloadList.py
security/patches/bug-797572
toolkit/components/osfile/osfileutils.cpp
toolkit/components/osfile/osfileutils.h
xpcom/base/dmd.h
--- a/Makefile.in
+++ b/Makefile.in
@@ -43,18 +43,20 @@ ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 tier_base_dirs += \
   other-licenses/android \
   $(NULL)
 endif
 
 ifdef MOZ_MEMORY
 tier_base_dirs += memory/mozjemalloc
 ifdef MOZ_JEMALLOC
+ifndef MOZ_NATIVE_JEMALLOC
 tier_base_dirs += memory/jemalloc
 endif
+endif
 tier_base_dirs += memory/build
 endif
 ifndef MOZ_NATIVE_ZLIB
 tier_base_dirs += modules/zlib
 endif
 tier_base_dirs += \
   mozglue \
   memory/mozalloc \
@@ -75,17 +77,17 @@ DIST_GARBAGE = config.cache config.log c
    netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
    $(topsrcdir)/.mozconfig.mk $(topsrcdir)/.mozconfig.out
 
 default alldep all:: $(topsrcdir)/configure config.status
 	$(RM) -r $(DIST)/sdk
 	$(RM) -r $(DIST)/include
 	$(RM) -r $(DIST)/private
 	$(RM) -r $(DIST)/public
-	$(RM) $(DIST)/chrome.manifest
+	$(RM) $(DIST)/bin/chrome.manifest $(DIST)/bin/components/components.manifest
 	$(RM) -r _tests
 
 $(topsrcdir)/configure: $(topsrcdir)/configure.in
 	@echo "STOP!  configure.in has changed, and your configure is out of date."
 	@echo "Please rerun autoconf and re-configure your build directory."
 	@echo "To ignore this message, touch 'configure' in the source directory,"
 	@echo "but your build might not succeed."
 	@exit 1
--- a/accessible/src/atk/AccessibleWrap.cpp
+++ b/accessible/src/atk/AccessibleWrap.cpp
@@ -737,32 +737,30 @@ ConvertToAtkAttributeSet(nsIPersistentPr
 
     //libspi will free it
     return objAttributeSet;
 }
 
 AtkAttributeSet*
 GetAttributeSet(Accessible* aAccessible)
 {
-    nsCOMPtr<nsIPersistentProperties> attributes;
-    aAccessible->GetAttributes(getter_AddRefs(attributes));
-
-    if (attributes) {
-        // Deal with attributes that we only need to expose in ATK
-        if (aAccessible->State() & states::HASPOPUP) {
-          // There is no ATK state for haspopup, must use object attribute to expose the same info
-          nsAutoString oldValueUnused;
-          attributes->SetStringProperty(NS_LITERAL_CSTRING("haspopup"), NS_LITERAL_STRING("true"),
-                                        oldValueUnused);
-        }
-
-        return ConvertToAtkAttributeSet(attributes);
+  nsCOMPtr<nsIPersistentProperties> attributes = aAccessible->Attributes();
+  if (attributes) {
+    // There is no ATK state for haspopup, must use object attribute to expose
+    // the same info.
+    if (aAccessible->State() & states::HASPOPUP) {
+      nsAutoString unused;
+      attributes->SetStringProperty(NS_LITERAL_CSTRING("haspopup"),
+                                    NS_LITERAL_STRING("true"), unused);
     }
 
-    return nullptr;
+    return ConvertToAtkAttributeSet(attributes);
+  }
+
+  return nullptr;
 }
 
 AtkAttributeSet *
 getAttributesCB(AtkObject *aAtkObj)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   return accWrap ? GetAttributeSet(accWrap) : nullptr;
 }
--- a/accessible/src/base/AccEvent.h
+++ b/accessible/src/base/AccEvent.h
@@ -57,17 +57,17 @@ public:
      // eDoNotEmit : This event is confirmed as a duplicate, do not emit it.
      eDoNotEmit
   };
 
   // Initialize with an nsIAccessible
   AccEvent(uint32_t aEventType, Accessible* aAccessible,
            EIsFromUserInput aIsFromUserInput = eAutoDetect,
            EEventRule aEventRule = eRemoveDupes);
-  // Initialize with an nsIDOMNode
+  // Initialize with an nsINode
   AccEvent(uint32_t aEventType, nsINode* aNode,
            EIsFromUserInput aIsFromUserInput = eAutoDetect,
            EEventRule aEventRule = eRemoveDupes);
   virtual ~AccEvent() {}
 
   // AccEvent
   uint32_t GetEventType() const { return mEventType; }
   EEventRule GetEventRule() const { return mEventRule; }
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/AccTypes.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#pragma once
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * Accessible object types used when creating an accessible based on the frame.
+ */
+enum AccType {
+  eNoAccessible,
+  eHTMLBRAccessible,
+  eHTMLButtonAccessible,
+  eHTMLCanvasAccessible,
+  eHTMLCaptionAccessible,
+  eHTMLCheckboxAccessible,
+  eHTMLComboboxAccessible,
+  eHTMLFileInputAccessible,
+  eHTMLGroupboxAccessible,
+  eHTMLHRAccessible,
+  eHTMLImageMapAccessible,
+  eHTMLLabelAccessible,
+  eHTMLLiAccessible,
+  eHTMLSelectListAccessible,
+  eHTMLMediaAccessible,
+  eHTMLObjectFrameAccessible,
+  eHTMLRadioButtonAccessible,
+  eHTMLTableAccessible,
+  eHTMLTableCellAccessible,
+  eHTMLTableRowAccessible,
+  eHTMLTextFieldAccessible,
+  eHyperTextAccessible,
+  eImageAccessible,
+  eOuterDocAccessible,
+  eTextLeafAccessible
+};
+}
+}
+
--- a/accessible/src/base/Logging.cpp
+++ b/accessible/src/base/Logging.cpp
@@ -679,17 +679,17 @@ logging::Node(const char* aDescr, nsINod
     return;
   }
 
   if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) {
     printf("%s: %p, document\n", aDescr, static_cast<void*>(aNode));
     return;
   }
 
-  nsINode* parentNode = aNode->GetNodeParent();
+  nsINode* parentNode = aNode->GetParentNode();
   int32_t idxInParent = parentNode ? parentNode->IndexOf(aNode) : - 1;
 
   if (aNode->IsNodeOfType(nsINode::eTEXT)) {
     printf("%s: %p, text node, idx in parent: %d\n",
            aDescr, static_cast<void*>(aNode), idxInParent);
     return;
   }
 
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -53,16 +53,17 @@ EXPORTS = \
   nsAccessibilityService.h \
   nsAccessNode.h \
   $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/a11y
 
 EXPORTS_mozilla/a11y = \
   FocusManager.h \
+  AccTypes.h \
   States.h \
   Role.h \
   $(NULL)
 
 ifdef MOZ_DEBUG
 EXPORTS_mozilla/a11y += \
   Logging.h \
   $(NULL)
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -419,18 +419,18 @@ NotificationController::CoalesceEvents()
         }
 
         // Ignore events unattached from DOM since we don't coalesce them.
         if (!thisEvent->mNode->IsInDoc())
           continue;
 
         // Coalesce events by sibling targets (this is a case for reorder
         // events).
-        if (thisEvent->mNode->GetNodeParent() ==
-            tailEvent->mNode->GetNodeParent()) {
+        if (thisEvent->mNode->GetParentNode() ==
+            tailEvent->mNode->GetParentNode()) {
           tailEvent->mEventRule = thisEvent->mEventRule;
           return;
         }
 
         // This and tail events can be anywhere in the tree, make assumptions
         // for mutation events.
 
         // Coalesce tail event if tail node is descendant of this node. Stop
@@ -516,17 +516,17 @@ void
 NotificationController::ApplyToSiblings(uint32_t aStart, uint32_t aEnd,
                                         uint32_t aEventType, nsINode* aNode,
                                         AccEvent::EEventRule aEventRule)
 {
   for (uint32_t index = aStart; index < aEnd; index ++) {
     AccEvent* accEvent = mEvents[index];
     if (accEvent->mEventType == aEventType &&
         accEvent->mEventRule != AccEvent::eDoNotEmit && accEvent->mNode &&
-        accEvent->mNode->GetNodeParent() == aNode->GetNodeParent()) {
+        accEvent->mNode->GetParentNode() == aNode->GetParentNode()) {
       accEvent->mEventRule = aEventRule;
     }
   }
 }
 
 void
 NotificationController::CoalesceSelChangeEvents(AccSelChangeEvent* aTailEvent,
                                                 AccSelChangeEvent* aThisEvent,
@@ -700,17 +700,17 @@ NotificationController::TextEnumerator(n
                                        void* aUserArg)
 {
   DocAccessible* document = static_cast<DocAccessible*>(aUserArg);
   nsIContent* textNode = aEntry->GetKey();
   Accessible* textAcc = document->GetAccessible(textNode);
 
   // If the text node is not in tree or doesn't have frame then this case should
   // have been handled already by content removal notifications.
-  nsINode* containerNode = textNode->GetNodeParent();
+  nsINode* containerNode = textNode->GetParentNode();
   if (!containerNode) {
     NS_ASSERTION(!textAcc,
                  "Text node was removed but accessible is kept alive!");
     return PL_DHASH_NEXT;
   }
 
   nsIFrame* textFrame = textNode->GetPrimaryFrame();
   if (!textFrame) {
--- a/accessible/src/base/nsARIAMap.h
+++ b/accessible/src/base/nsARIAMap.h
@@ -87,25 +87,25 @@ const bool kUseMapRole = true;
 const bool kUseNativeRole = false;
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // ARIA attribute characteristic masks
 
 /**
  * This mask indicates the attribute should not be exposed as an object
- * attribute via the catch-all logic in Accessible::GetAttributes.
+ * attribute via the catch-all logic in Accessible::Attributes().
  * This means it either isn't mean't to be exposed as an object attribute, or
  * that it should, but is already handled in other code.
  */
 const uint8_t ATTR_BYPASSOBJ  = 0x0001;
 
 /**
  * This mask indicates the attribute is expected to have an NMTOKEN or bool value.
- * (See for example usage in Accessible::GetAttributes)
+ * (See for example usage in Accessible::Attributes())
  */
 const uint8_t ATTR_VALTOKEN   = 0x0010;
 
 /**
  * Small footprint storage of persistent aria attribute characteristics.
  */
 struct nsAttributeCharacteristics
 {
--- a/accessible/src/base/nsAccDocManager.h
+++ b/accessible/src/base/nsAccDocManager.h
@@ -35,17 +35,24 @@ public:
    */
   DocAccessible* GetDocAccessible(nsIDocument* aDocument);
 
   /**
    * Return document accessible for the given presshell.
    */
   DocAccessible* GetDocAccessible(const nsIPresShell* aPresShell)
   {
-    return aPresShell ? GetDocAccessible(aPresShell->GetDocument()) : nullptr;
+    if (!aPresShell)
+      return nullptr;
+
+    DocAccessible* doc = aPresShell->GetDocAccessible();
+    if (doc)
+      return doc;
+
+    return GetDocAccessible(aPresShell->GetDocument());
   }
 
   /**
    * Search through all document accessibles for an accessible with the given
    * unique id.
    */
   Accessible* FindAccessibleInCache(nsINode* aNode) const;
 
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -376,18 +376,19 @@ nsAccUtils::GetScreenCoordsForParent(nsA
   Accessible* parent = document->GetContainerAccessible(aAccessNode->GetNode());
   if (!parent)
     return nsIntPoint(0, 0);
 
   nsIFrame *parentFrame = parent->GetFrame();
   if (!parentFrame)
     return nsIntPoint(0, 0);
 
-  nsIntRect parentRect = parentFrame->GetScreenRectExternal();
-  return nsIntPoint(parentRect.x, parentRect.y);
+  nsRect rect = parentFrame->GetScreenRectInAppUnits();
+  return nsPoint(rect.x, rect.y).
+    ToNearestPixels(parentFrame->PresContext()->AppUnitsPerDevPixel());
 }
 
 uint8_t
 nsAccUtils::GetAttributeCharacteristics(nsIAtom* aAtom)
 {
     for (uint32_t i = 0; i < nsARIAMap::gWAIUnivAttrMapLength; i++)
       if (*nsARIAMap::gWAIUnivAttrMap[i].attributeName == aAtom)
         return nsARIAMap::gWAIUnivAttrMap[i].characteristics;
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -11,17 +11,16 @@
 #include "nsIAccessibleText.h"
 
 #include "nsAccessibilityService.h"
 #include "nsCoreUtils.h"
 
 #include "mozilla/dom/Element.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
-#include "nsIDOMNode.h"
 #include "nsIPersistentProperties2.h"
 #include "nsIPresShell.h"
 #include "nsPoint.h"
 
 class nsAccessNode;
 class Accessible;
 class HyperTextAccessible;
 class DocAccessible;
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -163,311 +163,81 @@ nsAccessibilityService::GetRootDocumentA
       return aCanCreate ?
         GetDocAccessible(documentNode) : GetDocAccessibleFromCache(documentNode);
     }
   }
   return nullptr;
 }
 
 already_AddRefed<Accessible>
-nsAccessibilityService::CreateOuterDocAccessible(nsIContent* aContent,
-                                                 nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new OuterDocAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLButtonAccessible(nsIContent* aContent,
-                                                   nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLButtonAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLLIAccessible(nsIContent* aContent,
-                                               nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLLIAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHyperTextAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HyperTextAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLCheckboxAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLCheckboxAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLComboboxAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLComboboxAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLCanvasAccessible(nsIContent* aContent,
-                                                   nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLCanvasAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLFileInputAccessible(nsIContent* aContent,
-                                                      nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLFileInputAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLImageAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new ImageAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLImageMapAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLImageMapAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLGroupboxAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLGroupboxAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLListboxAccessible(nsIContent* aContent,
-                                                    nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLSelectListAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLMediaAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new EnumRoleAccessible(aContent, GetDocAccessible(aPresShell),
-                           roles::GROUPING);
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame,
                                                         nsIContent* aContent,
-                                                        nsIPresShell* aPresShell)
+                                                        DocAccessible* aDoc)
 {
   // We can have several cases here:
   // 1) a text or html embedded document where the contentDocument variable in
   //    the object element holds the content;
   // 2) web content that uses a plugin, which means we will have to go to
   //    the plugin to get the accessible content;
   // 3) an image or imagemap, where the image frame points back to the object
   //    element DOMNode.
 
   if (aFrame->GetRect().IsEmpty())
     return nullptr;
 
-
   // 1) for object elements containing either HTML or TXT documents
   nsCOMPtr<nsIDOMHTMLObjectElement> obj(do_QueryInterface(aContent));
   if (obj) {
     nsCOMPtr<nsIDOMDocument> domDoc;
     obj->GetContentDocument(getter_AddRefs(domDoc));
-    if (domDoc)
-      return CreateOuterDocAccessible(aContent, aPresShell);
+    if (domDoc) {
+      Accessible* newAcc = new OuterDocAccessible(aContent, aDoc);
+      NS_ADDREF(newAcc);
+      return newAcc;
+    }
   }
 
 #if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
   // 2) for plugins
   nsRefPtr<nsNPAPIPluginInstance> pluginInstance;
   if (NS_SUCCEEDED(aFrame->GetPluginInstance(getter_AddRefs(pluginInstance))) &&
       pluginInstance) {
 #ifdef XP_WIN
     // Note: pluginPort will be null if windowless.
     HWND pluginPort = nullptr;
     aFrame->GetPluginPort(&pluginPort);
 
     Accessible* accessible =
-      new HTMLWin32ObjectOwnerAccessible(aContent, GetDocAccessible(aPresShell),
-                                         pluginPort);
+      new HTMLWin32ObjectOwnerAccessible(aContent, aDoc, pluginPort);
     NS_ADDREF(accessible);
     return accessible;
 
 #elif MOZ_ACCESSIBILITY_ATK
     if (!AtkSocketAccessible::gCanEmbed)
       return nullptr;
 
     nsCString plugId;
     nsresult rv = pluginInstance->GetValueFromPlugin(
       NPPVpluginNativeAccessibleAtkPlugId, &plugId);
     if (NS_SUCCEEDED(rv) && !plugId.IsEmpty()) {
       AtkSocketAccessible* socketAccessible =
-        new AtkSocketAccessible(aContent, GetDocAccessible(aPresShell),
-                                plugId);
+        new AtkSocketAccessible(aContent, aDoc, plugId);
 
       NS_ADDREF(socketAccessible);
       return socketAccessible;
     }
 #endif
   }
 #endif
 
   // 3) for images and imagemaps, or anything else with a child frame
   // we have the object frame, get the image frame
-  nsIFrame* frame = aFrame->GetFirstPrincipalChild();
-  return frame ? frame->CreateAccessible() : nullptr;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLRadioButtonAccessible(nsIContent* aContent,
-                                                        nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLRadioButtonAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLTableAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLTableAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLTableCellAccessible(nsIContent* aContent,
-                                                      nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLTableCellAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLTableRowAccessible(nsIContent* aContent,
-                                                     nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new EnumRoleAccessible(aContent, GetDocAccessible(aPresShell), roles::ROW);
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateTextLeafAccessible(nsIContent* aContent,
-                                                 nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new TextLeafAccessibleWrap(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLTextFieldAccessible(nsIContent* aContent,
-                                                      nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLTextFieldAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLLabelAccessible(nsIContent* aContent,
-                                                  nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLLabelAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLHRAccessible(nsIContent* aContent,
-                                               nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLHRAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLBRAccessible(nsIContent* aContent,
-                                               nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLBRAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLCaptionAccessible(nsIContent* aContent,
-                                                    nsIPresShell* aPresShell)
-{
-  Accessible* accessible =
-    new HTMLCaptionAccessible(aContent, GetDocAccessible(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
+  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
+  return childFrame ? CreateAccessibleByFrameType(childFrame, aContent, aDoc) :
+    nullptr;
 }
 
 void
 nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
                                              nsIContent* aContainer,
                                              nsIContent* aStartChild,
                                              nsIContent* aEndChild)
 {
@@ -948,17 +718,17 @@ nsAccessibilityService::GetOrCreateAcces
     frame->GetRenderedText(&text, nullptr, nullptr, 0, UINT32_MAX);
     if (text.IsEmpty()) {
       if (aIsSubtreeHidden)
         *aIsSubtreeHidden = true;
 
       return nullptr;
     }
 
-    newAcc = frame->CreateAccessible();
+    newAcc = CreateAccessibleByFrameType(frame, content, aDoc);
     if (aDoc->BindToDocument(newAcc, nullptr)) {
       newAcc->AsTextLeaf()->SetText(text);
       return newAcc;
     }
 
     return nullptr;
   }
 
@@ -1105,17 +875,17 @@ nsAccessibilityService::GetOrCreateAcces
           // is no better place:
           if (aIsSubtreeHidden)
             *aIsSubtreeHidden = true;
 
           return nullptr;
         }
 
         // Try using frame to do it.
-        newAcc = frame->CreateAccessible();
+        newAcc = CreateAccessibleByFrameType(frame, content, aDoc);
       }
     }
   }
 
   if (!newAcc) {
     // Elements may implement nsIAccessibleProvider via XBL. This allows them to
     // say what kind of accessible to create.
     newAcc = CreateAccessibleByType(content, aDoc);
@@ -1654,16 +1424,105 @@ nsAccessibilityService::CreateHTMLAccess
       new HTMLProgressMeterAccessible(aContent, aDoc);
     NS_ADDREF(accessible);
     return accessible;
   }
 
   return nullptr;
  }
 
+already_AddRefed<Accessible>
+nsAccessibilityService::CreateAccessibleByFrameType(nsIFrame* aFrame,
+                                                    nsIContent* aContent,
+                                                    DocAccessible* aDoc)
+{
+  nsRefPtr<Accessible> newAcc;
+  switch (aFrame->AccessibleType()) {
+    case eNoAccessible:
+      return nullptr;
+    case eHTMLBRAccessible:
+      newAcc = new HTMLBRAccessible(aContent, aDoc);
+      break;
+    case eHTMLButtonAccessible:
+      newAcc = new HTMLButtonAccessible(aContent, aDoc);
+      break;
+    case eHTMLCanvasAccessible:
+      newAcc = new HTMLCanvasAccessible(aContent, aDoc);
+      break;
+    case eHTMLCaptionAccessible:
+      newAcc = new HTMLCaptionAccessible(aContent, aDoc);
+      break;
+    case eHTMLCheckboxAccessible:
+      newAcc = new HTMLCheckboxAccessible(aContent, aDoc);
+      break;
+    case eHTMLComboboxAccessible:
+      newAcc = new HTMLComboboxAccessible(aContent, aDoc);
+      break;
+    case eHTMLFileInputAccessible:
+      newAcc = new HTMLFileInputAccessible(aContent, aDoc);
+      break;
+    case eHTMLGroupboxAccessible:
+      newAcc = new HTMLGroupboxAccessible(aContent, aDoc);
+      break;
+    case eHTMLHRAccessible:
+      newAcc = new HTMLHRAccessible(aContent, aDoc);
+      break;
+    case eHTMLImageMapAccessible:
+      newAcc = new HTMLImageMapAccessible(aContent, aDoc);
+      break;
+    case eHTMLLabelAccessible:
+      newAcc = new HTMLLabelAccessible(aContent, aDoc);
+      break;
+    case eHTMLLiAccessible:
+      newAcc = new HTMLLIAccessible(aContent, aDoc);
+      break;
+    case eHTMLSelectListAccessible:
+      newAcc = new HTMLSelectListAccessible(aContent, aDoc);
+      break;
+    case eHTMLMediaAccessible:
+      newAcc = new EnumRoleAccessible(aContent, aDoc, roles::GROUPING);
+      break;
+    case eHTMLObjectFrameAccessible: {
+      nsObjectFrame* objectFrame = do_QueryFrame(aFrame);
+      newAcc = CreateHTMLObjectFrameAccessible(objectFrame, aContent, aDoc);
+      break;
+    }
+
+    case eHTMLRadioButtonAccessible:
+      newAcc = new HTMLRadioButtonAccessible(aContent, aDoc);
+      break;
+    case eHTMLTableAccessible:
+      newAcc = new HTMLTableAccessibleWrap(aContent, aDoc);
+      break;
+    case eHTMLTableCellAccessible:
+      newAcc = new HTMLTableCellAccessibleWrap(aContent, aDoc);
+      break;
+    case eHTMLTableRowAccessible:
+      newAcc = new EnumRoleAccessible(aContent, aDoc, roles::ROW);
+      break;
+    case eHTMLTextFieldAccessible:
+      newAcc = new HTMLTextFieldAccessible(aContent, aDoc);
+      break;
+    case eHyperTextAccessible:
+      newAcc = new HyperTextAccessibleWrap(aContent, aDoc);
+      break;
+    case eImageAccessible:
+      newAcc = new ImageAccessibleWrap(aContent, aDoc);
+      break;
+    case eOuterDocAccessible:
+      newAcc = new OuterDocAccessible(aContent, aDoc);
+      break;
+    case eTextLeafAccessible:
+      newAcc = new TextLeafAccessibleWrap(aContent, aDoc);
+      break;
+  }
+
+  return newAcc.forget();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibilityService (DON'T put methods here)
 
 Accessible*
 nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
 {
 #ifdef MOZ_ACCESSIBILITY_ATK
   ApplicationAccessible* applicationAcc = ApplicationAcc();
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -11,16 +11,17 @@
 #include "a11yGeneric.h"
 #include "nsAccDocManager.h"
 
 #include "mozilla/a11y/FocusManager.h"
 
 #include "nsIObserver.h"
 
 class nsImageFrame;
+class nsObjectFrame;
 class nsITreeView;
 
 namespace mozilla {
 namespace a11y {
 
 class ApplicationAccessible;
 
 /**
@@ -75,64 +76,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLERETRIEVAL
   NS_DECL_NSIOBSERVER
 
   // nsIAccessibilityService
   virtual Accessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
                                                 bool aCanCreate);
   already_AddRefed<Accessible>
-    CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLBRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLCanvasAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLCaptionAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLCheckboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLComboboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLFileInputAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLGroupboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLHRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLImageAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLImageMapAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLListboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLMediaAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
     CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame, nsIContent* aContent,
-                                    nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLRadioButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLTableAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLTableCellAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLTableRowAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateTextLeafAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHTMLTextFieldAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateHyperTextAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  already_AddRefed<Accessible>
-    CreateOuterDocAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
+                                    DocAccessible* aDoc);
 
   /**
    * Adds/remove ATK root accessible for gtk+ native window to/from children
    * of the application accessible.
    */
   virtual Accessible* AddNativeRootAccessible(void* aAtkAccessible);
   virtual void RemoveNativeRootAccessible(Accessible* aRootAccessible);
 
@@ -235,16 +190,23 @@ private:
    * Create accessible for HTML node by tag name.
    */
   already_AddRefed<Accessible>
     CreateHTMLAccessibleByMarkup(nsIFrame* aFrame, nsIContent* aContent,
                                  DocAccessible* aDoc,
                                  bool aIsLegalPartOfHTMLTable);
 
   /**
+   * Create an accessible whose type depends on the given frame.
+   */
+  already_AddRefed<Accessible>
+    CreateAccessibleByFrameType(nsIFrame* aFrame, nsIContent* aContent,
+                                DocAccessible* aDoc);
+
+  /**
    * Create accessible if parent is a deck frame.
    */
   already_AddRefed<Accessible>
     CreateAccessibleForDeckChild(nsIFrame* aFrame, nsIContent* aContent,
                                  DocAccessible* aDoc);
 
 #ifdef MOZ_XUL
   /**
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsCoreUtils.h"
 
 #include "nsIAccessibleTypes.h"
 
 #include "nsAccessNode.h"
 
+#include "nsIBaseWindow.h"
+#include "nsIDocShellTreeOwner.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsRange.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocShell.h"
@@ -243,17 +245,17 @@ nsCoreUtils::GetRoleContent(nsINode *aNo
 bool
 nsCoreUtils::IsAncestorOf(nsINode *aPossibleAncestorNode,
                           nsINode *aPossibleDescendantNode,
                           nsINode *aRootNode)
 {
   NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, false);
 
   nsINode *parentNode = aPossibleDescendantNode;
-  while ((parentNode = parentNode->GetNodeParent()) &&
+  while ((parentNode = parentNode->GetParentNode()) &&
          parentNode != aRootNode) {
     if (parentNode == aPossibleAncestorNode)
       return true;
   }
 
   return false;
 }
 
@@ -298,29 +300,24 @@ nsCoreUtils::ScrollSubstringTo(nsIFrame*
   return NS_OK;
 }
 
 void
 nsCoreUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame,
                                 nsIFrame *aFrame,
                                 const nsIntPoint& aPoint)
 {
-  nsIScrollableFrame *scrollableFrame = do_QueryFrame(aScrollableFrame);
+  nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollableFrame);
   if (!scrollableFrame)
     return;
 
-  nsPresContext *presContext = aFrame->PresContext();
-
-  nsIntRect frameRect = aFrame->GetScreenRectExternal();
-  int32_t devDeltaX = aPoint.x - frameRect.x;
-  int32_t devDeltaY = aPoint.y - frameRect.y;
-
-  nsPoint deltaPoint;
-  deltaPoint.x = presContext->DevPixelsToAppUnits(devDeltaX);
-  deltaPoint.y = presContext->DevPixelsToAppUnits(devDeltaY);
+  nsPoint point =
+    aPoint.ToAppUnits(aFrame->PresContext()->AppUnitsPerDevPixel());
+  nsRect frameRect = aFrame->GetScreenRectInAppUnits();
+  nsPoint deltaPoint(point.x - frameRect.x, point.y - frameRect.y);
 
   nsPoint scrollPoint = scrollableFrame->GetScrollPosition();
   scrollPoint -= deltaPoint;
 
   scrollableFrame->ScrollTo(scrollPoint, nsIScrollableFrame::INSTANT);
 }
 
 void
@@ -381,29 +378,25 @@ nsCoreUtils::ConvertScrollTypeToPercents
 nsIntPoint
 nsCoreUtils::GetScreenCoordsForWindow(nsINode *aNode)
 {
   nsIntPoint coords(0, 0);
   nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShellTreeItemFor(aNode));
   if (!treeItem)
     return coords;
 
-  nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
-  treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
-  nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(rootTreeItem);
-  if (!domDoc)
+  nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
+  treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
+  if (!treeOwner)
     return coords;
 
-  nsCOMPtr<nsIDOMWindow> window;
-  domDoc->GetDefaultView(getter_AddRefs(window));
-  if (!window)
-    return coords;
+  nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(treeOwner);
+  if (baseWindow)
+    baseWindow->GetPosition(&coords.x, &coords.y); // in device pixels
 
-  window->GetScreenX(&coords.x);
-  window->GetScreenY(&coords.y);
   return coords;
 }
 
 already_AddRefed<nsIDocShellTreeItem>
 nsCoreUtils::GetDocShellTreeItemFor(nsINode *aNode)
 {
   if (!aNode)
     return nullptr;
@@ -476,36 +469,16 @@ nsCoreUtils::IsErrorPage(nsIDocument *aD
   uri->GetPath(path);
 
   NS_NAMED_LITERAL_CSTRING(neterror, "neterror");
   NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
 
   return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
 }
 
-already_AddRefed<nsIDOMNode>
-nsCoreUtils::GetDOMNodeForContainer(nsIDocShellTreeItem *aContainer)
-{
-  nsCOMPtr<nsIDocShell> shell = do_QueryInterface(aContainer);
-
-  nsCOMPtr<nsIContentViewer> cv;
-  shell->GetContentViewer(getter_AddRefs(cv));
-
-  if (!cv)
-    return nullptr;
-
-  nsIDocument* doc = cv->GetDocument();
-  if (!doc)
-    return nullptr;
-
-  nsIDOMNode* node = nullptr;
-  CallQueryInterface(doc, &node);
-  return node;
-}
-
 bool
 nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID)
 {
   nsIAtom *idAttribute = aContent->GetIDAttributeName();
   return idAttribute ? aContent->GetAttr(kNameSpaceID_None, idAttribute, aID) : false;
 }
 
 bool
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -11,17 +11,16 @@
 #include "nsIBoxObject.h"
 #include "nsIPresShell.h"
 
 #include "nsIDOMDOMStringList.h"
 #include "nsPoint.h"
 #include "nsTArray.h"
 
 class nsRange;
-class nsIDOMNode;
 class nsIFrame;
 class nsIDocShellTreeItem;
 class nsITreeColumn;
 class nsITreeBoxObject;
 class nsIWidget;
 
 /**
  * Core utils.
@@ -164,17 +163,18 @@ public:
    * Converts scroll type constant defined in nsIAccessibleScrollType to
    * vertical and horizontal parameters.
    */
   static void ConvertScrollTypeToPercents(uint32_t aScrollType,
                                           nsIPresShell::ScrollAxis *aVertical,
                                           nsIPresShell::ScrollAxis *aHorizontal);
 
   /**
-   * Returns coordinates relative screen for the top level window.
+   * Returns coordinates in device pixels relative screen for the top level
+   * window.
    *
    * @param aNode  the DOM node hosted in the window.
    */
   static nsIntPoint GetScreenCoordsForWindow(nsINode *aNode);
 
   /**
    * Return document shell tree item for the given DOM node.
    */
@@ -205,22 +205,16 @@ public:
    * Return presShell for the document containing the given DOM node.
    */
   static nsIPresShell *GetPresShellFor(nsINode *aNode)
   {
     return aNode->OwnerDoc()->GetShell();
   }
 
   /**
-   * Return document node for the given document shell tree item.
-   */
-  static already_AddRefed<nsIDOMNode>
-    GetDOMNodeForContainer(nsIDocShellTreeItem *aContainer);
-
-  /**
    * Get the ID for an element, in some types of XML this may not be the ID attribute
    * @param aContent  Node to get the ID for
    * @param aID       Where to put ID string
    * @return          true if there is an ID set for this node
    */
   static bool GetID(nsIContent *aContent, nsAString& aID);
 
   /**
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -27,17 +27,17 @@ nsTextEquivUtils::GetNameFromSubtree(Acc
                                      nsAString& aName)
 {
   aName.Truncate();
 
   if (gInitiatorAcc)
     return NS_OK;
 
   gInitiatorAcc = aAccessible;
-  if (GetRoleRule(aAccessible->Role()) == eFromSubtree) {
+  if (IsNameFromSubtreeAllowed(aAccessible)) {
     //XXX: is it necessary to care the accessible is not a document?
     if (aAccessible->IsContent()) {
       nsAutoString name;
       AppendFromAccessibleChildren(aAccessible, &name);
       name.CompressWhitespace();
       if (!IsWhitespaceString(name))
         aName = name;
     }
--- a/accessible/src/base/nsTextEquivUtils.h
+++ b/accessible/src/base/nsTextEquivUtils.h
@@ -84,16 +84,24 @@ public:
    * node or html:br) and appends it to the given string.
    *
    * @param aContent       [in] the text content
    * @param aString        [in, out] the string
    */
   static nsresult AppendTextEquivFromTextContent(nsIContent *aContent,
                                                  nsAString *aString);
 
+  /**
+   * Return true if the given accessible allows name from subtree.
+   */
+  static bool IsNameFromSubtreeAllowed(Accessible* aAccessible)
+  {
+    return GetRoleRule(aAccessible->Role()) == eFromSubtree;
+  }
+
 private:
   /**
    * Iterates accessible children and calculates text equivalent from each
    * child.
    */
   static nsresult AppendFromAccessibleChildren(Accessible* aAccessible,
                                                nsAString *aString);
   
--- a/accessible/src/generic/ARIAGridAccessible.cpp
+++ b/accessible/src/generic/ARIAGridAccessible.cpp
@@ -609,29 +609,26 @@ ARIAGridCellAccessible::ApplyARIAState(u
   if (nsAccUtils::HasDefinedARIAToken(rowContent,
                                       nsGkAtoms::aria_selected) &&
       !rowContent->AttrValueIs(kNameSpaceID_None,
                                nsGkAtoms::aria_selected,
                                nsGkAtoms::_false, eCaseMatters))
     *aState |= states::SELECTABLE | states::SELECTED;
 }
 
-nsresult
-ARIAGridCellAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
+already_AddRefed<nsIPersistentProperties>
+ARIAGridCellAccessible::NativeAttributes()
 {
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsresult rv = HyperTextAccessibleWrap::GetAttributesInternal(aAttributes);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    HyperTextAccessibleWrap::NativeAttributes();
 
   // Expose "table-cell-index" attribute.
   Accessible* thisRow = Row();
   if (!thisRow)
-    return NS_OK;
+    return attributes.forget();
 
   int32_t colIdx = 0, colCount = 0;
   uint32_t childCount = thisRow->ChildCount();
   for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
     Accessible* child = thisRow->GetChildAt(childIdx);
     if (child == this)
       colIdx = colCount;
 
@@ -640,20 +637,19 @@ ARIAGridCellAccessible::GetAttributesInt
         role == roles::COLUMNHEADER)
       colCount++;
   }
 
   int32_t rowIdx = RowIndexFor(thisRow);
 
   nsAutoString stringIdx;
   stringIdx.AppendInt(rowIdx * colCount + colIdx);
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex,
-                         stringIdx);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
 
-  return NS_OK;
+  return attributes.forget();
 }
 
 void
 ARIAGridCellAccessible::Shutdown()
 {
   mTableCell = nullptr;
   HyperTextAccessibleWrap::Shutdown();
 }
--- a/accessible/src/generic/ARIAGridAccessible.h
+++ b/accessible/src/generic/ARIAGridAccessible.h
@@ -111,17 +111,17 @@ public:
 
   // nsIAccessibleTableCell
   NS_FORWARD_NSIACCESSIBLETABLECELL(xpcAccessibleTableCell::)
 
   // Accessible
   virtual TableCellAccessible* AsTableCell() { return this; }
   virtual void Shutdown();
   virtual void ApplyARIAState(uint64_t* aState) const;
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
 
 protected:
 
   /**
    * Return a containing row.
    */
   Accessible* Row() const
   {
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -270,37 +270,35 @@ Accessible::Name(nsString& aName)
   if (xblAccessible) {
     xblAccessible->GetAccessibleName(aName);
     if (!aName.IsEmpty())
       return eNameOK;
   }
 
   ENameValueFlag nameFlag = NativeName(aName);
   if (!aName.IsEmpty())
-    return eNameOK;
+    return nameFlag;
 
   // In the end get the name from tooltip.
   if (mContent->IsHTML()) {
     if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName)) {
       aName.CompressWhitespace();
       return eNameFromTooltip;
     }
   } else if (mContent->IsXUL()) {
     if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aName)) {
       aName.CompressWhitespace();
       return eNameFromTooltip;
     }
-  } else {
-    return eNameOK;
   }
 
   if (nameFlag != eNoNameOnPurpose)
     aName.SetIsVoid(true);
 
-  return eNameOK;
+  return nameFlag;
 }
 
 NS_IMETHODIMP
 Accessible::GetDescription(nsAString& aDescription)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
@@ -1050,44 +1048,47 @@ Accessible::TakeFocus()
   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(focusContent));
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   if (fm)
     fm->SetFocus(element, 0);
 
   return NS_OK;
 }
 
-void
+ENameValueFlag
 Accessible::GetHTMLName(nsString& aLabel)
 {
   Accessible* labelAcc = nullptr;
   HTMLLabelIterator iter(Document(), this);
   while ((labelAcc = iter.Next())) {
     nsTextEquivUtils::AppendTextEquivFromContent(this, labelAcc->GetContent(),
                                                  &aLabel);
     aLabel.CompressWhitespace();
   }
 
-  if (aLabel.IsEmpty())
-    nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
+  if (!aLabel.IsEmpty())
+    return eNameOK;
+
+  nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
+  return aLabel.IsEmpty() ? eNameOK : eNameFromSubtree;
 }
 
 /**
   * 3 main cases for XUL Controls to be labeled
   *   1 - control contains label="foo"
   *   2 - control has, as a child, a label element
   *        - label has either value="foo" or children
   *   3 - non-child label contains control="controlID"
   *        - label has either value="foo" or children
   * Once a label is found, the search is discontinued, so a control
   *  that has a label child as well as having a label external to
   *  the control that uses the control="controlID" syntax will use
   *  the child label for its Name.
   */
-void
+ENameValueFlag
 Accessible::GetXULName(nsString& aName)
 {
   // CASE #1 (via label attribute) -- great majority of the cases
   nsCOMPtr<nsIDOMXULLabeledControlElement> labeledEl =
     do_QueryInterface(mContent);
   if (labeledEl) {
     labeledEl->GetLabel(aName);
   } else {
@@ -1120,35 +1121,35 @@ Accessible::GetXULName(nsString& aName)
         // If no value attribute, a non-empty label must contain
         // children that define its text -- possibly using HTML
         nsTextEquivUtils::
           AppendTextEquivFromContent(this, labelAcc->GetContent(), &aName);
       }
     }
   }
 
-  // XXX If CompressWhiteSpace worked on nsAString we could avoid a copy
   aName.CompressWhitespace();
   if (!aName.IsEmpty())
-    return;
+    return eNameOK;
 
   // Can get text from title of <toolbaritem> if we're a child of a <toolbaritem>
   nsIContent *bindingParent = mContent->GetBindingParent();
   nsIContent *parent = bindingParent? bindingParent->GetParent() :
                                       mContent->GetParent();
   while (parent) {
     if (parent->Tag() == nsGkAtoms::toolbaritem &&
         parent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName)) {
       aName.CompressWhitespace();
-      return;
+      return eNameOK;
     }
     parent = parent->GetParent();
   }
 
   nsTextEquivUtils::GetNameFromSubtree(this, aName);
+  return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
 }
 
 nsresult
 Accessible::HandleAccEvent(AccEvent* aEvent)
 {
   NS_ENSURE_ARG_POINTER(aEvent);
 
   nsCOMPtr<nsIObserverService> obsService =
@@ -1180,198 +1181,208 @@ Accessible::GetRole(uint32_t *aRole)
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   *aRole = Role();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Accessible::GetAttributes(nsIPersistentProperties **aAttributes)
+Accessible::GetAttributes(nsIPersistentProperties** aAttributes)
 {
-  NS_ENSURE_ARG_POINTER(aAttributes);  // In/out param. Created if necessary.
-  
+  NS_ENSURE_ARG_POINTER(aAttributes);
+  *aAttributes = nullptr;
+
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIPersistentProperties> attributes = *aAttributes;
-  if (!attributes) {
-    // Create only if an array wasn't already passed in
-    attributes = do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
-    NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
-    NS_ADDREF(*aAttributes = attributes);
-  }
- 
-  nsresult rv = GetAttributesInternal(attributes);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAutoString id;
-  nsAutoString oldValueUnused;
-  if (nsCoreUtils::GetID(mContent, id)) {
-    // Expose ID. If an <iframe id> exists override the one on the <body> of the source doc,
-    // because the specific instance is what makes the ID useful for scripts
-    attributes->SetStringProperty(NS_LITERAL_CSTRING("id"), id, oldValueUnused);
-  }
-  
-  nsAutoString xmlRoles;
+  nsCOMPtr<nsIPersistentProperties> attributes = Attributes();
+  attributes.swap(*aAttributes);
+
+  return NS_OK;
+}
+
+already_AddRefed<nsIPersistentProperties>
+Accessible::Attributes()
+{
+  nsCOMPtr<nsIPersistentProperties> attributes = NativeAttributes();
+  if (!HasOwnContent() || !mContent->IsElement())
+    return attributes.forget();
+
+  // 'xml-roles' attribute coming from ARIA.
+  nsAutoString xmlRoles, unused;
   if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::role, xmlRoles)) {
-    attributes->SetStringProperty(NS_LITERAL_CSTRING("xml-roles"),  xmlRoles, oldValueUnused);          
+    attributes->SetStringProperty(NS_LITERAL_CSTRING("xml-roles"),
+                                  xmlRoles, unused);
   }
 
-  if (HasNumericValue()) {
-    // We support values, so expose the string value as well, via the valuetext object attribute
-    // We test for the value interface because we don't want to expose traditional get_accValue()
-    // information such as URL's on links and documents, or text in an input
-    nsAutoString valuetext;
-    GetValue(valuetext);
-    attributes->SetStringProperty(NS_LITERAL_CSTRING("valuetext"), valuetext, oldValueUnused);
-  }
-
-  // Expose checkable object attribute if the accessible has checkable state
-  if (State() & states::CHECKABLE)
-    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::checkable, NS_LITERAL_STRING("true"));
-
-  // Group attributes (level/setsize/posinset)
-  GroupPos groupPos = GroupPosition();
-  nsAccUtils::SetAccGroupAttrs(attributes, groupPos.level,
-                               groupPos.setSize, groupPos.posInSet);
-
   // Expose object attributes from ARIA attributes.
   aria::AttrIterator attribIter(mContent);
   nsAutoString name, value;
-  while(attribIter.Next(name, value)) {
-    attributes->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, 
-                                  oldValueUnused);
-  }
+  while(attribIter.Next(name, value))
+    attributes->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused);
 
   // If there is no aria-live attribute then expose default value of 'live'
   // object attribute used for ARIA role of this accessible.
   if (mRoleMapEntry) {
     nsAutoString live;
     nsAccUtils::GetAccAttr(attributes, nsGkAtoms::live, live);
     if (live.IsEmpty()) {
       if (nsAccUtils::GetLiveAttrValue(mRoleMapEntry->liveAttRule, live))
         nsAccUtils::SetAccAttr(attributes, nsGkAtoms::live, live);
     }
   }
 
-  return NS_OK;
+  return attributes.forget();
 }
 
-nsresult
-Accessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
+already_AddRefed<nsIPersistentProperties>
+Accessible::NativeAttributes()
 {
-  // If the accessible isn't primary for its node (such as list item bullet or
-  // xul tree item then don't calculate content based attributes.
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+
+  nsAutoString unused;
+
+  // We support values, so expose the string value as well, via the valuetext
+  // object attribute. We test for the value interface because we don't want
+  // to expose traditional Value() information such as URL's on links and
+  // documents, or text in an input.
+  if (HasNumericValue()) {
+    nsAutoString valuetext;
+    GetValue(valuetext);
+    attributes->SetStringProperty(NS_LITERAL_CSTRING("valuetext"), valuetext,
+                                  unused);
+  }
+
+  // Expose checkable object attribute if the accessible has checkable state
+  if (State() & states::CHECKABLE) {
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::checkable,
+                           NS_LITERAL_STRING("true"));
+  }
+
+  // Expose 'explicit-name' attribute.
+  if (!nsTextEquivUtils::IsNameFromSubtreeAllowed(this) ||
+      Name(unused) != eNameFromSubtree) {
+    attributes->SetStringProperty(NS_LITERAL_CSTRING("explicit-name"),
+                                  NS_LITERAL_STRING("true"), unused);
+  }
+
+  // Group attributes (level/setsize/posinset)
+  GroupPos groupPos = GroupPosition();
+  nsAccUtils::SetAccGroupAttrs(attributes, groupPos.level,
+                               groupPos.setSize, groupPos.posInSet);
+
+  // If the accessible doesn't have own content (such as list item bullet or
+  // xul tree item) then don't calculate content based attributes.
   if (!HasOwnContent())
-    return NS_OK;
-
-  // Attributes set by this method will not be used to override attributes on a sub-document accessible
-  // when there is a <frame>/<iframe> element that spawned the sub-document
-
-  nsEventShell::GetEventAttributes(GetNode(), aAttributes);
- 
-  // Expose class because it may have useful microformat information
-  // Let the class from an iframe's document be exposed, don't override from <iframe class>
-  nsAutoString _class;
-  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, _class))
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::_class, _class);
-
-  // Get container-foo computed live region properties based on the closest container with
-  // the live region attribute. 
-  // Inner nodes override outer nodes within the same document --
-  //   The inner nodes can be used to override live region behavior on more general outer nodes
-  // However, nodes in outer documents override nodes in inner documents:
-  //   Outer doc author may want to override properties on a widget they used in an iframe
+    return attributes.forget();
+
+  nsEventShell::GetEventAttributes(GetNode(), attributes);
+
+  // Get container-foo computed live region properties based on the closest
+  // container with the live region attribute. Inner nodes override outer nodes
+  // within the same document. The inner nodes can be used to override live
+  // region behavior on more general outer nodes. However, nodes in outer
+  // documents override nodes in inner documents: outer doc author may want to
+  // override properties on a widget they used in an iframe.
   nsIContent* startContent = mContent;
   while (startContent) {
     nsIDocument* doc = startContent->GetDocument();
-    nsIContent* rootContent = nsCoreUtils::GetRoleContent(doc);
-    if (!rootContent)
-      return NS_OK;
-
-    nsAccUtils::SetLiveContainerAttributes(aAttributes, startContent,
-                                           rootContent);
+    if (!doc)
+      break;
+
+    nsAccUtils::SetLiveContainerAttributes(attributes, startContent,
+                                           nsCoreUtils::GetRoleContent(doc));
 
     // Allow ARIA live region markup from outer documents to override
     nsCOMPtr<nsISupports> container = doc->GetContainer(); 
     nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
       do_QueryInterface(container);
     if (!docShellTreeItem)
       break;
 
     nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
     docShellTreeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
     if (!sameTypeParent || sameTypeParent == docShellTreeItem)
       break;
 
-    nsIDocument *parentDoc = doc->GetParentDocument();
+    nsIDocument* parentDoc = doc->GetParentDocument();
     if (!parentDoc)
       break;
 
-    startContent = parentDoc->FindContentForSubDocument(doc);      
+    startContent = parentDoc->FindContentForSubDocument(doc);
   }
 
   if (!mContent->IsElement())
-    return NS_OK;
+    return attributes.forget();
+
+  nsAutoString id;
+  if (nsCoreUtils::GetID(mContent, id))
+    attributes->SetStringProperty(NS_LITERAL_CSTRING("id"), id, unused);
+
+  // Expose class because it may have useful microformat information.
+  nsAutoString _class;
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, _class))
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::_class, _class);
 
   // Expose tag.
   nsAutoString tagName;
   mContent->NodeInfo()->GetName(tagName);
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tag, tagName);
-
-  // Expose draggable object attribute?
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tag, tagName);
+
+  // Expose draggable object attribute.
   nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mContent);
   if (htmlElement) {
     bool draggable = false;
     htmlElement->GetDraggable(&draggable);
     if (draggable) {
-      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::draggable,
+      nsAccUtils::SetAccAttr(attributes, nsGkAtoms::draggable,
                              NS_LITERAL_STRING("true"));
     }
   }
 
   // Don't calculate CSS-based object attributes when no frame (i.e.
   // the accessible is unattached from the tree).
   if (!mContent->GetPrimaryFrame())
-    return NS_OK;
+    return attributes.forget();
 
   // CSS style based object attributes.
   nsAutoString value;
   StyleInfo styleInfo(mContent->AsElement(), mDoc->PresShell());
 
   // Expose 'display' attribute.
   styleInfo.Display(value);
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::display, value);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::display, value);
 
   // Expose 'text-align' attribute.
   styleInfo.TextAlign(value);
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textAlign, value);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::textAlign, value);
 
   // Expose 'text-indent' attribute.
   styleInfo.TextIndent(value);
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textIndent, value);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::textIndent, value);
 
   // Expose 'margin-left' attribute.
   styleInfo.MarginLeft(value);
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginLeft, value);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::marginLeft, value);
 
   // Expose 'margin-right' attribute.
   styleInfo.MarginRight(value);
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginRight, value);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::marginRight, value);
 
   // Expose 'margin-top' attribute.
   styleInfo.MarginTop(value);
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginTop, value);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::marginTop, value);
 
   // Expose 'margin-bottom' attribute.
   styleInfo.MarginBottom(value);
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginBottom, value);
-
-  return NS_OK;
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::marginBottom, value);
+
+  return attributes.forget();
 }
 
 GroupPos
 Accessible::GroupPosition()
 {
   GroupPos groupPos;
 
   // Get group position from ARIA attributes.
@@ -2415,44 +2426,40 @@ Accessible::Shutdown()
   if (mParent)
     mParent->RemoveChild(this);
 
   nsAccessNodeWrap::Shutdown();
 }
 
 // Accessible protected
 void
-Accessible::ARIAName(nsAString& aName)
+Accessible::ARIAName(nsString& aName)
 {
-  nsAutoString label;
-
   // aria-labelledby now takes precedence over aria-label
   nsresult rv = nsTextEquivUtils::
-    GetTextEquivFromIDRefs(this, nsGkAtoms::aria_labelledby, label);
+    GetTextEquivFromIDRefs(this, nsGkAtoms::aria_labelledby, aName);
   if (NS_SUCCEEDED(rv)) {
-    label.CompressWhitespace();
-    aName = label;
+    aName.CompressWhitespace();
   }
 
-  if (label.IsEmpty() &&
-      mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_label,
-                        label)) {
-    label.CompressWhitespace();
-    aName = label;
+  if (aName.IsEmpty() &&
+      mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_label, aName)) {
+    aName.CompressWhitespace();
   }
 }
 
 // Accessible protected
 ENameValueFlag
 Accessible::NativeName(nsString& aName)
 {
   if (mContent->IsHTML())
-    GetHTMLName(aName);
-  else if (mContent->IsXUL())
-    GetXULName(aName);
+    return GetHTMLName(aName);
+
+  if (mContent->IsXUL())
+    return GetXULName(aName);
 
   return eNameOK;
 }
 
 // Accessible protected
 void
 Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent)
 {
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -54,16 +54,21 @@ enum ENameValueFlag {
 
  /**
   * Name was left empty by the author on purpose:
   * name.IsEmpty() && !name.IsVoid().
   */
  eNoNameOnPurpose,
 
  /**
+  * Name was computed from the subtree.
+  */
+ eNameFromSubtree,
+
+ /**
   * Tooltip was used as a name.
   */
  eNameFromTooltip
 };
 
 /**
  * Group position (level, position in set and set size).
  */
@@ -238,20 +243,19 @@ public:
   uint64_t VisibilityState();
 
   /**
    * Return true if native unavailable state present.
    */
   virtual bool NativelyUnavailable() const;
 
   /**
-   * Returns attributes for accessible without explicitly setted ARIA
-   * attributes.
+   * Return object attributes for the accessible.
    */
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> Attributes();
 
   /**
    * Return group position (level, position in set and set size).
    */
   virtual mozilla::a11y::GroupPos GroupPosition();
 
   /**
    * Used by ChildAtPoint() method to get direct or deepest child at point.
@@ -500,16 +504,18 @@ public:
   inline bool IsXULDeck() const { return mFlags & eXULDeckAccessible; }
 
   inline bool IsListControl() const { return mFlags & eListControlAccessible; }
 
   inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
 
   inline bool IsMenuPopup() const { return mFlags & eMenuPopupAccessible; }
 
+  inline bool IsProgress() const { return mFlags & eProgressAccessible; }
+
   inline bool IsRoot() const { return mFlags & eRootAccessible; }
   mozilla::a11y::RootAccessible* AsRoot();
 
   virtual mozilla::a11y::TableAccessible* AsTable() { return nullptr; }
 
   virtual mozilla::a11y::TableCellAccessible* AsTableCell() { return nullptr; }
 
   inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
@@ -700,16 +706,28 @@ public:
 
   /**
   * Return true if the accessible has a numeric value.
   */
   bool HasNumericValue() const;
 
 protected:
 
+  /**
+   * Return the accessible name provided by native markup. It doesn't take
+   * into account ARIA markup used to specify the name.
+   */
+  virtual mozilla::a11y::ENameValueFlag NativeName(nsString& aName);
+
+  /**
+   * Return object attributes provided by native markup. It doesn't take into
+   * account ARIA.
+   */
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes();
+
   //////////////////////////////////////////////////////////////////////////////
   // Initializing, cache and tree traverse methods
 
   /**
    * Cache accessible children.
    */
   virtual void CacheChildren();
 
@@ -771,49 +789,44 @@ protected:
     eHyperTextAccessible = 1 << 12,
     eHTMLFileInputAccessible = 1 << 13,
     eHTMLListItemAccessible = 1 << 14,
     eImageAccessible = 1 << 15,
     eImageMapAccessible = 1 << 16,
     eListControlAccessible = 1 << 17,
     eMenuButtonAccessible = 1 << 18,
     eMenuPopupAccessible = 1 << 19,
-    eRootAccessible = 1 << 20,
-    eTextLeafAccessible = 1 << 21,
-    eXULDeckAccessible = 1 << 22,
-    eXULTreeAccessible = 1 << 23
+    eProgressAccessible = 1 << 20,
+    eRootAccessible = 1 << 21,
+    eTextLeafAccessible = 1 << 22,
+    eXULDeckAccessible = 1 << 23,
+    eXULTreeAccessible = 1 << 24
   };
 
   //////////////////////////////////////////////////////////////////////////////
   // Miscellaneous helpers
 
   /**
    * Return ARIA role (helper method).
    */
   mozilla::a11y::role ARIATransformRole(mozilla::a11y::role aRole);
 
   //////////////////////////////////////////////////////////////////////////////
   // Name helpers
 
   /**
-   * Return the accessible name provided by native markup. It doesn't take
-   * into account ARIA markup used to specify the name.
-   */
-  virtual mozilla::a11y::ENameValueFlag NativeName(nsString& aName);
-
-  /**
    * Returns the accessible name specified by ARIA.
    */
-  void ARIAName(nsAString& aName);
+  void ARIAName(nsString& aName);
 
   /**
    * Compute the name of HTML/XUL node.
    */
-  void GetHTMLName(nsString& aName);
-  void GetXULName(nsString& aName);
+  mozilla::a11y::ENameValueFlag GetHTMLName(nsString& aName);
+  mozilla::a11y::ENameValueFlag GetXULName(nsString& aName);
 
   // helper method to verify frames
   static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
 
   /**
    * Return an accessible for the given DOM node, or if that node isn't
    * accessible, return the accessible for the next DOM node which has one
    * (based on forward depth first search).
--- a/accessible/src/generic/ApplicationAccessible.cpp
+++ b/accessible/src/generic/ApplicationAccessible.cpp
@@ -105,22 +105,20 @@ ApplicationAccessible::Value(nsString& a
 }
 
 uint64_t
 ApplicationAccessible::State()
 {
   return IsDefunct() ? states::DEFUNCT : 0;
 }
 
-NS_IMETHODIMP
-ApplicationAccessible::GetAttributes(nsIPersistentProperties** aAttributes)
+already_AddRefed<nsIPersistentProperties>
+ApplicationAccessible::NativeAttributes()
 {
-  NS_ENSURE_ARG_POINTER(aAttributes);
-  *aAttributes = nullptr;
-  return NS_OK;
+  return nullptr;
 }
 
 GroupPos
 ApplicationAccessible::GroupPosition()
 {
   return GroupPos();
 }
 
--- a/accessible/src/generic/ApplicationAccessible.h
+++ b/accessible/src/generic/ApplicationAccessible.h
@@ -40,17 +40,16 @@ public:
   // nsIAccessible
   NS_IMETHOD GetRootDocument(nsIAccessibleDocument** aRootDocument);
   NS_IMETHOD ScrollTo(uint32_t aScrollType);
   NS_IMETHOD ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY);
   NS_IMETHOD GetLanguage(nsAString& aLanguage);
   NS_IMETHOD GetParent(nsIAccessible **aParent);
   NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
   NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
   NS_IMETHOD GetBounds(int32_t *aX, int32_t *aY,
                        int32_t *aWidth, int32_t *aHeight);
   NS_IMETHOD SetSelected(bool aIsSelected);
   NS_IMETHOD TakeSelection();
   NS_IMETHOD TakeFocus();
   NS_IMETHOD GetActionName(uint8_t aIndex, nsAString &aName);
   NS_IMETHOD GetActionDescription(uint8_t aIndex, nsAString &aDescription);
   NS_IMETHOD DoAction(uint8_t aIndex);
@@ -58,16 +57,17 @@ public:
   // nsIAccessibleApplication
   NS_DECL_NSIACCESSIBLEAPPLICATION
 
   // nsAccessNode
   virtual void Init();
   virtual void Shutdown();
 
   // Accessible
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual GroupPos GroupPosition();
   virtual ENameValueFlag Name(nsString& aName);
   virtual void ApplyARIAState(uint64_t* aState) const;
   virtual void Description(nsString& aDescription);
   virtual void Value(nsString& aValue);
   virtual mozilla::a11y::role NativeRole();
   virtual uint64_t State();
   virtual uint64_t NativeState();
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -38,16 +38,17 @@
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
 #include "nsFocusManager.h"
+#include "mozilla/Assertions.h"
 #include "mozilla/dom/Element.h"
 
 #ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
@@ -80,18 +81,18 @@ DocAccessible::
                   nsIPresShell* aPresShell) :
   HyperTextAccessibleWrap(aRootContent, this),
   mDocument(aDocument), mScrollPositionChangedTicks(0),
   mLoadState(eTreeConstructionPending), mLoadEventType(0),
   mVirtualCursor(nullptr),
   mPresShell(aPresShell)
 {
   mFlags |= eDocAccessible | eNotNodeMapEntry;
-  if (mPresShell)
-    mPresShell->SetAccDocument(this);
+  MOZ_ASSERT(mPresShell, "should have been given a pres shell");
+  mPresShell->SetDocAccessible(this);
 
   mDependentIDsHash.Init();
   // XXX aaronl should we use an algorithm for the initial cache size?
   mAccessibleCache.Init(kDefaultCacheSize);
   mNodeToAccessibleMap.Init(kDefaultCacheSize);
 
   // If this is a XUL Document, it should not implement nsHyperText
   if (mDocument && mDocument->IsXUL())
@@ -333,27 +334,34 @@ DocAccessible::ApplyARIAState(uint64_t* 
 {
   // Combine with states from outer doc
   // 
   Accessible::ApplyARIAState(aState);
 
   // Allow iframe/frame etc. to have final state override via ARIA
   if (mParent)
     mParent->ApplyARIAState(aState);
-
 }
 
-NS_IMETHODIMP
-DocAccessible::GetAttributes(nsIPersistentProperties** aAttributes)
+already_AddRefed<nsIPersistentProperties>
+DocAccessible::Attributes()
 {
-  Accessible::GetAttributes(aAttributes);
-  if (mParent) {
-    mParent->GetAttributes(aAttributes); // Add parent attributes (override inner)
-  }
-  return NS_OK;
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    HyperTextAccessibleWrap::Attributes();
+
+  if (!mParent)
+    return attributes.forget();
+
+  // Override ARIA object attributes from outerdoc.
+  aria::AttrIterator attribIter(mParent->GetContent());
+  nsAutoString name, value, unused;
+  while(attribIter.Next(name, value))
+    attributes->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused);
+
+  return attributes.forget();
 }
 
 Accessible*
 DocAccessible::FocusedChild()
 {
   // Return an accessible for the current global focus, which does not have to
   // be contained within the current document.
   return FocusMgr()->FocusedAccessible();
@@ -631,17 +639,17 @@ DocAccessible::Shutdown()
   if (!mPresShell) // already shutdown
     return;
 
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocDestroy))
     logging::DocDestroy("document shutdown", mDocument, this);
 #endif
 
-  mPresShell->SetAccDocument(nullptr);
+  mPresShell->SetDocAccessible(nullptr);
 
   if (mNotificationController) {
     mNotificationController->Shutdown();
     mNotificationController = nullptr;
   }
 
   RemoveEventListeners();
 
@@ -1116,16 +1124,24 @@ DocAccessible::AttributeChangedImpl(nsIC
   }
 
   if (aAttribute == nsGkAtoms::contenteditable) {
     nsRefPtr<AccEvent> editableChangeEvent =
       new AccStateChangeEvent(aContent, states::EDITABLE);
     FireDelayedAccessibleEvent(editableChangeEvent);
     return;
   }
+
+  if (aAttribute == nsGkAtoms::value) {
+    Accessible* accessible = GetAccessible(aContent);
+    if(accessible && accessible->IsProgress()) {
+      FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
+                                 aContent);
+    }
+  }
 }
 
 // DocAccessible protected member
 void
 DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
 {
   // Note: For universal/global ARIA states and properties we don't care if
   // there is an ARIA role present or not.
@@ -1373,17 +1389,17 @@ Accessible*
 DocAccessible::GetAccessibleOrContainer(nsINode* aNode)
 {
   if (!aNode || !aNode->IsInDoc())
     return nullptr;
 
   nsINode* currNode = aNode;
   Accessible* accessible = nullptr;
   while (!(accessible = GetAccessible(currNode)) &&
-         (currNode = currNode->GetNodeParent()));
+         (currNode = currNode->GetParentNode()));
 
   return accessible;
 }
 
 bool
 DocAccessible::BindToDocument(Accessible* aAccessible,
                               nsRoleMapEntry* aRoleMapEntry)
 {
--- a/accessible/src/generic/DocAccessible.h
+++ b/accessible/src/generic/DocAccessible.h
@@ -63,17 +63,16 @@ class DocAccessible : public HyperTextAc
 
 public:
 
   DocAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
                 nsIPresShell* aPresShell);
   virtual ~DocAccessible();
 
   // nsIAccessible
-  NS_IMETHOD GetAttributes(nsIPersistentProperties** aAttributes);
   NS_IMETHOD TakeFocus(void);
 
   // nsIScrollPositionListener
   virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) {}
   virtual void ScrollPositionDidChange(nscoord aX, nscoord aY);
 
   // nsIDocumentObserver
   NS_DECL_NSIDOCUMENTOBSERVER
@@ -89,16 +88,17 @@ public:
   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;
   virtual bool NativelyUnavailable() const;
   virtual void ApplyARIAState(uint64_t* aState) const;
+  virtual already_AddRefed<nsIPersistentProperties> Attributes();
 
   virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
 
 #ifdef A11Y_LOG
   virtual nsresult HandleAccEvent(AccEvent* aEvent);
 #endif
 
   virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
@@ -264,17 +264,17 @@ public:
    */
   Accessible* GetAccessibleOrContainer(nsINode* aNode);
 
   /**
    * Return a container accessible for the given DOM node.
    */
   Accessible* GetContainerAccessible(nsINode* aNode)
   {
-    return aNode ? GetAccessibleOrContainer(aNode->GetNodeParent()) : nullptr;
+    return aNode ? GetAccessibleOrContainer(aNode->GetParentNode()) : nullptr;
   }
 
   /**
    * Return true if the given ID is referred by relation attribute.
    *
    * @note Different elements may share the same ID if they are hosted inside
    *       XBL bindings. Be careful the result of this method may be  senseless
    *       while it's called for XUL elements (where XBL is used widely).
--- a/accessible/src/generic/FormControlAccessible.h
+++ b/accessible/src/generic/FormControlAccessible.h
@@ -16,17 +16,17 @@ namespace a11y {
   */
 template<int Max>
 class ProgressMeterAccessible : public LeafAccessible
 {
 public:
   ProgressMeterAccessible(nsIContent* aContent, DocAccessible* aDoc) :
     LeafAccessible(aContent, aDoc)
   {
-    mFlags = mFlags | eHasNumericValue;
+    mFlags |= eHasNumericValue | eProgressAccessible;
   }
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLEVALUE
 
   // Accessible
   virtual void Value(nsString& aValue);
   virtual mozilla::a11y::role NativeRole();
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -1130,64 +1130,61 @@ HyperTextAccessible::GetLevelInternal()
   if (tag == nsGkAtoms::h5)
     return 5;
   if (tag == nsGkAtoms::h6)
     return 6;
 
   return AccessibleWrap::GetLevelInternal();
 }
 
-nsresult
-HyperTextAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
+already_AddRefed<nsIPersistentProperties>
+HyperTextAccessible::NativeAttributes()
 {
-  nsresult rv = AccessibleWrap::GetAttributesInternal(aAttributes);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    AccessibleWrap::NativeAttributes();
 
-  // Indicate when the current object uses block-level formatting
-  // via formatting: block
-  // XXX: 'formatting' attribute is deprecated and will be removed in Mozilla2,
-  // use 'display' attribute instead.
+  // 'formatting' attribute is deprecated, 'display' attribute should be
+  // instead.
   nsIFrame *frame = GetFrame();
   if (frame && frame->GetType() == nsGkAtoms::blockFrame) {
-    nsAutoString oldValueUnused;
-    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("formatting"), NS_LITERAL_STRING("block"),
-                                   oldValueUnused);
+    nsAutoString unused;
+    attributes->SetStringProperty(NS_LITERAL_CSTRING("formatting"),
+                                  NS_LITERAL_STRING("block"), unused);
   }
 
   if (FocusMgr()->IsFocused(this)) {
     int32_t lineNumber = CaretLineNumber();
     if (lineNumber >= 1) {
       nsAutoString strLineNumber;
       strLineNumber.AppendInt(lineNumber);
-      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::lineNumber,
-                             strLineNumber);
+      nsAccUtils::SetAccAttr(attributes, nsGkAtoms::lineNumber, strLineNumber);
     }
   }
 
   // For the html landmark elements we expose them like we do aria landmarks to
   // make AT navigation schemes "just work". Note html:header is redundant as
   // a landmark since it usually contains headings. We're not yet sure how the
   // web will use html:footer but our best bet right now is as contentinfo.
   if (mContent->Tag() == nsGkAtoms::nav)
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("navigation"));
   else if (mContent->Tag() == nsGkAtoms::section) 
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("region"));
   else if (mContent->Tag() == nsGkAtoms::footer) 
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("contentinfo"));
   else if (mContent->Tag() == nsGkAtoms::aside) 
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("complementary"));
   else if (mContent->Tag() == nsGkAtoms::article)
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("article"));
 
-  return  NS_OK;
+  return attributes.forget();
 }
 
 /*
  * Given an offset, the x, y, width, and height values are filled appropriately.
  */
 NS_IMETHODIMP
 HyperTextAccessible::GetCharacterExtents(int32_t aOffset, int32_t* aX, int32_t* aY,
                                          int32_t* aWidth, int32_t* aHeight,
@@ -1948,22 +1945,24 @@ HyperTextAccessible::ScrollSubstringToPo
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible public
 
 // Accessible protected
 ENameValueFlag
 HyperTextAccessible::NativeName(nsString& aName)
 {
-  AccessibleWrap::NativeName(aName);
+  ENameValueFlag nameFlag = AccessibleWrap::NativeName(aName);
+  if (!aName.IsEmpty())
+    return nameFlag;
 
   // Get name from title attribute for HTML abbr and acronym elements making it
   // a valid name from markup. Otherwise their name isn't picked up by recursive
   // name computation algorithm. See NS_OK_NAME_FROM_TOOLTIP.
-  if (aName.IsEmpty() && IsAbbreviation() &&
+  if (IsAbbreviation() &&
       mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName))
     aName.CompressWhitespace();
 
   return eNameOK;
 }
 
 void
 HyperTextAccessible::InvalidateChildren()
--- a/accessible/src/generic/HyperTextAccessible.h
+++ b/accessible/src/generic/HyperTextAccessible.h
@@ -46,17 +46,17 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLETEXT
   NS_DECL_NSIACCESSIBLEHYPERTEXT
   NS_DECL_NSIACCESSIBLEEDITABLETEXT
 
   // Accessible
   virtual int32_t GetLevelInternal();
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual mozilla::a11y::role NativeRole();
   virtual uint64_t NativeState();
 
   virtual void InvalidateChildren();
   virtual bool RemoveChild(Accessible* aAccessible);
 
   // HyperTextAccessible (static helper method)
 
--- a/accessible/src/generic/ImageAccessible.cpp
+++ b/accessible/src/generic/ImageAccessible.cpp
@@ -72,26 +72,25 @@ ImageAccessible::NativeState()
 ENameValueFlag
 ImageAccessible::NativeName(nsString& aName)
 {
   bool hasAltAttrib =
     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName);
   if (!aName.IsEmpty())
     return eNameOK;
 
-  Accessible::NativeName(aName);
-  if (aName.IsEmpty() && hasAltAttrib) {
-    // No accessible name but empty 'alt' attribute is present. If further name
-    // computation algorithm doesn't provide non empty name then it means
-    // an empty 'alt' attribute was used to indicate a decorative image (see
-    // nsIAccessible::name attribute for details).
-    return eNoNameOnPurpose;
-  }
+  ENameValueFlag nameFlag = Accessible::NativeName(aName);
+  if (!aName.IsEmpty())
+    return nameFlag;
 
-  return eNameOK;
+  // No accessible name but empty 'alt' attribute is present. If further name
+  // computation algorithm doesn't provide non empty name then it means
+  // an empty 'alt' attribute was used to indicate a decorative image (see
+  // Accessible::Name() method for details).
+  return hasAltAttrib ? eNoNameOnPurpose : eNameOK;
 }
 
 role
 ImageAccessible::NativeRole()
 {
   return roles::GRAPHIC;
 }
 
@@ -165,31 +164,28 @@ ImageAccessible::GetImagePosition(uint32
 NS_IMETHODIMP
 ImageAccessible::GetImageSize(int32_t* aWidth, int32_t* aHeight)
 {
   int32_t x, y;
   return GetBounds(&x, &y, aWidth, aHeight);
 }
 
 // Accessible
-nsresult
-ImageAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
+already_AddRefed<nsIPersistentProperties>
+ImageAccessible::NativeAttributes()
 {
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsresult rv = LinkableAccessible::GetAttributesInternal(aAttributes);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    LinkableAccessible::NativeAttributes();
 
   nsAutoString src;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
   if (!src.IsEmpty())
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::src, src);
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::src, src);
 
-  return NS_OK;
+  return attributes.forget();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Private methods
 
 already_AddRefed<nsIURI>
 ImageAccessible::GetLongDescURI() const
 {
--- a/accessible/src/generic/ImageAccessible.h
+++ b/accessible/src/generic/ImageAccessible.h
@@ -33,17 +33,17 @@ public:
   NS_IMETHOD DoAction(uint8_t index);
 
   // nsIAccessibleImage
   NS_DECL_NSIACCESSIBLEIMAGE
 
   // Accessible
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
 
   // ActionAccessible
   virtual uint8_t ActionCount();
 
 protected:
   // Accessible
   virtual ENameValueFlag NativeName(nsString& aName) MOZ_OVERRIDE;
 
--- a/accessible/src/generic/OuterDocAccessible.cpp
+++ b/accessible/src/generic/OuterDocAccessible.cpp
@@ -62,29 +62,16 @@ OuterDocAccessible::ChildAtPoint(int32_t
   Accessible* child = GetChildAt(0);
   NS_ENSURE_TRUE(child, nullptr);
 
   if (aWhichChild == eDeepestChild)
     return child->ChildAtPoint(aX, aY, eDeepestChild);
   return child;
 }
 
-nsresult
-OuterDocAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
-{
-  nsAutoString tag;
-  aAttributes->GetStringProperty(NS_LITERAL_CSTRING("tag"), tag);
-  if (!tag.IsEmpty()) {
-    // We're overriding the ARIA attributes on an sub document, but we don't want to
-    // override the other attributes
-    return NS_OK;
-  }
-  return Accessible::GetAttributesInternal(aAttributes);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessible
 
 uint8_t
 OuterDocAccessible::ActionCount()
 {
   // Internal frame, which is the doc's parent, should not have a click action.
   return 0;
--- a/accessible/src/generic/OuterDocAccessible.h
+++ b/accessible/src/generic/OuterDocAccessible.h
@@ -33,17 +33,16 @@ public:
   NS_IMETHOD GetActionDescription(uint8_t aIndex, nsAString& aDescription);
   NS_IMETHOD DoAction(uint8_t aIndex);
 
   // nsAccessNode
   virtual void Shutdown();
 
   // Accessible
   virtual mozilla::a11y::role NativeRole();
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
                                    EWhichChildAtPoint aWhichChild);
 
   virtual void InvalidateChildren();
   virtual bool AppendChild(Accessible* aAccessible);
   virtual bool RemoveChild(Accessible* aAccessible);
 
   // ActionAccessible
--- a/accessible/src/generic/RootAccessible.cpp
+++ b/accessible/src/generic/RootAccessible.cpp
@@ -470,19 +470,23 @@ RootAccessible::ProcessDOMEvent(nsIDOMEv
 
     FocusMgr()->ActiveItemChanged(nullptr);
 #ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eFocus))
       logging::ActiveItemChangeCausedBy("DOMMenuBarInactive", accessible);
 #endif
   }
   else if (eventType.EqualsLiteral("ValueChange")) {
-    targetDocument->
-      FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
-                                 targetNode, AccEvent::eRemoveDupes);
+
+    //We don't process 'ValueChange' events for progress meters since we listen
+    //@value attribute change for them.
+    if (!accessible->IsProgress())
+      targetDocument->
+        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
+                                   targetNode);
   }
 #ifdef DEBUG_DRAGDROPSTART
   else if (eventType.EqualsLiteral("mouseover")) {
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_DRAGDROP_START,
                             accessible);
   }
 #endif
 }
--- a/accessible/src/html/HTMLElementAccessibles.cpp
+++ b/accessible/src/html/HTMLElementAccessibles.cpp
@@ -53,17 +53,17 @@ HTMLBRAccessible::NativeName(nsString& a
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLLabelAccessible, HyperTextAccessible)
 
 ENameValueFlag
 HTMLLabelAccessible::NativeName(nsString& aName)
 {
   nsTextEquivUtils::GetNameFromSubtree(this, aName);
-  return eNameOK;
+  return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
 }
 
 role
 HTMLLabelAccessible::NativeRole()
 {
   return roles::LABEL;
 }
 
@@ -84,20 +84,19 @@ HTMLOutputAccessible::RelationByType(uin
 }
 
 role
 HTMLOutputAccessible::NativeRole()
 {
   return roles::SECTION;
 }
 
-nsresult
-HTMLOutputAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
+already_AddRefed<nsIPersistentProperties>
+HTMLOutputAccessible::NativeAttributes()
 {
-  nsresult rv = AccessibleWrap::GetAttributesInternal(aAttributes);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::live,
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    AccessibleWrap::NativeAttributes();
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::live,
                          NS_LITERAL_STRING("polite"));
 
-  return NS_OK;
+  return attributes.forget();
 }
 
--- a/accessible/src/html/HTMLElementAccessibles.h
+++ b/accessible/src/html/HTMLElementAccessibles.h
@@ -72,16 +72,16 @@ public:
 
   HTMLOutputAccessible(nsIContent* aContent, DocAccessible* aDoc) :
     HyperTextAccessibleWrap(aContent, aDoc) {};
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // Accessible
   virtual a11y::role NativeRole();
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties* aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual Relation RelationByType(uint32_t aType);
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/src/html/HTMLFormControlAccessible.cpp
+++ b/accessible/src/html/HTMLFormControlAccessible.cpp
@@ -254,23 +254,23 @@ role
 HTMLButtonAccessible::NativeRole()
 {
   return roles::PUSHBUTTON;
 }
 
 ENameValueFlag
 HTMLButtonAccessible::NativeName(nsString& aName)
 {
-  Accessible::NativeName(aName);
+  ENameValueFlag nameFlag = Accessible::NativeName(aName);
   if (!aName.IsEmpty() || mContent->Tag() != nsGkAtoms::input)
-    return eNameOK;
+    return nameFlag;
 
-  // No name from HTML or ARIA
-  if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName) &&
-      !mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName)) {
+  // Note: No need to check @value attribute since it results in anonymous text
+  // node. The name is calculated from subtree in this case.
+  if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName)) {
     // Use the button's (default) label if nothing else works
     nsIFrame* frame = GetFrame();
     if (frame) {
       nsIFormControlFrame* fcFrame = do_QueryFrame(frame);
       if (fcFrame)
         fcFrame->GetFormProperty(nsGkAtoms::defaultLabel, aName);
     }
   }
@@ -318,19 +318,19 @@ HTMLTextFieldAccessible::NativeRole()
   }
   
   return roles::ENTRY;
 }
 
 ENameValueFlag
 HTMLTextFieldAccessible::NativeName(nsString& aName)
 {
-  Accessible::NativeName(aName);
+  ENameValueFlag nameFlag = Accessible::NativeName(aName);
   if (!aName.IsEmpty())
-    return eNameOK;
+    return nameFlag;
 
   if (mContent->GetBindingParent()) {
     // XXX: bug 459640
     // There's a binding parent.
     // This means we're part of another control, so use parent accessible for name.
     // This ensures that a textbox inside of a XUL widget gets
     // an accessible name.
     Accessible* parent = Parent();
@@ -608,19 +608,19 @@ HTMLGroupboxAccessible::GetLegend()
   }
 
   return nullptr;
 }
 
 ENameValueFlag
 HTMLGroupboxAccessible::NativeName(nsString& aName)
 {
-  Accessible::NativeName(aName);
+  ENameValueFlag nameFlag = Accessible::NativeName(aName);
   if (!aName.IsEmpty())
-    return eNameOK;
+    return nameFlag;
 
   nsIContent* legendContent = GetLegend();
   if (legendContent)
     nsTextEquivUtils::AppendTextEquivFromContent(this, legendContent, &aName);
 
   return eNameOK;
 }
 
@@ -670,40 +670,40 @@ HTMLLegendAccessible::NativeRole()
 ////////////////////////////////////////////////////////////////////////////////
 
 HTMLFigureAccessible::
   HTMLFigureAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc)
 {
 }
 
-nsresult
-HTMLFigureAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
+already_AddRefed<nsIPersistentProperties>
+HTMLFigureAccessible::NativeAttributes()
 {
-  nsresult rv = HyperTextAccessibleWrap::GetAttributesInternal(aAttributes);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    HyperTextAccessibleWrap::NativeAttributes();
 
   // Expose figure xml-role.
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                          NS_LITERAL_STRING("figure"));
-  return NS_OK;
+  return attributes.forget();
 }
 
 role
 HTMLFigureAccessible::NativeRole()
 {
   return roles::FIGURE;
 }
 
 ENameValueFlag
 HTMLFigureAccessible::NativeName(nsString& aName)
 {
-  HyperTextAccessibleWrap::NativeName(aName);
+  ENameValueFlag nameFlag = HyperTextAccessibleWrap::NativeName(aName);
   if (!aName.IsEmpty())
-    return eNameOK;
+    return nameFlag;
 
   nsIContent* captionContent = Caption();
   if (captionContent)
     nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent, &aName);
 
   return eNameOK;
 }
 
--- a/accessible/src/html/HTMLFormControlAccessible.h
+++ b/accessible/src/html/HTMLFormControlAccessible.h
@@ -184,17 +184,17 @@ public:
  * Accessible for HTML5 figure element.
  */
 class HTMLFigureAccessible : public HyperTextAccessibleWrap
 {
 public:
   HTMLFigureAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // Accessible
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties* aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual mozilla::a11y::role NativeRole();
   virtual Relation RelationByType(uint32_t aType);
 
 protected:
   // Accessible
   virtual ENameValueFlag NativeName(nsString& aName) MOZ_OVERRIDE;
 
   // HTMLLegendAccessible
--- a/accessible/src/html/HTMLImageMapAccessible.cpp
+++ b/accessible/src/html/HTMLImageMapAccessible.cpp
@@ -158,19 +158,19 @@ HTMLAreaAccessible::
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLAreaAccessible: nsIAccessible
 
 ENameValueFlag
 HTMLAreaAccessible::NativeName(nsString& aName)
 {
-  Accessible::NativeName(aName);
+  ENameValueFlag nameFlag = Accessible::NativeName(aName);
   if (!aName.IsEmpty())
-    return eNameOK;
+    return nameFlag;
 
   if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
     GetValue(aName);
 
   return eNameOK;
 }
 
 void
--- a/accessible/src/html/HTMLSelectAccessible.cpp
+++ b/accessible/src/html/HTMLSelectAccessible.cpp
@@ -195,16 +195,17 @@ HTMLSelectOptionAccessible::NativeName(n
     return eNameOK;
 
   // CASE #2 -- no label parameter, get the first child, 
   // use it if it is a text node
   nsIContent* text = mContent->GetFirstChild();
   if (text && text->IsNodeOfType(nsINode::eTEXT)) {
     nsTextEquivUtils::AppendTextEquivFromTextContent(text, &aName);
     aName.CompressWhitespace();
+    return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
   }
 
   return eNameOK;
 }
 
 uint64_t
 HTMLSelectOptionAccessible::NativeState()
 {
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -88,37 +88,35 @@ HTMLTableCellAccessible::NativeState()
 }
 
 uint64_t
 HTMLTableCellAccessible::NativeInteractiveState() const
 {
   return HyperTextAccessibleWrap::NativeInteractiveState() | states::SELECTABLE;
 }
 
-nsresult
-HTMLTableCellAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
+already_AddRefed<nsIPersistentProperties>
+HTMLTableCellAccessible::NativeAttributes()
 {
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsresult rv = HyperTextAccessibleWrap::GetAttributesInternal(aAttributes);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    HyperTextAccessibleWrap::NativeAttributes();
 
   // table-cell-index attribute
   TableAccessible* table = Table();
   if (!table)
-    return NS_OK;
+    return attributes.forget();
 
   int32_t rowIdx = -1, colIdx = -1;
-  rv = GetCellIndexes(rowIdx, colIdx);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsresult rv = GetCellIndexes(rowIdx, colIdx);
+  if (NS_FAILED(rv))
+    return attributes.forget();
 
   nsAutoString stringIdx;
   stringIdx.AppendInt(table->CellIndexAt(rowIdx, colIdx));
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex, stringIdx);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
 
   // abbr attribute
 
   // Pick up object attribute from abbr DOM element (a child of the cell) or
   // from abbr DOM attribute.
   nsAutoString abbrText;
   if (ChildCount() == 1) {
     Accessible* abbr = FirstChild();
@@ -127,25 +125,25 @@ HTMLTableCellAccessible::GetAttributesIn
         AppendTextEquivFromTextContent(abbr->GetContent()->GetFirstChild(),
                                        &abbrText);
     }
   }
   if (abbrText.IsEmpty())
     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::abbr, abbrText);
 
   if (!abbrText.IsEmpty())
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::abbr, abbrText);
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::abbr, abbrText);
 
   // axis attribute
   nsAutoString axisText;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::axis, axisText);
   if (!axisText.IsEmpty())
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::axis, axisText);
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::axis, axisText);
 
-  return NS_OK;
+  return attributes.forget();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableCellAccessible: nsIAccessibleTableCell implementation
 
 TableAccessible*
 HTMLTableCellAccessible::Table() const
 {
@@ -383,19 +381,19 @@ uint64_t
 HTMLTableAccessible::NativeState()
 {
   return Accessible::NativeState() | states::READONLY;
 }
 
 ENameValueFlag
 HTMLTableAccessible::NativeName(nsString& aName)
 {
-  Accessible::NativeName(aName);
+  ENameValueFlag nameFlag = Accessible::NativeName(aName);
   if (!aName.IsEmpty())
-    return eNameOK;
+    return nameFlag;
 
   // Use table caption as a name.
   Accessible* caption = Caption();
   if (caption) {
     nsIContent* captionContent = caption->GetContent();
     if (captionContent) {
       nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent, &aName);
       if (!aName.IsEmpty())
@@ -403,29 +401,28 @@ HTMLTableAccessible::NativeName(nsString
     }
   }
 
   // If no caption then use summary as a name.
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, aName);
   return eNameOK;
 }
 
-nsresult
-HTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
+already_AddRefed<nsIPersistentProperties>
+HTMLTableAccessible::NativeAttributes()
 {
-  nsresult rv = AccessibleWrap::GetAttributesInternal(aAttributes);
-  NS_ENSURE_SUCCESS(rv, rv);
-
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    AccessibleWrap::NativeAttributes();
   if (IsProbablyLayoutTable()) {
-    nsAutoString oldValueUnused;
-    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
-                                   NS_LITERAL_STRING("true"), oldValueUnused);
+    nsAutoString unused;
+    attributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
+                                  NS_LITERAL_STRING("true"), unused);
   }
 
-  return NS_OK;
+  return attributes.forget();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableAccessible: nsIAccessible implementation
 
 Relation
 HTMLTableAccessible::RelationByType(uint32_t aType)
 {
@@ -957,17 +954,17 @@ HTMLTableAccessible::Description(nsStrin
 }
 
 bool
 HTMLTableAccessible::HasDescendant(const nsAString& aTagName, bool aAllowEmpty)
 {
   nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mContent));
   NS_ENSURE_TRUE(tableElt, false);
 
-  nsCOMPtr<nsIDOMNodeList> nodeList;
+  nsCOMPtr<nsIDOMHTMLCollection> nodeList;
   tableElt->GetElementsByTagName(aTagName, getter_AddRefs(nodeList));
   NS_ENSURE_TRUE(nodeList, false);
 
   nsCOMPtr<nsIDOMNode> foundItem;
   nodeList->Item(0, getter_AddRefs(foundItem));
   if (!foundItem)
     return false;
 
--- a/accessible/src/html/HTMLTableAccessible.h
+++ b/accessible/src/html/HTMLTableAccessible.h
@@ -37,17 +37,17 @@ public:
   NS_FORWARD_NSIACCESSIBLETABLECELL(xpcAccessibleTableCell::)
 
   // Accessible
   virtual TableCellAccessible* AsTableCell() { return this; }
   virtual void Shutdown();
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual uint64_t NativeInteractiveState() const;
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
 
   // TableCellAccessible
   virtual TableAccessible* Table() const MOZ_OVERRIDE;
   virtual uint32_t ColIdx() const MOZ_OVERRIDE;
   virtual uint32_t RowIdx() const MOZ_OVERRIDE;
   virtual uint32_t ColExtent() const MOZ_OVERRIDE;
   virtual uint32_t RowExtent() const MOZ_OVERRIDE;
   virtual void ColHeaderCells(nsTArray<Accessible*>* aCells) MOZ_OVERRIDE;
@@ -140,17 +140,17 @@ public:
   // nsAccessNode
   virtual void Shutdown();
 
   // Accessible
   virtual TableAccessible* AsTable() { return this; }
   virtual void Description(nsString& aDescription);
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual Relation RelationByType(uint32_t aRelationType);
 
   // HTMLTableAccessible
 
   /**
    * Retun cell element at the given row and column index.
    */
   nsresult GetCellAt(int32_t aRowIndex, int32_t aColIndex,
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -93,17 +93,19 @@ var AccessFu = {
 
     Input.attach(this.chromeWin);
     Output.attach(this.chromeWin);
     this.touchAdapter.attach(this.chromeWin);
 
     Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
     Services.obs.addObserver(this, 'Accessibility:NextObject', false);
     Services.obs.addObserver(this, 'Accessibility:PreviousObject', false);
-    Services.obs.addObserver(this, 'Accessibility:CurrentObject', false);
+    Services.obs.addObserver(this, 'Accessibility:Focus', false);
+    this.chromeWin.addEventListener('TabOpen', this);
+    this.chromeWin.addEventListener('TabSelect', this);
   },
 
   /**
    * Disable AccessFu and return to default interaction mode.
    */
   _disable: function _disable() {
     if (!this._enabled)
       return;
@@ -113,31 +115,34 @@ var AccessFu = {
     Logger.info('disable');
 
     this.chromeWin.document.removeChild(this.stylesheet);
     for each (let mm in Utils.getAllMessageManagers(this.chromeWin))
       mm.sendAsyncMessage('AccessFu:Stop');
 
     Input.detach();
 
+    this.chromeWin.removeEventListener('TabOpen', this);
+    this.chromeWin.removeEventListener('TabSelect', this);
+
     Services.obs.removeObserver(this, 'remote-browser-frame-shown');
     Services.obs.removeObserver(this, 'Accessibility:NextObject');
     Services.obs.removeObserver(this, 'Accessibility:PreviousObject');
-    Services.obs.removeObserver(this, 'Accessibility:CurrentObject');
+    Services.obs.removeObserver(this, 'Accessibility:Focus');
   },
 
   _enableOrDisable: function _enableOrDisable() {
     try {
       if (this._activatePref == ACCESSFU_ENABLE ||
           this._systemPref && this._activatePref == ACCESSFU_AUTO)
         this._enable();
       else
         this._disable();
     } catch (x) {
-      Logger.error(x);
+      Logger.logException(x);
     }
   },
 
   receiveMessage: function receiveMessage(aMessage) {
     if (Logger.logLevel >= Logger.DEBUG)
       Logger.debug('Recieved', aMessage.name, JSON.stringify(aMessage.json));
 
     switch (aMessage.name) {
@@ -147,17 +152,17 @@ var AccessFu = {
                           {method: 'start', buildApp: Utils.MozBuildApp});
       break;
       case 'AccessFu:Present':
       try {
         for each (let presenter in aMessage.json) {
           Output[presenter.type](presenter.details, aMessage.target);
         }
       } catch (x) {
-        Logger.error(x);
+        Logger.logException(x);
       }
       break;
       case 'AccessFu:Input':
       Input.setEditState(aMessage.json);
       break;
     }
   },
 
@@ -178,21 +183,23 @@ var AccessFu = {
         this._enableOrDisable();
         break;
       case 'Accessibility:NextObject':
         Input.moveCursor('moveNext', 'Simple', 'gesture');
         break;
       case 'Accessibility:PreviousObject':
         Input.moveCursor('movePrevious', 'Simple', 'gesture');
         break;
-      case 'Accessibility:CurrentObject':
-        let mm = Utils.getCurrentBrowser(this.chromeWin).
-          frameLoader.messageManager;
-        mm.sendAsyncMessage('AccessFu:VirtualCursor',
-                            {action: 'presentLastPivot'});
+      case 'Accessibility:Focus':
+        this._focused = JSON.parse(aData);
+        if (this._focused) {
+          let mm = Utils.getMessageManager(Utils.getCurrentBrowser(this.chromeWin));
+          mm.sendAsyncMessage('AccessFu:VirtualCursor',
+                              {action: 'whereIsIt', move: true});
+        }
         break;
       case 'nsPref:changed':
         if (aData == 'activate') {
           this._activatePref = this.prefsBranch.getIntPref('activate');
           this._enableOrDisable();
         }
         break;
       case 'remote-browser-frame-shown':
@@ -200,25 +207,52 @@ var AccessFu = {
         this._loadFrameScript(
           aSubject.QueryInterface(Ci.nsIFrameLoader).messageManager);
         break;
       }
     }
   },
 
   handleEvent: function handleEvent(aEvent) {
-    if (aEvent.type == 'mozContentEvent' &&
-        aEvent.detail.type == 'accessibility-screenreader') {
-      this._systemPref = aEvent.detail.enabled;
-      this._enableOrDisable();
+    switch (aEvent.type) {
+      case 'mozContentEvent':
+      {
+        if (aEvent.detail.type == 'accessibility-screenreader') {
+          this._systemPref = aEvent.detail.enabled;
+          this._enableOrDisable();
+        }
+        break;
+      }
+      case 'TabOpen':
+      {
+        this._loadFrameScript(Utils.getMessageManager(aEvent.target));
+        break;
+      }
+      case 'TabSelect':
+      {
+        if (this._focused) {
+          let mm = Utils.getMessageManager(Utils.getCurrentBrowser(this.chromeWin));
+          // We delay this for half a second so the awesomebar could close,
+          // and we could use the current coordinates for the content item.
+          // XXX TODO figure out how to avoid magic wait here.
+          this.chromeWin.setTimeout(
+            function () {
+              mm.sendAsyncMessage('AccessFu:VirtualCursor', {action: 'whereIsIt'});
+            }, 500);
+        }
+        break;
+      }
     }
   },
 
   // So we don't enable/disable twice
-  _enabled: false
+  _enabled: false,
+
+  // Layerview is focused
+  _focused: false
 };
 
 var Output = {
   attach: function attach(aWindow) {
     this.chromeWin = aWindow;
   },
 
   Speech: function Speech(aDetails, aBrowser) {
@@ -302,17 +336,17 @@ var Input = {
       case 'keypress':
         this._handleKeypress(aEvent);
         break;
       case 'mozAccessFuGesture':
         this._handleGesture(aEvent);
         break;
       }
     } catch (x) {
-      Logger.error(x);
+      Logger.logException(x);
     }
   },
 
   _handleGesture: function _handleGesture(aEvent) {
     let detail = aEvent.detail;
     Logger.info('Gesture', detail.type,
                 '(fingers: ' + detail.touches.length + ')');
 
--- a/accessible/src/jsat/EventManager.jsm
+++ b/accessible/src/jsat/EventManager.jsm
@@ -37,17 +37,18 @@ var EventManager = {
       }
 
       this.present(
         function(p) {
           return p.tabStateChanged(null, 'newtab');
         }
       );
     } catch (x) {
-      Logger.error('Failed to start EventManager:', x);
+      Logger.error('Failed to start EventManager');
+      Logger.logException(x);
     }
   },
 
   stop: function stop() {
     Services.obs.removeObserver(this, 'accessible-event');
     this.presenters = [];
     this._started = false;
   },
@@ -72,51 +73,53 @@ var EventManager = {
             return p.actionInvoked(activatedAcc, 'click');
           }
         );
         break;
       }
       case 'scroll':
       case 'resize':
       {
+        // the target could be an element, document or window
+        let window = null;
+        if (aEvent.target instanceof Ci.nsIDOMWindow)
+          window = aEvent.target;
+        else if (aEvent.target instanceof Ci.nsIDOMDocument)
+          window = aEvent.target.defaultView;
+        else if (aEvent.target instanceof Ci.nsIDOMElement)
+          window = aEvent.target.ownerDocument.defaultView;
         this.present(
           function(p) {
-            return p.viewportChanged();;
+            return p.viewportChanged(window);
           }
         );
         break;
       }
       }
     } catch (x) {
-      Logger.error('Error handling DOM event:', x);
+      Logger.error('Error handling DOM event');
+      Logger.logException(x);
     }
   },
 
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case 'accessible-event':
         var event;
         try {
           event = aSubject.QueryInterface(Ci.nsIAccessibleEvent);
           this.handleAccEvent(event);
         } catch (x) {
-          Logger.error('Error handing accessible event:', x);
+          Logger.error('Error handing accessible event');
+          Logger.logException(x);
           return;
         }
     }
   },
 
-  presentLastPivot: function presentLastPivot() {
-    this.present(
-      function(p) {
-        return p.presentLastPivot();
-      }
-    );
-  },
-
   handleAccEvent: function handleAccEvent(aEvent) {
     if (Logger.logLevel >= Logger.DEBUG)
       Logger.debug('A11yEvent', Logger.eventToString(aEvent),
                    Logger.accessibleToString(aEvent.accessible));
 
     switch (aEvent.eventType) {
       case Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED:
       {
@@ -243,20 +246,31 @@ var EventManager = {
 
   present: function present(aPresenterFunc) {
     try {
       this.sendMsgFunc(
         "AccessFu:Present",
         [aPresenterFunc(p) for each (p in this.presenters)].
           filter(function(d) {return !!d;}));
     } catch (x) {
-      Logger.error(x);
+      Logger.logException(x);
     }
   },
 
+  presentVirtualCursorPosition: function presentVirtualCursorPosition(aVirtualCursor) {
+    let presenterContext =
+      new PresenterContext(aVirtualCursor.position, null);
+
+    this.present(
+      function(p) {
+        return p.pivotChanged(presenterContext, Ci.nsIAccessiblePivot.REASON_NONE);
+      }
+    );
+  },
+
   onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
     let tabstate = '';
 
     let loadingState = Ci.nsIWebProgressListener.STATE_TRANSFERRING |
       Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
     let loadedState = Ci.nsIWebProgressListener.STATE_STOP |
       Ci.nsIWebProgressListener.STATE_IS_NETWORK;
 
--- a/accessible/src/jsat/Presenters.jsm
+++ b/accessible/src/jsat/Presenters.jsm
@@ -99,22 +99,17 @@ Presenter.prototype = {
    *    landscape/portrait toggle.
    * @param {Window} aWindow window of viewport that changed.
    */
   viewportChanged: function viewportChanged(aWindow) {},
 
   /**
    * We have entered or left text editing mode.
    */
-  editingModeChanged: function editingModeChanged(aIsEditing) {},
-
-  /**
-   * Re-present the last pivot change.
-   */
-  presentLastPivot: function AndroidPresenter_presentLastPivot() {}
+  editingModeChanged: function editingModeChanged(aIsEditing) {}
 };
 
 /**
  * Visual presenter. Draws a box around the virtual cursor's position.
  */
 
 function VisualPresenter() {}
 
@@ -124,31 +119,33 @@ VisualPresenter.prototype = {
   type: 'Visual',
 
   /**
    * The padding in pixels between the object and the highlight border.
    */
   BORDER_PADDING: 2,
 
   viewportChanged: function VisualPresenter_viewportChanged(aWindow) {
-    if (this._currentContext)
+    if (this._currentAccessible) {
+      let context = new PresenterContext(this._currentAccessible);
       return {
         type: this.type,
         details: {
           method: 'show',
-          bounds: this._currentContext.bounds,
+          bounds: context.bounds,
           padding: this.BORDER_PADDING
         }
       };
+    }
 
     return null;
   },
 
   pivotChanged: function VisualPresenter_pivotChanged(aContext, aReason) {
-    this._currentContext = aContext;
+    this._currentAccessible = aContext.accessible;
 
     if (!aContext.accessible)
       return {type: this.type, details: {method: 'hide'}};
 
     try {
       aContext.accessible.scrollTo(
         Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE);
       return {
@@ -201,18 +198,16 @@ AndroidPresenter.prototype = {
   ANDROID_VIEW_SCROLLED: 0x1000,
   ANDROID_ANNOUNCEMENT: 0x4000,
   ANDROID_VIEW_ACCESSIBILITY_FOCUSED: 0x8000,
 
   pivotChanged: function AndroidPresenter_pivotChanged(aContext, aReason) {
     if (!aContext.accessible)
       return null;
 
-    this._currentContext = aContext;
-
     let androidEvents = [];
 
     let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT &&
                             Utils.AndroidSdkVersion >= 14);
     let focusEventType = (Utils.AndroidSdkVersion >= 16) ?
       this.ANDROID_VIEW_ACCESSIBILITY_FOCUSED :
       this.ANDROID_VIEW_FOCUSED;
 
@@ -268,38 +263,35 @@ AndroidPresenter.prototype = {
                                                              aPageState) {
     return this._appAnnounce(
       UtteranceGenerator.genForTabStateChange(aDocObj, aPageState));
   },
 
   textChanged: function AndroidPresenter_textChanged(aIsInserted, aStart,
                                                      aLength, aText,
                                                      aModifiedText) {
-    let androidEvent = {
-      type: this.type,
-      details: [{
-        eventType: this.ANDROID_VIEW_TEXT_CHANGED,
-        text: [aText],
-        fromIndex: aStart,
-        removedCount: 0,
-        addedCount: 0
-      }]
+    let eventDetails = {
+      eventType: this.ANDROID_VIEW_TEXT_CHANGED,
+      text: [aText],
+      fromIndex: aStart,
+      removedCount: 0,
+      addedCount: 0
     };
 
     if (aIsInserted) {
-      androidEvent.addedCount = aLength;
-      androidEvent.beforeText =
+      eventDetails.addedCount = aLength;
+      eventDetails.beforeText =
         aText.substring(0, aStart) + aText.substring(aStart + aLength);
     } else {
-      androidEvent.removedCount = aLength;
-      androidEvent.beforeText =
+      eventDetails.removedCount = aLength;
+      eventDetails.beforeText =
         aText.substring(0, aStart) + aModifiedText + aText.substring(aStart);
     }
 
-    return androidEvent;
+    return {type: this.type, details: [eventDetails]};
   },
 
   viewportChanged: function AndroidPresenter_viewportChanged(aWindow) {
     if (Utils.AndroidSdkVersion < 14)
       return null;
 
     return {
       type: this.type,
@@ -328,23 +320,16 @@ AndroidPresenter.prototype = {
         eventType: (Utils.AndroidSdkVersion >= 16) ?
           this.ANDROID_ANNOUNCEMENT : this.ANDROID_VIEW_TEXT_CHANGED,
         text: aUtterance,
         addedCount: aUtterance.join(' ').length,
         removedCount: 0,
         fromIndex: 0
       }]
     };
-  },
-
-  presentLastPivot: function AndroidPresenter_presentLastPivot() {
-    if (this._currentContext)
-      return this.pivotChanged(this._currentContext);
-    else
-      return null;
   }
 };
 
 /**
  * A speech presenter for direct TTS output
  */
 
 function SpeechPresenter() {}
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -84,42 +84,44 @@ var Utils = {
 
   getCurrentBrowser: function getCurrentBrowser(aWindow) {
     if (this.MozBuildApp == 'b2g')
       return this.getBrowserApp(aWindow).contentBrowser;
     return this.getBrowserApp(aWindow).selectedBrowser;
   },
 
   getCurrentContentDoc: function getCurrentContentDoc(aWindow) {
-    return this.getCurrentBrowser(aWindow).contentDocument;
+    let browser = this.getCurrentBrowser(aWindow);
+    return browser ? browser.contentDocument : null;
   },
 
   getMessageManager: function getMessageManager(aBrowser) {
     try {
       return aBrowser.QueryInterface(Ci.nsIFrameLoaderOwner).
          frameLoader.messageManager;
     } catch (x) {
-      Logger.error(x);
+      Logger.logException(x);
       return null;
     }
   },
 
   getAllMessageManagers: function getAllMessageManagers(aWindow) {
     let messageManagers = [];
 
     for (let i = 0; i < aWindow.messageManager.childCount; i++)
       messageManagers.push(aWindow.messageManager.getChildAt(i));
 
-    let remoteframes = this.getCurrentContentDoc(aWindow).
-      querySelectorAll('iframe[remote=true]');
+    let document = this.getCurrentContentDoc(aWindow);
 
-    for (let i = 0; i < remoteframes.length; ++i)
-      messageManagers.push(this.getMessageManager(remoteframes[i]));
+    if (document) {
+      let remoteframes = document.querySelectorAll('iframe[remote=true]');
 
-    Logger.info(messageManagers.length);
+      for (let i = 0; i < remoteframes.length; ++i)
+        messageManagers.push(this.getMessageManager(remoteframes[i]));
+    }
 
     return messageManagers;
   },
 
   getViewport: function getViewport(aWindow) {
     switch (this.MozBuildApp) {
       case 'mobile/android':
         return aWindow.BrowserApp.selectedTab.getViewport();
@@ -187,16 +189,26 @@ var Logger = {
       this, [this.WARNING].concat(Array.prototype.slice.call(arguments)));
   },
 
   error: function error() {
     this.log.apply(
       this, [this.ERROR].concat(Array.prototype.slice.call(arguments)));
   },
 
+  logException: function logException(aException) {
+    try {
+      this.error(
+        aException.message,
+        '(' + aException.fileName + ':' + aException.lineNumber + ')');
+    } catch (x) {
+      this.error(x);
+    }
+  },
+
   accessibleToString: function accessibleToString(aAccessible) {
     let str = '[ defunct ]';
     try {
       str = '[ ' + Utils.AccRetrieval.getStringRole(aAccessible.role) +
         ' | ' + aAccessible.name + ' ]';
     } catch (x) {
     }
 
--- a/accessible/src/jsat/content-script.js
+++ b/accessible/src/jsat/content-script.js
@@ -49,18 +49,24 @@ function virtualCursorControl(aMessage) 
         let acc = Utils.AccRetrieval.
           getAccessibleFor(content.document.activeElement);
         moved = vc.moveNext(rule, acc, true);
       }
       break;
     case 'moveToPoint':
       moved = vc.moveToPoint(rule, details.x, details.y, true);
       break;
-    case 'presentLastPivot':
-      EventManager.presentLastPivot();
+    case 'whereIsIt':
+      if (!forwardMessage(vc, aMessage)) {
+        if (!vc.position && aMessage.json.move)
+          vc.moveFirst(TraversalRules.Simple);
+        else
+          EventManager.presentVirtualCursorPosition(vc);
+      }
+
       break;
     default:
       break;
     }
 
     if (moved == true) {
       forwardMessage(vc, aMessage);
     } else if (moved == false && details.action != 'moveToPoint') {
--- a/accessible/src/mac/mozAccessible.mm
+++ b/accessible/src/mac/mozAccessible.mm
@@ -434,21 +434,20 @@ GetClosestInterestingAccessible(id anObj
 
 - (NSString*)subrole
 {
   if (!mGeckoAccessible)
     return nil;
 
   // XXX maybe we should cache the subrole.
   nsAutoString xmlRoles;
-  nsCOMPtr<nsIPersistentProperties> attributes;
 
   // XXX we don't need all the attributes (see bug 771113)
-  nsresult rv = mGeckoAccessible->GetAttributes(getter_AddRefs(attributes));
-  if (NS_SUCCEEDED(rv) && attributes)
+  nsCOMPtr<nsIPersistentProperties> attributes = mGeckoAccessible->Attributes();
+  if (attributes)
     nsAccUtils::GetAccAttr(attributes, nsGkAtoms::xmlroles, xmlRoles);
 
   nsWhitespaceTokenizer tokenizer(xmlRoles);
 
   while (tokenizer.hasMoreTokens()) {
     const nsDependentSubstring token(tokenizer.nextToken());
 
     if (token.EqualsLiteral("banner"))
--- a/accessible/src/mac/mozHTMLAccessible.mm
+++ b/accessible/src/mac/mozHTMLAccessible.mm
@@ -13,18 +13,17 @@
 
 @implementation mozHeadingAccessible
 
 - (NSString*)title
 {
   nsAutoString title;
   // XXX use the flattening API when there are available
   // see bug 768298
-  nsresult rv = mGeckoAccessible->GetContent()->GetTextContent(title);
-  NS_ENSURE_SUCCESS(rv, nil);
+  mGeckoAccessible->GetContent()->GetTextContent(title);
 
   return nsCocoaUtils::ToNSString(title);
 }
 
 - (id)value
 {
   if (!mGeckoAccessible || !mGeckoAccessible->IsHyperText())
     return nil;
--- a/accessible/src/msaa/AccessibleWrap.cpp
+++ b/accessible/src/msaa/AccessibleWrap.cpp
@@ -1435,21 +1435,17 @@ AccessibleWrap::get_attributes(BSTR *aAt
   // The format is name:value;name:value; with \ for escaping these
   // characters ":;=,\".
 __try {
   *aAttributes = NULL;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  nsCOMPtr<nsIPersistentProperties> attributes;
-  nsresult rv = GetAttributes(getter_AddRefs(attributes));
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
+  nsCOMPtr<nsIPersistentProperties> attributes = Attributes();
   return ConvertToIA2Attributes(attributes, aAttributes);
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // IDispatch
--- a/accessible/src/msaa/ApplicationAccessibleWrap.cpp
+++ b/accessible/src/msaa/ApplicationAccessibleWrap.cpp
@@ -16,39 +16,34 @@
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 NS_IMPL_ISUPPORTS_INHERITED0(ApplicationAccessibleWrap,
                              ApplicationAccessible)
 
-NS_IMETHODIMP
-ApplicationAccessibleWrap::GetAttributes(nsIPersistentProperties** aAttributes)
+already_AddRefed<nsIPersistentProperties>
+ApplicationAccessibleWrap::NativeAttributes()
 {
-  NS_ENSURE_ARG_POINTER(aAttributes);
-  *aAttributes = nullptr;
-
   nsCOMPtr<nsIPersistentProperties> attributes =
     do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
-  NS_ENSURE_STATE(attributes);
 
   nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   if (gfxInfo) {
     bool isD2DEnabled = false;
     gfxInfo->GetD2DEnabled(&isD2DEnabled);
     nsAutoString unused;
     attributes->SetStringProperty(
       NS_LITERAL_CSTRING("D2D"),
       isD2DEnabled ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"),
         unused);
   }
 
-  attributes.swap(*aAttributes);
-  return NS_OK;
+  return attributes.forget();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // IUnknown
 
 STDMETHODIMP
 ApplicationAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
--- a/accessible/src/msaa/ApplicationAccessibleWrap.h
+++ b/accessible/src/msaa/ApplicationAccessibleWrap.h
@@ -17,18 +17,18 @@ namespace a11y {
  
 class ApplicationAccessibleWrap: public ApplicationAccessible,
                                  public IAccessibleApplication
 {
 public:
   // nsISupporst
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIAccessible
-  NS_IMETHOD GetAttributes(nsIPersistentProperties** aAttributes);
+  // nsAccessible
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
 
   // IUnknown
   STDMETHODIMP QueryInterface(REFIID, void**);
 
   // IAccessibleApplication
   virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_appName(
             /* [retval][out] */ BSTR *name);
 
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -42,17 +42,17 @@ nsAccessNodeWrap::
 nsAccessNodeWrap::~nsAccessNodeWrap()
 {
 }
 
 //-----------------------------------------------------
 // nsISupports methods
 //-----------------------------------------------------
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsAccessNodeWrap, nsAccessNode, nsIWinAccessNode);
+NS_IMPL_ISUPPORTS_INHERITED1(nsAccessNodeWrap, nsAccessNode, nsIWinAccessNode)
 
 //-----------------------------------------------------
 // nsIWinAccessNode methods
 //-----------------------------------------------------
 
 NS_IMETHODIMP
 nsAccessNodeWrap::QueryNativeInterface(REFIID aIID, void** aInstancePtr)
 {
@@ -87,17 +87,17 @@ nsAccessNodeWrap::QueryService(REFGUID g
   *ppv = nullptr;
 
   // Provide a special service ID for getting the accessible for the browser tab
   // document that contains this accessible object. If this accessible object
   // is not inside a browser tab then the service fails with E_NOINTERFACE.
   // A use case for this is for screen readers that need to switch context or
   // 'virtual buffer' when focus moves from one browser tab area to another.
   static const GUID SID_IAccessibleContentDocument =
-    { 0xa5d8e1f3,0x3571,0x4d8f,0x95,0x21,0x07,0xed,0x28,0xfb,0x07,0x2e };
+    { 0xa5d8e1f3,0x3571,0x4d8f,{0x95,0x21,0x07,0xed,0x28,0xfb,0x07,0x2e} };
   if (guidService == SID_IAccessibleContentDocument) {
     if (iid != IID_IAccessible)
       return E_NOINTERFACE;
 
     nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = 
       nsCoreUtils::GetDocShellTreeItemFor(mContent);
     if (!docShellTreeItem)
       return E_UNEXPECTED;
@@ -120,17 +120,17 @@ nsAccessNodeWrap::QueryService(REFGUID g
     // Make sure this is a document.
     DocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root);
     if (!docAcc)
       return E_UNEXPECTED;
 
     *ppv = static_cast<IAccessible*>(docAcc);
 
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
-    return NS_OK;
+    return S_OK;
   }
 
   // Can get to IAccessibleApplication from any node via QS
   if (guidService == IID_IAccessibleApplication) {
     ApplicationAccessible* applicationAcc = ApplicationAcc();
     if (!applicationAcc)
       return E_NOINTERFACE;
 
@@ -148,17 +148,17 @@ nsAccessNodeWrap::QueryService(REFGUID g
    * if (pServProv) {
    *   const GUID unused;
    *   pServProv->QueryService(unused, IID_ISimpleDOMDocument, (void**)&pAccDoc);
    *   pServProv->Release();
    * }
    */
 
   static const GUID IID_SimpleDOMDeprecated =
-    { 0x0c539790,0x12e4,0x11cf,0xb6,0x61,0x00,0xaa,0x00,0x4c,0xd6,0xd8 };
+    { 0x0c539790,0x12e4,0x11cf,{0xb6,0x61,0x00,0xaa,0x00,0x4c,0xd6,0xd8} };
   if (guidService == IID_ISimpleDOMNode ||
       guidService == IID_SimpleDOMDeprecated ||
       guidService == IID_IAccessible ||  guidService == IID_IAccessible2)
     return QueryInterface(iid, ppv);
 
   return E_INVALIDARG;
 }
 
@@ -404,17 +404,17 @@ nsAccessNodeWrap::MakeAccessNode(nsINode
 
 STDMETHODIMP nsAccessNodeWrap::get_parentNode(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
 {
 __try {
   nsINode* node = GetNode();
   if (!node)
     return E_FAIL;
 
-  *aNode = MakeAccessNode(node->GetNodeParent());
+  *aNode = MakeAccessNode(node->GetParentNode());
 
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
 
   return S_OK;
 }
 
 STDMETHODIMP nsAccessNodeWrap::get_firstChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
 {
--- a/accessible/src/windows/uia/uiaRawElmProvider.cpp
+++ b/accessible/src/windows/uia/uiaRawElmProvider.cpp
@@ -183,18 +183,17 @@ uiaRawElmProvider::GetPropertyValue(PROP
 
       break;
     }
     
     //ARIA Role / shortcut
     case UIA_AriaRolePropertyId: {
       nsAutoString xmlRoles;
 
-      nsCOMPtr<nsIPersistentProperties> attributes;
-      mAcc->GetAttributes(getter_AddRefs(attributes));
+      nsCOMPtr<nsIPersistentProperties> attributes = mAcc->Attributes();
       attributes->GetStringProperty(NS_LITERAL_CSTRING("xml-roles"), xmlRoles);
 
       if(!xmlRoles.IsEmpty()) {
         aPropertyValue->vt = VT_BSTR;
         aPropertyValue->bstrVal = ::SysAllocString(xmlRoles.get());
         return S_OK;
       }
 
--- a/accessible/src/xforms/nsXFormsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsAccessible.cpp
@@ -55,18 +55,17 @@ nsXFormsAccessible::
 nsresult
 nsXFormsAccessible::GetBoundChildElementValue(const nsAString& aTagName,
                                               nsAString& aValue)
 {
   NS_ENSURE_TRUE(sXFormsService, NS_ERROR_FAILURE);
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsINodeList* nodes = mContent->GetChildNodesList();
-  NS_ENSURE_STATE(nodes);
+  nsINodeList* nodes = mContent->ChildNodes();
 
   uint32_t length;
   nsresult rv = nodes->GetLength(&length);
   NS_ENSURE_SUCCESS(rv, rv);
 
   for (uint32_t index = 0; index < length; index++) {
     nsIContent* content = nodes->GetNodeAt(index);
     if (content->NodeInfo()->Equals(aTagName) &&
@@ -540,17 +539,17 @@ nsXFormsSelectableItemAccessible::DoActi
 }
 
 bool
 nsXFormsSelectableItemAccessible::IsSelected()
 {
   nsresult rv;
 
   nsINode* parent = mContent;
-  while ((parent = parent->GetNodeParent())) {
+  while ((parent = parent->GetParentNode())) {
     nsCOMPtr<nsIContent> content(do_QueryInterface(parent));
     if (!content)
       return false;
 
     nsCOMPtr<nsINodeInfo> nodeinfo = content->NodeInfo();
     if (!nodeinfo->NamespaceEquals(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS)))
       continue;
 
--- a/accessible/src/xforms/nsXFormsWidgetsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsWidgetsAccessible.cpp
@@ -151,13 +151,13 @@ void
 nsXFormsComboboxPopupWidgetAccessible::Value(nsString& aValue)
 {
   aValue.Truncate();
 }
 
 void
 nsXFormsComboboxPopupWidgetAccessible::CacheChildren()
 {
-  nsCOMPtr<nsIDOMNode> parent = do_QueryInterface(mContent->GetNodeParent());
+  nsCOMPtr<nsIDOMNode> parent = do_QueryInterface(mContent->GetParentNode());
   // Parent node must be an xforms:select1 element.
   CacheSelectChildren(parent);
 }
 
--- a/accessible/src/xul/XULElementAccessibles.cpp
+++ b/accessible/src/xul/XULElementAccessibles.cpp
@@ -120,20 +120,21 @@ XULLinkAccessible::Value(nsString& aValu
 
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, aValue);
 }
 
 ENameValueFlag
 XULLinkAccessible::NativeName(nsString& aName)
 {
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
-  if (aName.IsEmpty())
-    nsTextEquivUtils::GetNameFromSubtree(this, aName);
+  if (!aName.IsEmpty())
+    return eNameOK;
 
-  return eNameOK;
+  nsTextEquivUtils::GetNameFromSubtree(this, aName);
+  return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
 }
 
 role
 XULLinkAccessible::NativeRole()
 {
   return roles::LINK;
 }
 
--- a/accessible/src/xul/XULListboxAccessible.cpp
+++ b/accessible/src/xul/XULListboxAccessible.cpp
@@ -629,18 +629,17 @@ XULListitemAccessible::NativeName(nsStri
   if (childContent) {
     if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell,
                                          kNameSpaceID_XUL)) {
       childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
       return eNameOK;
     }
   }
 
-  GetXULName(aName);
-  return eNameOK;
+  return GetXULName(aName);
 }
 
 role
 XULListitemAccessible::NativeRole()
 {
   Accessible* list = GetListAccessible();
   if (!list) {
     NS_ERROR("No list accessible for listitem accessible!");
@@ -853,27 +852,25 @@ XULListCellAccessible::Shutdown()
 }
 
 role
 XULListCellAccessible::NativeRole()
 {
   return roles::CELL;
 }
 
-nsresult
-XULListCellAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
+already_AddRefed<nsIPersistentProperties>
+XULListCellAccessible::NativeAttributes()
 {
-  NS_ENSURE_ARG_POINTER(aAttributes);
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    HyperTextAccessibleWrap::NativeAttributes();
 
   // "table-cell-index" attribute
   TableAccessible* table = Table();
-  NS_ENSURE_STATE(table); // we expect to be in a listbox (table)
+  if (!table) // we expect to be in a listbox (table)
+    return attributes.forget();
 
   nsAutoString stringIdx;
   stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx()));
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex,
-                         stringIdx);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
 
-  return NS_OK;
+  return attributes.forget();
 }
--- a/accessible/src/xul/XULListboxAccessible.h
+++ b/accessible/src/xul/XULListboxAccessible.h
@@ -169,17 +169,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessibleTableCell
   NS_FORWARD_NSIACCESSIBLETABLECELL(xpcAccessibleTableCell::)
 
   // Accessible
   virtual TableCellAccessible* AsTableCell() { return this; }
   virtual void Shutdown();
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual a11y::role NativeRole();
 
   // TableCellAccessible
   virtual TableAccessible* Table() const MOZ_OVERRIDE;
   virtual uint32_t ColIdx() const MOZ_OVERRIDE;
   virtual uint32_t RowIdx() const MOZ_OVERRIDE;
   virtual void ColHeaderCells(nsTArray<Accessible*>* aHeaderCells) MOZ_OVERRIDE;
   virtual bool Selected() MOZ_OVERRIDE;
--- a/accessible/src/xul/XULTreeGridAccessible.cpp
+++ b/accessible/src/xul/XULTreeGridAccessible.cpp
@@ -722,41 +722,39 @@ XULTreeGridCellAccessible::Init()
     mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
   else
     mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridCellAccessible: Accessible public implementation
 
-nsresult
-XULTreeGridCellAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
+already_AddRefed<nsIPersistentProperties>
+XULTreeGridCellAccessible::NativeAttributes()
 {
-  NS_ENSURE_ARG_POINTER(aAttributes);
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
 
   // "table-cell-index" attribute
   TableAccessible* table = Table();
   if (!table)
-    return NS_ERROR_FAILURE;
+    return attributes.forget();
 
   nsAutoString stringIdx;
   stringIdx.AppendInt(table->CellIndexAt(mRow, ColIdx()));
-  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex, stringIdx);
+  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
 
   // "cycles" attribute
   bool isCycler = false;
   nsresult rv = mColumn->GetCycler(&isCycler);
   if (NS_SUCCEEDED(rv) && isCycler)
-    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::cycles,
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::cycles,
                            NS_LITERAL_STRING("true"));
 
-  return NS_OK;
+  return attributes.forget();
 }
 
 role
 XULTreeGridCellAccessible::NativeRole()
 {
   return roles::GRID_CELL;
 }
 
--- a/accessible/src/xul/XULTreeGridAccessible.h
+++ b/accessible/src/xul/XULTreeGridAccessible.h
@@ -153,17 +153,17 @@ public:
   // nsAccessNode
   virtual void Init();
 
   // Accessible
   virtual TableCellAccessible* AsTableCell() { return this; }
   virtual void Shutdown();
   virtual ENameValueFlag Name(nsString& aName);
   virtual Accessible* FocusedChild();
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties* aAttributes);
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual int32_t IndexInParent() const;
   virtual Relation RelationByType(uint32_t aType);
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual uint64_t NativeInteractiveState() const;
 
   // ActionAccessible
   virtual uint8_t ActionCount();
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -19,16 +19,17 @@ DIRS	= \
   focus \
   hittest \
   hyperlink \
   hypertext \
   name \
   pivot \
   relations \
   role \
+  scroll \
   selectable \
   states \
   table \
   text \
   textcaret \
   textselection \
   tree \
   treeupdate \
--- a/accessible/tests/mochitest/attributes/test_obj.html
+++ b/accessible/tests/mochitest/attributes/test_obj.html
@@ -33,18 +33,22 @@ https://bugzilla.mozilla.org/show_bug.cg
       testAttrs("dropeffect", {"dropeffect" : "copy"}, true);
       testAttrs("grabbed", {"grabbed" : "true"}, true);
       testAttrs("hidden", {"hidden" : "true"}, true);
       testAttrs("sortAscending", {"sort" : "ascending"}, true);
       testAttrs("sortDescending", {"sort" : "descending"}, true);
       testAttrs("sortNone", {"sort" : "none"}, true);
       testAttrs("sortOther", {"sort" : "other"}, true);
 
+      // inherited attributes by subdocuments
+      var subdoc = getAccessible("iframe").firstChild;
+      testAttrs(subdoc, {"busy" : "true"}, true);
+
       // live object attribute
-      
+
       // HTML
       testAttrs("output", {"live" : "polite"}, true);
 
       // ARIA
       testAttrs("live", {"live" : "polite"}, true);
       testAttrs("live2", {"live" : "polite"}, true);
       testAbsentAttrs("live3", {"live" : ""});
       testAttrs("log", {"live" : "polite"}, true);
@@ -167,16 +171,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   <div id="dropeffect" aria-dropeffect="copy"></div>
   <div id="grabbed" aria-grabbed="true"></div>
   <div id="hidden" aria-hidden="true"></div>
   <div id="sortAscending" role="columnheader" aria-sort="ascending"></div>
   <div id="sortDescending" role="columnheader" aria-sort="descending"></div>
   <div id="sortNone" role="columnheader" aria-sort="none"></div>
   <div id="sortOther" role="columnheader" aria-sort="other"></div>
 
+  <!-- inherited from iframe -->
+  <iframe id="iframe" src="data:text/html,<html><body></body></html>"
+          aria-busy="true"></iframe>
+
   <!-- html -->
   <output id="output"></output>
 
   <!-- back to aria -->
   <div id="live" aria-live="polite">excuse <div id="liveChild">me</div></div>
   <div id="live2" role="marquee" aria-live="polite">excuse <div id="live2Child">me</div></div>
   <div id="live3" role="region">excuse</div>
   <div id="log" role="log">excuse <div id="logChild">me</div></div>
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -68,16 +68,20 @@ const SEAMONKEY = navigator.userAgent.ma
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible general
 
 const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
 
 const SCROLL_TYPE_ANYWHERE = nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE;
 
+const COORDTYPE_SCREEN_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE;
+const COORDTYPE_WINDOW_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_WINDOW_RELATIVE;
+const COORDTYPE_PARENT_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_PARENT_RELATIVE;
+
 const kEmbedChar = String.fromCharCode(0xfffc);
 
 const kDiscBulletText = String.fromCharCode(0x2022) + " ";
 const kCircleBulletText = String.fromCharCode(0x25e6) + " ";
 const kSquareBulletText = String.fromCharCode(0x25aa) + " ";
 
 /**
  * nsIAccessibleRetrieval service.
--- a/accessible/tests/mochitest/events/test_valuechange.html
+++ b/accessible/tests/mochitest/events/test_valuechange.html
@@ -21,86 +21,106 @@
 
 
     /**
      * Do tests.
      */
     var gQueue = null;
 
     // Value change invoker
-    function changeValue(aNodeOrID, aValuenow, aValuetext)
+    function changeARIAValue(aNodeOrID, aValuenow, aValuetext)
     {
       this.DOMNode = getNode(aNodeOrID);
 
-      this.invoke = function changeValue_invoke() {
+      this.invoke = function changeARIAValue_invoke() {
 
         // Note: this should not fire an EVENT_VALUE_CHANGE when aria-valuetext
         // is not empty
         if (aValuenow != undefined)
           this.DOMNode.setAttribute("aria-valuenow", aValuenow);
  
         // Note: this should always fire an EVENT_VALUE_CHANGE
         if (aValuetext != undefined)
           this.DOMNode.setAttribute("aria-valuetext", aValuetext);
       }
 
-      this.check = function changeValue_check() {
+      this.check = function changeARIAValue_check() {
         var acc = getAccessible(aNodeOrID, [nsIAccessibleValue]);
         if (!acc)
           return;
 
         // Note: always test against valuetext first because the existence of 
         // aria-valuetext takes precedence over aria-valuenow in gecko.
         is(acc.value, (aValuetext != undefined)? aValuetext : aValuenow,
             "Wrong value of " + prettyName(aNodeOrID));
       }
 
-      this.getID = function changeValue_getID() {
+      this.getID = function changeARIAValue_getID() {
         return prettyName(aNodeOrID) + " value changed";
       }
     }
 
-    function changeInputValue(aID, aValue)
+    function changeValue(aID, aValue)
     {
       this.DOMNode = getNode(aID);
 
-      this.invoke = function changeInputValue_invoke()
+      this.invoke = function changeValue_invoke()
       {
         this.DOMNode.value = aValue;
       }
 
-      this.check = function changeInputValue_check()
+      this.check = function changeValue_check()
       {
         var acc = getAccessible(this.DOMNode);
         is(acc.value, aValue, "Wrong value for " + prettyName(aID));
       }
 
-      this.getID = function changeInputValue_getID()
+      this.getID = function changeValue_getID()
       {
         return prettyName(aID) + " value changed";
       }
     }
 
+    function changeProcessValue(aID, aValue) {
+        this.DOMNode = getNode(aID);
+
+        this.invoke = function changeProcessValue_invoke() {
+            this.DOMNode.value = aValue;
+        }
+
+        this.check = function changeProcessValue_check() {
+            var acc = getAccessible(this.DOMNode);
+            is(acc.value, aValue+"%", "Wrong value for " + prettyName(aID));
+        }
+
+        this.getID = function changeProcessValue_getID() {
+            return prettyName(aID) + " value changed";
+        }
+    }
+
     function doTests()
     {
       // Test initial values
       testValue("slider_vn", "5", 5, 0, 1000, 0);
       testValue("slider_vnvt", "plain", 0, 0, 5, 0);
       testValue("slider_vt", "hi", 0, 0, 3, 0);
       testValue("scrollbar", "5", 5, 0, 1000, 0);
+      testValue("progress", "22%", 22, 0, 100, 0);
 
       // Test value change events
       gQueue = new eventQueue(nsIAccessibleEvent.EVENT_VALUE_CHANGE);
 
-      gQueue.push(new changeValue("slider_vn", "6", undefined));
-      gQueue.push(new changeValue("slider_vt", undefined, "hey!"));
-      gQueue.push(new changeValue("slider_vnvt", "3", "sweet"));
-      gQueue.push(new changeValue("scrollbar", "6", undefined));
+      gQueue.push(new changeARIAValue("slider_vn", "6", undefined));
+      gQueue.push(new changeARIAValue("slider_vt", undefined, "hey!"));
+      gQueue.push(new changeARIAValue("slider_vnvt", "3", "sweet"));
+      gQueue.push(new changeARIAValue("scrollbar", "6", undefined));
 
-      gQueue.push(new changeInputValue("combobox", "hello"));
+      gQueue.push(new changeValue("combobox", "hello"));
+
+      gQueue.push(new changeProcessValue("progress", "50"));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
@@ -117,16 +137,22 @@
     title="We dont expose new aria role 'scrollbar' and property aria-orientation">
    Mozilla Bug 529289
   </a>
   <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=703202"
     title="ARIA comboboxes don't fire value change events">
    Mozilla Bug 703202
   </a>
+  <a target="_blank"
+    href="https://bugzilla.mozilla.org/show_bug.cgi?id=761901"
+    title=" HTML5 progress accessible should fire value change event">
+   Mozilla Bug 761901
+  </a>
+
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <!-- ARIA sliders -->
@@ -140,10 +166,14 @@
        aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
 
   <!-- ARIA scrollbar -->
   <div id="scrollbar" role="scrollbar" aria-valuenow="5"
        aria-valuemin="0" aria-valuemax="1000">slider</div>
 
   <!-- ARIA combobox -->
   <input id="combobox" role="combobox" aria-autocomplete="inline">
+
+  <!-- progress bar -->
+  <progress id="progress" value="22" max="100"></progress>
+
 </body>
 </html>
--- a/accessible/tests/mochitest/layout.js
+++ b/accessible/tests/mochitest/layout.js
@@ -87,32 +87,57 @@ function getChildAtPoint(aIdentifier, aX
       return acc.getDeepestChildAtPoint(x, y);
     return acc.getChildAtPoint(x, y);
   } catch (e) {  }
 
   return null;
 }
 
 /**
+ * Test the accessible position.
+ */
+function testPos(aID, aPoint)
+{
+  var [expectedX, expectedY] =
+    (aPoint != undefined) ? aPoint : getBoundsForDOMElm(aID);
+
+  var [x, y] = getBounds(aID);
+  is(x, expectedX, "Wrong x coordinate of " + prettyName(aID));
+  is(y, expectedY, "Wrong y coordinate of " + prettyName(aID));
+}
+
+/**
  * Test the accessible boundaries.
  */
 function testBounds(aID, aRect)
 {
   var [expectedX, expectedY, expectedWidth, expectedHeight] =
     (aRect != undefined) ? aRect : getBoundsForDOMElm(aID);
 
   var [x, y, width, height] = getBounds(aID);
   is(x, expectedX, "Wrong x coordinate of " + prettyName(aID));
   is(y, expectedY, "Wrong y coordinate of " + prettyName(aID));
   is(width, expectedWidth, "Wrong width of " + prettyName(aID));
   is(height, expectedHeight, "Wrong height of " + prettyName(aID));
 }
 
 /**
- * Return the accessible coordinates and size relative to the screen.
+ * Return the accessible coordinates relative to the screen in device pixels.
+ */
+function getPos(aID)
+{
+  var accessible = getAccessible(aID);
+  var x = {}, y = {};
+  accessible.getBounds(x, y, {}, {});
+  return [x.value, y.value];
+}
+
+/**
+ * Return the accessible coordinates and size relative to the screen in device
+ * pixels.
  */
 function getBounds(aID)
 {
   var accessible = getAccessible(aID);
   var x = {}, y = {}, width = {}, height = {};
   accessible.getBounds(x, y, width, height);
   return [x.value, y.value, width.value, height.value];
 }
--- a/accessible/tests/mochitest/name/markup.js
+++ b/accessible/tests/mochitest/name/markup.js
@@ -183,16 +183,21 @@ function testNameForAttrRule(aElm, aRule
         name += " ";
 
       name += labelElm.getAttribute("a11yname");
     }
   }
 
   var msg = "Attribute '" + attr + "' test. ";
   testName(aElm, name, msg);
+  if (aRule.getAttribute("explict-name") != "false")
+    testAttrs(aElm, {"explicit-name" : "true"}, true);
+  else
+    testAbsentAttrs(aElm, {"explicit-name" : "true"});
+
   aElm.removeAttribute(attr);
 
   gTestIterator.iterateNext();
 }
 
 function testNameForElmRule(aElm, aRule)
 {
   var labelElm;
@@ -230,16 +235,17 @@ function testNameForElmRule(aElm, aRule)
   if (!labelElm) {
     ok(false, msg + " Failed to find '" + tagname + "' element.");
     gTestIterator.iterateNext();
     return;
   }
 
   var msg = "Element '" + tagname + "' test.";
   testName(aElm, labelElm.getAttribute("a11yname"), msg);
+  testAttrs(aElm, {"explicit-name" : "true"}, true);
 
   var parentNode = labelElm.parentNode;
 
   if (gDumpToConsole) {
     dump("\nProcessed elm rule. Wait for reorder event on " +
          prettyName(parentNode) + "\n");
   }
   waitForEvent(EVENT_REORDER, parentNode,
@@ -247,16 +253,17 @@ function testNameForElmRule(aElm, aRule)
 
   parentNode.removeChild(labelElm);
 }
 
 function testNameForSubtreeRule(aElm, aRule)
 {
   var msg = "From subtree test.";
   testName(aElm, aElm.getAttribute("a11yname"), msg);
+  testAbsentAttrs(aElm, {"explicit-name" : "true"});
 
   if (gDumpToConsole) {
     dump("\nProcessed from subtree rule. Wait for reorder event on " +
          prettyName(aElm) + "\n");
   }
   waitForEvent(EVENT_REORDER, aElm, gTestIterator.iterateNext, gTestIterator);
 
   while (aElm.firstChild)
--- a/accessible/tests/mochitest/name/markuprules.xml
+++ b/accessible/tests/mochitest/name/markuprules.xml
@@ -120,17 +120,17 @@
     <ruleset id="htmlelm">
       <ruleset ref="htmlelm_start"/>
       <ruleset ref="htmlelm_end"/>
     </ruleset>
 
     <!-- specific -->
     <ruleset id="htmlinputbutton">
       <ruleset ref="htmlelm_start"/>
-      <rule attr="value" type="string"/>
+      <rule attr="value" type="string" explict-name="false"/>
       <rule attr="alt" type="string"/>
       <rule attr="src" type="string"/>
       <rule attr="data" type="string"/>
       <ruleset ref="htmlelm_end"/>
     </ruleset>
 
     <ruleset id="htmloption">
       <ruleset ref="aria"/>
--- a/accessible/tests/mochitest/name/test_markup.html
+++ b/accessible/tests/mochitest/name/test_markup.html
@@ -8,16 +8,18 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="../name.js"></script>
+  <script type="application/javascript"
+          src="../attributes.js"></script>
 
   <script type="application/javascript"
           src="markup.js"></script>
 
   <script type="application/javascript">
     // gA11yEventDumpID = "eventdump";
     //gDumpToConsole = true;
     //gA11yEventDumpToConsole = true;
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/scroll/Makefile.in
@@ -0,0 +1,18 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH		= @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = accessible/scroll
+
+include $(DEPTH)/config/autoconf.mk
+
+MOCHITEST_A11Y_FILES =\
+		test_zoom.html \
+		$(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/scroll/test_zoom.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Test scrollToPoint when page is zoomed</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../layout.js"></script>
+
+  <script type="application/javascript">
+    function testScrollToPoint()
+    {
+      // scrollToPoint relative screen
+      var anchor = getAccessible("bottom1");
+      var [x, y] = getPos(anchor);
+      var [docX, docY] = getPos(document);
+
+      anchor.scrollToPoint(COORDTYPE_SCREEN_RELATIVE, docX, docY);
+      testPos(anchor, [x, docY]);
+
+      // scrollToPoint relative window
+      anchor = getAccessible("bottom2");
+      var [x, y] = getPos(anchor);
+      var wnd = getRootAccessible().DOMDocument.defaultView;
+      var scrollToX = docX - wnd.screenX, scrollToY = docY - wnd.screenY;
+
+      anchor.scrollToPoint(COORDTYPE_WINDOW_RELATIVE, scrollToX, scrollToY);
+      testPos(anchor, [x, docY]);
+
+      // scrollToPoint relative parent
+      anchor = getAccessible("bottom3");
+      var [x, y] = getPos(anchor);
+      var [parentX, parentY] = getPos(anchor.parent);
+      var scrollToX = parentX - docX, scrollToY = parentY - docY;
+
+      anchor.scrollToPoint(COORDTYPE_PARENT_RELATIVE, scrollToX, scrollToY);
+      testPos(anchor, [x, docY]);
+    }
+
+    function doTest()
+    {
+      testScrollToPoint();
+      zoomDocument(document, 2.0);
+      testScrollToPoint(); // zoom and test again
+
+      zoomDocument(document, 1.0);
+      SimpleTest.finish();
+    }
+
+    addA11yLoadEvent(doTest);
+    SimpleTest.waitForExplicitFinish();
+  </script>
+
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=727942"
+     title="scrollToPoint is broken when page is zoomed">
+    Mozilla Bug 727942
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <h1>Below there is a bunch of named anchors</h1>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  This is in the middle anchor #1<a id="bottom1"></a>
+  <br><br><br><br><br><br><br><br><br><br>
+  This is in the middle anchor #2<a id="bottom2"></a>
+  <br><br><br><br><br><br><br><br><br><br>
+  This is in the middle anchor #3<a id="bottom3"></a>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+</body>
+</html>
--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -54,17 +54,17 @@ if [ ! "$LIBXUL_SDK" ]; then
       build/stlport/stl/config/_android.h
     "
   fi
   add_makefiles "
     memory/mozalloc/Makefile
     mozglue/Makefile
     mozglue/build/Makefile
   "
-  if [ "$MOZ_JEMALLOC" ]; then
+  if [ "$MOZ_JEMALLOC" -a -z "$MOZ_NATIVE_JEMALLOC" ]; then
     add_makefiles "
       memory/jemalloc/Makefile
     "
   fi
   if [ "$MOZ_MEMORY" ]; then
     add_makefiles "
       memory/mozjemalloc/Makefile
       memory/build/Makefile
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -261,20 +261,21 @@ pref("media.cache_size", 4096);    // 4M
 pref("media.video-queue.default-size", 3);
 
 //  0: don't show fullscreen keyboard
 //  1: always show fullscreen keyboard
 // -1: show fullscreen keyboard based on threshold pref
 pref("widget.ime.android.landscape_fullscreen", -1);
 pref("widget.ime.android.fullscreen_threshold", 250); // in hundreths of inches
 
-// optimize images memory usage
+// optimize images' memory usage
 pref("image.mem.decodeondraw", true);
 pref("content.image.allow_locking", false);
 pref("image.mem.min_discard_timeout_ms", 10000);
+pref("image.mem.max_decoded_image_kb", 5120); /* 5MB */
 
 // enable touch events interfaces
 pref("dom.w3c_touch_events.enabled", true);
 pref("dom.w3c_touch_events.safetyX", 0); // escape borders in units of 1/240"
 pref("dom.w3c_touch_events.safetyY", 120); // escape borders in units of 1/240"
 
 #ifdef MOZ_SAFE_BROWSING
 // Safe browsing does nothing unless this pref is set
--- a/b2g/chrome/content/payment.js
+++ b/b2g/chrome/content/payment.js
@@ -61,16 +61,20 @@ function closePaymentFlowDialog(aCallbac
   content.addEventListener("mozContentEvent",
                            function closePaymentFlowReturn(evt) {
     if (evt.detail.id == id && aCallback) {
       aCallback();
     }
 
     content.removeEventListener("mozContentEvent",
                                 closePaymentFlowReturn);
+
+    let glue = Cc["@mozilla.org/payment/ui-glue;1"]
+                 .createInstance(Ci.nsIPaymentUIGlue);
+    glue.cleanup();
   });
 
   browser.shell.sendChromeEvent(detail);
 }
 
 addEventListener("DOMContentLoaded", function(e) {
   content.wrappedJSObject.paymentSuccess = paymentSuccess;
   content.wrappedJSObject.paymentFailed = paymentFailed;
--- a/b2g/chrome/content/runapp.js
+++ b/b2g/chrome/content/runapp.js
@@ -1,44 +1,72 @@
+"use strict";
+
 // runapp.js:
 // Provide a --runapp APPNAME command-line option.
 
+let runAppObj;
 window.addEventListener('load', function() {
   // Get the command line arguments that were passed to the b2g client
   let args = window.arguments[0].QueryInterface(Ci.nsICommandLine);
   let appname;
 
   // - Check if the argument is present before doing any work.
   try {
     // Returns null if the argument was not specified.  Throws
     // NS_ERROR_INVALID_ARG if there is no parameter specified (because
     // it was the last argument or the next argument starts with '-').
     // However, someone could still explicitly pass an empty argument!
     appname = args.handleFlagWithParam('runapp', false);
-  }
-  catch(e) {
+  } catch(e) {
     // treat a missing parameter like an empty parameter (=> show usage)
     appname = '';
   }
 
   // not specified, bail.
-  if (appname === null)
+  if (appname === null) {
     return;
+  }
+
+  runAppObj = new AppRunner(appname);
+  Services.obs.addObserver(runAppObj, 'webapps-registry-ready', false);
+});
+
+window.addEventListener('unload', function() {
+  Services.obs.removeObserver(runAppObj, 'webapps-registry-ready');
+});
 
-  // - Get the list of apps since the parameter was specified
-  let appsReq = navigator.mozApps.mgmt.getAll();
-  appsReq.onsuccess = function() {
-    let apps = appsReq.result;
+function AppRunner(aName) {
+  this._req = null;
+  this._appName = aName;
+}
+AppRunner.prototype = {
+  observe: function(aSubject, aTopic, aData) {
+    if (aTopic == 'webapps-registry-ready') {
+      this.doRunApp();
+    }
+  },
+
+  doRunApp: function() {
+    // - Get the list of apps since the parameter was specified
+    this._req = navigator.mozApps.mgmt.getAll();
+    this._req.onsuccess = this.getAllSuccess.bind(this);
+    this._req.onerror = this.getAllError.bind(this);
+  },
+
+  getAllSuccess: function() {
+    let apps = this._req.result;
+
     function findAppWithName(name) {
       let normalizedSearchName = name.replace(/[- ]+/g, '').toLowerCase();
 
       for (let i = 0; i < apps.length; i++) {
         let app = apps[i];
         let normalizedAppName =
-              app.manifest.name.replace(/[- ]+/g, '').toLowerCase();
+          app.manifest.name.replace(/[- ]+/g, '').toLowerCase();
         if (normalizedSearchName === normalizedAppName) {
           return app;
         }
       }
       return null;
     }
 
     function usageAndDie(justApps) {
@@ -54,40 +82,41 @@ window.addEventListener('load', function
       for (let i = 0; i < apps.length; i++) {
         dump('  ' + apps[i].manifest.name + '\n');
       }
 
       // Exit the b2g client
       Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
     }
 
-    if (appname === '') {
+    if (this._appName === '') {
       usageAndDie();
       return;
     }
 
-    let app = findAppWithName(appname);
+    let app = findAppWithName(this._appName);
     if (!app) {
-      dump('Could not find app: "' + appname + '". Maybe you meant one of:\n');
+      dump('Could not find app: "' + this._appName + '". Maybe you meant one of:\n');
       usageAndDie(true);
       return;
     }
 
     let setReq =
       navigator.mozSettings.createLock().set({'lockscreen.enabled': false});
     setReq.onsuccess = function() {
-      // give the event loop another turn to disable the lock screen
+      // give the event loop 100ms to disable the lock screen
       window.setTimeout(function() {
         dump('--runapp launching app: ' + app.manifest.name + '\n');
         app.launch();
-      }, 0);
+      }, 100);
     };
     setReq.onerror = function() {
       dump('--runapp failed to disable lock-screen.  Giving up.\n');
     };
 
     dump('--runapp found app: ' + app.manifest.name +
          ', disabling lock screen...\n');
- };
- appsReq.onerror = function() {
-   dump('Problem getting the list of all apps!');
- };
-});
+  },
+
+  getAllError: function() {
+    dump('Problem getting the list of all apps!');
+  }
+};
\ No newline at end of file
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -493,16 +493,20 @@ Services.obs.addObserver(function onSyst
   shell.sendSystemMessage(msg);
 }, 'system-messages-open-app', false);
 
 Services.obs.addObserver(function(aSubject, aTopic, aData) {
   shell.sendChromeEvent({ type: "fullscreenoriginchange",
                           fullscreenorigin: aData });
 }, "fullscreen-origin-change", false);
 
+Services.obs.addObserver(function onWebappsStart(subject, topic, data) {
+  shell.sendChromeEvent({ type: 'webapps-registry-start' });
+}, 'webapps-registry-start', false);
+
 Services.obs.addObserver(function onWebappsReady(subject, topic, data) {
   shell.sendChromeEvent({ type: 'webapps-registry-ready' });
 }, 'webapps-registry-ready', false);
 
 Services.obs.addObserver(function onBluetoothVolumeChange(subject, topic, data) {
   if (data == 'up') {
     shell.sendChromeEvent({ type: 'volume-up-button-press' });
     shell.sendChromeEvent({ type: 'volume-up-button-release' });
@@ -850,8 +854,18 @@ window.addEventListener('ContentStart', 
 (function volumeStateTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'volume-state-changed',
       active: (aData == 'Shared')
     });
 }, 'volume-state-changed', false);
 })();
+
+Services.obs.addObserver(function(aSubject, aTopic, aData) {
+  let data = JSON.parse(aData);
+  shell.sendChromeEvent({
+    type: "activity-done",
+    success: data.success,
+    manifestURL: data.manifestURL,
+    pageURL: data.pageURL
+  });
+}, "activity-done", false);
--- a/b2g/chrome/content/shell.xul
+++ b/b2g/chrome/content/shell.xul
@@ -12,16 +12,16 @@
 #endif
         style="background: black; overflow: hidden; width:320px; height:480px"
         onload="shell.start();"
         onunload="shell.stop();">
 
   <script type="application/javascript" src="chrome://browser/content/settings.js"/>
   <script type="application/javascript" src="chrome://browser/content/shell.js"/>
 
-#ifndef ANDROID
+#ifndef MOZ_WIDGET_GONK
   <!-- this script handles the screen argument for desktop builds -->
   <script type="application/javascript" src="chrome://browser/content/screen.js"/>
   <!-- this script handles the "runapp" argument for desktop builds -->
   <script type="application/javascript" src="chrome://browser/content/runapp.js"/>
 #endif
   <!-- The html:iframe containing the UI is created here. -->
 </window>
--- a/b2g/components/PaymentGlue.js
+++ b/b2g/components/PaymentGlue.js
@@ -28,20 +28,26 @@ function debug (s) {
 function PaymentUI() {
 }
 
 PaymentUI.prototype = {
 
   confirmPaymentRequest: function confirmPaymentRequest(aRequests,
                                                         aSuccessCb,
                                                         aErrorCb) {
+    let _error = function _error(errorMsg) {
+      if (aErrorCb) {
+        aErrorCb.onresult(errorMsg);
+      }
+    };
+
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     let content = browser.getContentWindow();
-    if (!content && aErrorCb) {
-      aErrorCb.onresult("NO_CONTENT_WINDOW");
+    if (!content) {
+      _error("NO_CONTENT_WINDOW");
       return;
     }
 
     // The UI should listen for mozChromeEvent 'open-payment-confirmation-dialog'
     // type in order to create and show the payment request confirmation frame
     // embeded within a trusted dialog.
     let id = kOpenPaymentConfirmationEvent + "-" + this.getRandomId();
     let detail = {
@@ -51,82 +57,114 @@ PaymentUI.prototype = {
     };
 
     // Once the user confirm the payment request and makes his choice, we get
     // back to the DOM part to get the appropriate payment flow information
     // based on the selected payment provider.
     content.addEventListener("mozContentEvent", function handleSelection(evt) {
       let msg = evt.detail;
       if (msg.id != id) {
-        debug("mozContentEvent. evt.detail.id != " + id);
-        content.removeEventListener("mozContentEvent", handleSelection);
         return;
       }
 
       if (msg.userSelection && aSuccessCb) {
         aSuccessCb.onresult(msg.userSelection);
-      } else if (msg.errorMsg && aErrorCb) {
-        aErrorCb.onresult(msg.errorMsg);
+      } else if (msg.errorMsg) {
+        _error(msg.errorMsg);
       }
 
       content.removeEventListener("mozContentEvent", handleSelection);
     });
 
     browser.shell.sendChromeEvent(detail);
   },
 
   showPaymentFlow: function showPaymentFlow(aPaymentFlowInfo, aErrorCb) {
     debug("showPaymentFlow. uri " + aPaymentFlowInfo.uri);
+
+    let _error = function _error(errorMsg) {
+      if (aErrorCb) {
+        aErrorCb.onresult(errorMsg);
+      }
+    };
+
     // We ask the UI to browse to the selected payment flow.
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     let content = browser.getContentWindow();
-    if (!content && aErrorCb) {
-      aErrorCb.onresult("NO_CONTENT_WINDOW");
+    if (!content) {
+      _error("NO_CONTENT_WINDOW");
       return;
     }
 
     let id = kOpenPaymentFlowEvent + "-" + this.getRandomId();
     let detail = {
       type: kOpenPaymentFlowEvent,
       id: id,
       uri: aPaymentFlowInfo.uri,
       method: aPaymentFlowInfo.requestMethod,
       jwt: aPaymentFlowInfo.jwt
     };
 
     // At some point the UI would send the created iframe back so the
     // callbacks for firing DOMRequest events can be loaded on its
     // content.
-    content.addEventListener("mozContentEvent", function loadPaymentShim(evt) {
-      if (evt.detail.id != id || !evt.detail.frame) {
+    content.addEventListener("mozContentEvent", (function loadPaymentShim(evt) {
+      if (evt.detail.id != id) {
         content.removeEventListener("mozContentEvent", loadPaymentShim);
         return;
       }
 
       // Try to load the payment shim file containing the payment callbacks
       // in the content script.
+      if (!evt.detail.frame && !evt.detail.errorMsg) {
+        _error("ERROR_LOADING_PAYMENT_SHIM");
+        return;
+      }
       let frame = evt.detail.frame;
       let frameLoader = frame.QueryInterface(Ci.nsIFrameLoaderOwner)
                         .frameLoader;
       let mm = frameLoader.messageManager;
       try {
         mm.loadFrameScript(kPaymentShimFile, true);
       } catch (e) {
         debug("Error loading " + kPaymentShimFile + " as a frame script: " + e);
-        if (aErrorCb) {
-          aErrorCb.onresult("ERROR_LOADING_PAYMENT_SHIM");
-        }
+        _error("ERROR_LOADING_PAYMENT_SHIM");
       } finally {
         content.removeEventListener("mozContentEvent", loadPaymentShim);
       }
-    });
+    }).bind(this));
+
+    // We also listen for UI notifications about a closed payment flow. The UI
+    // should provide the reason of the closure within the 'errorMsg' parameter
+    this._notifyPayFlowClosed = function _notifyPayFlowClosed (evt) {
+      if (evt.detail.id != id) {
+        return;
+      }
+      if (evt.detail.errorMsg) {
+        _error(evt.detail.errorMsg);
+        content.removeEventListener("mozContentEvent",
+                                    this._notifyPayFlowClosed);
+        return;
+      }
+    };
+    content.addEventListener("mozContentEvent",
+                             this._notifyPayFlowClosed.bind(this));
 
     browser.shell.sendChromeEvent(detail);
   },
 
+  cleanup: function cleanup() {
+    let browser = Services.wm.getMostRecentWindow("navigator:browser");
+    let content = browser.getContentWindow();
+    if (!content) {
+      return;
+    }
+    content.removeEventListener("mozContentEvent", this._notifyPayFlowClosed);
+  },
+
   getRandomId: function getRandomId() {
     return uuidgen.generateUUID().toString();
   },
 
   classID: Components.ID("{8b83eabc-7929-47f4-8b48-4dea8d887e4b}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue])
 }
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -21,33 +21,42 @@ let log =
 const APPLY_PROMPT_TIMEOUT =
       Services.prefs.getIntPref("b2g.update.apply-prompt-timeout");
 const APPLY_IDLE_TIMEOUT =
       Services.prefs.getIntPref("b2g.update.apply-idle-timeout");
 const SELF_DESTRUCT_TIMEOUT =
       Services.prefs.getIntPref("b2g.update.self-destruct-timeout");
 
 const APPLY_IDLE_TIMEOUT_SECONDS = APPLY_IDLE_TIMEOUT / 1000;
-
+const NETWORK_ERROR_OFFLINE = 111;
 
 XPCOMUtils.defineLazyServiceGetter(Services, "aus",
                                    "@mozilla.org/updates/update-service;1",
                                    "nsIApplicationUpdateService");
 
+XPCOMUtils.defineLazyServiceGetter(Services, "um",
+                                   "@mozilla.org/updates/update-manager;1",
+                                   "nsIUpdateManager");
+
 XPCOMUtils.defineLazyServiceGetter(Services, "idle",
                                    "@mozilla.org/widget/idleservice;1",
                                    "nsIIdleService");
 
+XPCOMUtils.defineLazyServiceGetter(Services, "settings",
+                                   "@mozilla.org/settingsService;1",
+                                   "nsISettingsService");
+
 function UpdatePrompt() {
   this.wrappedJSObject = this;
 }
 
 UpdatePrompt.prototype = {
   classID: Components.ID("{88b3eb21-d072-4e3b-886d-f89d8c49fe59}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt,
+                                         Ci.nsIUpdateCheckListener,
                                          Ci.nsIRequestObserver,
                                          Ci.nsIProgressEventSink,
                                          Ci.nsIObserver]),
   _xpcom_factory: XPCOMUtils.generateSingletonFactory(UpdatePrompt),
 
   _update: null,
   _applyPromptTimer: null,
   _waitingForIdle: false,
@@ -83,67 +92,116 @@ UpdatePrompt.prototype = {
     log("Update is ready to apply, registering idle timeout of " +
         APPLY_IDLE_TIMEOUT_SECONDS + " seconds before prompting.");
 
     this._update = aUpdate;
     this.waitForIdle();
   },
 
   showUpdateError: function UP_showUpdateError(aUpdate) {
-    if (aUpdate.state == "failed") {
-      log("Failed to download update, errorCode: " + aUpdate.errorCode);
-    }
+    log("Update error, state: " + aUpdate.state + ", errorCode: " +
+        aUpdate.errorCode);
+
+    this.sendUpdateEvent("update-error", aUpdate);
+    this.setUpdateStatus(aUpdate.statusText);
   },
 
   showUpdateHistory: function UP_showUpdateHistory(aParent) { },
   showUpdateInstalled: function UP_showUpdateInstalled() { },
 
+  // nsIUpdateCheckListener
+
+  onCheckComplete: function UP_onCheckComplete(request, updates, updateCount) {
+    if (Services.um.activeUpdate) {
+      return;
+    }
+
+    if (updateCount == 0) {
+      this.setUpdateStatus("no-updates");
+      return;
+    }
+
+    let update = Services.aus.selectUpdate(updates, updateCount);
+    if (!update) {
+      this.setUpdateStatus("already-latest-version");
+      return;
+    }
+
+    this.setUpdateStatus("check-complete");
+    this.showUpdateAvailable(update);
+  },
+
+  onError: function UP_onError(request, update) {
+    if (update.errorCode == NETWORK_ERROR_OFFLINE) {
+      this.setUpdateStatus("retry-when-online");
+    }
+
+    Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
+    Services.aus.onError(request, update);
+  },
+
+  onProgress: function UP_onProgress(request, position, totalSize) {
+    Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
+    Services.aus.onProgress(request, position, totalSize);
+  },
+
   // Custom functions
 
   waitForIdle: function UP_waitForIdle() {
     if (this._waitingForIdle) {
       return;
     }
 
     this._waitingForIdle = true;
     Services.idle.addIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
     Services.obs.addObserver(this, "quit-application", false);
   },
 
+  setUpdateStatus: function UP_setUpdateStatus(aStatus) {
+    log("Setting gecko.updateStatus: " + aStatus);
+
+    let lock = Services.settings.createLock();
+    lock.set("gecko.updateStatus", aStatus, null);
+  },
+
   showApplyPrompt: function UP_showApplyPrompt(aUpdate) {
     if (!this.sendUpdateEvent("update-prompt-apply", aUpdate)) {
       log("Unable to prompt, forcing restart");
       this.restartProcess();
       return;
     }
 
     // Schedule a fallback timeout in case the UI is unable to respond or show
     // a prompt for some reason.
     this._applyPromptTimer = this.createTimer(APPLY_PROMPT_TIMEOUT);
   },
 
   sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
     let detail = {
       displayVersion: aUpdate.displayVersion,
-      detailsURL: aUpdate.detailsURL
+      detailsURL: aUpdate.detailsURL,
+      statusText: aUpdate.statusText,
+      state: aUpdate.state,
+      errorCode: aUpdate.errorCode,
+      isOSUpdate: aUpdate.isOSUpdate
     };
 
     let patch = aUpdate.selectedPatch;
-    if (!patch) {
+    if (!patch && aUpdate.patchCount > 0) {
       // For now we just check the first patch to get size information if a
       // patch hasn't been selected yet.
-      if (aUpdate.patchCount == 0) {
-        log("Warning: no patches available in update");
-        return false;
-      }
       patch = aUpdate.getPatchAt(0);
     }
 
-    detail.size = patch.size;
-    detail.updateType = patch.type;
+    if (patch) {
+      detail.size = patch.size;
+      detail.updateType = patch.type;
+    } else {
+      log("Warning: no patches available in update");
+    }
 
     this._update = aUpdate;
     return this.sendChromeEvent(aType, detail);
   },
 
   sendChromeEvent: function UP_sendChromeEvent(aType, aDetail) {
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     if (!browser) {
@@ -247,21 +305,27 @@ UpdatePrompt.prototype = {
       log("Error: Couldn't reboot into recovery to apply FOTA update " +
           aOsUpdatePath);
     }
   },
 
   forceUpdateCheck: function UP_forceUpdateCheck() {
     log("Forcing update check");
 
+    // If we already have an active update available, don't try to
+    // download again, just prompt for install.
+    if (Services.um.activeUpdate) {
+      this.setUpdateStatus("check-complete");
+      this.showApplyPrompt(Services.um.activeUpdate);
+      return;
+    }
+
     let checker = Cc["@mozilla.org/updates/update-checker;1"]
                     .createInstance(Ci.nsIUpdateChecker);
-
-    Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
-    checker.checkForUpdates(Services.aus, true);
+    checker.checkForUpdates(this, true);
   },
 
   handleEvent: function UP_handleEvent(evt) {
     if (evt.type !== "mozContentEvent") {
       return;
     }
 
     let detail = evt.detail;
--- a/b2g/components/YoutubeProtocolHandler.js
+++ b/b2g/components/YoutubeProtocolHandler.js
@@ -70,37 +70,44 @@ YoutubeProtocolHandler.prototype = {
       if (pos == -1) {
         return;
       }
       let streams = decodeURIComponent(xhr.responseText
                                        .substring(pos + key.length)).split(",");
       let uri;
       let mimeType;
 
-      // Recognized mime types, ordered from the less usable to the most usable.
-      let recognizedTypes = ["video/webm"];
+      // itag is an undocumented value which maps to resolution and mimetype
+      // see https://en.wikipedia.org/wiki/YouTube#Quality_and_codecs
+      // Ordered from least to most preferred
+      let recognizedItags = [
+        "17", // 144p 3GP
+        "36", // 240p 3GP
+        "43", // 360p WebM
 #ifdef MOZ_WIDGET_GONK
-      recognizedTypes.push("video/mp4");
+        "18", // 360p H.264
 #endif
+      ];
 
-      let bestType = -1;
+      let bestItag = -1;
 
       let extras = { }
 
       streams.forEach(function(aStream) {
         let params = extractParameters(aStream);
         let url = params["url"];
         let type = params["type"] ? params["type"].split(";")[0] : null;
+        let itag = params["itag"];
 
         let index;
-        if (url && type && ((index = recognizedTypes.indexOf(type)) != -1) &&
-            index > bestType) {
-          uri = url;
+        if (url && type && ((index = recognizedItags.indexOf(itag)) != -1) &&
+            index > bestItag) {
+          uri = url + '&signature=' + (params["sig"] ? params['sig'] : '');
           mimeType = type;
-          bestType = index;
+          bestItag = index;
         }
         for (let param in params) {
           if (["thumbnail_url", "length_seconds", "title"].indexOf(param) != -1) {
             extras[param] = decodeURIComponent(params[param]);
           }
         }
       });
 
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/debug
+++ b/b2g/config/mozconfigs/ics_armv7a_gecko/debug
@@ -1,16 +1,16 @@
 mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
 
 mk_add_options MOZ_MAKE_FLAGS="-j8"
 
 ac_add_options --enable-application=b2g
 ac_add_options --enable-b2g-camera
 
-ac_add_options --target=arm-android-eabi
+ac_add_options --target=arm-linux-androideabi
 ac_add_options --with-gonk="$topsrcdir/gonk-toolchain"
 export TOOLCHAIN_HOST=linux-x86
 export GONK_PRODUCT=generic
 ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-"
 ac_add_options --disable-elf-hack
 ac_add_options --enable-debug-symbols
 ac_add_options --enable-debug
 # IonMonkey disabled in bug 789373
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/nightly
+++ b/b2g/config/mozconfigs/ics_armv7a_gecko/nightly
@@ -2,17 +2,17 @@
 
 mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
 
 mk_add_options MOZ_MAKE_FLAGS="-j8"
 
 ac_add_options --enable-application=b2g
 ac_add_options --enable-b2g-camera
 
-ac_add_options --target=arm-android-eabi
+ac_add_options --target=arm-linux-androideabi
 ac_add_options --with-gonk="$topsrcdir/gonk-toolchain"
 export TOOLCHAIN_HOST=linux-x86
 export GONK_PRODUCT=generic
 ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-"
 ac_add_options --disable-elf-hack
 ac_add_options --enable-debug-symbols
 # ac_add_options --enable-profiling
 # IonMonkey disabled in bug 789373
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -1,13 +1,13 @@
 ; This Source Code Form is subject to the terms of the Mozilla Public
 ; License, v. 2.0. If a copy of the MPL was not distributed with this
 ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-; Package file for the B2G build. 
+; Package file for the B2G build.
 ;
 ; File format:
 ;
 ; [] designates a toplevel component. Example: [xpcom]
 ; - in front of a file specifies it to be removed from the destination
 ; * wildcard support to recursively copy the entire directory
 ; ; file comment
 ;
@@ -375,21 +375,23 @@
 @BINPATH@/components/nsDownloadManagerUI.manifest
 @BINPATH@/components/nsDownloadManagerUI.js
 @BINPATH@/components/NetworkGeolocationProvider.manifest
 @BINPATH@/components/NetworkGeolocationProvider.js
 @BINPATH@/components/GPSDGeolocationProvider.manifest
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
+#ifndef MOZ_WIDGET_GONK
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
 @BINPATH@/components/amContentHandler.js
 @BINPATH@/components/amWebInstallListener.js
 @BINPATH@/components/nsBlocklistService.js
+#endif
 
 #ifdef MOZ_UPDATER
 @BINPATH@/components/nsUpdateService.manifest
 @BINPATH@/components/nsUpdateService.js
 @BINPATH@/components/nsUpdateServiceStub.js
 #endif
 @BINPATH@/components/nsUpdateTimerManager.manifest
 @BINPATH@/components/nsUpdateTimerManager.js
--- a/browser/app/macbuild/Contents/Info.plist.in
+++ b/browser/app/macbuild/Contents/Info.plist.in
@@ -198,16 +198,18 @@
 				<string>file</string>
 			</array>
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
 	<string>%MAC_BUNDLE_VERSION%</string>
 	<key>NSAppleScriptEnabled</key>
 	<true/>
+	<key>LSApplicationCategoryType</key>
+	<string>public.app-category.productivity</string>
 	<key>LSMinimumSystemVersion</key>
 	<string>10.6</string>
 	<key>LSMinimumSystemVersionByArchitecture</key>
 	<dict>
 		<key>i386</key>
 		<string>10.6.0</string>
 		<key>x86_64</key>
 		<string>10.6.0</string>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -110,18 +110,20 @@ pref("app.update.cert.maxErrors", 5);
 // pairs for the certificate used by the server that hosts the update xml file
 // as specified in the |app.update.url| preference. When these preferences are
 // present the following conditions apply for a successful update check:
 // 1. the uri scheme must be https
 // 2. the preference name must exist as an attribute name on the certificate and
 //    the value for the name must be the same as the value for the attribute name
 //    on the certificate.
 // If these conditions aren't met it will be treated the same as when there is
-// no update available. This validation will not be performed when using the
-// |app.update.url.override| preference for update checking.
+// no update available. This validation will not be performed when the
+// |app.update.url.override| user preference has been set for testing updates or
+// when the |app.update.cert.checkAttributes| preference is set to false. Also,
+// the |app.update.url.override| preference should ONLY be used for testing.
 pref("app.update.certs.1.issuerName", "OU=Equifax Secure Certificate Authority,O=Equifax,C=US");
 pref("app.update.certs.1.commonName", "aus3.mozilla.org");
 
 pref("app.update.certs.2.issuerName", "CN=Thawte SSL CA,O=\"Thawte, Inc.\",C=US");
 pref("app.update.certs.2.commonName", "aus3.mozilla.org");
 
 // Whether or not app updates are enabled
 pref("app.update.enabled", true);
@@ -1165,17 +1167,17 @@ pref("pdfjs.previousHandler.preferredAct
 pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
 
 // The maximum amount of decoded image data we'll willingly keep around (we
 // might keep around more than this, but we'll try to get down to this value).
 // (This is intentionally on the high side; see bug 746055.)
 pref("image.mem.max_decoded_image_kb", 256000);
 
 // Example social provider
-pref("social.manifest.motown", "{\"origin\":\"https://motown-dev.mozillalabs.com\",\"name\":\"MoTown\",\"workerURL\":\"https://motown-dev.mozillalabs.com/social/worker.js\",\"iconURL\":\"https://motown-dev.mozillalabs.com/images/motown-icon.png\",\"sidebarURL\":\"https://motown-dev.mozillalabs.com/social/sidebar\"}");
+pref("social.manifest.facebook", "{\"origin\":\"https://www.facebook.com\",\"name\":\"Facebook Messenger\",\"workerURL\":\"https://www.facebook.com/desktop/fbdesktop2/socialfox/fbworker.js.php\",\"iconURL\":\"data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAX0lEQVQ4jWP4%2F%2F8%2FAyUYTFhHzjgDxP9JxGeQDSBVMxgTbUBCxer%2Fr999%2BQ8DJBuArJksA9A10s8AXIBoA0B%2BR%2FY%2FjD%2BEwoBoA1yT5v3PbdmCE8MAshhID%2FUMoDgzUYIBj0Cgi7ar4coAAAAASUVORK5CYII%3D\",\"sidebarURL\":\"https://www.facebook.com/desktop/fbdesktop2/?socialfox=true\"}");
 // Comma-separated list of nsIURI::prePaths that are allowed to activate
 // built-in social functionality.
-pref("social.activation.whitelist", "https://motown-dev.mozillalabs.com");
+pref("social.activation.whitelist", "https://www.facebook.com");
 pref("social.sidebar.open", true);
 pref("social.active", false);
 pref("social.toast-notifications.enabled", true);
 
 pref("dom.identity.enabled", false);
--- a/browser/base/content/abouthome/aboutHome.js
+++ b/browser/base/content/abouthome/aboutHome.js
@@ -95,19 +95,18 @@ let gObserver = new MutationObserver(fun
   }
 });
 
 window.addEventListener("load", function () {
   // Delay search engine setup, cause browser.js::BrowserOnAboutPageLoad runs
   // later and may use asynchronous getters.
   window.gObserver.observe(document.documentElement, { attributes: true });
   fitToWidth();
+  window.addEventListener("resize", fitToWidth);
 });
-window.addEventListener("resize", fitToWidth);
-
 
 function onSearchSubmit(aEvent)
 {
   let searchTerms = document.getElementById("searchText").value;
   let searchURL = document.documentElement.getAttribute("searchEngineURL");
   if (searchURL && searchTerms.length > 0) {
     const SEARCH_TOKENS = {
       "_searchTerms_": encodeURIComponent(searchTerms)
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -173,16 +173,34 @@ let SocialUI = {
 
   undoActivation: function SocialUI_undoActivation() {
     Social.active = false;
     this.notificationPanel.hidePopup();
   },
 
   haveLoggedInUser: function SocialUI_haveLoggedInUser() {
     return !!(Social.provider && Social.provider.profile && Social.provider.profile.userName);
+  },
+
+  closeSocialPanelForLinkTraversal: function (target, linkNode) {
+    // No need to close the panel if this traversal was not retargeted
+    if (target == "" || target == "_self")
+      return;
+
+    // Check to see whether this link traversal was in a social panel
+    let win = linkNode.ownerDocument.defaultView;
+    let container = win.QueryInterface(Ci.nsIInterfaceRequestor)
+                                  .getInterface(Ci.nsIWebNavigation)
+                                  .QueryInterface(Ci.nsIDocShell)
+                                  .chromeEventHandler;
+    let containerParent = container.parentNode;
+    if (containerParent.classList.contains("social-panel") &&
+        containerParent instanceof Ci.nsIDOMXULPopupElement) {
+      containerParent.hidePopup();
+    }
   }
 }
 
 let SocialChatBar = {
   get chatbar() {
     return document.getElementById("pinnedchats");
   },
   // Whether the chats can be shown for this window.
@@ -622,17 +640,17 @@ var SocialToolbar = {
   get button() {
     return document.getElementById("social-provider-button");
   },
 
   updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
     let tbi = document.getElementById("social-toolbar-item");
     tbi.hidden = !Social.uiVisible;
     if (!SocialUI.haveLoggedInUser()) {
-      let parent = document.getElementById("social-notification-box");
+      let parent = document.getElementById("social-notification-panel");
       while (parent.hasChildNodes())
         parent.removeChild(parent.firstChild);
 
       while (tbi.lastChild != tbi.firstChild)
         tbi.removeChild(tbi.lastChild);
     }
   },
 
@@ -657,17 +675,16 @@ var SocialToolbar = {
   },
 
   updateButton: function SocialToolbar_updateButton() {
     this.updateButtonHiddenState();
     let provider = Social.provider;
     let icons = provider.ambientNotificationIcons;
     let iconNames = Object.keys(icons);
     let iconBox = document.getElementById("social-toolbar-item");
-    let notifBox = document.getElementById("social-notification-box");
     let panel = document.getElementById("social-notification-panel");
     panel.hidden = false;
 
     let command = document.getElementById("Social:ToggleNotifications");
     command.setAttribute("checked", Services.prefs.getBoolPref("social.toast-notifications.enabled"));
 
     const CACHE_PREF_NAME = "social.cached.notificationIcons";
     // provider.profile == undefined means no response yet from the provider
@@ -775,40 +792,39 @@ var SocialToolbar = {
       let labelValue = icon.counter || "";
       // Only update the value attribute if it has changed to reduce layout changes.
       if (!label.hasAttribute("value") || label.getAttribute("value") != labelValue)
         label.setAttribute("value", labelValue);
 
       if (image.getAttribute("src") != icon.iconURL)
         image.setAttribute("src", icon.iconURL);
     }
-    notifBox.appendChild(notificationFrames);
+    panel.appendChild(notificationFrames);
     iconBox.appendChild(iconContainers);
 
     for (let frame of createdFrames) {
       if (frame.docShell) {
         frame.docShell.isActive = false;
         frame.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                       .getInterface(Ci.nsIWebProgress)
                       .addProgressListener(new SocialErrorListener("notification-panel"),
                                            Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
                                            Ci.nsIWebProgress.NOTIFY_LOCATION);
       }
     }
   },
 
   showAmbientPopup: function SocialToolbar_showAmbientPopup(aToolbarButtonBox) {
     let panel = document.getElementById("social-notification-panel");
-    let notifBox = document.getElementById("social-notification-box");
     let notificationFrameId = aToolbarButtonBox.getAttribute("notificationFrameId");
     let notificationFrame = document.getElementById(notificationFrameId);
 
     // Clear dimensions on all browsers so the panel size will
     // only use the selected browser.
-    let frameIter = notifBox.firstElementChild;
+    let frameIter = panel.firstElementChild;
     while (frameIter) {
       frameIter.collapsed = (frameIter != notificationFrame);
       frameIter = frameIter.nextElementSibling;
     }
 
     function dispatchPanelEvent(name) {
       let evt = notificationFrame.contentDocument.createEvent("CustomEvent");
       evt.initCustomEvent(name, true, true, {});
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -373,35 +373,33 @@ window[chromehidden~="toolbar"] toolbar:
 /*  Full Screen UI */
 
 #fullscr-toggler {
   height: 1px;
   background: black;
 }
 
 #full-screen-warning-container {
-  pointer-events: none;
   position: fixed;
   top: 0;
   left: 0;
   width: 100%;
   height: 100%;
 }
 
 #full-screen-warning-container[fade-warning-out] {
   transition-property: opacity !important;
   transition-duration: 500ms !important;
   opacity: 0.0;
 }
 
 #full-screen-warning-message {
-  pointer-events: auto;
   /* We must specify a max-width, otherwise word-wrap:break-word doesn't
      work in descendant <description> and <label> elements. Bug 630864. */
-  max-width: 800px;  
+  max-width: 800px;
 }
 
 #full-screen-domain-text,
 #full-screen-remember-decision > .checkbox-label-box > .checkbox-label {
   word-wrap: break-word;
   /* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */
   min-width: 1px;
 }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2548,17 +2548,17 @@ let BrowserOnClick = {
     let elmId = aTargetElm.getAttribute("id");
     let secHistogram = Cc["@mozilla.org/base/telemetry;1"].
                         getService(Ci.nsITelemetry).
                         getHistogramById("SECURITY_UI");
 
     switch (elmId) {
       case "exceptionDialogButton":
         secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_CLICK_ADD_EXCEPTION);
-        let params = { exceptionAdded : false, handlePrivateBrowsing : true };
+        let params = { exceptionAdded : false };
 
         try {
           switch (Services.prefs.getIntPref("browser.ssl_override_behavior")) {
             case 2 : // Pre-fetch & pre-populate
               params.prefetchCert = true;
             case 1 : // Pre-populate
               params.location = aOwnerDoc.location.href;
           }
@@ -3910,16 +3910,22 @@ var XULBrowserWindow = {
       field.label = text;
       field.setAttribute("crop", type == "overLink" ? "center" : "end");
       this.statusText = text;
     }
   },
 
   // Called before links are navigated to to allow us to retarget them if needed.
   onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
+    let target = this._onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
+    SocialUI.closeSocialPanelForLinkTraversal(target, linkNode);
+    return target;
+  },
+
+  _onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
     // Don't modify non-default targets or targets that aren't in top-level app
     // tab docshells (isAppTab will be false for app tab subframes).
     if (originalTarget != "" || !isAppTab)
       return originalTarget;
 
     // External links from within app tabs should always open in new tabs
     // instead of replacing the app tab's page (Bug 575561)
     let linkHost;
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -262,19 +262,17 @@
       </hbox>
     </panel>
 
     <panel id="social-notification-panel"
            class="social-panel"
            type="arrow"
            hidden="true"
            consumeoutsideclicks="true"
-           noautofocus="true">
-      <box id="social-notification-box" flex="1"></box>
-    </panel>
+           noautofocus="true"/>
     <panel id="social-flyout-panel"
            class="social-panel"
            onpopupshown="SocialFlyout.onShown()"
            onpopuphidden="SocialFlyout.onHidden()"
            side="right"
            type="arrow"
            hidden="true"
            noautofocus="true"
@@ -1075,17 +1073,18 @@
       </toolbar>
       <deck id="devtools-sidebar-deck" flex="1"/>
     </vbox>
     <splitter id="social-sidebar-splitter"
               class="chromeclass-extrachrome sidebar-splitter"
               observes="socialSidebarBroadcaster"/>
     <vbox id="social-sidebar-box"
           class="chromeclass-extrachrome"
-          observes="socialSidebarBroadcaster">
+          observes="socialSidebarBroadcaster"
+          persist="width">
       <browser id="social-sidebar-browser"
                type="content"
                disableglobalhistory="true"
                flex="1"
                style="min-width: 14em; width: 18em; max-width: 36em;"/>
     </vbox>
     <vbox id="browser-border-end" hidden="true" layer="true"/>
   </hbox>
index 37e54a1e9a0637be9a078eb4e51465eb609a3174..e0e575a812b1734cc83c21875229c57628cd15ed
GIT binary patch
literal 2718
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
Y16U66*5))iEdT%j07*qoM6N<$f@&ch82|tP
--- a/browser/base/content/socialchat.xml
+++ b/browser/base/content/socialchat.xml
@@ -320,17 +320,17 @@
               if (aCallback)
                 aCallback(cb.iframe.contentWindow);
               return;
             }
             this.chatboxForURL.delete(aURL);
           }
           cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
           if (aMode == "minimized")
-            cb.minimized = true;
+            cb.setAttribute("minimized", "true");
           this.selectedChat = cb;
           this.insertBefore(cb, this.firstChild);
           cb.init(aProvider, aURL, aCallback);
           this.chatboxForURL.set(aURL, Cu.getWeakReference(cb));
         ]]></body>
       </method>
 
     </implementation>
--- a/browser/base/content/test/browser_minimize.js
+++ b/browser/base/content/test/browser_minimize.js
@@ -15,16 +15,20 @@ function waitForInactive() {
         return;
     }
     is(gBrowser.docShell.isActive, false, "Docshell should be inactive");
     window.restore();
     waitForActive();
 }
 
 function test() {
+    registerCleanupFunction(function() {
+      window.restore();
+    });
+
     waitForExplicitFinish();
     is(gBrowser.docShell.isActive, true, "Docshell should be active");
     window.minimize();
     // XXX On Linux minimize/restore seem to be very very async, but
     // our window.windowState changes sync.... so we can't rely on the
     // latter correctly reflecting the state of the former.  In
     // particular, a restore() call before minimizing is done will not
     // actually restore the window, but change the window state.  As a
--- a/browser/base/content/test/browser_pluginnotification.js
+++ b/browser/base/content/test/browser_pluginnotification.js
@@ -906,10 +906,71 @@ function test21e() {
     var plugin = doc.getElementById(id);
     var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
     ok(rect.width == 0, "Test 21e, Plugin with id=" + plugin.id + " overlay rect should have 0px width after being clicked");
     ok(rect.height == 0, "Test 21e, Plugin with id=" + plugin.id + " overlay rect should have 0px height after being clicked");
     var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     ok(objLoadingContent.activated, "Test 21e, Plugin with id=" + plugin.id + " should be activated");
   }
 
+  Services.prefs.setBoolPref("plugins.click_to_play", true);
+  prepareTest(test22, gTestRoot + "plugin_test.html");
+}
+
+// Tests that a click-to-play plugin retains its activated state upon reloading
+function test22() {
+  ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 22, Should have a click-to-play notification");
+
+  // Plugin should start as CTP
+  var pluginNode = gTestBrowser.contentDocument.getElementById("test");
+  ok(pluginNode, "Test 22, Found plugin in page");
+  var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
+  is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 22, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
+
+  // Activate
+  objLoadingContent.playPlugin();
+  is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 22, plugin should have started");
+  ok(pluginNode.activated, "Test 22, plugin should be activated");
+
+  // Reload plugin
+  var oldVal = pluginNode.getObjectValue();
+  pluginNode.src = pluginNode.src;
+  is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 22, Plugin should have retained activated state");
+  ok(pluginNode.activated, "Test 22, plugin should have remained activated");
+  // Sanity, ensure that we actually reloaded the instance, since this behavior might change in the future.
+  var pluginsDiffer;
+  try {
+    pluginNode.checkObjectValue(oldVal);
+  } catch (e) {
+    pluginsDiffer = true;
+  }
+  ok(pluginsDiffer, "Test 22, plugin should have reloaded");
+
+  prepareTest(test23, gTestRoot + "plugin_test.html");
+}
+
+// Tests that a click-to-play plugin resets its activated state when changing types
+function test23() {
+  ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 23, Should have a click-to-play notification");
+
+  // Plugin should start as CTP
+  var pluginNode = gTestBrowser.contentDocument.getElementById("test");
+  ok(pluginNode, "Test 23, Found plugin in page");
+  var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
+  is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 23, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
+
+  // Activate
+  objLoadingContent.playPlugin();
+  is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 23, plugin should have started");
+  ok(pluginNode.activated, "Test 23, plugin should be activated");
+
+  // Reload plugin (this may need RunSoon() in the future when plugins change state asynchronously)
+  pluginNode.type = null;
+  pluginNode.src = pluginNode.src; // We currently don't properly change state just on type change, bug 767631
+  is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, plugin should be unloaded");
+  pluginNode.type = "application/x-test";
+  pluginNode.src = pluginNode.src;
+  is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, Plugin should not have activated");
+  is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 23, Plugin should be click-to-play");
+  ok(!pluginNode.activated, "Test 23, plugin node should not be activated");
+
   finishTest();
 }
--- a/browser/base/content/test/browser_social_chatwindow.js
+++ b/browser/base/content/test/browser_social_chatwindow.js
@@ -99,16 +99,17 @@ var tests = {
     ok(port, "provider has a port");
     port.postMessage({topic: "test-init"});
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "got-chatbox-message":
           ok(true, "got a chat window opened");
           let chats = document.getElementById("pinnedchats");
+          ok(chats.selectedChat.minimized, "chatbox from worker opened as minimized");
           while (chats.selectedChat) {
             chats.selectedChat.close();
           }
           ok(!chats.selectedChat, "chats are all closed");
           port.close();
           ensureSocialUrlNotRemembered(chatUrl);
           next();
           break;
--- a/browser/base/content/test/browser_social_flyout.js
+++ b/browser/base/content/test/browser_social_flyout.js
@@ -73,33 +73,78 @@ var tests = {
           SocialFlyout.dispatchPanelEvent("socialTest-MakeWider");
           break;
       }
     }
     port.postMessage({topic: "test-init"});
   },
 
   testCloseSelf: function(next) {
+    // window.close is affected by the pref dom.allow_scripts_to_close_windows,
+    // which defaults to false, but is set to true by the test harness.
+    // so temporarily set it back.
+    const ALLOW_SCRIPTS_TO_CLOSE_PREF = "dom.allow_scripts_to_close_windows";
+    // note clearUserPref doesn't do what we expect, as the test harness itself
+    // changes the pref value - so clearUserPref resets it to false rather than
+    // the true setup by the test harness.
+    let oldAllowScriptsToClose = Services.prefs.getBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF);    
+    Services.prefs.setBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF, false);
     let panel = document.getElementById("social-flyout-panel");
     let port = Social.provider.getWorkerPort();
     ok(port, "provider has a port");
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "test-init-done":
           port.postMessage({topic: "test-flyout-open"});
           break;
         case "got-flyout-visibility":
           let iframe = panel.firstChild;
           iframe.contentDocument.addEventListener("SocialTest-DoneCloseSelf", function _doneHandler() {
             iframe.contentDocument.removeEventListener("SocialTest-DoneCloseSelf", _doneHandler, false);
             is(panel.state, "closed", "flyout should have closed itself");
+            Services.prefs.setBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF, oldAllowScriptsToClose);
             next();
           }, false);
           is(panel.state, "open", "flyout should be open");
           port.close(); // so we don't get the -visibility message as it hides...
           SocialFlyout.dispatchPanelEvent("socialTest-CloseSelf");
           break;
       }
     }
     port.postMessage({topic: "test-init"});
+  },
+
+  testCloseOnLinkTraversal: function(next) {
+
+    function onTabOpen(event) {
+      gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, true);
+      is(panel.state, "closed", "flyout should be closed");
+      ok(true, "Link should open a new tab");
+      executeSoon(function(){
+        gBrowser.removeTab(event.target);
+        next();
+      });
+    }
+
+    let panel = document.getElementById("social-flyout-panel");
+    let port = Social.provider.getWorkerPort();
+    ok(port, "provider has a port");
+    port.onmessage = function (e) {
+      let topic = e.data.topic;
+      switch (topic) {
+        case "test-init-done":
+          port.postMessage({topic: "test-flyout-open"});
+          break;
+        case "got-flyout-visibility":
+          if (e.data.result == "shown") {
+            // click on our test link
+            is(panel.state, "open", "flyout should be open");
+            gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true); 
+            let iframe = panel.firstChild;
+            iframe.contentDocument.getElementById('traversal').click();
+          }
+          break;
+      }
+    }
+    port.postMessage({topic: "test-init"});
   }
 }
--- a/browser/base/content/test/social_flyout.html
+++ b/browser/base/content/test/social_flyout.html
@@ -26,10 +26,12 @@
         var evt = document.createEvent("CustomEvent");
         evt.initCustomEvent("SocialTest-DoneCloseSelf", true, true, {});
         document.documentElement.dispatchEvent(evt);
       }, false);
     </script>
   </head>
   <body style="max-width: 250px;" onload="pingWorker();">
     <p>This is a test social flyout panel.</p>
+    <a id="traversal" href="http://mochi.test">test link</a>
   </body>
 </html>
+
--- a/browser/branding/aurora/pref/firefox-branding.js
+++ b/browser/branding/aurora/pref/firefox-branding.js
@@ -1,18 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // We don't have pages ready for this, so leave these prefs empty for now (bug 648330)
 pref("startup.homepage_override_url","");
 pref("startup.homepage_welcome_url","");
 // The time interval between checks for a new version (in seconds)
-// nightly=8 hours, official=24 hours
-pref("app.update.interval", 28800);
+pref("app.update.interval", 28800); // 8 hours
 // The time interval between the downloading of mar file chunks in the
 // background (in seconds)
 pref("app.update.download.backgroundInterval", 60);
 // Give the user x seconds to react before showing the big UI. default=24 hours
 pref("app.update.promptWaitTime", 86400);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
 pref("app.update.url.manual", "http://www.mozilla.com/firefox/channel/");
--- a/browser/branding/official/pref/firefox-branding.js
+++ b/browser/branding/official/pref/firefox-branding.js
@@ -1,20 +1,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 pref("startup.homepage_override_url","http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/whatsnew/?oldversion=%OLD_VERSION%");
 pref("startup.homepage_welcome_url","http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/firstrun/");
 // Interval: Time between checks for a new version (in seconds)
-// nightly=6 hours, official=24 hours
-pref("app.update.interval", 86400);
+pref("app.update.interval", 43200); // 12 hours
 // The time interval between the downloading of mar file chunks in the
 // background (in seconds)
-pref("app.update.download.backgroundInterval", 600);
+pref("app.update.download.backgroundInterval", 60);
 // Give the user x seconds to react before showing the big UI. default=24 hours
 pref("app.update.promptWaitTime", 86400);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
 pref("app.update.url.manual", "http://www.firefox.com");
 // A default value for the "More information about this update" link
 // supplied in the "An update is available" page of the update wizard. 
 pref("app.update.url.details", "http://www.mozilla.com/%LOCALE%/%APP%/releases/");
--- a/browser/components/preferences/in-content/tests/Makefile.in
+++ b/browser/components/preferences/in-content/tests/Makefile.in
@@ -20,14 +20,17 @@ include $(topsrcdir)/config/rules.mk
     browser_connection.js \
     privacypane_tests.js \
     browser_privacypane_1.js \
     browser_privacypane_2.js \
     browser_privacypane_3.js \
     browser_privacypane_4.js \
     browser_privacypane_5.js \
     browser_privacypane_6.js \
-    browser_privacypane_7.js \
     browser_privacypane_8.js \
     $(NULL)
 
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+_BROWSER_FILES += browser_privacypane_7.js
+endif
+
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/components/preferences/jar.mn
+++ b/browser/components/preferences/jar.mn
@@ -28,17 +28,17 @@ browser.jar:
 *   content/browser/preferences/languages.xul
     content/browser/preferences/languages.js
 *   content/browser/preferences/main.xul
     content/browser/preferences/main.js
 *   content/browser/preferences/permissions.xul
     content/browser/preferences/permissions.js
 *   content/browser/preferences/preferences.xul
     content/browser/preferences/privacy.xul
-    content/browser/preferences/privacy.js
+*   content/browser/preferences/privacy.js
     content/browser/preferences/sanitize.xul
     content/browser/preferences/security.xul
     content/browser/preferences/security.js
     content/browser/preferences/selectBookmark.xul
     content/browser/preferences/selectBookmark.js
 #ifdef MOZ_SERVICES_SYNC
     content/browser/preferences/sync.xul
     content/browser/preferences/sync.js
--- a/browser/components/preferences/privacy.js
+++ b/browser/components/preferences/privacy.js
@@ -217,28 +217,32 @@ var gPrivacyPane = {
   },
 
   autoStartPrivateBrowsingObserver:
   {
     QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]),
 
     observe: function PPP_observe(aSubject, aTopic, aData)
     {
-      let privateBrowsingService = Components.classes["@mozilla.org/privatebrowsing;1"].
-        getService(Components.interfaces.nsIPrivateBrowsingService);
-
       // Toggle the private browsing mode without switching the session
       let prefValue = document.getElementById("browser.privatebrowsing.autostart").value;
       let keepCurrentSession = document.getElementById("browser.privatebrowsing.keep_current_session");
       keepCurrentSession.value = true;
+
+#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+      let privateBrowsingService = Components.classes["@mozilla.org/privatebrowsing;1"].
+        getService(Components.interfaces.nsIPrivateBrowsingService);
+
       // If activating from within the private browsing mode, reset the
       // private session
       if (prefValue && privateBrowsingService.privateBrowsingEnabled)
         privateBrowsingService.privateBrowsingEnabled = false;
       privateBrowsingService.privateBrowsingEnabled = prefValue;
+#endif
+
       keepCurrentSession.reset();
     }
   },
 
   // HISTORY
 
   /**
    * Read the location bar enabled and suggestion prefs
--- a/browser/components/preferences/tests/Makefile.in
+++ b/browser/components/preferences/tests/Makefile.in
@@ -18,16 +18,19 @@ include $(topsrcdir)/config/rules.mk
     browser_bug705422.js \
     privacypane_tests.js \
     browser_privacypane_1.js \
     browser_privacypane_2.js \
     browser_privacypane_3.js \
     browser_privacypane_4.js \
     browser_privacypane_5.js \
     browser_privacypane_6.js \
-    browser_privacypane_7.js \
     browser_privacypane_8.js \
     browser_permissions.js \
     browser_chunk_permissions.js \
     $(NULL)
 
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+_BROWSER_FILES += browser_privacypane_7.js
+endif
+
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -461,16 +461,17 @@ PrivateBrowsingService.prototype = {
       case "command-line-startup":
         this._obs.removeObserver(this, "command-line-startup");
         aSubject.QueryInterface(Ci.nsICommandLine);
         if (aSubject.findFlag("private", false) >= 0) {
           // Don't need to go into PB mode if it's already set to autostart
           if (this._autoStarted)
             aSubject.handleFlag("private", false);
 
+          Services.prefs.setBoolPref("browser.privatebrowsing.autostart", true);
           this.privateBrowsingEnabled = true;
           this._autoStarted = true;
           this._lastChangedByCommandLine = true;
         }
         else if (aSubject.findFlag("private-toggle", false) >= 0) {
           this._lastChangedByCommandLine = true;
         }
         break;
--- a/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_certexceptionsui.js
+++ b/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_certexceptionsui.js
@@ -14,64 +14,37 @@ function test() {
   const EXCEPTIONS_DLG_URL = 'chrome://pippki/content/exceptionDialog.xul';
   const EXCEPTIONS_DLG_FEATURES = 'chrome,centerscreen';
   const INVALID_CERT_LOCATION = 'https://nocert.example.com/';
   waitForExplicitFinish();
 
   // enter private browsing mode
   pb.privateBrowsingEnabled = true;
 
-  step1();
+  doTest();
 
-  // Test the certificate exceptions dialog as it is invoked from about:certerror
-  function step1() {
+  // Test the certificate exceptions dialog
+  function doTest() {
     let params = {
       exceptionAdded : false,
       location: INVALID_CERT_LOCATION,
-      handlePrivateBrowsing : true,
       prefetchCert: true,
     };
     function testCheckbox() {
       win.removeEventListener("load", testCheckbox, false);
       Services.obs.addObserver(function (aSubject, aTopic, aData) {
         Services.obs.removeObserver(arguments.callee, "cert-exception-ui-ready", false);
         ok(win.gCert, "The certificate information should be available now");
 
         let checkbox = win.document.getElementById("permanent");
         ok(checkbox.hasAttribute("disabled"),
           "the permanent checkbox should be disabled when handling the private browsing mode");
         ok(!checkbox.hasAttribute("checked"),
           "the permanent checkbox should not be checked when handling the private browsing mode");
         win.close();
-        step2();
-      }, "cert-exception-ui-ready", false);
-    }
-    var win = openDialog(EXCEPTIONS_DLG_URL, "", EXCEPTIONS_DLG_FEATURES, params);
-    win.addEventListener("load", testCheckbox, false);
-  }
-
-  // Test the certificate excetions dialog as it is invoked from the Preferences dialog
-  function step2() {
-    let params = {
-      exceptionAdded : false,
-      location: INVALID_CERT_LOCATION,
-      prefetchCert: true,
-    };
-    function testCheckbox() {
-      win.removeEventListener("load", testCheckbox, false);
-      Services.obs.addObserver(function (aSubject, aTopic, aData) {
-        Services.obs.removeObserver(arguments.callee, "cert-exception-ui-ready", false);
-        ok(win.gCert, "The certificate information should be available now");
-
-        let checkbox = win.document.getElementById("permanent");
-        ok(!checkbox.hasAttribute("disabled"),
-          "the permanent checkbox should not be disabled when not handling the private browsing mode");
-        ok(checkbox.hasAttribute("checked"),
-          "the permanent checkbox should be checked when not handling the private browsing mode");
-        win.close();
         cleanup();
       }, "cert-exception-ui-ready", false);
     }
     var win = openDialog(EXCEPTIONS_DLG_URL, "", EXCEPTIONS_DLG_FEATURES, params);
     win.addEventListener("load", testCheckbox, false);
   }
 
   function cleanup() {
--- a/browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_viewsource.js
+++ b/browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_viewsource.js
@@ -47,32 +47,25 @@ function test() {
 
     function step1() {
       function observer(aSubject, aTopic, aData) {
         if (aTopic == "domwindowclosed") {
           ok(true, "Entering the private browsing mode should close the view source window");
           Services.ww.unregisterNotification(observer);
 
           step2();
+        } else if (aTopic == "domwindowopened") {
+          ok(false, "Entering the private browsing mode should not open any view source window");
+        } else if (aTopic == "private-browsing-transition-complete") {
+          Services.obs.removeObserver(observer, "private-browsing-transition-complete");
+          step3();
         }
-        else if (aTopic == "domwindowopened")
-          ok(false, "Entering the private browsing mode should not open any view source window");
       }
       Services.ww.registerNotification(observer);
-
-      gBrowser.addTabsProgressListener({
-        onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
-          if (aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP |
-                             Ci.nsIWebProgressListener.STATE_IS_WINDOW)) {
-            gBrowser.removeTabsProgressListener(this);
-
-            step3();
-          }
-        }
-      });
+      Services.obs.addObserver(observer, "private-browsing-transition-complete", false);
 
       // enter private browsing mode
       pb.privateBrowsingEnabled = true;
     }
 
     let events = 0, step2, step3;
     step2 = step3 = function() {
       if (++events == 2)
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -618,16 +618,30 @@
           // Add observer for suggest preference
           var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                               .getService(Components.interfaces.nsIPrefBranch);
           prefs.addObserver("browser.search.suggest.enabled", this, false);
         ]]></body>
       </method>
 
       <!--
+        This overrides the searchParam property in autocomplete.xml.  We're
+        hijacking this property as a vehicle for delivering the privacy
+        information about the window into the guys of nsSearchSuggestions.
+
+        Note that the setter is the same as the parent.  We were not sure whether
+        we can override just the getter.  If that proves to be the case, the setter
+        can be removed.
+      -->
+      <property name="searchParam"
+                onget="return this.getAttribute('autocompletesearchparam') +
+                       (PrivateBrowsingUtils.isWindowPrivate(window) ? '|private' : '');"
+                onset="this.setAttribute('autocompletesearchparam', val); return val;"/>
+
+      <!--
         This method overrides the autocomplete binding's openPopup (essentially
         duplicating the logic from the autocomplete popup binding's
         openAutocompletePopup method), modifying it so that the popup is aligned with
         the inner textbox, but sized to not extend beyond the search bar border.
       -->
       <method name="openPopup">
         <body><![CDATA[
           var popup = this.popup;
--- a/browser/components/search/test/browser_426329.js
+++ b/browser/components/search/test/browser_426329.js
@@ -188,17 +188,17 @@ function test() {
 
       testSearchHistory();
     }, 5000);
   }
 
   function testSearchHistory() {
     var textbox = searchBar._textbox;
     for (var i = 0; i < searchEntries.length; i++) {
-      let exists = textbox._formHistSvc.entryExists(textbox.searchParam, searchEntries[i]);
+      let exists = textbox._formHistSvc.entryExists(textbox.getAttribute("autocompletesearchparam"), searchEntries[i]);
       ok(exists, "form history entry '" + searchEntries[i] + "' should exist");
     }
     testAutocomplete();
   }
 
   function testAutocomplete() {
     var popup = searchBar.textbox.popup;
     popup.addEventListener("popupshowing", function() {
--- a/browser/config/mozconfigs/linux32/l10n-mozconfig
+++ b/browser/config/mozconfigs/linux32/l10n-mozconfig
@@ -1,9 +1,12 @@
 ac_add_options --with-l10n-base=../../l10n-central
 ac_add_options --enable-official-branding
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 
+# Avoid dependency on libstdc++ 4.5
+ac_add_options --enable-stdcxx-compat
+
 . $topsrcdir/build/unix/mozconfig.linux
 
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/l10n-mozconfig
+++ b/browser/config/mozconfigs/linux64/l10n-mozconfig
@@ -1,9 +1,12 @@
 ac_add_options --with-l10n-base=../../l10n-central
 ac_add_options --enable-official-branding
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 
+# Avoid dependency on libstdc++ 4.5
+ac_add_options --enable-stdcxx-compat
+
 . $topsrcdir/build/unix/mozconfig.linux
 
 
 . "$topsrcdir/build/mozconfig.common.override"
new file mode 100644
--- /dev/null
+++ b/browser/config/mozconfigs/macosx-universal/l10n-mozconfig
@@ -0,0 +1,13 @@
+. "$topsrcdir/browser/config/mozconfigs/common"
+
+ac_add_options --with-l10n-base=../../l10n-central
+
+if [ "${MOZ_UPDATE_CHANNEL}" = "release" -o "${MOZ_UPDATE_CHANNEL}" = "beta" ]; then
+ac_add_options --enable-official-branding
+fi
+
+ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
+ac_add_options --enable-update-packaging
+ac_add_options --with-ccache
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -691,28 +691,16 @@ var Scratchpad = {
             file = aFile;
           } else {
             file = Components.classes["@mozilla.org/file/local;1"].
                    createInstance(Components.interfaces.nsILocalFile);
             let filePath = this.getRecentFiles()[aIndex];
             file.initWithPath(filePath);
           }
 
-          if (!file.exists()) {
-            this.notificationBox.appendNotification(
-              this.strings.GetStringFromName("fileNoLongerExists.notification"),
-              "file-no-longer-exists",
-              null,
-              this.notificationBox.PRIORITY_WARNING_HIGH,
-              null);
-
-            this.clearFiles(aIndex, 1);
-            return;
-          }
-
           this.setFilename(file.path);
           this.importFromFile(file, false);
           this.setRecentFile(file);
         }
       }.bind(this));
     }.bind(this);
 
     if (aIndex > -1) {
@@ -845,33 +833,16 @@ var Scratchpad = {
                               this.strings.
                               GetStringFromName("clearRecentMenuItems.label"));
       clearItems.setAttribute("command", "sp-cmd-clearRecentFiles");
       recentFilesPopup.appendChild(clearItems);
     }
   },
 
   /**
-   * Clear a range of files from the list.
-   *
-   * @param integer aIndex
-   *        Index of file in menu to remove.
-   * @param integer aLength
-   *        Number of files from the index 'aIndex' to remove.
-   */
-  clearFiles: function SP_clearFile(aIndex, aLength)
-  {
-    let filePaths = this.getRecentFiles();
-    let branch = Services.prefs.
-                 getBranch("devtools.scratchpad.");
-    filePaths.splice(aIndex, aLength);
-    branch.setCharPref("recentFilePaths", JSON.stringify(filePaths));
-  },
-
-  /**
    * Clear all recent files.
    */
   clearRecentFiles: function SP_clearRecentFiles()
   {
     Services.prefs.clearUserPref("devtools.scratchpad.recentFilePaths");
   },
 
   /**
@@ -891,18 +862,21 @@ var Scratchpad = {
           this.populateRecentFilesMenu();
         }
 
         menu.removeAttribute("hidden");
       }
 
       let filePaths = this.getRecentFiles();
       if (maxRecent < filePaths.length) {
+        let branch = Services.prefs.
+                     getBranch("devtools.scratchpad.");
         let diff = filePaths.length - maxRecent;
-        this.clearFiles(0, diff);
+        filePaths.splice(0, diff);
+        branch.setCharPref("recentFilePaths", JSON.stringify(filePaths));
       }
     }
   },
   /**
    * Save the textbox content to the currently open file.
    *
    * @param function aCallback
    *        Optional function you want to call when file is saved
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_651942_recent_files.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_651942_recent_files.js
@@ -96,71 +96,45 @@ function testOpenOldestRecent()
 // The "devtools.scratchpad.recentFilesMax"-preference was set to zero (0).
 // This should disable the "Open Recent"-menu by hiding it (this should not
 // remove any files from the list). Test to see if it's been hidden.
 function testHideMenu()
 {
   let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
   ok(menu.hasAttribute("hidden"), "The menu was hidden successfully.");
 
-  Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 2);
+  Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 1);
 }
 
 // We have set the recentFilesMax-pref to one (1), this enables the feature,
 // removes the two oldest files, rebuilds the menu and removes the
 // "hidden"-attribute from it. Test to see if this works.
 function testChangedMaxRecent()
 {
   let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
   ok(!menu.hasAttribute("hidden"), "The menu is visible. \\o/");
 
   lists.recentFiles04 = gScratchpad.getRecentFiles();
 
-  is(lists.recentFiles04.length, 2,
+  is(lists.recentFiles04.length, 1,
      "Two recent files were successfully removed from the 'recent files'-list");
 
   let doc = gScratchpadWindow.document;
   let popup = doc.getElementById("sp-menu-open_recentPopup");
 
   let menuitemLabel = popup.children[0].getAttribute("label");
   let correctMenuItem = false;
   if (menuitemLabel === lists.recentFiles03[2] &&
-      menuitemLabel === lists.recentFiles04[1]) {
+      menuitemLabel === lists.recentFiles04[0]) {
     correctMenuItem = true;
   }
 
   is(correctMenuItem, true,
      "Two recent files were successfully removed from the 'Open Recent'-menu");
 
-  // We now remove one file from the harddrive and use the recent-menuitem for
-  // it to make sure the user is notified that the file no longer exists.
-  // This is tested in testOpenDeletedFile().
-  gFile02.remove(false);
-  gFile02 = null;
-  gScratchpad.openFile(1);
-}
-
-// By now we should have two recent files stored in the list but one of the
-// files should be missing on the harddrive.
-function testOpenDeletedFile() {
-  let doc = gScratchpadWindow.document;
-  let popup = doc.getElementById("sp-menu-open_recentPopup");
-
-  is(gScratchpad.getRecentFiles().length, 1,
-     "The missing file was successfully removed from the list.");
-  // The number of recent files stored, plus the separator and the
-  // clearRecentMenuItems-item.
-  is(popup.children.length, 3,
-     "The missing file was successfully removed from the menu.");
-  ok(gScratchpad.notificationBox.currentNotification,
-     "The notification was successfully displayed.");
-  is(gScratchpad.notificationBox.currentNotification.label,
-     gScratchpad.strings.GetStringFromName("fileNoLongerExists.notification"),
-     "The notification label is correct.");
-
   gScratchpad.clearRecentFiles();
 }
 
 // We have cleared the last file. Test to see if the last file was removed,
 // the menu is empty and was disabled successfully.
 function testClearedAll()
 {
   let doc = gScratchpadWindow.document;
@@ -281,20 +255,16 @@ var PreferenceObserver = {
         testHideMenu();
         break;
       case 6:
         this.timesFired = 7;
         testChangedMaxRecent();
         break;
       case 7:
         this.timesFired = 8;
-        testOpenDeletedFile();
-        break;
-      case 8:
-        this.timesFired = 9;
         testClearedAll();
         break;
     }
   },
 
   uninit: function PO_uninit () {
     this.branch.removeObserver("", this);
   }
@@ -302,17 +272,18 @@ var PreferenceObserver = {
 
 function test()
 {
   waitForExplicitFinish();
 
   registerCleanupFunction(function () {
     gFile01.remove(false);
     gFile01 = null;
-    // gFile02 was removed earlier.
+    gFile02.remove(false);
+    gFile02 = null;
     gFile03.remove(false);
     gFile03 = null;
     gFile04.remove(false);
     gFile04 = null;
     lists.recentFiles01 = null;
     lists.recentFiles02 = null;
     lists.recentFiles03 = null;
     lists.recentFiles04 = null;
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,4 +1,4 @@
 This is the pdf.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 0.5.184
+Current extension version is: 0.6.39
 
--- a/browser/extensions/pdfjs/components/PdfStreamConverter.js
+++ b/browser/extensions/pdfjs/components/PdfStreamConverter.js
@@ -26,40 +26,46 @@ const Cu = Components.utils;
 // True only if this is the version of pdf.js that is included with firefox.
 const MOZ_CENTRAL = true;
 const PDFJS_EVENT_ID = 'pdf.js.message';
 const PDF_CONTENT_TYPE = 'application/pdf';
 const PREF_PREFIX = 'pdfjs';
 const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
 const MAX_DATABASE_LENGTH = 4096;
 const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
-const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
-const METRO_ID = '{99bceaaa-e3c6-48c1-b981-ef9b46b67d60}';
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/NetUtil.jsm');
 
 
 let appInfo = Cc['@mozilla.org/xre/app-info;1']
                   .getService(Ci.nsIXULAppInfo);
-let privateBrowsing, inPrivateBrowsing;
 let Svc = {};
 XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
                                    '@mozilla.org/mime;1',
                                    'nsIMIMEService');
 
+let isInPrivateBrowsing;
 if (appInfo.ID === FIREFOX_ID) {
-  privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
-                          .getService(Ci.nsIPrivateBrowsingService);
-  inPrivateBrowsing = privateBrowsing.privateBrowsingEnabled;
-} else if (appInfo.ID === SEAMONKEY_ID ||
-           appInfo.ID === METRO_ID) {
-  privateBrowsing = null;
-  inPrivateBrowsing = false;
+  let privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
+                            .getService(Ci.nsIPrivateBrowsingService);
+  isInPrivateBrowsing = function getInPrivateBrowsing() {
+    return privateBrowsing.privateBrowsingEnabled;
+  };
+} else {
+  isInPrivateBrowsing = function() { return false; };
+}
+
+function getChromeWindow(domWindow) {
+  var containingBrowser = domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                                   .getInterface(Ci.nsIWebNavigation)
+                                   .QueryInterface(Ci.nsIDocShell)
+                                   .chromeEventHandler;
+  return containingBrowser.ownerDocument.defaultView;
 }
 
 function getBoolPref(pref, def) {
   try {
     return Services.prefs.getBoolPref(pref);
   } catch (ex) {
     return def;
   }
@@ -268,25 +274,25 @@ ChromeActions.prototype = {
                                            aOffset, aCount);
         }
       };
 
       channel.asyncOpen(listener, null);
     });
   },
   setDatabase: function(data) {
-    if (inPrivateBrowsing)
+    if (isInPrivateBrowsing())
       return;
     // Protect against something sending tons of data to setDatabase.
     if (data.length > MAX_DATABASE_LENGTH)
       return;
     setStringPref(PREF_PREFIX + '.database', data);
   },
   getDatabase: function() {
-    if (inPrivateBrowsing)
+    if (isInPrivateBrowsing())
       return '{}';
     return getStringPref(PREF_PREFIX + '.database', '{}');
   },
   getLocale: function() {
     return getStringPref('general.useragent.locale', 'en-US');
   },
   getLoadingType: function() {
     return this.dataListener ? 'passive' : 'active';
@@ -331,18 +337,21 @@ ChromeActions.prototype = {
     } catch (e) {
       log('Unable to retrive localized strings: ' + e);
       return 'null';
     }
   },
   pdfBugEnabled: function() {
     return getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false);
   },
-  searchEnabled: function() {
-    return getBoolPref(PREF_PREFIX + '.searchEnabled', false);
+  supportsIntegratedFind: function() {
+    // Integrated find is only supported when we're not in a frame and when the
+    // new find events code exists.
+    return this.domWindow.frameElement === null &&
+           'updateControlState' in getChromeWindow(this.domWindow).gFindBar;
   },
   fallback: function(url, sendResponse) {
     var self = this;
     var domWindow = this.domWindow;
     var strings = getLocalizedStrings('chrome.properties');
     var message = getLocalizedString(strings, 'unsupported_feature');
 
     var notificationBox = null;
@@ -386,16 +395,30 @@ ChromeActions.prototype = {
       // added in the future we still only care about removed at the moment.
       if (eventType !== 'removed')
         return;
       // Don't send a response again if we already responded when the button was
       // clicked.
       if (!sentResponse)
         sendResponse(false);
     });
+  },
+  updateFindControlState: function(data) {
+    if (!this.supportsIntegratedFind())
+      return;
+    // Verify what we're sending to the findbar.
+    var result = data.result;
+    var findPrevious = data.findPrevious;
+    var findPreviousType = typeof findPrevious;
+    if ((typeof result !== 'number' || result < 0 || result > 3) ||
+        (findPreviousType !== 'undefined' && findPreviousType !== 'boolean')) {
+      return;
+    }
+    getChromeWindow(this.domWindow).gFindBar
+                                   .updateControlState(result, findPrevious);
   }
 };
 
 // Event listener to trigger chrome privedged code.
 function RequestListener(actions) {
   this.actions = actions;
 }
 // Receive an event and synchronously or asynchronously responds.
@@ -426,16 +449,67 @@ RequestListener.prototype.receive = func
         listener.initEvent('pdf.js.response', true, false);
         return message.dispatchEvent(listener);
       }
     }
     actions[action].call(this.actions, data, response);
   }
 };
 
+// Forwards events from the eventElement to the contentWindow only if the
+// content window matches the currently selected browser window.
+function FindEventManager(eventElement, contentWindow, chromeWindow) {
+  this.types = ['find',
+                'findagain',
+                'findhighlightallchange',
+                'findcasesensitivitychange'];
+  this.chromeWindow = chromeWindow;
+  this.contentWindow = contentWindow;
+  this.eventElement = eventElement;
+}
+
+FindEventManager.prototype.bind = function() {
+  var unload = function(e) {
+    this.unbind();
+    this.contentWindow.removeEventListener(e.type, unload);
+  }.bind(this);
+  this.contentWindow.addEventListener('unload', unload);
+
+  for (var i = 0; i < this.types.length; i++) {
+    var type = this.types[i];
+    this.eventElement.addEventListener(type, this, true);
+  }
+};
+
+FindEventManager.prototype.handleEvent = function(e) {
+  var chromeWindow = this.chromeWindow;
+  var contentWindow = this.contentWindow;
+  // Only forward the events if they are for our dom window.
+  if (chromeWindow.gBrowser.selectedBrowser.contentWindow === contentWindow) {
+    var detail = e.detail;
+    detail.__exposedProps__ = {
+      query: 'r',
+      caseSensitive: 'r',
+      highlightAll: 'r',
+      findPrevious: 'r'
+    };
+    var forward = contentWindow.document.createEvent('CustomEvent');
+    forward.initCustomEvent(e.type, true, true, detail);
+    contentWindow.dispatchEvent(forward);
+    e.preventDefault();
+  }
+};
+
+FindEventManager.prototype.unbind = function() {
+  for (var i = 0; i < this.types.length; i++) {
+    var type = this.types[i];
+    this.eventElement.removeEventListener(type, this, true);
+  }
+};
+
 function PdfStreamConverter() {
 }
 
 PdfStreamConverter.prototype = {
 
   // properties required for XPCOM registration:
   classID: Components.ID('{d0c5195d-e798-49d4-b1d3-9324328b2291}'),
   classDescription: 'pdf.js Component',
@@ -538,31 +612,39 @@ PdfStreamConverter.prototype = {
         var domWindow = getDOMWindow(channel);
         // Double check the url is still the correct one.
         if (domWindow.document.documentURIObject.equals(aRequest.URI)) {
           let actions = new ChromeActions(domWindow, dataListener);
           let requestListener = new RequestListener(actions);
           domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
             requestListener.receive(event);
           }, false, true);
+          if (actions.supportsIntegratedFind()) {
+            var chromeWindow = getChromeWindow(domWindow);
+            var findEventManager = new FindEventManager(chromeWindow.gFindBar,
+                                                        domWindow,
+                                                        chromeWindow);
+            findEventManager.bind();
+          }
         }
         listener.onStopRequest.apply(listener, arguments);
       }
     };
 
     // Keep the URL the same so the browser sees it as the same.
     channel.originalURI = aRequest.URI;
     channel.asyncOpen(proxy, aContext);
     if (useFetchByChrome) {
       // We can use resource principal when data is fetched by the chrome
       // e.g. useful for NoScript
       var securityManager = Cc['@mozilla.org/scriptsecuritymanager;1']
                             .getService(Ci.nsIScriptSecurityManager);
       var uri = ioService.newURI(PDF_VIEWER_WEB_PAGE, null, null);
-      // FF16 and below had getCodebasePrincipal (bug 774585)
+      // FF16 and below had getCodebasePrincipal, it was replaced by
+      // getNoAppCodebasePrincipal (bug 758258).
       var resourcePrincipal = 'getNoAppCodebasePrincipal' in securityManager ?
                               securityManager.getNoAppCodebasePrincipal(uri) :
                               securityManager.getCodebasePrincipal(uri);
       channel.owner = resourcePrincipal;
     }
   },
 
   // nsIRequestObserver::onStopRequest
--- a/browser/extensions/pdfjs/content/PdfJs.jsm
+++ b/browser/extensions/pdfjs/content/PdfJs.jsm
@@ -18,20 +18,22 @@ var EXPORTED_SYMBOLS = ["PdfJs"];
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cm = Components.manager;
 const Cu = Components.utils;
 
 const PREF_PREFIX = 'pdfjs';
 const PREF_DISABLED = PREF_PREFIX + '.disabled';
-const PREF_FIRST_RUN = PREF_PREFIX + '.firstRun';
+const PREF_MIGRATION_VERSION = PREF_PREFIX + '.migrationVersion';
 const PREF_PREVIOUS_ACTION = PREF_PREFIX + '.previousHandler.preferredAction';
 const PREF_PREVIOUS_ASK = PREF_PREFIX + '.previousHandler.alwaysAskBeforeHandling';
+const PREF_DISABLED_PLUGIN_TYPES = 'plugin.disable_full_page_plugin_for_types';
 const TOPIC_PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged';
+const PDF_CONTENT_TYPE = 'application/pdf';
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://pdf.js.components/PdfStreamConverter.js');
 
 let Svc = {};
 XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
                                    '@mozilla.org/mime;1',
@@ -40,16 +42,24 @@ XPCOMUtils.defineLazyServiceGetter(Svc, 
 function getBoolPref(aPref, aDefaultValue) {
   try {
     return Services.prefs.getBoolPref(aPref);
   } catch (ex) {
     return aDefaultValue;
   }
 }
 
+function getIntPref(aPref, aDefaultValue) {
+  try {
+    return Services.prefs.getIntPref(aPref);
+  } catch (ex) {
+    return aDefaultValue;
+  }
+}
+
 // Register/unregister a constructor as a component.
 let Factory = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]),
   _targetConstructor: null,
 
   register: function register(targetConstructor) {
     this._targetConstructor = targetConstructor;
     var proto = targetConstructor.prototype;
@@ -79,47 +89,80 @@ let Factory = {
   }
 };
 
 let PdfJs = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
   _registered: false,
 
   init: function init() {
-    // On first run make pdf.js the default handler.
-    if (!getBoolPref(PREF_DISABLED, true) && getBoolPref(PREF_FIRST_RUN, false)) {
-      Services.prefs.setBoolPref(PREF_FIRST_RUN, false);
-
-      let handlerInfo = Svc.mime.getFromTypeAndExtension('application/pdf', 'pdf');
-      // Store the previous settings of preferredAction and
-      // alwaysAskBeforeHandling in case we need to revert them in a hotfix that
-      // would turn pdf.js off.
-      Services.prefs.setIntPref(PREF_PREVIOUS_ACTION, handlerInfo.preferredAction);
-      Services.prefs.setBoolPref(PREF_PREVIOUS_ASK, handlerInfo.alwaysAskBeforeHandling);
-
-      let handlerService = Cc['@mozilla.org/uriloader/handler-service;1'].
-                           getService(Ci.nsIHandlerService);
-
-      // Change and save mime handler settings.
-      handlerInfo.alwaysAskBeforeHandling = false;
-      handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
-      handlerService.store(handlerInfo);
+    if (!getBoolPref(PREF_DISABLED, true)) {
+      this._migrate();
     }
 
     if (this.enabled)
       this._ensureRegistered();
     else
       this._ensureUnregistered();
 
     // Listen for when pdf.js is completely disabled or a different pdf handler
     // is chosen.
     Services.prefs.addObserver(PREF_DISABLED, this, false);
     Services.obs.addObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
   },
 
+  _migrate: function migrate() {
+    const VERSION = 1;
+    var currentVersion = getIntPref(PREF_MIGRATION_VERSION, 0);
+    if (currentVersion >= VERSION) {
+      return;
+    }
+    // Make pdf.js the default pdf viewer on the first migration.
+    if (currentVersion < 2) {
+      this._becomeHandler();
+    }
+    Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
+  },
+
+  _becomeHandler: function _becomeHandler() {
+    let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
+    let prefs = Services.prefs;
+    if (handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally &&
+        handlerInfo.preferredAction !== false) {
+      // Store the previous settings of preferredAction and
+      // alwaysAskBeforeHandling in case we need to revert them in a hotfix that
+      // would turn pdf.js off.
+      prefs.setIntPref(PREF_PREVIOUS_ACTION, handlerInfo.preferredAction);
+      prefs.setBoolPref(PREF_PREVIOUS_ASK, handlerInfo.alwaysAskBeforeHandling);
+    }
+
+    let handlerService = Cc['@mozilla.org/uriloader/handler-service;1'].
+                         getService(Ci.nsIHandlerService);
+
+    // Change and save mime handler settings.
+    handlerInfo.alwaysAskBeforeHandling = false;
+    handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
+    handlerService.store(handlerInfo);
+
+    // Also disable any plugins for pdfs.
+    var stringTypes = '';
+    var types = [];
+    if (prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
+      stringTypes = prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
+    }
+    if (stringTypes !== '') {
+      types = stringTypes.split(',');
+    }
+
+    if (types.indexOf(PDF_CONTENT_TYPE) === -1) {
+      types.push(PDF_CONTENT_TYPE);
+    }
+    prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES, types.join(','));
+  },
+
   // nsIObserver
   observe: function observe(aSubject, aTopic, aData) {
     if (this.enabled)
       this._ensureRegistered();
     else
       this._ensureUnregistered();
   },
   
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..08a2c25327d7df3c77186cc3048bf02b7e72f393
GIT binary patch
literal 371
zc%17D@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6n3BBRT^Rni_n+Ah<Z%{wL>4nJ
za0`PlBg3pY5<o%r5>H=O_B&jxVj>1dW-W_hU|?kNba4#PIA1#9tk+=&k=FgQ+pdT`
zUbe$HMe!GtU6WGBI$aLYZm~5FlsUCLM9rJ>x)ki1v&;2jM441q`dLYetDQYE-*|TQ
z^E<_9?^Y%rUfkJzY)ZIaD_<MC&cmBh$CtgYp8dL|p1-2*N5P)WO~<yom=<t<b<MX{
zV0F4SV~dnB5HBwOxorLKx2`PB3<(U3Mv^-!Sehqq>wl!)(o;G8S#tSeKda!GbIv?G
zbmhsbOZ!$BA5pw%wO?3d{?EV_k<*RN+E-q_-@A4@_jI3mOCvtN%FsWiAoSU(>6p5s
zu;<LjPZQOdDxY?~D4*1|{qN@6tRl%q{~C{f`Y<K**{Z}4_g5KqIsN)|hXdZr_a9ya
P3?c?kS3j3^P6<r_kMx(q
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..beef8ccea48c932571c9c9009df916a61c850a1c
GIT binary patch
literal 381
zc$@)!0fPRCP)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e00002VoOIv0RM-N
z%)bBt010qNS#tmY3ljhU3ljkVnw%H_000McNliru+zJI29sn4uetG}^0S-w-K~yNu
zb&)+w13?gmpWQt!_hI5eD#4IKO<|GNA0TLBqfH`0&_WQwe<O&XAP9<DC}<P>Cn>#B
z0z$y#_7d0P?!t27TP(BlKC{g1C~Qf5JYZ(0Y`HA=4{6~34>Y$nUyp4>0?NXx%y!n^
zPO8lU5v<pjhGYCX!!bT>vjOn@v3E&~2En%3M*;>A02l=3;j?=|jFv2*(IokqkYu+`
z?f#Sot_0GOokeN4@_t0%AeiK{n7pfbJT>4jCFQRS;-#{C!?(j16Xd+w6vSiLIVVO7
zT0|%UMkoT>Cd44_!h@@9OoxH>aKs|3a2xe<yZqHZjL=WD-gRM@<<aV&v0^Vvl-BK`
bNbKrg3mRK+IzR8P00000NkvXXu0mjfaG9N{
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..beef8ccea48c932571c9c9009df916a61c850a1c
GIT binary patch
literal 381
zc$@)!0fPRCP)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e00002VoOIv0RM-N
z%)bBt010qNS#tmY3ljhU3ljkVnw%H_000McNliru+zJI29sn4uetG}^0S-w-K~yNu
zb&)+w13?gmpWQt!_hI5eD#4IKO<|GNA0TLBqfH`0&_WQwe<O&XAP9<DC}<P>Cn>#B
z0z$y#_7d0P?!t27TP(BlKC{g1C~Qf5JYZ(0Y`HA=4{6~34>Y$nUyp4>0?NXx%y!n^
zPO8lU5v<pjhGYCX!!bT>vjOn@v3E&~2En%3M*;>A02l=3;j?=|jFv2*(IokqkYu+`
z?f#Sot_0GOokeN4@_t0%AeiK{n7pfbJT>4jCFQRS;-#{C!?(j16Xd+w6vSiLIVVO7
zT0|%UMkoT>Cd44_!h@@9OoxH>aKs|3a2xe<yZqHZjL=WD-gRM@<<aV&v0^Vvl-BK`
bNbKrg3mRK+IzR8P00000NkvXXu0mjfaG9N{
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..08a2c25327d7df3c77186cc3048bf02b7e72f393
GIT binary patch
literal 371
zc%17D@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6n3BBRT^Rni_n+Ah<Z%{wL>4nJ
za0`PlBg3pY5<o%r5>H=O_B&jxVj>1dW-W_hU|?kNba4#PIA1#9tk+=&k=FgQ+pdT`
zUbe$HMe!GtU6WGBI$aLYZm~5FlsUCLM9rJ>x)ki1v&;2jM441q`dLYetDQYE-*|TQ
z^E<_9?^Y%rUfkJzY)ZIaD_<MC&cmBh$CtgYp8dL|p1-2*N5P)WO~<yom=<t<b<MX{
zV0F4SV~dnB5HBwOxorLKx2`PB3<(U3Mv^-!Sehqq>wl!)(o;G8S#tSeKda!GbIv?G
zbmhsbOZ!$BA5pw%wO?3d{?EV_k<*RN+E-q_-@A4@_jI3mOCvtN%FsWiAoSU(>6p5s
zu;<LjPZQOdDxY?~D4*1|{qN@6tRl%q{~C{f`Y<K**{Z}4_g5KqIsN)|hXdZr_a9ya
P3?c?kS3j3^P6<r_kMx(q
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1b2df8093d630ca5e4b7c9127fd4fc855655599b
GIT binary patch
literal 9025
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..604e652e5ec48052efa7b342c41c33729dbd287c
GIT binary patch
literal 503
zc$@+E0SNwyP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0005LNkl<Zc-obb
zy-Px27{$$?$UZCyA`$~HWJC>7L`x76v;_%@mM9iB^r1sVf!&a+LRUjYsGy;SXlXDS
zqS4Xa%|ApGMeLk-iHe)y13!4)=bZC?+^cI*oxlhzV3LU5D72Q<MRPnJ-!GL)kJW1R
zov`PO8a=H}9?#`+$!4?p242AnVb2*gdj7h}U?dVbV4z;FKgVLRw8diCHJi-=_MB0p
zhhD7>ti@vS4yLDQG<t>g5*Q=w6NyBM8a-G`S{uxk%jE}{?yXkqCe|j<DHz6ViyA%j
zYHctN@fxOENs>0OHhj|zoKb`4hF+}=rVE9F3R6Z^Rhdr$-2y3-$y`vQ2kR-VKQN;x
z3QcOQR^uk8Hk)mQu*WP-&F}XI;T`=Q9`X5ne*E)Gm=u8uQbhDhGMNm+I|q7xguPy`
zr&6iJU^;I!8e!bzJfF{p@!n6^yWQ?Xco)GC==chIJf1CtWrR-<K6W~tN0_gHRj@8t
z1~xDN^g2;}fk0p#;WLCo2nQVwM@W2O6Lnw|^nxyNvM89c+3YsL`v~vZ?e;_QzJ6i+
tw+vuGmgQZS%eB*Pn57q2od8n1;SVuD34zFH^ql|z002ovPDHLkV1l!1+}HpB
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -39,48 +39,62 @@ select {
   display: none;
 }
 [hidden] {
   display: none !important;
 }
 
 #viewerContainer:-webkit-full-screen {
   top: 0px;
-  border-top: 5px solid transparent;
+  border-top: 2px solid transparent;
   background-color: #404040;
   background-image: url(images/texture.png);
   width: 100%;
   height: 100%;
   overflow: hidden;
+  cursor: none;
 }
 
 #viewerContainer:-moz-full-screen {
   top: 0px;
-  border-top: 5px solid transparent;
+  border-top: 2px solid transparent;
   background-color: #404040;
   background-image: url(images/texture.png);
   width: 100%;
   height: 100%;
   overflow: hidden;
-}
-
-:-webkit-full-screen .page:last-child {
-  margin-bottom: 40px;
+  cursor: none;
 }
 
-:-moz-full-screen .page:last-child {
-  margin-bottom: 40px;
-}
-
-#viewerContainer:full-screen {
+#viewerContainer:fullscreen {
   top: 0px;
+  border-top: 2px solid transparent;
   background-color: #404040;
   background-image: url(images/texture.png);
   width: 100%;
   height: 100%;
+  overflow: hidden;
+  cursor: none;
+}
+
+
+:-webkit-full-screen .page {
+  margin-bottom: 100%;
+}
+
+:-moz-full-screen .page {
+  margin-bottom: 100%;
+}
+
+:fullscreen .page {
+  margin-bottom: 100%;
+}
+
+#viewerContainer.presentationControls {
+  cursor: default;
 }
 
 /* outer/inner center provides horizontal center */
 html[dir='ltr'] .outerCenter {
   float: right;
   position: relative;
   right: 50%;
 }
@@ -199,17 +213,16 @@ html[dir='ltr'] #sidebarContent {
 }
 html[dir='rtl'] #sidebarContent {
   right: 0;
 }
 
 #viewerContainer {
   overflow: auto;
   box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05);
-  padding-top: 30px;
   position: absolute;
   top: 32px;
   right: 0;
   bottom: 0;
   left: 0;
 }
 
 .toolbar {
@@ -240,17 +253,17 @@ html[dir='rtl'] #sidebarContent {
                     linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
   box-shadow: inset -2px 0 0 hsla(0,0%,100%,.08),
               inset 0 1px 1px hsla(0,0%,0%,.15),
               inset 0 -1px 0 hsla(0,0%,100%,.05),
               0 1px 0 hsla(0,0%,0%,.15),
               0 1px 1px hsla(0,0%,0%,.1);
 }
 
-#toolbarViewer {
+#toolbarViewer, .findbar {
   position: relative;
   height: 32px;
   background-image: url(images/texture.png),
                     -webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
   background-image: url(images/texture.png),
                     -moz-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
   background-image: url(images/texture.png),
                     -ms-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
@@ -260,16 +273,104 @@ html[dir='rtl'] #sidebarContent {
                     linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
   border-left: 1px solid hsla(0,0%,0%,.5);
   box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08),
               inset 0 1px 1px hsla(0,0%,0%,.15),
               inset 0 -1px 0 hsla(0,0%,100%,.05),
               0 1px 0 hsla(0,0%,0%,.15),
               0 1px 1px hsla(0,0%,0%,.1);
 }
+
+.findbar {
+  top: 32px;
+  position: absolute;
+  z-index: 10000;
+  height: 32px;
+
+  min-width: 16px;
+  padding: 0px 6px 0px 6px;
+  margin: 4px 2px 4px 2px;
+  color: hsl(0,0%,85%);
+  font-size: 12px;
+  line-height: 14px;
+  text-align: left;
+  cursor: default;
+}
+
+html[dir='ltr'] .findbar {
+  left: 68px;
+}
+
+html[dir='rtl'] .findbar {
+  right: 68px;
+}
+
+.findbar label {
+  -webkit-user-select:none;
+  -moz-user-select:none;
+}
+
+#findInput[data-status="pending"] {
+  background-image: url(images/loading-small.png);
+  background-repeat: no-repeat;
+  background-position: right;
+}
+
+.doorHanger {
+  border: 1px solid hsla(0,0%,0%,.5);
+  border-radius: 2px;
+  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
+}
+.doorHanger:after, .doorHanger:before {
+  bottom: 100%;
+  border: solid transparent;
+  content: " ";
+  height: 0;
+  width: 0;
+  position: absolute;
+  pointer-events: none;
+}
+.doorHanger:after {
+  border-bottom-color: hsla(0,0%,32%,.99);
+  border-width: 8px;
+}
+.doorHanger:before {
+  border-bottom-color: hsla(0,0%,0%,.5);
+  border-width: 9px;
+}
+
+html[dir='ltr'] .doorHanger:after {
+  left: 16px;
+  margin-left: -8px;
+}
+
+html[dir='ltr'] .doorHanger:before {
+  left: 16px;
+  margin-left: -9px;
+}
+
+html[dir='rtl'] .doorHanger:after {
+  right: 16px;
+  margin-right: -8px;
+}
+
+html[dir='rtl'] .doorHanger:before {
+  right: 16px;
+  margin-right: -9px;
+}
+
+#findMsg {
+  font-style: italic;
+  color: #A6B7D0;
+}
+
+.notFound {
+  background-color: rgb(255, 137, 153);
+}
+
 html[dir='ltr'] #toolbarViewerLeft {
   margin-left: -1px;
 }
 html[dir='rtl'] #toolbarViewerRight {
   margin-left: -1px;
 }
 
 
@@ -282,22 +383,24 @@ html[dir='rtl'] #toolbarViewerRight {
 html[dir='ltr'] #toolbarViewerRight,
 html[dir='rtl'] #toolbarViewerLeft {
   position: absolute;
   top: 0;
   right: 0;
 }
 html[dir='ltr'] #toolbarViewerLeft > *,
 html[dir='ltr'] #toolbarViewerMiddle > *,
-html[dir='ltr'] #toolbarViewerRight > * {
+html[dir='ltr'] #toolbarViewerRight > *,
+html[dir='ltr'] .findbar > * {
   float: left;
 }
 html[dir='rtl'] #toolbarViewerLeft > *,
 html[dir='rtl'] #toolbarViewerMiddle > *,
-html[dir='rtl'] #toolbarViewerRight > * {
+html[dir='rtl'] #toolbarViewerRight > *,
+html[dir='rtl'] .findbar > * {
   float: right;
 }
 
 html[dir='ltr'] .splitToolbarButton {
   margin: 3px 2px 4px 0;
   display: inline-block;
 }
 html[dir='rtl'] .splitToolbarButton {
@@ -625,16 +728,36 @@ html[dir='rtl'] .toolbarButton:first-chi
   min-width: 30px;
 }
 
 .toolbarButton#sidebarToggle::before {
   display: inline-block;
   content: url(images/toolbarButton-sidebarToggle.png);
 }
 
+html[dir='ltr'] .toolbarButton.findPrevious::before {
+  display: inline-block;
+  content: url(images/findbarButton-previous.png);
+}
+
+html[dir='rtl'] .toolbarButton.findPrevious::before {
+  display: inline-block;
+  content: url(images/findbarButton-previous-rtl.png);
+}
+
+html[dir='ltr'] .toolbarButton.findNext::before {
+  display: inline-block;
+  content: url(images/findbarButton-next.png);
+}
+
+html[dir='rtl'] .toolbarButton.findNext::before {
+  display: inline-block;
+  content: url(images/findbarButton-next-rtl.png);
+}
+
 html[dir='ltr'] .toolbarButton.pageUp::before {
   display: inline-block;
   content: url(images/toolbarButton-pageUp.png);
 }
 
 html[dir='rtl'] .toolbarButton.pageUp::before {
   display: inline-block;
   content: url(images/toolbarButton-pageUp-rtl.png);
@@ -697,17 +820,17 @@ html[dir='rtl'] .toolbarButton.pageDown:
   content: url(images/toolbarButton-viewThumbnail.png);
 }
 
 #viewOutline.toolbarButton::before {
   display: inline-block;
   content: url(images/toolbarButton-viewOutline.png);
 }
 
-#viewSearch.toolbarButton::before {
+#viewFind.toolbarButton::before {
   display: inline-block;
   content: url(images/toolbarButton-search.png);
 }
 
 
 .toolbarField {
   padding: 3px 6px;
   margin: 4px 0 4px 0;
@@ -724,16 +847,21 @@ html[dir='rtl'] .toolbarButton.pageDown:
   font-size: 12px;
   line-height: 14px;
   outline-style: none;
   -moz-transition-property: background-color, border-color, box-shadow;
   -moz-transition-duration: 150ms;
   -moz-transition-timing-function: ease;
 }
 
+.toolbarField[type=checkbox] {
+  display: inline-block;
+  margin: 8px 0px;
+}
+
 .toolbarField.pageNumber {
   min-width: 16px;
   text-align: right;
   width: 40px;
 }
 
 .toolbarField.pageNumber::-webkit-inner-spin-button,
 .toolbarField.pageNumber::-webkit-outer-spin-button {
@@ -839,35 +967,33 @@ a:focus > .thumbnail > .thumbnailSelecti
   -webkit-user-select:none;
   -moz-user-select:none;
 }
 
 .outlineItem > .outlineItems {
   margin-left: 20px;
 }
 
-.outlineItem > a,
-#searchResults > a {
+.outlineItem > a {
   text-decoration: none;
   display: inline-block;
   min-width: 95%;
   height: 20px;
   padding: 2px 0 0 10px;
   margin-bottom: 1px;
   border-radius: 2px;
   color: hsla(0,0%,100%,.8);
   font-size: 13px;
   line-height: 15px;
   -moz-user-select:none;
   cursor: default;
   white-space: nowrap;
 }
 
-.outlineItem > a:hover,
-#searchResults > a:hover {
+.outlineItem > a:hover {
   background-color: hsla(0,0%,100%,.02);
   background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
   background-clip: padding-box;
   box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
               0 0 1px hsla(0,0%,100%,.2) inset,
               0 0 1px hsla(0,0%,0%,.2);
   color: hsla(0,0%,100%,.9);
 }
@@ -884,54 +1010,24 @@ a:focus > .thumbnail > .thumbnailSelecti
 
 .noOutline,
 .noResults {
   font-size: 12px;
   color: hsla(0,0%,100%,.8);
   font-style: italic;
 }
 
-#searchScrollView {
+#findScrollView {
   position: absolute;
   top: 10px;
   bottom: 10px;
   left: 10px;
   width: 280px;
 }
 
-#searchToolbar {
-  padding-left: 0px;
-  right: 0px;
-  padding-top: 0px;
-  padding-bottom: 5px;
-}
-
-#searchToolbar > input {
-  margin-left: 4px;
-  width: 124px;
-}
-
-#searchToolbar button {
-  width: auto;
-  margin: 0;
-  padding: 0 6px;
-  height: 22px;
-}
-
-#searchResults {
-  overflow: auto;
-  position: absolute;
-  top: 30px;
-  bottom: 0px;
-  left: 0px;
-  right: 0;
-  padding: 4px 4px 0;
-  font-size: smaller;
-}
-
 #sidebarControls {
   position:absolute;
   width: 180px;
   height: 32px;
   left: 15px;
   bottom: 35px;
 }
 
@@ -1064,16 +1160,40 @@ canvas {
 
 .textLayer > div {
   color: transparent;
   position: absolute;
   line-height:1.3;
   white-space:pre;
 }
 
+.textLayer .highlight {
+  margin: -1px;
+  padding: 1px;
+
+  background-color: rgba(180, 0, 170, 0.2);
+  border-radius: 4px;
+}
+
+.textLayer .highlight.begin {
+  border-radius: 4px 0px 0px 4px;
+}
+
+.textLayer .highlight.end {
+  border-radius: 0px 4px 4px 0px;
+}
+
+.textLayer .highlight.middle {
+  border-radius: 0px;
+}
+
+.textLayer .highlight.selected {
+  background-color: rgba(0, 100, 0, 0.2);
+}
+
 /* TODO: file FF bug to support ::-moz-selection:window-inactive
    so we can override the opaque grey background when the window is inactive;
    see https://bugzilla.mozilla.org/show_bug.cgi?id=706209 */
 ::selection { background:rgba(0,0,255,0.3); }
 ::-moz-selection { background:rgba(0,0,255,0.3); }
 
 .annotComment > div {
   position: absolute;
@@ -1286,17 +1406,17 @@ canvas {
   }
   html[dir='rtl'] .outerCenter {
     float: right;
     right: 180px;
   }
 }
 
 @media all and (max-width: 600px) {
-  #toolbarViewerRight {
+  #toolbarViewerRight, #findbar, #viewFind {
     display: none;
   }
 }
 
 @media all and (max-width: 500px) {
   #scaleSelectContainer, #pageNumberLabel {
     display: none;
   }
--- a/browser/extensions/pdfjs/content/web/viewer.html
+++ b/browser/extensions/pdfjs/content/web/viewer.html
@@ -46,17 +46,17 @@ limitations under the License.
 
 var PDFJS = {};
 
 (function pdfjsWrapper() {
   // Use strict in our context only - users might not want it
   'use strict';
 
   PDFJS.build =
-'e98eba1';
+'c8cf445';
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 /* Copyright 2012 Mozilla Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -352,18 +352,27 @@ var Page = (function PageClosure() {
                   // entry in the dictionary.
                   if (!isValidUrl(url))
                     url = '';
                   item.url = url;
                   break;
                 case 'GoTo':
                   item.dest = a.get('D');
                   break;
+                case 'GoToR':
+                  var url = a.get('F');
+                  // TODO: pdf reference says that GoToR
+                  // can also have 'NewWindow' attribute
+                  if (!isValidUrl(url))
+                    url = '';
+                  item.url = url;
+                  item.dest = a.get('D');
+                  break;
                 default:
-                  TODO('other link types');
+                  TODO('unrecognized link type: ' + a.get('S').name);
               }
             } else if (annotation.has('Dest')) {
               // simple destination link
               var dest = annotation.get('Dest');
               item.dest = isName(dest) ? dest.name : dest;
             }
             break;
           case 'Widget':
@@ -633,18 +642,16 @@ var PDFDocument = (function PDFDocumentC
 
 
 
 // Use only for debugging purposes. This should not be used in any code that is
 // in mozilla master.
 var log = (function() {
   if ('console' in globalScope && 'log' in globalScope['console']) {
     return globalScope['console']['log'].bind(globalScope['console']);
-  } else if ('print' in globalScope) {
-    return globalScope['print'].bind(globalScope);
   } else {
     return function nop() {
     };
   }
 })();
 
 // A notice for devs that will not trigger the fallback UI.  These are good
 // for things that are helpful to devs, such as warning that Workers were
@@ -897,17 +904,17 @@ var Util = PDFJS.Util = (function UtilCl
 
 var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
   function PageViewport(viewBox, scale, rotate, offsetX, offsetY) {
     // creating transform to convert pdf coordinate system to the normal
     // canvas like coordinates taking in account scale and rotation
     var centerX = (viewBox[2] + viewBox[0]) / 2;
     var centerY = (viewBox[3] + viewBox[1]) / 2;
     var rotateA, rotateB, rotateC, rotateD;
-    switch (rotate) {
+    switch (rotate % 360) {
       case -180:
       case 180:
         rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
         break;
       case -270:
       case 90:
         rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
         break;
@@ -1950,17 +1957,18 @@ var WorkerTransport = (function WorkerTr
 var TextRenderingMode = {
   FILL: 0,
   STROKE: 1,
   FILL_STROKE: 2,
   INVISIBLE: 3,
   FILL_ADD_TO_PATH: 4,
   STROKE_ADD_TO_PATH: 5,
   FILL_STROKE_ADD_TO_PATH: 6,
-  ADD_TO_PATH: 7
+  ADD_TO_PATH: 7,
+  ADD_TO_PATH_FLAG: 4
 };
 
 // Minimal font size that would be used during canvas fillText operations.
 var MIN_FONT_SIZE = 1;
 
 function createScratchCanvas(width, height) {
   var canvas = document.createElement('canvas');
   canvas.width = width;
@@ -2336,16 +2344,20 @@ var CanvasGraphics = (function CanvasGra
     },
     save: function CanvasGraphics_save() {
       this.ctx.save();
       var old = this.current;
       this.stateStack.push(old);
       this.current = old.clone();
     },
     restore: function CanvasGraphics_restore() {
+      if ('textClipLayers' in this) {
+        this.completeTextClipping();
+      }
+
       var prev = this.stateStack.pop();
       if (prev) {
         this.current = prev;
         this.ctx.restore();
       }
     },
     transform: function CanvasGraphics_transform(a, b, c, d, e, f) {
       this.ctx.transform(a, b, c, d, e, f);
@@ -2465,16 +2477,74 @@ var CanvasGraphics = (function CanvasGra
 
     // Text
     beginText: function CanvasGraphics_beginText() {
       this.current.textMatrix = IDENTITY_MATRIX;
       this.current.x = this.current.lineX = 0;
       this.current.y = this.current.lineY = 0;
     },
     endText: function CanvasGraphics_endText() {
+      if ('textClipLayers' in this) {
+        this.swapImageForTextClipping();
+      }
+    },
+    getCurrentTextClipping: function CanvasGraphics_getCurrentTextClipping() {
+      var ctx = this.ctx;
+      var transform = ctx.mozCurrentTransform;
+      if ('textClipLayers' in this) {
+        // we need to reset only font and transform
+        var maskCtx = this.textClipLayers.maskCtx;
+        maskCtx.setTransform.apply(maskCtx, transform);
+        maskCtx.font = ctx.font;
+        return maskCtx;
+      }
+
+      var canvasWidth = ctx.canvas.width;
+      var canvasHeight = ctx.canvas.height;
+      // keeping track of the text clipping of the separate canvas
+      var maskCanvas = createScratchCanvas(canvasWidth, canvasHeight);
+      var maskCtx = maskCanvas.getContext('2d');
+      maskCtx.setTransform.apply(maskCtx, transform);
+      maskCtx.font = ctx.font;
+      var textClipLayers = {
+        maskCanvas: maskCanvas,
+        maskCtx: maskCtx
+      };
+      this.textClipLayers = textClipLayers;
+      return maskCtx;
+    },
+    swapImageForTextClipping:
+      function CanvasGraphics_swapImageForTextClipping() {
+      var ctx = this.ctx;
+      var canvasWidth = ctx.canvas.width;
+      var canvasHeight = ctx.canvas.height;
+      // saving current image content and clearing whole canvas
+      ctx.save();
+      ctx.setTransform(1, 0, 0, 1, 0, 0);
+      var data = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
+      this.textClipLayers.imageData = data;
+      ctx.clearRect(0, 0, canvasWidth, canvasHeight);
+      ctx.restore();
+    },
+    completeTextClipping: function CanvasGraphics_completeTextClipping() {
+      var ctx = this.ctx;
+      // applying mask to the image (result is saved in maskCanvas)
+      var maskCtx = this.textClipLayers.maskCtx;
+      maskCtx.setTransform(1, 0, 0, 1, 0, 0);
+      maskCtx.globalCompositeOperation = 'source-in';
+      maskCtx.drawImage(ctx.canvas, 0, 0);
+
+      // restoring image data and applying the result of masked drawing
+      ctx.save();
+      ctx.setTransform(1, 0, 0, 1, 0, 0);
+      ctx.putImageData(this.textClipLayers.imageData, 0, 0);
+      ctx.drawImage(this.textClipLayers.maskCanvas, 0, 0);
+      ctx.restore();
+
+      delete this.textClipLayers;
     },
     setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) {
       this.current.charSpacing = spacing;
     },
     setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) {
       this.current.wordSpacing = spacing;
     },
     setHScale: function CanvasGraphics_setHScale(scale) {
@@ -2532,18 +2602,16 @@ var CanvasGraphics = (function CanvasGra
       var browserFontSize = size >= MIN_FONT_SIZE ? size : MIN_FONT_SIZE;
       this.current.fontSizeScale = browserFontSize != MIN_FONT_SIZE ? 1.0 :
                                    size / MIN_FONT_SIZE;
 
       var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface;
       this.ctx.font = rule;
     },
     setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) {
-      if (mode >= TextRenderingMode.FILL_ADD_TO_PATH)
-        TODO('unsupported text rendering mode: ' + mode);
       this.current.textRenderingMode = mode;
     },
     setTextRise: function CanvasGraphics_setTextRise(rise) {
       this.current.textRise = rise;
     },
     moveText: function CanvasGraphics_moveText(x, y) {
       this.current.x = this.current.lineX += x;
       this.current.y = this.current.lineY += y;
@@ -2568,30 +2636,33 @@ var CanvasGraphics = (function CanvasGra
       var fontMatrix = current.fontMatrix || IDENTITY_MATRIX;
 
       ctx.transform.apply(ctx, current.textMatrix);
       ctx.scale(1, -1);
       ctx.translate(current.x, -current.y - current.textRise);
       ctx.transform.apply(ctx, fontMatrix);
       ctx.scale(textHScale, 1);
     },
-    getTextGeometry: function CanvasGraphics_getTextGeometry() {
+    createTextGeometry: function CanvasGraphics_createTextGeometry() {
       var geometry = {};
       var ctx = this.ctx;
       var font = this.current.font;
       var ctxMatrix = ctx.mozCurrentTransform;
       if (ctxMatrix) {
         var bl = Util.applyTransform([0, 0], ctxMatrix);
         var tr = Util.applyTransform([1, 1], ctxMatrix);
         geometry.x = bl[0];
         geometry.y = bl[1];
         geometry.hScale = tr[0] - bl[0];
         geometry.vScale = tr[1] - bl[1];
       }
       geometry.spaceWidth = font.spaceWidth;
+      geometry.fontName = font.loadedName;
+      geometry.fontFamily = font.fallbackName;
+      geometry.fontSize = this.current.fontSize;
       return geometry;
     },
 
     showText: function CanvasGraphics_showText(str, skipTextSelection) {
       var ctx = this.ctx;
       var current = this.current;
       var font = current.font;
       var glyphs = font.charsToGlyphs(str);
@@ -2615,17 +2686,17 @@ var CanvasGraphics = (function CanvasGra
         ctx.transform.apply(ctx, current.textMatrix);
         ctx.translate(current.x, current.y);
 
         ctx.scale(textHScale, 1);
 
         if (textSelection) {
           this.save();
           ctx.scale(1, -1);
-          geom = this.getTextGeometry();
+          geom = this.createTextGeometry();
           this.restore();
         }
         for (var i = 0; i < glyphsLength; ++i) {
 
           var glyph = glyphs[i];
           if (glyph === null) {
             // word break
             this.ctx.translate(wordSpacing, 0);
@@ -2656,17 +2727,17 @@ var CanvasGraphics = (function CanvasGra
         var lineWidth = current.lineWidth;
         var scale = Math.abs(current.textMatrix[0] * fontMatrix[0]);
         if (scale == 0 || lineWidth == 0)
           lineWidth = this.getSinglePixelWidth();
         else
           lineWidth /= scale;
 
         if (textSelection)
-          geom = this.getTextGeometry();
+          geom = this.createTextGeometry();
 
         if (fontSizeScale != 1.0) {
           ctx.scale(fontSizeScale, fontSizeScale);
           lineWidth /= fontSizeScale;
         }
 
         ctx.lineWidth = lineWidth;
 
@@ -2696,35 +2767,40 @@ var CanvasGraphics = (function CanvasGra
                 ctx.strokeText(character, scaledX, 0);
                 break;
               case TextRenderingMode.FILL_STROKE:
               case TextRenderingMode.FILL_STROKE_ADD_TO_PATH:
                 ctx.fillText(character, scaledX, 0);
                 ctx.strokeText(character, scaledX, 0);
                 break;
               case TextRenderingMode.INVISIBLE:
+              case TextRenderingMode.ADD_TO_PATH:
                 break;
             }
+            if (textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG) {
+              var clipCtx = this.getCurrentTextClipping();
+              clipCtx.fillText(character, scaledX, 0);
+            }
           }
 
           x += charWidth;
 
           var glyphUnicode = glyph.unicode === ' ' ? '\u00A0' : glyph.unicode;
           if (glyphUnicode in NormalizedUnicodes)
             glyphUnicode = NormalizedUnicodes[glyphUnicode];
 
           canvasWidth += charWidth;
         }
         current.x += x * textHScale2;
         ctx.restore();
       }
 
       if (textSelection) {
         geom.canvasWidth = canvasWidth;
-        this.textLayer.appendText(font.fallbackName, fontSize, geom);
+        this.textLayer.appendText(geom);
       }
 
       return canvasWidth;
     },
     showSpacedText: function CanvasGraphics_showSpacedText(arr) {
       var ctx = this.ctx;
       var current = this.current;
       var font = current.font;
@@ -2743,17 +2819,17 @@ var CanvasGraphics = (function CanvasGra
         // Type3 fonts - each glyph is a "mini-PDF" (see also showText)
         if (font.coded) {
           ctx.transform.apply(ctx, current.textMatrix);
           ctx.scale(1, -1);
           ctx.translate(current.x, -1 * current.y);
           ctx.scale(textHScale, 1);
         } else
           this.applyTextTransforms();
-        geom = this.getTextGeometry();
+        geom = this.createTextGeometry();
         ctx.restore();
       }
 
       for (var i = 0; i < arrLength; ++i) {
         var e = arr[i];
         if (isNum(e)) {
           var spacingLength = -e * 0.001 * fontSize * textHScale;
           current.x += spacingLength;
@@ -2767,17 +2843,17 @@ var CanvasGraphics = (function CanvasGra
             canvasWidth += shownCanvasWidth;
         } else {
           error('TJ array element ' + e + ' is not string or num');
         }
       }
 
       if (textSelection) {
         geom.canvasWidth = canvasWidth;
-        this.textLayer.appendText(font.fallbackName, fontSize, geom);
+        this.textLayer.appendText(geom);
       }
     },
     nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
       this.nextLine();
       this.showText(text);
     },
     nextLineSetSpacingShowText:
       function CanvasGraphics_nextLineSetSpacingShowText(wordSpacing,
@@ -3108,18 +3184,32 @@ var CanvasGraphics = (function CanvasGra
       var tmpCanvas = createScratchCanvas(w, h);
       var tmpCtx = tmpCanvas.getContext('2d');
       this.putBinaryImageData(tmpCtx, imgData, w, h);
 
       ctx.drawImage(tmpCanvas, 0, -h);
       this.restore();
     },
 
-    putBinaryImageData: function CanvasGraphics_putBinaryImageData() {
-      //
+    putBinaryImageData: function CanvasGraphics_putBinaryImageData(ctx, imgData,
+                                                                   w, h) {
+      var tmpImgData = 'createImageData' in ctx ? ctx.createImageData(w, h) :
+        ctx.getImageData(0, 0, w, h);
+
+      var tmpImgDataPixels = tmpImgData.data;
+      var data = imgData.data;
+      if ('set' in tmpImgDataPixels)
+        tmpImgDataPixels.set(data);
+      else {
+        // Copy over the imageData pixel by pixel.
+        for (var i = 0, ii = tmpImgDataPixels.length; i < ii; i++)
+          tmpImgDataPixels[i] = data[i];
+      }
+
+      ctx.putImageData(tmpImgData, 0, 0);
     },
 
     // Marked content
 
     markPoint: function CanvasGraphics_markPoint(tag) {
       // TODO Marked content.
     },
     markPointProps: function CanvasGraphics_markPointProps(tag, properties) {
@@ -3176,57 +3266,16 @@ var CanvasGraphics = (function CanvasGra
       var inverse = this.ctx.mozCurrentTransformInverse;
       return Math.abs(inverse[0] + inverse[2]);
     }
   };
 
   return CanvasGraphics;
 })();
 
-function checkPutBinaryImageDataCompatibility() {
-  // Feature detection if the browser can use an Uint8Array directly as imgData.
-  var canvas = document.createElement('canvas');
-  canvas.width = 1;
-  canvas.height = 1;
-  var ctx = canvas.getContext('2d');
-
-  try {
-    ctx.putImageData({
-      width: 1,
-      height: 1,
-      data: new Uint8Array(4)
-    }, 0, 0);
-
-    CanvasGraphics.prototype.putBinaryImageData =
-      function CanvasGraphicsPutBinaryImageDataNative(ctx, imgData) {
-        ctx.putImageData(imgData, 0, 0);
-      };
-  } catch (e) {
-    CanvasGraphics.prototype.putBinaryImageData =
-      function CanvasGraphicsPutBinaryImageDataShim(ctx, imgData, w, h) {
-        var tmpImgData = 'createImageData' in ctx ? ctx.createImageData(w, h) :
-          ctx.getImageData(0, 0, w, h);
-
-        var tmpImgDataPixels = tmpImgData.data;
-        var data = imgData.data;
-        if ('set' in tmpImgDataPixels)
-          tmpImgDataPixels.set(data);
-        else {
-          // Copy over the imageData pixel by pixel.
-          for (var i = 0, ii = tmpImgDataPixels.length; i < ii; i++)
-            tmpImgDataPixels[i] = data[i];
-        }
-
-        ctx.putImageData(tmpImgData, 0, 0);
-      };
-  }
-}
-if (!isWorker) {
-  checkPutBinaryImageDataCompatibility();
-}
 
 
 var Name = (function NameClosure() {
   function Name(name) {
     this.name = name;
   }
 
   Name.prototype = {};
@@ -13265,33 +13314,39 @@ var PartialEvaluator = (function Partial
 
   PartialEvaluator.prototype = {
     loadFont: function PartialEvaluator_loadFont(fontName, font, xref,
                                                  resources, dependency) {
       var fontRes = resources.get('Font');
 
       assert(fontRes, 'fontRes not available');
 
+      ++this.fontIdCounter;
+
       font = xref.fetchIfRef(font) || fontRes.get(fontName);
-      assertWellFormed(isDict(font));
-
-      ++this.fontIdCounter;
+      if (!isDict(font)) {
+        return {
+          translated: new ErrorFont('Font ' + fontName + ' is not available'),
+          loadedName: 'font_' + this.uniquePrefix + this.fontIdCounter
+        };
+      }
+
       var loadedName = font.loadedName;
       if (!loadedName) {
         // keep track of each font we translated so the caller can
         // load them asynchronously before calling display on a page
         loadedName = 'font_' + this.uniquePrefix + this.fontIdCounter;
         font.loadedName = loadedName;
 
         var translated;
         try {
           translated = this.translateFont(font, xref, resources,
                                           dependency);
         } catch (e) {
-          translated = { error: e };
+          translated = new ErrorFont(e instanceof Error ? e.message : e);
         }
         font.translated = translated;
 
         var data = translated;
         if (data.loadCharProcs) {
           delete data.loadCharProcs;
 
           var charProcs = font.get('CharProcs').getAll();
@@ -13329,20 +13384,17 @@ var PartialEvaluator = (function Partial
         }
       }
 
       function handleSetFont(fontName, font) {
         font = self.loadFont(fontName, font, xref, resources, dependency);
 
         var loadedName = font.loadedName;
         if (!font.sent) {
-          var data = font.translated;
-
-          if (data instanceof Font)
-            data = data.exportData();
+          var data = font.translated.exportData();
 
           handler.send('obj', [
               loadedName,
               'Font',
               data
           ]);
           font.sent = true;
         }
@@ -13630,16 +13682,18 @@ var PartialEvaluator = (function Partial
       }
 
       return queue;
     },
 
     getTextContent: function partialEvaluatorGetIRQueue(
                                                     stream, resources, state) {
       var bidiTexts;
+      var kSpaceFactor = 0.35;
+      var kMultipleSpaceFactor = 1.5;
 
       if (!state) {
         bidiTexts = [];
         state = {
           bidiTexts: bidiTexts
         };
       } else {
         bidiTexts = state.bidiTexts;
@@ -13671,18 +13725,23 @@ var PartialEvaluator = (function Partial
               font = handleSetFont(args[0].name).translated;
               break;
             case 'TJ':
               var items = args[0];
               for (var j = 0, jj = items.length; j < jj; j++) {
                 if (typeof items[j] === 'string') {
                   chunk += fontCharsToUnicode(items[j], font);
                 } else if (items[j] < 0 && font.spaceWidth > 0) {
-                  var numFakeSpaces = Math.round(-items[j] / font.spaceWidth);
-                  if (numFakeSpaces > 0) {
+                  var fakeSpaces = -items[j] / font.spaceWidth;
+                  if (fakeSpaces > kMultipleSpaceFactor) {
+                    fakeSpaces = Math.round(fakeSpaces);
+                    while (fakeSpaces--) {
+                      chunk += ' ';
+                    }
+                  } else if (fakeSpaces > kSpaceFactor) {
                     chunk += ' ';
                   }
                 }
               }
               break;
             case 'Tj':
               chunk += fontCharsToUnicode(args[0], font);
               break;
@@ -16504,65 +16563,68 @@ var Font = (function FontClosure() {
 
     var numTables = 1;
     var cmap = '\x00\x00' + // version
                string16(numTables) +  // numTables
                '\x00\x03' + // platformID
                '\x00\x01' + // encodingID
                string32(4 + numTables * 8); // start of the table record
 
-    var segCount = ranges.length + 1;
+    var trailingRangesCount = ranges[ranges.length - 1][1] < 0xFFFF ? 1 : 0;
+    var segCount = ranges.length + trailingRangesCount;
     var segCount2 = segCount * 2;
     var searchRange = getMaxPower2(segCount) * 2;
     var searchEntry = Math.log(segCount) / Math.log(2);
     var rangeShift = 2 * segCount - searchRange;
 
     // Fill up the 4 parallel arrays describing the segments.
     var startCount = '';
     var endCount = '';
     var idDeltas = '';
     var idRangeOffsets = '';
     var glyphsIds = '';
     var bias = 0;
 
     if (deltas) {
-      for (var i = 0; i < segCount - 1; i++) {
+      for (var i = 0, ii = ranges.length; i < ii; i++) {
         var range = ranges[i];
         var start = range[0];
         var end = range[1];
         var offset = (segCount - i) * 2 + bias * 2;
         bias += (end - start + 1);
 
         startCount += string16(start);
         endCount += string16(end);
         idDeltas += string16(0);
         idRangeOffsets += string16(offset);
 
         var codes = range[2];
         for (var j = 0, jj = codes.length; j < jj; ++j)
           glyphsIds += string16(deltas[codes[j]]);
       }
     } else {
-      for (var i = 0; i < segCount - 1; i++) {
+      for (var i = 0, ii = ranges.length; i < ii; i++) {
         var range = ranges[i];
         var start = range[0];
         var end = range[1];
         var startCode = range[2][0];
 
         startCount += string16(start);
         endCount += string16(end);
         idDeltas += string16((startCode - start + 1) & 0xFFFF);
         idRangeOffsets += string16(0);
       }
     }
 
-    endCount += '\xFF\xFF';
-    startCount += '\xFF\xFF';
-    idDeltas += '\x00\x01';
-    idRangeOffsets += '\x00\x00';
+    if (trailingRangesCount > 0) {
+      endCount += '\xFF\xFF';
+      startCount += '\xFF\xFF';
+      idDeltas += '\x00\x01';
+      idRangeOffsets += '\x00\x00';
+    }
 
     var format314 = '\x00\x00' + // language
                     string16(segCount2) +
                     string16(searchRange) +
                     string16(searchEntry) +
                     string16(rangeShift) +
                     endCount + '\x00\x00' + startCount +
                     idDeltas + idRangeOffsets + glyphsIds;
@@ -17233,16 +17295,19 @@ var Font = (function FontClosure() {
 
         return true;
       }
 
       // Check that required tables are present
       var requiredTables = ['OS/2', 'cmap', 'head', 'hhea',
                              'hmtx', 'maxp', 'name', 'post'];
 
+      var optionalTables = ['cvt ', 'fpgm', 'glyf', 'loca', 'prep',
+                            'CFF ', 'VORG', 'vhea', 'vmtx'];
+
       var header = readOpenTypeHeader(font);
       var numTables = header.numTables;
 
       var cmap, post, maxp, hhea, hmtx, vhea, vmtx, head, loca, glyf, os2;
       var tables = [];
       for (var i = 0; i < numTables; i++) {
         var table = readTableEntry(font);
         var index = requiredTables.indexOf(table.tag);
@@ -17258,16 +17323,19 @@ var Font = (function FontClosure() {
           else if (table.tag == 'hmtx')
             hmtx = table;
           else if (table.tag == 'head')
             head = table;
           else if (table.tag == 'OS/2')
             os2 = table;
 
           requiredTables.splice(index, 1);
+        } else if (optionalTables.indexOf(table.tag) < 0) {
+          // skipping table if it's not a required or optional table
+          continue;
         } else {
           if (table.tag == 'vmtx')
             vmtx = table;
           else if (table.tag == 'vhea')
             vhea = table;
           else if (table.tag == 'loca')
             loca = table;
           else if (table.tag == 'glyf')
@@ -17563,16 +17631,22 @@ var Font = (function FontClosure() {
           }
           this.useToFontChar = true;
         }
 
         createGlyphNameMap(glyphs, ids, properties);
         this.glyphNameMap = properties.glyphNameMap;
       }
 
+      if (glyphs.length === 0) {
+        // defines at least one glyph
+        glyphs.push({ unicode: 0xF000, code: 0xF000, glyph: '.notdef' });
+        ids.push(0);
+      }
+
       // Converting glyphs and ids into font's cmap table
       cmap.data = createCMapTable(glyphs, ids);
       var unicodeIsEnabled = [];
       for (var i = 0, ii = glyphs.length; i < ii; i++) {
         unicodeIsEnabled[glyphs[i].unicode] = true;
       }
       this.unicodeIsEnabled = unicodeIsEnabled;
 
@@ -18075,16 +18149,19 @@ var Font = (function FontClosure() {
 var ErrorFont = (function ErrorFontClosure() {
   function ErrorFont(error) {
     this.error = error;
   }
 
   ErrorFont.prototype = {
     charsToGlyphs: function ErrorFont_charsToGlyphs() {
       return [];
+    },
+    exportData: function ErrorFont_exportData() {
+      return {error: this.error};
     }
   };
 
   return ErrorFont;
 })();
 
 var CallothersubrCmd = (function CallothersubrCmdClosure() {
   function CallothersubrCmd(index) {
@@ -18298,16 +18375,31 @@ var Type1Parser = function type1Parser()
               charstring.push(3);
               i++;
               continue;
             }
 
             assert(argc == 0, 'callothersubr with arguments is not supported');
             charstring.push(new CallothersubrCmd(index));
             continue;
+          } else if (escape == 7) { // sbw
+            var args = breakUpArgs(charstring, 4);
+            var arg0 = args[0];
+            var arg1 = args[1];
+            var arg2 = args[2];
+            lsb = arg0.value;
+            width = arg2.value;
+            // To convert to type2 we have to move the width value to the first
+            // part of the charstring and then use rmoveto with (dx, dy).
+            // The height argument will not be used for vmtx and vhea tables
+            // reconstruction -- ignoring it.
+            charstring = arg2.arg;
+            charstring = charstring.concat(arg0.arg, arg1.arg);
+            charstring.push('rmoveto');
+            continue;
           } else if (escape == 17 || escape == 33) {
             // pop or setcurrentpoint commands can be ignored
             // since we are not doing callothersubr
             continue;
           } else if (escape == 6) {
             // seac is like type 2's special endchar but it doesn't use the
             // first argument asb, so remove it.
             var args = breakUpArgs(charstring, 5);
@@ -19105,20 +19197,19 @@ var CFFFont = (function CFFFontClosure()
       var unassignedUnicodeItems = [];
       var inverseEncoding = [];
       // CID fonts don't have an encoding.
       if (encoding !== null)
         for (var charcode in encoding)
           inverseEncoding[encoding[charcode]] = charcode | 0;
       else
         inverseEncoding = charsets;
-      for (var i = 0, ii = charsets.length; i < ii; i++) {
+      var i = charsets[0] == '.notdef' ? 1 : 0;
+      for (var ii = charsets.length; i < ii; i++) {
         var glyph = charsets[i];
-        if (glyph == '.notdef')
-          continue;
 
         var code = inverseEncoding[i];
         if (!code || isSpecialUnicode(code)) {
           unassignedUnicodeItems.push(i);
           continue;
         }
         charstrings.push({
           unicode: code,
@@ -31240,16 +31331,17 @@ function MessageHandler(name, comObj) {
   // If there's no console available, console_error in the
   // action handler will do nothing.
   if ('console' in globalScope) {
     ah['console_error'] = [function ahConsoleError(data) {
       globalScope['console'].error.apply(null, data);
     }];
   } else {
     ah['console_error'] = [function ahConsoleError(data) {
+      log.apply(null, data);
     }];
   }
   ah['_warn'] = [function ah_Warn(data) {
     warn(data);
   }];
 
   comObj.onmessage = function messageHandlerComObjOnMessage(event) {
     var data = event.data;
@@ -35955,45 +36047,55 @@ var JpegImage = (function jpegImage() {
       <div id="sidebarContainer">
         <div id="toolbarSidebar" class="splitToolbarButton toggled">
           <button id="viewThumbnail" class="toolbarButton group toggled" title="Show Thumbnails" tabindex="1" data-l10n-id="thumbs">
              <span data-l10n-id="thumbs_label">Thumbnails</span>
           </button>
           <button id="viewOutline" class="toolbarButton group" title="Show Document Outline" tabindex="2" data-l10n-id="outline">
              <span data-l10n-id="outline_label">Document Outline</span>
           </button>
-          <button id="viewSearch" class="toolbarButton group hidden" title="Search Document" tabindex="3" data-l10n-id="search_panel">
-             <span data-l10n-id="search_panel_label">Search Document</span>
-          </button>
         </div>
         <div id="sidebarContent">
           <div id="thumbnailView">
           </div>
           <div id="outlineView" class="hidden">
           </div>
-          <div id="searchView" class="hidden">
-            <div id="searchToolbar">
-              <input id="searchTermsInput" class="toolbarField">
-              <button id="searchButton" class="textButton toolbarButton" data-l10n-id="search">Find</button>
-            </div>
-            <div id="searchResults"></div>
-          </div>
         </div>
       </div>  <!-- sidebarContainer -->
 
       <div id="mainContainer">
+        <div class="findbar hidden doorHanger" id="findbar">
+          <label for="findInput" class="toolbarLabel" data-l10n-id="find_label">Find:</label>
+          <input id="findInput" class="toolbarField" tabindex="20">
+          <div class="splitToolbarButton">
+            <button class="toolbarButton findPrevious" title="" id="findPrevious" tabindex="21" data-l10n-id="find_previous">
+              <span data-l10n-id="find_previous_label">Previous</span>
+            </button>
+            <div class="splitToolbarButtonSeparator"></div>
+            <button class="toolbarButton findNext" title="" id="findNext" tabindex="22" data-l10n-id="find_next">
+              <span data-l10n-id="find_next_label">Next</span>
+            </button>
+          </div>
+          <input type="checkbox" id="findHighlightAll" class="toolbarField">
+          <label for="findHighlightAll" class="toolbarLabel" tabindex="23" data-l10n-id="find_highlight">Highlight all</label>
+          <input type="checkbox" id="findMatchCase" class="toolbarField">
+          <label for="findMatchCase" class="toolbarLabel" tabindex="24" data-l10n-id="find_match_case_label">Match case</label>
+          <span id="findMsg" class="toolbarLabel"></span>
+        </div>
         <div class="toolbar">
           <div id="toolbarContainer">
-
             <div id="toolbarViewer">
               <div id="toolbarViewerLeft">
-                <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="4" data-l10n-id="toggle_slider">
+                <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="3" data-l10n-id="toggle_slider">
                   <span data-l10n-id="toggle_slider_label">Toggle Sidebar</span>
                 </button>
                 <div class="toolbarButtonSpacer"></div>
+                <button id="viewFind" class="toolbarButton group" title="Find in Document" tabindex="4" data-l10n-id="findbar">
+                   <span data-l10n-id="findbar_label">Find</span>
+                </button>
                 <div class="splitToolbarButton">
                   <button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="5" data-l10n-id="previous">
                     <span data-l10n-id="previous_label">Previous</span>
                   </button>
                   <div class="splitToolbarButtonSeparator"></div>
                   <button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="6" data-l10n-id="next">
                     <span data-l10n-id="next_label">Next</span>
                   </button>
@@ -36053,16 +36155,20 @@ var JpegImage = (function jpegImage() {
                   </span>
                 </div>
               </div>
             </div>
           </div>
         </div>
 
         <menu type="context" id="viewerContextMenu">
+          <menuitem label="First Page" id="first_page"
+                    data-l10n-id="first_page" ></menuitem>
+          <menuitem label="Last Page" id="last_page"
+                    data-l10n-id="last_page" ></menuitem>
           <menuitem label="Rotate Counter-Clockwise" id="page_rotate_ccw"
                     data-l10n-id="page_rotate_ccw" ></menuitem>
           <menuitem label="Rotate Clockwise" id="page_rotate_cw"
                     data-l10n-id="page_rotate_cw" ></menuitem>
         </menu>
 
         <div id="viewerContainer">
           <div id="viewer" contextmenu="viewerContextMenu"></div>
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -19,26 +19,33 @@
 
 var kDefaultURL = 'compressed.tracemonkey-pldi-09.pdf';
 var kDefaultScale = 'auto';
 var kDefaultScaleDelta = 1.1;
 var kUnknownScale = 0;
 var kCacheSize = 20;
 var kCssUnits = 96.0 / 72.0;
 var kScrollbarPadding = 40;
+var kVerticalPadding = 5;
 var kMinScale = 0.25;
 var kMaxScale = 4.0;
 var kImageDirectory = './images/';
 var kSettingsMemory = 20;
 var RenderingStates = {
   INITIAL: 0,
   RUNNING: 1,
   PAUSED: 2,
   FINISHED: 3
 };
+var FindStates = {
+  FIND_FOUND: 0,
+  FIND_NOTFOUND: 1,
+  FIND_WRAPPED: 2,
+  FIND_PENDING: 3
+};
 
 
 var mozL10n = document.mozL10n || document.webL10n;
 
 function getFileName(url) {
   var anchor = url.indexOf('#');
   var query = url.indexOf('?');
   var end = Math.min(
@@ -200,77 +207,479 @@ var FirefoxCom = (function FirefoxComClo
     }
   };
 })();
 
 
 // Settings Manager - This is a utility for saving settings
 // First we see if localStorage is available
 // If not, we use FUEL in FF
+// Use asyncStorage for B2G
 var Settings = (function SettingsClosure() {
   var isLocalStorageEnabled = (function localStorageEnabledTest() {
     // Feature test as per http://diveintohtml5.info/storage.html
     // The additional localStorage call is to get around a FF quirk, see
     // bug #495747 in bugzilla
     try {
       return 'localStorage' in window && window['localStorage'] !== null &&
           localStorage;
     } catch (e) {
       return false;
     }
   })();
 
   function Settings(fingerprint) {
-    var database = null;
-    var index;
-    database = FirefoxCom.requestSync('getDatabase', null) || '{}';
-
-    database = JSON.parse(database);
-    if (!('files' in database))
-      database.files = [];
-    if (database.files.length >= kSettingsMemory)
-      database.files.shift();
-    for (var i = 0, length = database.files.length; i < length; i++) {
-      var branch = database.files[i];
-      if (branch.fingerprint == fingerprint) {
-        index = i;
-        break;
-      }
-    }
-    if (typeof index != 'number')
-      index = database.files.push({fingerprint: fingerprint}) - 1;
-    this.file = database.files[index];
-    this.database = database;
+    this.fingerprint = fingerprint;
+    this.initializedPromise = new PDFJS.Promise();
+
+    var resolvePromise = (function settingsResolvePromise(db) {
+      this.initialize(db || '{}');
+      this.initializedPromise.resolve();
+    }).bind(this);
+
+
+    resolvePromise(FirefoxCom.requestSync('getDatabase', null));
+
   }
 
   Settings.prototype = {
+    initialize: function settingsInitialize(database) {
+      database = JSON.parse(database);
+      if (!('files' in database))
+        database.files = [];
+      if (database.files.length >= kSettingsMemory)
+        database.files.shift();
+      var index;
+      for (var i = 0, length = database.files.length; i < length; i++) {
+        var branch = database.files[i];
+        if (branch.fingerprint == this.fingerprint) {
+          index = i;
+          break;
+        }
+      }
+      if (typeof index != 'number')
+        index = database.files.push({fingerprint: this.fingerprint}) - 1;
+      this.file = database.files[index];
+      this.database = database;
+    },
+
     set: function settingsSet(name, val) {
-      if (!('file' in this))
-        return false;
+      if (!this.initializedPromise.isResolved)
+        return;
 
       var file = this.file;
       file[name] = val;
       var database = JSON.stringify(this.database);
       FirefoxCom.requestSync('setDatabase', database);
     },
 
     get: function settingsGet(name, defaultValue) {
-      if (!('file' in this))
+      if (!this.initializedPromise.isResolved)
         return defaultValue;
 
       return this.file[name] || defaultValue;
     }
   };
 
   return Settings;
 })();
 
 var cache = new Cache(kCacheSize);
 var currentPageNumber = 1;
 
+var PDFFindController = {
+  extractTextPromise: null,
+
+  // If active, find results will be highlighted.
+  active: false,
+
+  // Stores the text for each page.
+  pageContents: [],
+
+  pageMatches: [],
+
+  selected: {
+    pageIdx: 0,
+    matchIdx: 0
+  },
+
+  state: null,
+
+  dirtyMatch: false,
+
+  findTimeout: null,
+
+  initialize: function() {
+    var events = [
+      'find',
+      'findagain',
+      'findhighlightallchange',
+      'findcasesensitivitychange'
+    ];
+
+    this.handleEvent = this.handleEvent.bind(this);
+
+    for (var i = 0; i < events.length; i++) {
+      window.addEventListener(events[i], this.handleEvent);
+    }
+  },
+
+  calcFindMatch: function(pageContent) {
+    var query = this.state.query;
+    var caseSensitive = this.state.caseSensitive;
+    var queryLen = query.length;
+
+    if (queryLen === 0)
+      return [];
+
+    if (!caseSensitive) {
+      pageContent = pageContent.toLowerCase();
+      query = query.toLowerCase();
+    }
+
+    var matches = [];
+
+    var matchIdx = -queryLen;
+    while (true) {
+      matchIdx = pageContent.indexOf(query, matchIdx + queryLen);
+      if (matchIdx === -1) {
+        break;
+      }
+
+      matches.push(matchIdx);
+    }
+    return matches;
+  },
+
+  extractText: function() {
+    if (this.extractTextPromise) {
+      return this.extractTextPromise;
+    }
+    this.extractTextPromise = new PDFJS.Promise();
+
+    var self = this;
+    function extractPageText(pageIndex) {
+      PDFView.pages[pageIndex].getTextContent().then(
+        function textContentResolved(data) {
+          // Build the find string.
+          var bidiTexts = data.bidiTexts;
+          var str = '';
+
+          for (var i = 0; i < bidiTexts.length; i++) {
+            str += bidiTexts[i].str;
+          }
+
+          // Store the pageContent as a string.
+          self.pageContents.push(str);
+          // Ensure there is a empty array of matches.
+          self.pageMatches.push([]);
+
+          if ((pageIndex + 1) < PDFView.pages.length)
+            extractPageText(pageIndex + 1);
+          else
+            self.extractTextPromise.resolve();
+        }
+      );
+    }
+    extractPageText(0);
+    return this.extractTextPromise;
+  },
+
+  handleEvent: function(e) {
+    if (this.state === null || e.type !== 'findagain') {
+      this.dirtyMatch = true;
+    }
+    this.state = e.detail;
+    this.updateUIState(FindStates.FIND_PENDING);
+
+    var promise = this.extractText();
+
+    clearTimeout(this.findTimeout);
+    if (e.type === 'find') {
+      // Only trigger the find action after 250ms of silence.
+      this.findTimeout = setTimeout(function() {
+        promise.then(this.performFind.bind(this));
+      }.bind(this), 250);
+    } else {
+      promise.then(this.performFind.bind(this));
+    }
+  },
+
+  updatePage: function(idx) {
+    var page = PDFView.pages[idx];
+
+    if (this.selected.pageIdx === idx) {
+      // If the page is selected, scroll the page into view, which triggers
+      // rendering the page, which adds the textLayer. Once the textLayer is
+      // build, it will scroll onto the selected match.
+      page.scrollIntoView();
+    }
+
+    if (page.textLayer) {
+      page.textLayer.updateMatches();
+    }
+  },
+
+  performFind: function() {
+    // Recalculate all the matches.
+    // TODO: Make one match show up as the current match
+
+    var pages = PDFView.pages;
+    var pageContents = this.pageContents;
+    var pageMatches = this.pageMatches;
+
+    this.active = true;
+
+    if (this.dirtyMatch) {
+      // Need to recalculate the matches.
+      this.dirtyMatch = false;
+
+      this.selected = {
+        pageIdx: -1,
+        matchIdx: -1
+      };
+
+      // TODO: Make this way more lasily (aka. efficient) - e.g. calculate only
+      // the matches for the current visible pages.
+      var firstMatch = true;
+      for (var i = 0; i < pageContents.length; i++) {
+        var matches = pageMatches[i] = this.calcFindMatch(pageContents[i]);
+        if (firstMatch && matches.length !== 0) {
+          firstMatch = false;
+          this.selected = {
+            pageIdx: i,
+            matchIdx: 0
+          };
+        }
+        this.updatePage(i, true);
+      }
+      if (!firstMatch || !this.state.query) {
+        this.updateUIState(FindStates.FIND_FOUND);
+      } else {
+        this.updateUIState(FindStates.FIND_NOTFOUND);
+      }
+    } else {
+      // If there is NO selection, then there is no match at all -> no sense to
+      // handle previous/next action.
+      if (this.selected.pageIdx === -1) {
+        this.updateUIState(FindStates.FIND_NOTFOUND);
+        return;
+      }
+
+      // Handle findAgain case.
+      var previous = this.state.findPrevious;
+      var sPageIdx = this.selected.pageIdx;
+      var sMatchIdx = this.selected.matchIdx;
+      var findState = FindStates.FIND_FOUND;
+
+      if (previous) {
+        // Select previous match.
+
+        if (sMatchIdx !== 0) {
+          this.selected.matchIdx -= 1;
+        } else {
+          var len = pageMatches.length;
+          for (var i = sPageIdx - 1; i != sPageIdx; i--) {
+            if (i < 0)
+              i += len;
+
+            if (pageMatches[i].length !== 0) {
+              this.selected = {
+                pageIdx: i,
+                matchIdx: pageMatches[i].length - 1
+              };
+              break;
+            }
+          }
+          // If pageIdx stayed the same, select last match on the page.
+          if (this.selected.pageIdx === sPageIdx) {
+            this.selected.matchIdx = pageMatches[sPageIdx].length - 1;
+            findState = FindStates.FIND_WRAPPED;
+          } else if (this.selected.pageIdx > sPageIdx) {
+            findState = FindStates.FIND_WRAPPED;
+          }
+        }
+      } else {
+        // Select next match.
+
+        if (pageMatches[sPageIdx].length !== sMatchIdx + 1) {
+          this.selected.matchIdx += 1;
+        } else {
+          var len = pageMatches.length;
+          for (var i = sPageIdx + 1; i < len + sPageIdx; i++) {
+            if (pageMatches[i % len].length !== 0) {
+              this.selected = {
+                pageIdx: i % len,
+                matchIdx: 0
+              };
+              break;
+            }
+          }
+
+          // If pageIdx stayed the same, select first match on the page.
+          if (this.selected.pageIdx === sPageIdx) {
+            this.selected.matchIdx = 0;
+            findState = FindStates.FIND_WRAPPED;
+          } else if (this.selected.pageIdx < sPageIdx) {
+            findState = FindStates.FIND_WRAPPED;
+          }
+        }
+      }
+
+      this.updateUIState(findState, previous);
+      this.updatePage(sPageIdx, sPageIdx === this.selected.pageIdx);
+      if (sPageIdx !== this.selected.pageIdx) {
+        this.updatePage(this.selected.pageIdx, true);
+      }
+    }
+  },
+
+  updateUIState: function(state, previous) {
+    if (PDFView.supportsIntegratedFind) {
+      FirefoxCom.request('updateFindControlState',
+                         {result: state, findPrevious: previous});
+      return;
+    }
+    PDFFindBar.updateUIState(state, previous);
+  }
+};
+
+var PDFFindBar = {
+  // TODO: Enable the FindBar *AFTER* the pagesPromise in the load function
+  // got resolved
+
+  opened: false,
+
+  initialize: function() {
+    this.bar = document.getElementById('findbar');
+    this.toggleButton = document.getElementById('viewFind');
+    this.findField = document.getElementById('findInput');
+    this.highlightAll = document.getElementById('findHighlightAll');
+    this.caseSensitive = document.getElementById('findMatchCase');
+    this.findMsg = document.getElementById('findMsg');
+    this.findStatusIcon = document.getElementById('findStatusIcon');
+
+    var self = this;
+    this.toggleButton.addEventListener('click', function() {
+      self.toggle();
+    });
+
+    this.findField.addEventListener('input', function() {
+      self.dispatchEvent('');
+    });
+
+    this.bar.addEventListener('keydown', function(evt) {
+      switch (evt.keyCode) {
+        case 13: // Enter
+          if (evt.target === self.findField) {
+            self.dispatchEvent('again', evt.shiftKey);
+          }
+          break;
+        case 27: // Escape
+          self.close();
+          break;
+      }
+    });
+
+    document.getElementById('findPrevious').addEventListener('click',
+      function() { self.dispatchEvent('again', true); }
+    );
+
+    document.getElementById('findNext').addEventListener('click', function() {
+      self.dispatchEvent('again', false);
+    });
+
+    this.highlightAll.addEventListener('click', function() {
+      self.dispatchEvent('highlightallchange');
+    });
+
+    this.caseSensitive.addEventListener('click', function() {
+      self.dispatchEvent('casesensitivitychange');
+    });
+  },
+
+  dispatchEvent: function(aType, aFindPrevious) {
+    var event = document.createEvent('CustomEvent');
+    event.initCustomEvent('find' + aType, true, true, {
+      query: this.findField.value,
+      caseSensitive: this.caseSensitive.checked,
+      highlightAll: this.highlightAll.checked,
+      findPrevious: aFindPrevious
+    });
+    return window.dispatchEvent(event);
+  },
+
+  updateUIState: function(state, previous) {
+    var notFound = false;
+    var findMsg = '';
+    var status = '';
+
+    switch (state) {
+      case FindStates.FIND_FOUND:
+        break;
+
+      case FindStates.FIND_PENDING:
+        status = 'pending';
+        break;
+
+      case FindStates.FIND_NOTFOUND:
+        findMsg = mozL10n.get('find_not_found', null, 'Phrase not found');
+        notFound = true;
+        break;
+
+      case FindStates.FIND_WRAPPED:
+        if (previous) {
+          findMsg = mozL10n.get('find_wrapped_to_bottom', null,
+                                'Reached end of page, continued from bottom');
+        } else {
+          findMsg = mozL10n.get('find_wrapped_to_top', null,
+                                'Reached end of page, continued from top');
+        }
+        break;
+    }
+
+    if (notFound) {
+      this.findField.classList.add('notFound');
+    } else {
+      this.findField.classList.remove('notFound');
+    }
+
+    this.findField.setAttribute('data-status', status);
+    this.findMsg.textContent = findMsg;
+  },
+
+  open: function() {
+    if (this.opened) return;
+
+    this.opened = true;
+    this.toggleButton.classList.add('toggled');
+    this.bar.classList.remove('hidden');
+    this.findField.select();
+    this.findField.focus();
+  },
+
+  close: function() {
+    if (!this.opened) return;
+
+    this.opened = false;
+    this.toggleButton.classList.remove('toggled');
+    this.bar.classList.add('hidden');
+
+    PDFFindController.active = false;
+  },
+
+  toggle: function() {
+    if (this.opened) {
+      this.close();
+    } else {
+      this.open();
+    }
+  }
+};
+
 var PDFView = {
   pages: [],
   thumbnails: [],
   currentScale: kUnknownScale,
   currentScaleValue: null,
   initialBookmark: document.location.hash.substring(1),
   startedTextExtraction: false,
   pageText: [],
@@ -280,31 +689,36 @@ var PDFView = {
   fellback: false,
   pdfDocument: null,
   sidebarOpen: false,
   pageViewScroll: null,
   thumbnailViewScroll: null,
   isFullscreen: false,
   previousScale: null,
   pageRotation: 0,
+  mouseScrollTimeStamp: 0,
+  mouseScrollDelta: 0,
   lastScroll: 0,
 
   // called once when the document is loaded
   initialize: function pdfViewInitialize() {
     var self = this;
     var container = this.container = document.getElementById('viewerContainer');
     this.pageViewScroll = {};
     this.watchScroll(container, this.pageViewScroll, updateViewarea);
 
     var thumbnailContainer = this.thumbnailContainer =
                              document.getElementById('thumbnailView');
     this.thumbnailViewScroll = {};
     this.watchScroll(thumbnailContainer, this.thumbnailViewScroll,
                      this.renderHighestPriority.bind(this));
 
+    PDFFindBar.initialize();
+    PDFFindController.initialize();
+
     this.initialized = true;
     container.addEventListener('scroll', function() {
       self.lastScroll = Date.now();
     }, false);
   },
 
   // Helper function to keep track whether a div was scrolled up or down and
   // then call a callback.
@@ -351,20 +765,23 @@ var PDFView = {
     this.currentScaleValue = value;
     if (scale) {
       this.setScale(scale, true, noScroll);
       return;
     }
 
     var container = this.container;
     var currentPage = this.pages[this.page - 1];
+    if (!currentPage) {
+      return;
+    }
 
     var pageWidthScale = (container.clientWidth - kScrollbarPadding) /
                           currentPage.width * currentPage.scale / kCssUnits;
-    var pageHeightScale = (container.clientHeight - kScrollbarPadding) /
+    var pageHeightScale = (container.clientHeight - kVerticalPadding) /
                            currentPage.height * currentPage.scale / kCssUnits;
     switch (value) {
       case 'page-actual':
         scale = 1;
         break;
       case 'page-width':
         scale = pageWidthScale;
         break;
@@ -445,16 +862,26 @@ var PDFView = {
                   doc.webkitRequestFullScreen;
     Object.defineProperty(this, 'supportsFullScreen', { value: support,
                                                         enumerable: true,
                                                         configurable: true,
                                                         writable: false });
     return support;
   },
 
+  get supportsIntegratedFind() {
+    var support = false;
+    support = FirefoxCom.requestSync('supportsIntegratedFind');
+    Object.defineProperty(this, 'supportsIntegratedFind', { value: support,
+                                                            enumerable: true,
+                                                            configurable: true,
+                                                            writable: false });
+    return support;
+  },
+
   initPassiveLoading: function pdfViewInitPassiveLoading() {
     if (!PDFView.loadingBar) {
       PDFView.loadingBar = new ProgressBar('#loadingBar', {});
     }
 
     window.addEventListener('message', function window_message(e) {
       var args = e.data;
 
@@ -705,30 +1132,23 @@ var PDFView = {
       clearInterval(thumbsView._loadingInterval);
 
     var container = document.getElementById('viewer');
     while (container.hasChildNodes())
       container.removeChild(container.lastChild);
 
     var pagesCount = pdfDocument.numPages;
     var id = pdfDocument.fingerprint;
-    var storedHash = null;
     document.getElementById('numPages').textContent =
       mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}');
     document.getElementById('pageNumber').max = pagesCount;
+
     PDFView.documentFingerprint = id;
     var store = PDFView.store = new Settings(id);
-    if (store.get('exists', false)) {
-      var page = store.get('page', '1');
-      var zoom = store.get('zoom', PDFView.currentScale);
-      var left = store.get('scrollLeft', '0');
-      var top = store.get('scrollTop', '0');
-
-      storedHash = 'page=' + page + '&zoom=' + zoom + ',' + left + ',' + top;
-    }
+    var storePromise = store.initializedPromise;
 
     this.pageRotation = 0;
 
     var pages = this.pages = [];
     this.pageText = [];
     this.startedTextExtraction = false;
     var pagesRefMap = {};
     var thumbnails = this.thumbnails = [];
@@ -755,21 +1175,32 @@ var PDFView = {
     });
 
     var destinationsPromise = pdfDocument.getDestinations();
     destinationsPromise.then(function(destinations) {
       self.destinations = destinations;
     });
 
     // outline and initial view depends on destinations and pagesRefMap
-    PDFJS.Promise.all([pagesPromise, destinationsPromise]).then(function() {
+    var promises = [pagesPromise, destinationsPromise, storePromise];
+    PDFJS.Promise.all(promises).then(function() {
       pdfDocument.getOutline().then(function(outline) {
         self.outline = new DocumentOutlineView(outline);
       });
 
+      var storedHash = null;
+      if (store.get('exists', false)) {
+        var page = store.get('page', '1');
+        var zoom = store.get('zoom', PDFView.currentScale);
+        var left = store.get('scrollLeft', '0');
+        var top = store.get('scrollTop', '0');
+
+        storedHash = 'page=' + page + '&zoom=' + zoom + ',' + left + ',' + top;
+      }
+
       self.setInitialView(storedHash, scale);
     });
 
     pdfDocument.getMetadata().then(function(data) {
       var info = data.info, metadata = data.metadata;
       self.documentInfo = info;
       self.metadata = metadata;
 
@@ -887,82 +1318,16 @@ var PDFView = {
       case RenderingStates.INITIAL:
         PDFView.highestPriorityPage = type + view.id;
         view.draw(this.renderHighestPriority.bind(this));
         break;
     }
     return true;
   },
 
-  search: function pdfViewStartSearch() {
-    // Limit this function to run every <SEARCH_TIMEOUT>ms.
-    var SEARCH_TIMEOUT = 250;
-    var lastSearch = this.lastSearch;
-    var now = Date.now();
-    if (lastSearch && (now - lastSearch) < SEARCH_TIMEOUT) {
-      if (!this.searchTimer) {
-        this.searchTimer = setTimeout(function resumeSearch() {
-            PDFView.search();
-          },
-          SEARCH_TIMEOUT - (now - lastSearch)
-        );
-      }
-      return;
-    }
-    this.searchTimer = null;
-    this.lastSearch = now;
-
-    function bindLink(link, pageNumber) {
-      link.href = '#' + pageNumber;
-      link.onclick = function searchBindLink() {
-        PDFView.page = pageNumber;
-        return false;
-      };
-    }
-
-    var searchResults = document.getElementById('searchResults');
-
-    var searchTermsInput = document.getElementById('searchTermsInput');
-    searchResults.removeAttribute('hidden');
-    searchResults.textContent = '';
-
-    var terms = searchTermsInput.value;
-
-    if (!terms)
-      return;
-
-    // simple search: removing spaces and hyphens, then scanning every
-    terms = terms.replace(/\s-/g, '').toLowerCase();
-    var index = PDFView.pageText;
-    var pageFound = false;
-    for (var i = 0, ii = index.length; i < ii; i++) {
-      var pageText = index[i].replace(/\s-/g, '').toLowerCase();
-      var j = pageText.indexOf(terms);
-      if (j < 0)
-        continue;
-
-      var pageNumber = i + 1;
-      var textSample = index[i].substr(j, 50);
-      var link = document.createElement('a');
-      bindLink(link, pageNumber);
-      link.textContent = 'Page ' + pageNumber + ': ' + textSample;
-      searchResults.appendChild(link);
-
-      pageFound = true;
-    }
-    if (!pageFound) {
-      searchResults.textContent = '';
-      var noResults = document.createElement('div');
-      noResults.classList.add('noResults');
-      noResults.textContent = mozL10n.get('search_terms_not_found', null,
-                                              '(Not found)');
-      searchResults.appendChild(noResults);
-    }
-  },
-
   setHash: function pdfViewSetHash(hash) {
     if (!hash)
       return;
 
     if (hash.indexOf('=') >= 0) {
       var params = PDFView.parseQueryString(hash);
       // borrowing syntax from "Parameters for Opening PDF Files"
       if ('nameddest' in params) {
@@ -994,80 +1359,42 @@ var PDFView = {
       this.page = hash;
     else // named destination
       PDFView.navigateTo(unescape(hash));
   },
 
   switchSidebarView: function pdfViewSwitchSidebarView(view) {
     var thumbsView = document.getElementById('thumbnailView');
     var outlineView = document.getElementById('outlineView');
-    var searchView = document.getElementById('searchView');
 
     var thumbsButton = document.getElementById('viewThumbnail');
     var outlineButton = document.getElementById('viewOutline');
-    var searchButton = document.getElementById('viewSearch');
 
     switch (view) {
       case 'thumbs':
         thumbsButton.classList.add('toggled');
         outlineButton.classList.remove('toggled');
-        searchButton.classList.remove('toggled');
         thumbsView.classList.remove('hidden');
         outlineView.classList.add('hidden');
-        searchView.classList.add('hidden');
 
         PDFView.renderHighestPriority();
         break;
 
       case 'outline':
         thumbsButton.classList.remove('toggled');
         outlineButton.classList.add('toggled');
-        searchButton.classList.remove('toggled');
         thumbsView.classList.add('hidden');
         outlineView.classList.remove('hidden');
-        searchView.classList.add('hidden');
 
         if (outlineButton.getAttribute('disabled'))
           return;
         break;
-
-      case 'search':
-        thumbsButton.classList.remove('toggled');
-        outlineButton.classList.remove('toggled');
-        searchButton.classList.add('toggled');
-        thumbsView.classList.add('hidden');
-        outlineView.classList.add('hidden');
-        searchView.classList.remove('hidden');
-
-        var searchTermsInput = document.getElementById('searchTermsInput');
-        searchTermsInput.focus();
-        // Start text extraction as soon as the search gets displayed.
-        this.extractText();
-        break;
     }
   },
 
-  extractText: function() {
-    if (this.startedTextExtraction)
-      return;
-    this.startedTextExtraction = true;
-    var self = this;
-    function extractPageText(pageIndex) {
-      self.pages[pageIndex].pdfPage.getTextContent().then(
-        function textContentResolved(textContent) {
-          self.pageText[pageIndex] = textContent.join('');
-          self.search();
-          if ((pageIndex + 1) < self.pages.length)
-            extractPageText(pageIndex + 1);
-        }
-      );
-    }
-    extractPageText(0);
-  },
-
   getVisiblePages: function pdfViewGetVisiblePages() {
     return this.getVisibleElements(this.container,
                                    this.pages, true);
   },
 
   getVisibleThumbs: function pdfViewGetVisibleThumbs() {
     return this.getVisibleElements(this.thumbnailContainer,
                                    this.thumbnails);
@@ -1188,23 +1515,51 @@ var PDFView = {
     this.previousScale = this.currentScaleValue;
     this.parseScale('page-fit', true);
 
     // Wait for fullscreen to take effect
     setTimeout(function() {
       currentPage.scrollIntoView();
     }, 0);
 
+    this.showPresentationControls();
     return true;
   },
 
   exitFullscreen: function pdfViewExitFullscreen() {
     this.isFullscreen = false;
     this.parseScale(this.previousScale);
     this.page = this.page;
+    this.clearMouseScrollState();
+    this.hidePresentationControls();
+  },
+
+  showPresentationControls: function pdfViewShowPresentationControls() {
+    var DELAY_BEFORE_HIDING_CONTROLS = 3000;
+    var wrapper = document.getElementById('viewerContainer');
+    if (this.presentationControlsTimeout) {
+      clearTimeout(this.presentationControlsTimeout);
+    } else {
+      wrapper.classList.add('presentationControls');
+    }
+    this.presentationControlsTimeout = setTimeout(function hideControls() {
+      wrapper.classList.remove('presentationControls');
+      delete PDFView.presentationControlsTimeout;
+    }, DELAY_BEFORE_HIDING_CONTROLS);
+  },
+
+  hidePresentationControls: function pdfViewShowPresentationControls() {
+    if (!this.presentationControlsTimeout) {
+      return;
+    }
+    clearTimeout(this.presentationControlsTimeout);
+    delete this.presentationControlsTimeout;
+
+    var wrapper = document.getElementById('viewerContainer');
+    wrapper.classList.remove('presentationControls');
   },
 
   rotatePages: function pdfViewPageRotation(delta) {
 
     this.pageRotation = (this.pageRotation + 360 + delta) % 360;
 
     for (var i = 0, l = this.pages.length; i < l; i++) {
       var page = this.pages[i];
@@ -1221,41 +1576,107 @@ var PDFView = {
     this.parseScale(this.currentScaleValue, true);
 
     this.renderHighestPriority();
 
     // Wait for fullscreen to take effect
     setTimeout(function() {
       currentPage.scrollIntoView();
     }, 0);
+  },
+
+  /**
+   * This function flips the page in presentation mode if the user scrolls up
+   * or down with large enough motion and prevents page flipping too often.
+   *
+   * @this {PDFView}
+   * @param {number} mouseScrollDelta The delta value from the mouse event.
+   */
+  mouseScroll: function pdfViewMouseScroll(mouseScrollDelta) {
+    var MOUSE_SCROLL_COOLDOWN_TIME = 50;
+
+    var currentTime = (new Date()).getTime();
+    var storedTime = this.mouseScrollTimeStamp;
+
+    // In case one page has already been flipped there is a cooldown time
+    // which has to expire before next page can be scrolled on to.
+    if (currentTime > storedTime &&
+        currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME)
+      return;
+
+    // In case the user decides to scroll to the opposite direction than before
+    // clear the accumulated delta.
+    if ((this.mouseScrollDelta > 0 && mouseScrollDelta < 0) ||
+        (this.mouseScrollDelta < 0 && mouseScrollDelta > 0))
+      this.clearMouseScrollState();
+
+    this.mouseScrollDelta += mouseScrollDelta;
+
+    var PAGE_FLIP_THRESHOLD = 120;
+    if (Math.abs(this.mouseScrollDelta) >= PAGE_FLIP_THRESHOLD) {
+
+      var PageFlipDirection = {
+        UP: -1,
+        DOWN: 1
+      };
+
+      // In fullscreen mode scroll one page at a time.
+      var pageFlipDirection = (this.mouseScrollDelta > 0) ?
+                                PageFlipDirection.UP :
+                                PageFlipDirection.DOWN;
+      this.clearMouseScrollState();
+      var currentPage = this.page;
+
+      // In case we are already on the first or the last page there is no need
+      // to do anything.
+      if ((currentPage == 1 && pageFlipDirection == PageFlipDirection.UP) ||
+          (currentPage == this.pages.length &&
+           pageFlipDirection == PageFlipDirection.DOWN))
+        return;
+
+      this.page += pageFlipDirection;
+      this.mouseScrollTimeStamp = currentTime;
+    }
+  },
+
+  /**
+   * This function clears the member attributes used with mouse scrolling in
+   * presentation mode.
+   *
+   * @this {PDFView}
+   */
+  clearMouseScrollState: function pdfViewClearMouseScrollState() {
+    this.mouseScrollTimeStamp = 0;
+    this.mouseScrollDelta = 0;
   }
 };
 
 var PageView = function pageView(container, pdfPage, id, scale,
                                  stats, navigateTo) {
   this.id = id;
   this.pdfPage = pdfPage;
 
   this.rotation = 0;
   this.scale = scale || 1.0;
   this.viewport = this.pdfPage.getViewport(this.scale, this.pdfPage.rotate);
 
   this.renderingState = RenderingStates.INITIAL;
   this.resume = null;
 
   this.textContent = null;
+  this.textLayer = null;
 
   var anchor = document.createElement('a');
   anchor.name = '' + this.id;
 
   var div = this.el = document.createElement('div');
   div.id = 'pageContainer' + this.id;
   div.className = 'page';
-  div.style.width = this.viewport.width + 'px';
-  div.style.height = this.viewport.height + 'px';
+  div.style.width = Math.floor(this.viewport.width) + 'px';
+  div.style.height = Math.floor(this.viewport.height) + 'px';
 
   container.appendChild(anchor);
   container.appendChild(div);
 
   this.destroy = function pageViewDestroy() {
     this.update();
     this.pdfPage.destroy();
   };
@@ -1269,18 +1690,18 @@ var PageView = function pageView(contain
     }
 
     this.scale = scale || this.scale;
 
     var totalRotation = (this.rotation + this.pdfPage.rotate) % 360;
     var viewport = this.pdfPage.getViewport(this.scale, totalRotation);
 
     this.viewport = viewport;
-    div.style.width = viewport.width + 'px';
-    div.style.height = viewport.height + 'px';
+    div.style.width = Math.floor(viewport.width) + 'px';
+    div.style.height = Math.floor(viewport.height) + 'px';
 
     while (div.hasChildNodes())
       div.removeChild(div.lastChild);
     div.removeAttribute('data-loaded');
 
     delete this.canvas;
 
     this.loadingIconDiv = document.createElement('div');
@@ -1483,21 +1904,22 @@ var PageView = function pageView(contain
     this.canvas = canvas;
 
     var textLayerDiv = null;
     if (!PDFJS.disableTextLayer) {
       textLayerDiv = document.createElement('div');
       textLayerDiv.className = 'textLayer';
       div.appendChild(textLayerDiv);
     }
-    var textLayer = textLayerDiv ? new TextLayerBuilder(textLayerDiv) : null;
+    var textLayer = this.textLayer =
+          textLayerDiv ? new TextLayerBuilder(textLayerDiv, this.id - 1) : null;
 
     var scale = this.scale, viewport = this.viewport;
-    canvas.width = viewport.width;
-    canvas.height = viewport.height;
+    canvas.width = Math.floor(viewport.width);
+    canvas.height = Math.floor(viewport.height);
 
     var ctx = canvas.getContext('2d');
     ctx.save();
     ctx.fillStyle = 'rgb(255, 255, 255)';
     ctx.fillRect(0, 0, canvas.width, canvas.height);
     ctx.restore();
 
     // Rendering area
@@ -1842,60 +2264,70 @@ var CustomStyle = (function CustomStyleC
     var prop = this.getProp(propName);
     if (prop != 'undefined')
       element.style[prop] = str;
   };
 
   return CustomStyle;
 })();
 
-var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
+var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) {
   var textLayerFrag = document.createDocumentFragment();
+
   this.textLayerDiv = textLayerDiv;
   this.layoutDone = false;
   this.divContentDone = false;
+  this.pageIdx = pageIdx;
+  this.matches = [];
 
   this.beginLayout = function textLayerBuilderBeginLayout() {
     this.textDivs = [];
     this.textLayerQueue = [];
+    this.renderingDone = false;
   };
 
   this.endLayout = function textLayerBuilderEndLayout() {
     this.layoutDone = true;
     this.insertDivContent();
-  },
+  };
 
   this.renderLayer = function textLayerBuilderRenderLayer() {
     var self = this;
     var textDivs = this.textDivs;
     var textLayerDiv = this.textLayerDiv;
     var canvas = document.createElement('canvas');
     var ctx = canvas.getContext('2d');
 
     // No point in rendering so many divs as it'd make the browser unusable
     // even after the divs are rendered
-    if (textDivs.length > 100000)
+    var MAX_TEXT_DIVS_TO_RENDER = 100000;
+    if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER)
       return;
 
-    while (textDivs.length > 0) {
-      var textDiv = textDivs.shift();
+    for (var i = 0, ii = textDivs.length; i < ii; i++) {
+      var textDiv = textDivs[i];
       textLayerFrag.appendChild(textDiv);
 
       ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
       var width = ctx.measureText(textDiv.textContent).width;
 
       if (width > 0) {
         var textScale = textDiv.dataset.canvasWidth / width;
 
         CustomStyle.setProp('transform' , textDiv,
           'scale(' + textScale + ', 1)');
         CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
+
+        textLayerDiv.appendChild(textDiv);
       }
     }
 
+    this.renderingDone = true;
+    this.updateMatches();
+
     textLayerDiv.appendChild(textLayerFrag);
   };
 
   this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() {
     // Schedule renderLayout() if user has been scrolling, otherwise
     // run it right away
     var kRenderDelay = 200; // in ms
     var self = this;
@@ -1907,27 +2339,26 @@ var TextLayerBuilder = function textLaye
       if (this.renderTimer)
         clearTimeout(this.renderTimer);
       this.renderTimer = setTimeout(function() {
         self.setupRenderLayoutTimer();
       }, kRenderDelay);
     }
   };
 
-  this.appendText = function textLayerBuilderAppendText(fontName, fontSize,
-                                                        geom) {
+  this.appendText = function textLayerBuilderAppendText(geom) {
     var textDiv = document.createElement('div');
 
     // vScale and hScale already contain the scaling to pixel units
-    var fontHeight = fontSize * geom.vScale;
+    var fontHeight = geom.fontSize * geom.vScale;
     textDiv.dataset.canvasWidth = geom.canvasWidth * geom.hScale;
-    textDiv.dataset.fontName = fontName;
+    textDiv.dataset.fontName = geom.fontName;
 
     textDiv.style.fontSize = fontHeight + 'px';
-    textDiv.style.fontFamily = fontName;
+    textDiv.style.fontFamily = geom.fontFamily;
     textDiv.style.left = geom.x + 'px';
     textDiv.style.top = (geom.y - fontHeight) + 'px';
 
     // The content of the div is set in the `setTextContent` function.
 
     this.textDivs.push(textDiv);
   };
 
@@ -1952,16 +2383,211 @@ var TextLayerBuilder = function textLaye
 
     this.setupRenderLayoutTimer();
   };
 
   this.setTextContent = function textLayerBuilderSetTextContent(textContent) {
     this.textContent = textContent;
     this.insertDivContent();
   };
+
+  this.convertMatches = function textLayerBuilderConvertMatches(matches) {
+    var i = 0;
+    var iIndex = 0;
+    var bidiTexts = this.textContent.bidiTexts;
+    var end = bidiTexts.length - 1;
+    var queryLen = PDFFindController.state.query.length;
+
+    var lastDivIdx = -1;
+    var pos;
+
+    var ret = [];
+
+    // Loop over all the matches.
+    for (var m = 0; m < matches.length; m++) {
+      var matchIdx = matches[m];
+      // # Calculate the begin position.
+
+      // Loop over the divIdxs.
+      while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
+        iIndex += bidiTexts[i].str.length;
+        i++;
+      }
+
+      // TODO: Do proper handling here if something goes wrong.
+      if (i == bidiTexts.length) {
+        console.error('Could not find matching mapping');
+      }
+
+      var match = {
+        begin: {
+          divIdx: i,
+          offset: matchIdx - iIndex
+        }
+      };
+
+      // # Calculate the end position.
+      matchIdx += queryLen;
+
+      // Somewhat same array as above, but use a > instead of >= to get the end
+      // position right.
+      while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
+        iIndex += bidiTexts[i].str.length;
+        i++;
+      }
+
+      match.end = {
+        divIdx: i,
+        offset: matchIdx - iIndex
+      };
+      ret.push(match);
+    }
+
+    return ret;
+  };
+
+  this.renderMatches = function textLayerBuilder_renderMatches(matches) {
+    // Early exit if there is nothing to render.
+    if (matches.length === 0) {
+      return;
+    }
+
+    var bidiTexts = this.textContent.bidiTexts;
+    var textDivs = this.textDivs;
+    var prevEnd = null;
+    var isSelectedPage = this.pageIdx === PDFFindController.selected.pageIdx;
+    var selectedMatchIdx = PDFFindController.selected.matchIdx;
+    var highlightAll = PDFFindController.state.highlightAll;
+
+    var infty = {
+      divIdx: -1,
+      offset: undefined
+    };
+
+    function beginText(begin, className) {
+      var divIdx = begin.divIdx;
+      var div = textDivs[divIdx];
+      div.innerHTML = '';
+
+      var content = bidiTexts[divIdx].str.substring(0, begin.offset);
+      var node = document.createTextNode(content);
+      if (className) {
+        var isSelected = isSelectedPage &&
+                          divIdx === selectedMatchIdx;
+        var span = document.createElement('span');
+        span.className = className + (isSelected ? ' selected' : '');
+        span.appendChild(node);
+        div.appendChild(span);
+        return;
+      }
+      div.appendChild(node);
+    }
+
+    function appendText(from, to, className) {
+      var divIdx = from.divIdx;
+      var div = textDivs[divIdx];
+
+      var content = bidiTexts[divIdx].str.substring(from.offset, to.offset);
+      var node = document.createTextNode(content);
+      if (className) {
+        var span = document.createElement('span');
+        span.className = className;
+        span.appendChild(node);
+        div.appendChild(span);
+        return;
+      }
+      div.appendChild(node);
+    }
+
+    function highlightDiv(divIdx, className) {
+      textDivs[divIdx].className = className;
+    }
+
+    var i0 = selectedMatchIdx, i1 = i0 + 1, i;
+
+    if (highlightAll) {
+      i0 = 0;
+      i1 = matches.length;
+    } else if (!isSelectedPage) {
+      // Not highlighting all and this isn't the selected page, so do nothing.
+      return;
+    }
+
+    for (i = i0; i < i1; i++) {
+      var match = matches[i];
+      var begin = match.begin;
+      var end = match.end;
+
+      var isSelected = isSelectedPage && i === selectedMatchIdx;
+      var highlightSuffix = (isSelected ? ' selected' : '');
+      if (isSelected)
+        scrollIntoView(textDivs[begin.divIdx], {top: -50});
+
+      // Match inside new div.
+      if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
+        // If there was a previous div, then add the text at the end
+        if (prevEnd !== null) {
+          appendText(prevEnd, infty);
+        }
+        // clears the divs and set the content until the begin point.
+        beginText(begin);
+      } else {
+        appendText(prevEnd, begin);
+      }
+
+      if (begin.divIdx === end.divIdx) {
+        appendText(begin, end, 'highlight' + highlightSuffix);
+      } else {
+        appendText(begin, infty, 'highlight begin' + highlightSuffix);
+        for (var n = begin.divIdx + 1; n < end.divIdx; n++) {
+          highlightDiv(n, 'highlight middle' + highlightSuffix);
+        }
+        beginText(end, 'highlight end' + highlightSuffix);
+      }
+      prevEnd = end;
+    }
+
+    if (prevEnd) {
+      appendText(prevEnd, infty);
+    }
+  };
+
+  this.updateMatches = function textLayerUpdateMatches() {
+    // Only show matches, once all rendering is done.
+    if (!this.renderingDone)
+      return;
+
+    // Clear out all matches.
+    var matches = this.matches;
+    var textDivs = this.textDivs;
+    var bidiTexts = this.textContent.bidiTexts;
+    var clearedUntilDivIdx = -1;
+
+    // Clear out all current matches.
+    for (var i = 0; i < matches.length; i++) {
+      var match = matches[i];
+      var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
+      for (var n = begin; n <= match.end.divIdx; n++) {
+        var div = textDivs[n];
+        div.textContent = bidiTexts[n].str;
+        div.className = '';
+      }
+      clearedUntilDivIdx = match.end.divIdx + 1;
+    }
+
+    if (!PDFFindController.active)
+      return;
+
+    // Convert the matches on the page controller into the match format used
+    // for the textLayer.
+    this.matches = matches =
+      this.convertMatches(PDFFindController.pageMatches[this.pageIdx] || []);
+
+    this.renderMatches(this.matches);
+  };
 };
 
 document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
   PDFView.initialize();
   var params = PDFView.parseQueryString(document.location.search.substring(1));
 
   var file = window.location.toString()
 
@@ -1992,28 +2618,28 @@ document.addEventListener('DOMContentLoa
   if ('pdfBug' in hashParams && FirefoxCom.requestSync('pdfBugEnabled')) {
     PDFJS.pdfBug = true;
     var pdfBug = hashParams['pdfBug'];
     var enabled = pdfBug.split(',');
     PDFBug.enable(enabled);
     PDFBug.init();
   }
 
-  if (FirefoxCom.requestSync('searchEnabled')) {
-    document.querySelector('#viewSearch').classList.remove('hidden');
-  }
-
   if (!PDFView.supportsPrinting) {
     document.getElementById('print').classList.add('hidden');
   }
 
   if (!PDFView.supportsFullscreen) {
     document.getElementById('fullscreen').classList.add('hidden');
   }
 
+  if (PDFView.supportsIntegratedFind) {
+    document.querySelector('#viewFind').classList.add('hidden');
+  }
+
   // Listen for warnings to trigger the fallback UI.  Errors should be caught
   // and call PDFView.error() so we don't need to listen for those.
   PDFJS.LogManager.addLogger({
     warn: function() {
       PDFView.fallback();
     }
   });
 
@@ -2042,26 +2668,16 @@ document.addEventListener('DOMContentLoa
       PDFView.switchSidebarView('thumbs');
     });
 
   document.getElementById('viewOutline').addEventListener('click',
     function() {
       PDFView.switchSidebarView('outline');
     });
 
-  document.getElementById('viewSearch').addEventListener('click',
-    function() {
-      PDFView.switchSidebarView('search');
-    });
-
-  document.getElementById('searchButton').addEventListener('click',
-    function() {
-      PDFView.search();
-    });
-
   document.getElementById('previous').addEventListener('click',
     function() {
       PDFView.page--;
     });
 
   document.getElementById('next').addEventListener('click',
     function() {
       PDFView.page++;
@@ -2092,58 +2708,64 @@ document.addEventListener('DOMContentLoa
       window.print();
     });
 
   document.getElementById('download').addEventListener('click',
     function() {
       PDFView.download();
     });
 
-  document.getElementById('searchTermsInput').addEventListener('keydown',
-    function(event) {
-      if (event.keyCode == 13) {
-        PDFView.search();
-      }
-    });
-
   document.getElementById('pageNumber').addEventListener('change',
     function() {
       PDFView.page = this.value;
     });
 
   document.getElementById('scaleSelect').addEventListener('change',
     function() {
       PDFView.parseScale(this.value);
     });
 
+  document.getElementById('first_page').addEventListener('click',
+    function() {
+      PDFView.page = 1;
+    });
+
+  document.getElementById('last_page').addEventListener('click',
+    function() {
+      PDFView.page = PDFView.pdfDocument.numPages;
+    });
+
   document.getElementById('page_rotate_ccw').addEventListener('click',
-      function() {
-        PDFView.rotatePages(-90);
-      });
+    function() {
+      PDFView.rotatePages(-90);
+    });
 
   document.getElementById('page_rotate_cw').addEventListener('click',
-      function() {
-        PDFView.rotatePages(90);
-      });
+    function() {
+      PDFView.rotatePages(90);
+    });
 
   if (FirefoxCom.requestSync('getLoadingType') == 'passive') {
     PDFView.setTitleUsingUrl(file);
     PDFView.initPassiveLoading();
     return;
   }
 
   PDFView.open(file, 0);
 }, true);
 
 function updateViewarea() {
 
   if (!PDFView.initialized)
     return;
   var visible = PDFView.getVisiblePages();
   var visiblePages = visible.views;
+  if (visiblePages.length === 0) {
+    return;
+  }
 
   PDFView.renderHighestPriority();
 
   var currentId = PDFView.page;
   var firstPage = visible.first;
 
   for (var i = 0, ii = visiblePages.length, stillFullyVisible = false;
        i < ii; ++i) {
@@ -2177,21 +2799,23 @@ function updateViewarea() {
   var pdfOpenParams = '#page=' + pageNumber;
   pdfOpenParams += '&zoom=' + normalizedScaleValue;
   var currentPage = PDFView.pages[pageNumber - 1];
   var topLeft = currentPage.getPagePoint(PDFView.container.scrollLeft,
     (PDFView.container.scrollTop - firstPage.y));
   pdfOpenParams += ',' + Math.round(topLeft[0]) + ',' + Math.round(topLeft[1]);
 
   var store = PDFView.store;
-  store.set('exists', true);
-  store.set('page', pageNumber);
-  store.set('zoom', normalizedScaleValue);
-  store.set('scrollLeft', Math.round(topLeft[0]));
-  store.set('scrollTop', Math.round(topLeft[1]));
+  store.initializedPromise.then(function() {
+    store.set('exists', true);
+    store.set('page', pageNumber);
+    store.set('zoom', normalizedScaleValue);
+    store.set('scrollLeft', Math.round(topLeft[0]));
+    store.set('scrollTop', Math.round(topLeft[1]));
+  });
   var href = PDFView.getAnchorUrl(pdfOpenParams);
   document.getElementById('viewBookmark').href = href;
 }
 
 window.addEventListener('resize', function webViewerResize(evt) {
   if (PDFView.initialized &&
       (document.getElementById('pageWidthOption').selected ||
       document.getElementById('pageFitOption').selected ||
@@ -2296,30 +2920,54 @@ window.addEventListener('pagechange', fu
 window.addEventListener('DOMMouseScroll', function(evt) {
   if (evt.ctrlKey) {
     evt.preventDefault();
 
     var ticks = evt.detail;
     var direction = (ticks > 0) ? 'zoomOut' : 'zoomIn';
     for (var i = 0, length = Math.abs(ticks); i < length; i++)
       PDFView[direction]();
+  } else if (PDFView.isFullscreen) {
+    var FIREFOX_DELTA_FACTOR = -40;
+    PDFView.mouseScroll(evt.detail * FIREFOX_DELTA_FACTOR);
+  }
+}, false);
+
+window.addEventListener('mousemove', function keydown(evt) {
+  if (PDFView.isFullscreen) {
+    PDFView.showPresentationControls();
+  }
+}, false);
+
+window.addEventListener('mousedown', function mousedown(evt) {
+  if (PDFView.isFullscreen && evt.button === 0) {
+    // Mouse click in fullmode advances a page
+    evt.preventDefault();
+
+    PDFView.page++;
   }
 }, false);
 
 window.addEventListener('keydown', function keydown(evt) {
   var handled = false;
   var cmd = (evt.ctrlKey ? 1 : 0) |
             (evt.altKey ? 2 : 0) |
             (evt.shiftKey ? 4 : 0) |
             (evt.metaKey ? 8 : 0);
 
   // First, handle the key bindings that are independent whether an input
   // control is selected or not.
   if (cmd == 1 || cmd == 8) { // either CTRL or META key.
     switch (evt.keyCode) {
+      case 70:
+        if (!PDFView.supportsIntegratedFind) {
+          PDFFindBar.toggle();
+          handled = true;
+        }
+        break;
       case 61: // FF/Mac '='
       case 107: // FF '+' and '='
       case 187: // Chrome '+'
         PDFView.zoomIn();
         handled = true;
         break;
       case 173: // FF/Mac '-'
       case 109: // FF '-'
@@ -2329,51 +2977,85 @@ window.addEventListener('keydown', funct
         break;
       case 48: // '0'
         PDFView.parseScale(kDefaultScale, true);
         handled = true;
         break;
     }
   }
 
+  // CTRL or META with or without SHIFT.
+  if (cmd == 1 || cmd == 8 || cmd == 5 || cmd == 12) {
+    switch (evt.keyCode) {
+      case 71: // g
+        if (!PDFView.supportsIntegratedFind) {
+          PDFFindBar.dispatchEvent('again', cmd == 5 || cmd == 12);
+          handled = true;
+        }
+        break;
+    }
+  }
+
   if (handled) {
     evt.preventDefault();
     return;
   }
 
   // Some shortcuts should not get handled if a control/input element
   // is selected.
   var curElement = document.activeElement;
-  if (curElement && curElement.tagName == 'INPUT')
+  if (curElement && (curElement.tagName == 'INPUT' ||
+                     curElement.tagName == 'SELECT')) {
     return;
-  var controlsElement = document.getElementById('controls');
+  }
+  var controlsElement = document.getElementById('toolbar');
   while (curElement) {
     if (curElement === controlsElement && !PDFView.isFullscreen)
-      return; // ignoring if the 'controls' element is focused
+      return; // ignoring if the 'toolbar' element is focused
     curElement = curElement.parentNode;
   }
 
   if (cmd == 0) { // no control key pressed at all.
     switch (evt.keyCode) {
+      case 38: // up arrow
+      case 33: // pg up
+      case 8: // backspace
+        if (!PDFView.isFullscreen) {
+          break;
+        }
+        //  in fullscreen mode falls throw here
       case 37: // left arrow
       case 75: // 'k'
       case 80: // 'p'
         PDFView.page--;
         handled = true;
         break;
+      case 40: // down arrow
+      case 34: // pg down
+      case 32: // spacebar
+        if (!PDFView.isFullscreen) {
+          break;
+        }
+        //  in fullscreen mode falls throw here
       case 39: // right arrow
       case 74: // 'j'
       case 78: // 'n'
         PDFView.page++;
         handled = true;
         break;
 
-      case 32: // spacebar
+      case 36: // home
         if (PDFView.isFullscreen) {
-          PDFView.page++;
+          PDFView.page = 1;
+          handled = true;
+        }
+        break;
+      case 35: // end
+        if (PDFView.isFullscreen) {
+          PDFView.page = PDFView.pdfDocument.numPages;
           handled = true;
         }
         break;
 
       case 82: // 'r'
         PDFView.rotatePages(90);
         break;
     }
@@ -2384,16 +3066,17 @@ window.addEventListener('keydown', funct
       case 82: // 'r'
         PDFView.rotatePages(-90);
         break;
     }
   }
 
   if (handled) {
     evt.preventDefault();
+    PDFView.clearMouseScrollState();
   }
 });
 
 window.addEventListener('beforeprint', function beforePrint(evt) {
   PDFView.beforePrint();
 });
 
 window.addEventListener('afterprint', function afterPrint(evt) {
--- a/browser/extensions/pdfjs/extension-files
+++ b/browser/extensions/pdfjs/extension-files
@@ -1,16 +1,21 @@
 chrome.manifest
 components/PdfStreamConverter.js
 content/PdfJs.jsm
 content/web/debugger.js
 content/web/images/annotation-check.svg
 content/web/images/annotation-comment.svg
 content/web/images/annotation-text.svg
+content/web/images/findbarButton-next-rtl.png
+content/web/images/findbarButton-next.png
+content/web/images/findbarButton-previous-rtl.png
+content/web/images/findbarButton-previous.png
 content/web/images/loading-icon.gif
+content/web/images/loading-small.png
 content/web/images/texture.png
 content/web/images/toolbarButton-bookmark.png
 content/web/images/toolbarButton-download.png
 content/web/images/toolbarButton-fullscreen.png
 content/web/images/toolbarButton-menuArrows.png
 content/web/images/toolbarButton-openFile.png
 content/web/images/toolbarButton-pageDown-rtl.png
 content/web/images/toolbarButton-pageDown.png
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -719,31 +719,30 @@ Function CheckExistingInstall
       StrCpy $TmpVal "FoundMessageWindow"
       ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_INSTALL)"
       StrCpy $TmpVal "true"
     ${EndIf}
   ${EndIf}
 FunctionEnd
 
 Function LaunchApp
+  ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
+
   ClearErrors
   ${GetParameters} $0
   ${GetOptions} "$0" "/UAC:" $1
   ${If} ${Errors}
-    ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
     Exec "$\"$INSTDIR\${FileMainEXE}$\""
   ${Else}
     GetFunctionAddress $0 LaunchAppFromElevatedProcess
     UAC::ExecCodeSegment $0
   ${EndIf}
 FunctionEnd
 
 Function LaunchAppFromElevatedProcess
-  ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
-
   ; Find the installation directory when launching using GetFunctionAddress
   ; from an elevated installer since $INSTDIR will not be set in this installer
   ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
   ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
   ${GetPathFromString} "$0" $0
   ${GetParent} "$0" $1
   ; Set our current working directory to the application's install directory
   ; otherwise the 7-Zip temp directory will be in use and won't be deleted.
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -326,16 +326,17 @@ Function .onGUIEnd
 FunctionEnd
 
 Function .onUserAbort
   ${NSD_KillTimer} StartDownload
   ${NSD_KillTimer} OnDownload
   ${NSD_KillTimer} StartInstall
   ${NSD_KillTimer} CheckInstall
   ${NSD_KillTimer} FinishInstall
+  ${NSD_KillTimer} DisplayDownloadError
 
   Delete "$PLUGINSDIR\download.exe"
   Delete "$PLUGINSDIR\${CONFIG_INI}"
 FunctionEnd
 
 Function createDummy
 FunctionEnd
 
@@ -922,22 +923,18 @@ Function OnDownload
         Pop $0
         CertCheck::VerifyCertNameIssuer "$PLUGINSDIR\download.exe" \
                                         "${CertNameDownload}" "${CertIssuerDownload}"
         Pop $1
       ${EndIf}
 
       ${If} $0 == 0
       ${OrIf} $1 == 0
-        MessageBox MB_OKCANCEL|MB_ICONSTOP "$(ERROR_DOWNLOAD)" IDCANCEL +2 IDOK 0
-        ExecShell "open" "${URLManualDownload}"
-        ; The following will exit the installer
-        SetAutoClose true
-        StrCpy $R9 2
-        Call RelativeGotoPage
+        ; Use a timer so the UI has a chance to update
+        ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS}
         Return
       ${EndIf}
 
       ; Instead of extracting the files we use the downloaded installer to
       ; install in case it needs to perform operations that the stub doesn't
       ; know about.
       WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "InstallDirectoryPath" "$INSTDIR"
       ; Don't create the QuickLaunch or Taskbar shortcut from the launched installer
@@ -1015,22 +1012,18 @@ Function StartInstall
 FunctionEnd
 
 Function CheckInstall
   IntOp $InstallCounterStep $InstallCounterStep + 1
   ${If} $InstallCounterStep >= ${InstallProgresSteps} 
     ${NSD_KillTimer} CheckInstall
     ; Close the handle that prevents modification of the full installer
     System::Call 'kernel32::CloseHandle(i $HandleDownload)'
-    MessageBox MB_OKCANCEL|MB_ICONSTOP "$(ERROR_DOWNLOAD)" IDCANCEL +2 IDOK 0
-    ExecShell "open" "${URLManualDownload}"
-    ; The following will exit the installer
-    SetAutoClose true
-    StrCpy $R9 2
-    Call RelativeGotoPage
+    ; Use a timer so the UI has a chance to update
+    ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS}
     Return
   ${EndIf}
 
   SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
 
   ${If} ${FileExists} "$INSTDIR\install.log"
     Delete "$INSTDIR\install.tmp"
     CopyFiles /SILENT "$INSTDIR\install.log" "$INSTDIR\install.tmp"
@@ -1331,10 +1324,37 @@ Function LaunchAppFromElevatedProcess
   ; Find the installation directory when launching using GetFunctionAddress
   ; from an elevated installer since $INSTDIR will not be set in this installer
   ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
   ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
   ${GetPathFromString} "$0" $0
   Exec "$\"$0$\""
 FunctionEnd
 
+Function DisplayDownloadError
+  ${NSD_KillTimer} DisplayDownloadError
+  StrCpy $R9 "false"
+  MessageBox MB_OKCANCEL|MB_ICONSTOP "$(ERROR_DOWNLOAD)" IDCANCEL +2 IDOK 0
+  StrCpy $R9 "true"
+
+  ${If} "$R9" == "true"
+    ClearErrors
+    ${GetParameters} $0
+    ${GetOptions} "$0" "/UAC:" $1
+    ${If} ${Errors}
+      Call OpenManualDownloadURL
+    ${Else}
+      GetFunctionAddress $0 OpenManualDownloadURL
+      UAC::ExecCodeSegment $0
+    ${EndIf}
+  ${EndIf}
+
+  SetAutoClose true
+  StrCpy $R9 2
+  Call RelativeGotoPage
+FunctionEnd
+
+Function OpenManualDownloadURL
+  ExecShell "open" "${URLManualDownload}"
+FunctionEnd
+
 Section
 SectionEnd
--- a/browser/installer/windows/nsis/uninstaller.nsi
+++ b/browser/installer/windows/nsis/uninstaller.nsi
@@ -246,16 +246,17 @@ Section "Uninstall"
     Sleep 5000
     ${DeleteFile} "$INSTDIR\${FileMainEXE}"
     ClearErrors
   ${EndIf}
 
   ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Field 3" "State"
   ${If} "$0" == "1"
     ${un.DeleteRelativeProfiles} "Mozilla\Firefox"
+    ${un.DeleteRelativeProfiles} "Mozilla\MetroFirefox"
     RmDir "$APPDATA\Mozilla\Extensions\{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
     RmDir "$APPDATA\Mozilla\Extensions"
     RmDir "$APPDATA\Mozilla"
   ${EndIf}
 
   ; setup the application model id registration value
   ${un.InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs"
 
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
@@ -78,12 +78,8 @@ scratchpad.noargs=Scratchpad was created
 
 # LOCALIZATION NOTE  (notification.browserContext): This is the message displayed
 # over the top of the editor when the user has switched to browser context.
 browserContext.notification=This scratchpad executes in the Browser context.
 
 # LOCALIZATION NOTE (help.openDocumentationPage): This returns a localized link with
 # documentation for Scratchpad on MDN.
 help.openDocumentationPage=https://developer.mozilla.org/en/Tools/Scratchpad
-
-# LOCALIZATION NOTE (fileExists.notification): This is the message displayed
-# over the top of the the editor when a file does not exist.
-fileNoLongerExists.notification=This file no longer exists.
--- a/browser/locales/en-US/pdfviewer/chrome.properties
+++ b/browser/locales/en-US/pdfviewer/chrome.properties
@@ -1,8 +1,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/.
-
 # Chrome notification bar messages and buttons
 unsupported_feature=This PDF document might not be displayed correctly.
 open_with_different_viewer=Open With Different Viewer
 open_with_different_viewer.accessKey=o
--- a/browser/locales/en-US/pdfviewer/viewer.properties
+++ b/browser/locales/en-US/pdfviewer/viewer.properties
@@ -1,12 +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/.
-
 # Main toolbar buttons (tooltips and alt text for images)
 previous.title=Previous Page
 previous_label=Previous
 next.title=Next Page
 next_label=Next
 
 # LOCALIZATION NOTE (page_label, page_of):
 # These strings are concatenated to form the "Page: X of Y" string.
@@ -35,37 +31,47 @@ bookmark_label=Current View
 # (the _label strings are alt text for the buttons, the .title strings are
 # tooltips)
 toggle_slider.title=Toggle Slider
 toggle_slider_label=Toggle Slider
 outline.title=Show Document Outline
 outline_label=Document Outline
 thumbs.title=Show Thumbnails
 thumbs_label=Thumbnails
-search_panel.title=Search Document
-search_panel_label=Search
+findbar.title=Find in Document
+findbar_label=Find
 
 # Document outline messages
 no_outline=No Outline Available
 
 # Thumbnails panel item (tooltip and alt text for images)
 # LOCALIZATION NOTE (thumb_page_title): "{{page}}" will be replaced by the page
 # number.
 thumb_page_title=Page {{page}}
 # LOCALIZATION NOTE (thumb_page_canvas): "{{page}}" will be replaced by the page
 # number.
 thumb_page_canvas=Thumbnail of Page {{page}}
 
 # Context menu
+first_page.label=Go to First Page
+last_page.label=Go to Last Page
 page_rotate_cw.label=Rotate Clockwise
-page_rotate_ccw.label=Rotate Counter-Clockwise
+page_rotate_ccw.label=Rotate Counterclockwise
 
-# Search panel button title and messages
-search=Find
-search_terms_not_found=(Not found)
+# Find panel button title and messages
+find_label=Find:
+find_previous.title=Find the previous occurrence of the phrase
+find_previous_label=Previous
+find_next.title=Find the next occurrence of the phrase
+find_next_label=Next
+find_highlight=Highlight all
+find_match_case_label=Match case
+find_wrapped_to_bottom=Reached end of page, continued from bottom
+find_wrapped_to_top=Reached end of page, continued from top
+find_not_found=Phrase not found
 
 # Error panel labels
 error_more_info=More Information
 error_less_info=Less Information
 error_close=Close
 # LOCALIZATION NOTE (error_build): "{{build}}" will be replaced by the PDF.JS
 # build ID.
 error_build=PDF.JS Build: {{build}}
--- a/browser/themes/gnomestripe/downloads/downloads.css
+++ b/browser/themes/gnomestripe/downloads/downloads.css
@@ -28,16 +28,20 @@
   border-top: 1px solid ThreeDShadow;
   background-image: -moz-linear-gradient(hsla(0,0%,0%,.15), hsla(0,0%,0%,.08) 6px);
 }
 
 #downloadsHistory > .button-box {
   margin: 1em;
 }
 
+#downloadsHistory:-moz-focusring > .button-box {
+  outline: 1px -moz-dialogtext dotted;
+}
+
 /*** List items ***/
 
 richlistitem[type="download"] {
   height: 6em;
   margin: 0;
   border-top: 1px solid hsla(0,0%,100%,.2);
   border-bottom: 1px solid hsla(0,0%,0%,.15);
   background: transparent;
@@ -50,17 +54,17 @@ richlistitem[type="download"]:first-chil
   border-top: 1px solid transparent;
 }
 
 richlistitem[type="download"]:last-child {
   border-bottom: 1px solid transparent;
 }
 
 #downloadsListBox:-moz-focusring > richlistitem[type="download"][selected] {
-  outline: 1px #999 dotted;
+  outline: 1px -moz-dialogtext dotted;
   outline-offset: -1px;
   -moz-outline-radius: 3px;
 }
 
 .downloadTypeIcon {
   -moz-margin-end: 8px;
   /* Prevent flickering when changing states. */
   min-height: 32px;
@@ -93,16 +97,19 @@ richlistitem[type="download"]:last-child
   padding: 5px;
   list-style-image: url("chrome://browser/skin/downloads/buttons.png");
 }
 
 .downloadButton > .button-box {
   padding: 0;
 }
 
+.downloadButton:-moz-focusring > .button-box {
+  outline: 1px -moz-dialogtext dotted;
+}
 /*** Highlighted list items ***/
 
 richlistitem[type="download"][state="1"]:hover {
   border-radius: 3px;
   border-top: 1px solid hsla(0,0%,100%,.3);
   border-bottom: 1px solid hsla(0,0%,0%,.2);
   background-color: Highlight;
   background-image: -moz-linear-gradient(hsla(0,0%,100%,.1), hsla(0,0%,100%,0));
@@ -169,21 +176,16 @@ richlistitem[type="download"][state="1"]
 
 /*** Main indicator icon ***/
 
 #downloads-indicator-icon {
   background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
                               0, 16, 16, 0) center no-repeat;
 }
 
-#downloads-indicator-icon:-moz-lwtheme-brighttext {
-  background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
-                              0, 16, 16, 0) center no-repeat;
-}
-
 #downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
   background: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
                               16, 32, 32, 16) center no-repeat;
 }
 
 #downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
   background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
                               0, 16, 16, 0) center no-repeat;
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -4106,17 +4106,16 @@ html|*#gcli-output-frame {
   margin: 4px;
   -moz-margin-start: 0;
 }
 
 .social-panel > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
 }
 
-#social-notification-box,
 .social-panel-frame {
   border-radius: inherit;
 }
 
 /* === end of social toolbar provider menu === */
 
 .chat-status-icon {
   max-height: 16px;
old mode 100755
new mode 100644
index ce6ab03484051df84b7f9ed159cc74fbc442905b..2cd8cfe03726fe640373d5c1883ab0915cf5606b
GIT binary patch
literal 2091
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
V&ytIeV<-Rs002ovPDHLkV1f_x080P>
--- a/browser/themes/pinstripe/downloads/downloads.css
+++ b/browser/themes/pinstripe/downloads/downloads.css
@@ -38,16 +38,17 @@
 }
 
 #downloadsHistory > .button-box {
   color: #808080;
   margin: 1em;
 }
 
 #downloadsHistory:-moz-focusring > .button-box {
+  outline: 1px -moz-dialogtext dotted;
   border-top-left-radius: 6px;
   border-top-right-radius: 6px;
 }
 
 #downloadsPanel:not([hasdownloads]) > #downloadsHistory:-moz-focusring > .button-box {
   border-bottom-left-radius: 6px;
   border-bottom-right-radius: 6px;
 }
@@ -69,17 +70,17 @@ richlistitem[type="download"]:first-chil
   border-top: 1px solid transparent;
 }
 
 richlistitem[type="download"]:last-child {
   border-bottom: 1px solid transparent;
 }
 
 #downloadsListBox:-moz-focusring > richlistitem[type="download"][selected] {
-  outline: 1px #999 dotted;
+  outline: 1px -moz-dialogtext dotted;
   outline-offset: -1px;
   -moz-outline-radius: 3px;
 }
 
 .downloadTypeIcon {
   -moz-margin-end: 8px;
   /* Prevent flickering when changing states. */
   min-height: 32px;
@@ -111,16 +112,20 @@ richlistitem[type="download"]:last-child
   padding: 5px;
   list-style-image: url("chrome://browser/skin/downloads/buttons.png");
 }
 
 .downloadButton > .button-box {
   padding: 0;
 }
 
+.downloadButton:-moz-focusring > .button-box {
+  outline: 1px -moz-dialogtext dotted;
+}
+
 /*** Highlighted list items ***/
 
 richlistitem[type="download"][state="1"]:hover {
   border-radius: 3px;
   border-top: 1px solid hsla(0,0%,100%,.2);
   border-bottom: 1px solid hsla(0,0%,0%,.4);
   background-color: Highlight;
   background-image: -moz-linear-gradient(hsl(210,100%,50%), hsl(210,96%,41%));
@@ -128,46 +133,36 @@ richlistitem[type="download"][state="1"]
   cursor: pointer;
 }
 
 /*** Button icons ***/
 
 .downloadButton.downloadCancel {
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
-.downloadButton.downloadCancel:hover {
-  -moz-image-region: rect(0px, 32px, 16px, 16px);
-}
-.downloadButton.downloadCancel:active {
-  -moz-image-region: rect(0px, 48px, 16px, 28px);
-}
 
 .downloadButton.downloadShow {
   -moz-image-region: rect(16px, 16px, 32px, 0px);
 }
-.downloadButton.downloadShow:hover {
+richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow {
   -moz-image-region: rect(16px, 32px, 32px, 16px);
 }
-.downloadButton.downloadShow:active {
+richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:hover {
   -moz-image-region: rect(16px, 48px, 32px, 32px);
 }
+richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:active {
+  -moz-image-region: rect(16px, 64px, 32px, 48px);
+}
 
 .downloadButton.downloadRetry {
   -moz-image-region: rect(32px, 16px, 48px, 0px);
 }
-.downloadButton.downloadRetry:hover {
-  -moz-image-region: rect(32px, 32px, 48px, 16px);
-}
-.downloadButton.downloadRetry:active {
-  -moz-image-region: rect(32px, 48px, 48px, 32px);
-}
 
 /*** Status and progress indicator ***/
 
-#downloads-button,
 #downloads-indicator {
   width: 35px;
 }
 
 #downloads-indicator-anchor {
   min-width: 20px;
   min-height: 20px;
   /* Makes the outermost stack element positioned, so that its contents are
@@ -178,21 +173,16 @@ richlistitem[type="download"][state="1"]
 
 /*** Main indicator icon ***/
 
 #downloads-indicator-icon {
   background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
                               0, 140, 20, 120) center no-repeat;
 }
 
-#downloads-indicator-icon:-moz-lwtheme-brighttext {
-  background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
-                              0, 140, 20, 120) center no-repeat;
-}
-
 #downloads-indicator[attention]
 #downloads-indicator-icon {
   background: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
                               14, 34, 34, 14) center no-repeat;
 }
 
 #downloads-indicator:not([counter])
 #downloads-indicator-counter {
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -3390,17 +3390,16 @@ html|*#gcli-output-frame {
 #social-statusarea-user[_moz-menuactive] > vbox > #social-statusarea-username {
   text-decoration: underline;
 }
 
 .social-panel > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
 }
 
-#social-notification-box,
 .social-panel-frame {
   border-radius: inherit;
 }
 
 .chat-status-icon {
   max-height: 16px;
   max-width: 16px;
   padding: 0;
--- a/browser/themes/winstripe/downloads/downloads.css
+++ b/browser/themes/winstripe/downloads/downloads.css
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*** Panel and outer controls ***/
 
 %ifndef WINSTRIPE_AERO
 #downloadsHistory,
 #downloadsHistory:-moz-focusring > .button-box {
+  outline: 1px -moz-dialogtext dotted;
   border-bottom-left-radius: 6px;
   border-bottom-right-radius: 6px;
 }
 
 #downloadsPanel:not([hasdownloads]) > #downloadsHistory,
 #downloadsPanel:not([hasdownloads]) > #downloadsHistory:-moz-focusring > .button-box  {
   border-top-left-radius: 6px;
   border-top-right-radius: 6px;
@@ -64,17 +65,17 @@ richlistitem[type="download"]:first-chil
 
 @media (-moz-windows-default-theme) {
   richlistitem[type="download"]:last-child {
     border-bottom: 1px solid transparent;
   }
 }
 
 #downloadsListBox:-moz-focusring > richlistitem[type="download"][selected] {
-  outline: 1px #999 dotted;
+  outline: 1px -moz-dialogtext dotted;
   outline-offset: -1px;
   -moz-outline-radius: 3px;
 }
 
 .downloadTypeIcon {
   -moz-margin-end: 8px;
   /* Prevent flickering when changing states. */
   min-height: 32px;
@@ -106,16 +107,20 @@ richlistitem[type="download"]:first-chil
   padding: 5px;
   list-style-image: url("chrome://browser/skin/downloads/buttons.png");
 }
 
 .downloadButton > .button-box {
   padding: 0;
 }
 
+.downloadButton:-moz-focusring > .button-box {
+  outline: 1px -moz-dialogtext dotted;
+}
+
 /*** Highlighted list items ***/
 
 richlistitem[type="download"][state="1"]:hover {
   border-radius: 3px;