Merge m-c to Ionmonkey.
authorSean Stangl <sstangl@mozilla.com>
Tue, 05 Jun 2012 16:54:36 -0700
changeset 109872 adcd5d3c984efef3688189b11c6ec6276ad014c8
parent 109871 2062cc1c4b06ae78177df0a437f5a93d08a128b0 (current diff)
parent 98538 cf4face654512947c57af2ffabbf7ca220c20b37 (diff)
child 109873 ff28f1696c5a7f0da295c6ab92820d6e2342bab9
push id2248
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 19:23:44 +0000
treeherdermozilla-aurora@118a3b748323 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone16.0a1
Merge m-c to Ionmonkey.
accessible/src/base/Makefile.in
accessible/src/base/nsAccessibilityService.cpp
accessible/src/base/nsBaseWidgetAccessible.cpp
accessible/src/base/nsBaseWidgetAccessible.h
accessible/src/generic/Accessible.h
accessible/src/generic/BaseAccessibles.h
accessible/src/generic/FormControlAccessible.cpp
accessible/src/generic/FormControlAccessible.h
accessible/src/generic/ImageAccessible.cpp
accessible/src/generic/ImageAccessible.h
accessible/src/html/HTMLFormControlAccessible.cpp
accessible/src/html/HTMLFormControlAccessible.h
accessible/src/html/HTMLImageMapAccessible.cpp
accessible/src/html/HTMLLinkAccessible.cpp
accessible/src/html/HTMLLinkAccessible.h
accessible/src/html/nsHTMLImageMapAccessible.cpp
accessible/src/html/nsHTMLImageMapAccessible.h
accessible/src/html/nsHTMLLinkAccessible.cpp
accessible/src/html/nsHTMLLinkAccessible.h
accessible/src/xforms/nsXFormsWidgetsAccessible.cpp
accessible/src/xul/XULFormControlAccessible.cpp
accessible/src/xul/XULFormControlAccessible.h
accessible/src/xul/nsXULListboxAccessible.cpp
accessible/src/xul/nsXULListboxAccessible.h
accessible/src/xul/nsXULTreeGridAccessible.cpp
accessible/src/xul/nsXULTreeGridAccessible.h
accessible/tests/mochitest/value/test_general.html
browser/app/profile/firefox.js
browser/components/nsBrowserGlue.js
configure.in
content/base/public/nsDeprecatedOperationList.h
content/base/src/nsDOMLists.h
content/base/src/nsDOMTokenList.h
content/base/src/nsGenericElement.cpp
content/base/src/nsGkAtomList.h
content/base/src/nsWebSocket.cpp
content/base/src/nsWebSocket.h
content/base/src/nsXMLHttpRequest.h
content/base/test/Makefile.in
content/events/src/nsEventListenerManager.cpp
content/events/test/Makefile.in
content/html/content/public/nsHTMLVideoElement.h
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsHTMLAnchorElement.cpp
content/html/content/src/nsHTMLAreaElement.cpp
content/html/content/src/nsHTMLAudioElement.cpp
content/html/content/src/nsHTMLIFrameElement.cpp
content/html/content/src/nsHTMLImageElement.cpp
content/html/content/src/nsHTMLLinkElement.cpp
content/html/content/src/nsHTMLMetaElement.cpp
content/html/content/src/nsHTMLObjectElement.cpp
content/html/content/src/nsHTMLSharedObjectElement.cpp
content/html/content/src/nsHTMLSourceElement.cpp
content/html/content/src/nsHTMLVideoElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/html/document/src/nsHTMLDocument.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsGlobalWindow.cpp
dom/interfaces/html/nsIDOMHTMLDocument.idl
dom/locales/en-US/chrome/dom/dom.properties
dom/system/nsDeviceSensors.cpp
editor/libeditor/base/nsEditor.cpp
editor/libeditor/base/nsEditor.h
editor/libeditor/html/TypeInState.cpp
editor/libeditor/html/TypeInState.h
editor/libeditor/html/nsHTMLCSSUtils.cpp
editor/libeditor/html/nsHTMLCSSUtils.h
editor/libeditor/html/nsHTMLDataTransfer.cpp
editor/libeditor/html/nsHTMLEditRules.cpp
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/html/nsHTMLEditor.h
editor/libeditor/html/nsWSRunObject.cpp
editor/libeditor/html/nsWSRunObject.h
editor/libeditor/text/nsTextEditRules.cpp
editor/libeditor/text/nsTextEditRules.h
gfx/gl/GLContext.cpp
gfx/layers/d3d10/ImageLayerD3D10.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
js/src/gc/Barrier.h
js/src/gc/Marking.h
js/src/ion/Bailouts.cpp
js/src/ion/Ion.cpp
js/src/ion/IonFrameIterator-inl.h
js/src/ion/shared/Assembler-shared.h
js/src/jit-test/tests/jaeger/bug563000/trap-from-add-ool.js
js/src/js.msg
js/src/jsanalyze.cpp
js/src/jsanalyze.h
js/src/jsarray.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jsdbgapi.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsgc.cpp
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsinterpinlines.h
js/src/jsiter.cpp
js/src/jsiter.h
js/src/jsobj.cpp
js/src/jsopcode.cpp
js/src/jsopcode.h
js/src/jsopcode.tbl
js/src/jsscope.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsscriptinlines.h
js/src/jsstr.cpp
js/src/jsval.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MethodJIT.cpp
js/src/methodjit/MethodJIT.h
js/src/methodjit/MonoIC.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/methodjit/StubCalls.h
js/src/shell/js.cpp
js/src/vm/ArgumentsObject.cpp
js/src/vm/ArgumentsObject.h
js/src/vm/Debugger.cpp
js/src/vm/ScopeObject.cpp
js/src/vm/Stack-inl.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/xpconnect/src/dom_quickstubs.qsconf
js/xpconnect/wrappers/AccessCheck.cpp
js/xpconnect/wrappers/AccessCheck.h
layout/base/nsDocumentViewer.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresShell.cpp
layout/forms/nsFormControlFrame.cpp
layout/forms/nsFormControlFrame.h
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/GeckoConnectivityReceiver.java
services/sync/version.txt
toolkit/content/widgets/videocontrols.xml
toolkit/content/xul.css
toolkit/themes/pinstripe/global/media/videocontrols.css
toolkit/themes/winstripe/global/media/videocontrols.css
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/nsAppShell.cpp
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -26,17 +26,16 @@ CPPSRCS = \
   nsAccDocManager.cpp \
   nsAccessNode.cpp \
   nsARIAMap.cpp \
   nsCoreUtils.cpp \
   nsAccUtils.cpp \
   nsAccessibilityService.cpp \
   nsAccessiblePivot.cpp \
   nsAccTreeWalker.cpp \
-  nsBaseWidgetAccessible.cpp \
   nsEventShell.cpp \
   nsCaretAccessible.cpp \
   nsTextEquivUtils.cpp \
   RoleAsserts.cpp \
   StyleInfo.cpp \
   TextAttrs.cpp \
   TextUpdater.cpp \
   $(NULL)
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -10,25 +10,25 @@
 #include "ApplicationAccessibleWrap.h"
 #include "ARIAGridAccessibleWrap.h"
 #ifdef MOZ_ACCESSIBILITY_ATK
 #include "AtkSocketAccessible.h"
 #endif
 #include "DocAccessible-inl.h"
 #include "FocusManager.h"
 #include "HTMLElementAccessibles.h"
+#include "HTMLImageMapAccessible.h"
+#include "HTMLLinkAccessible.h"
 #include "HTMLListAccessible.h"
 #include "HyperTextAccessibleWrap.h"
 #include "nsAccessiblePivot.h"
 #include "nsAccUtils.h"
 #include "nsARIAMap.h"
 #include "nsIAccessibleProvider.h"
 #include "nsHTMLCanvasAccessible.h"
-#include "nsHTMLImageMapAccessible.h"
-#include "nsHTMLLinkAccessible.h"
 #include "nsHTMLSelectAccessible.h"
 #include "nsHTMLTableAccessibleWrap.h"
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
 #include "OuterDocAccessible.h"
 #include "Role.h"
 #include "RootAccessibleWrap.h"
 #include "States.h"
@@ -165,17 +165,17 @@ nsAccessibilityService::GetRootDocumentA
       }
 
       return aCanCreate ?
         GetDocAccessible(documentNode) : GetDocAccessibleFromCache(documentNode);
     }
   }
   return nsnull;
 }
- 
+
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateOuterDocAccessible(nsIContent* aContent,
                                                  nsIPresShell* aPresShell)
 {
   Accessible* accessible =
     new OuterDocAccessible(aContent, GetDocAccessible(aPresShell));
   NS_ADDREF(accessible);
   return accessible;
@@ -261,17 +261,17 @@ nsAccessibilityService::CreateHTMLImageA
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLImageMapAccessible(nsIContent* aContent,
                                                      nsIPresShell* aPresShell)
 {
   Accessible* accessible =
-    new nsHTMLImageMapAccessible(aContent, GetDocAccessible(aPresShell));
+    new HTMLImageMapAccessible(aContent, GetDocAccessible(aPresShell));
   NS_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLGroupboxAccessible(nsIContent* aContent,
                                                      nsIPresShell* aPresShell)
 {
@@ -291,18 +291,18 @@ nsAccessibilityService::CreateHTMLListbo
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLMediaAccessible(nsIContent* aContent,
                                                   nsIPresShell* aPresShell)
 {
   Accessible* accessible =
-    new nsEnumRoleAccessible(aContent, GetDocAccessible(aPresShell),
-                             roles::GROUPING);
+    new EnumRoleAccessible(aContent, GetDocAccessible(aPresShell),
+                           roles::GROUPING);
   NS_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame,
                                                         nsIContent* aContent,
                                                         nsIPresShell* aPresShell)
@@ -400,17 +400,17 @@ nsAccessibilityService::CreateHTMLTableC
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateHTMLTableRowAccessible(nsIContent* aContent,
                                                      nsIPresShell* aPresShell)
 {
   Accessible* accessible =
-    new nsEnumRoleAccessible(aContent, GetDocAccessible(aPresShell), roles::ROW);
+    new EnumRoleAccessible(aContent, GetDocAccessible(aPresShell), roles::ROW);
   NS_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreateTextLeafAccessible(nsIContent* aContent,
                                                  nsIPresShell* aPresShell)
 {
@@ -557,17 +557,17 @@ void
 nsAccessibilityService::UpdateImageMap(nsImageFrame* aImageFrame)
 {
   nsIPresShell* presShell = aImageFrame->PresContext()->PresShell();
   DocAccessible* document = GetDocAccessible(presShell);
   if (document) {
     Accessible* accessible =
       document->GetAccessible(aImageFrame->GetContent());
     if (accessible) {
-      nsHTMLImageMapAccessible* imageMap = accessible->AsImageMap();
+      HTMLImageMapAccessible* imageMap = accessible->AsImageMap();
       if (imageMap) {
         imageMap->UpdateChildAreas();
         return;
       }
 
       // If image map was initialized after we created an accessible (that'll
       // be an image accessible) then recreate it.
       RecreateAccessible(presShell, aImageFrame->GetContent());
@@ -1010,17 +1010,17 @@ nsAccessibilityService::GetOrCreateAcces
 
   bool isHTML = content->IsHTML();
   if (isHTML && content->Tag() == nsGkAtoms::map) {
     // Create hyper text accessible for HTML map if it is used to group links
     // (see http://www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass). If the HTML
     // map rect is empty then it is used for links grouping. Otherwise it should
     // be used in conjunction with HTML image element and in this case we don't
     // create any accessible for it and don't walk into it. The accessibles for
-    // HTML area (nsHTMLAreaAccessible) the map contains are attached as
+    // HTML area (HTMLAreaAccessible) the map contains are attached as
     // children of the appropriate accessible for HTML image
     // (ImageAccessible).
     if (nsLayoutUtils::GetAllInFlowRectsUnion(weakFrame,
                                               weakFrame->GetParent()).IsEmpty()) {
       if (aIsSubtreeHidden)
         *aIsSubtreeHidden = true;
 
       return nsnull;
@@ -1168,35 +1168,33 @@ nsAccessibilityService::GetOrCreateAcces
     // Elements may implement nsIAccessibleProvider via XBL. This allows them to
     // say what kind of accessible to create.
     newAcc = CreateAccessibleByType(content, docAcc);
   }
 
   if (!newAcc) {
     // Create generic accessibles for SVG and MathML nodes.
     if (content->IsSVG(nsGkAtoms::svg)) {
-      newAcc = new nsEnumRoleAccessible(content, docAcc,
-                                        roles::DIAGRAM);
+      newAcc = new EnumRoleAccessible(content, docAcc, roles::DIAGRAM);
     }
     else if (content->IsMathML(nsGkAtoms::math)) {
-      newAcc = new nsEnumRoleAccessible(content, docAcc,
-                                        roles::EQUATION);
+      newAcc = new EnumRoleAccessible(content, docAcc, roles::EQUATION);
     }
   }
 
   if (!newAcc) {
     newAcc = CreateAccessibleForDeckChild(weakFrame.GetFrame(), content,
                                           docAcc);
   }
 
   // If no accessible, see if we need to create a generic accessible because
   // of some property that makes this object interesting
-  // We don't do this for <body>, <html>, <window>, <dialog> etc. which 
+  // We don't do this for <body>, <html>, <window>, <dialog> etc. which
   // correspond to the doc accessible and will be created in any case
-  if (!newAcc && content->Tag() != nsGkAtoms::body && content->GetParent() && 
+  if (!newAcc && content->Tag() != nsGkAtoms::body && content->GetParent() &&
       ((weakFrame.GetFrame() && weakFrame.GetFrame()->IsFocusable()) ||
        (isHTML && nsCoreUtils::HasClickListener(content)) ||
        HasUniversalAriaProperty(content) || roleMapEntry ||
        HasRelatedContent(content) || nsCoreUtils::IsXLink(content))) {
     // This content is focusable or has an interesting dynamic content accessibility property.
     // If it's interesting we need it in the accessibility hierarchy so that events or
     // other accessibles can point to it, or so that it can hold a state, etc.
     if (isHTML) {
@@ -1414,18 +1412,17 @@ nsAccessibilityService::CreateAccessible
       break;
 
     }
     case nsIAccessibleProvider::XULMenuSeparator:
       accessible = new nsXULMenuSeparatorAccessible(aContent, aDoc);
       break;
 
     case nsIAccessibleProvider::XULPane:
-      accessible = new nsEnumRoleAccessible(aContent, aDoc,
-                                            roles::PANE);
+      accessible = new EnumRoleAccessible(aContent, aDoc, roles::PANE);
       break;
 
     case nsIAccessibleProvider::XULProgressMeter:
       accessible = new XULProgressMeterAccessible(aContent, aDoc);
       break;
 
     case nsIAccessibleProvider::XULStatusBar:
       accessible = new XULStatusBarAccessible(aContent, aDoc);
@@ -1621,27 +1618,27 @@ nsAccessibilityService::CreateHTMLAccess
   if (tag == nsGkAtoms::ul || tag == nsGkAtoms::ol ||
       tag == nsGkAtoms::dl) {
     Accessible* accessible = new HTMLListAccessible(aContent, aDoc);
     NS_IF_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::a) {
-    // Only some roles truly enjoy life as nsHTMLLinkAccessibles, for details
+    // Only some roles truly enjoy life as HTMLLinkAccessibles, for details
     // see closed bug 494807.
     nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent);
     if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
         roleMapEntry->role != roles::LINK) {
       Accessible* accessible = new HyperTextAccessibleWrap(aContent, aDoc);
       NS_IF_ADDREF(accessible);
       return accessible;
     }
 
-    Accessible* accessible = new nsHTMLLinkAccessible(aContent, aDoc);
+    Accessible* accessible = new HTMLLinkAccessible(aContent, aDoc);
     NS_IF_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::dt ||
       (tag == nsGkAtoms::li &&
        aFrame->GetType() != nsGkAtoms::blockFrame)) {
     // Normally for li, it is created by the list item frame (in nsBlockFrame)
@@ -1781,18 +1778,18 @@ nsAccessibilityService::CreateAccessible
 #ifdef MOZ_XUL
       if (parentContent->NodeInfo()->Equals(nsGkAtoms::tabpanels,
                                             kNameSpaceID_XUL)) {
         Accessible* accessible = new nsXULTabpanelAccessible(aContent, aDoc);
         NS_IF_ADDREF(accessible);
         return accessible;
       }
 #endif
-      Accessible* accessible = new nsEnumRoleAccessible(aContent, aDoc,
-                                                        roles::PROPERTYPAGE);
+      Accessible* accessible = new EnumRoleAccessible(aContent, aDoc,
+                                                      roles::PROPERTYPAGE);
       NS_IF_ADDREF(accessible);
       return accessible;
     }
   }
 
   return nsnull;
 }
 
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -22,23 +22,23 @@
 #include "nsRefPtrHashtable.h"
 
 class AccEvent;
 class AccGroupInfo;
 class EmbeddedObjCollector;
 class KeyBinding;
 class Accessible;
 class HyperTextAccessible;
-class nsHTMLImageMapAccessible;
 struct nsRoleMapEntry;
 class Relation;
 
 namespace mozilla {
 namespace a11y {
 
+class HTMLImageMapAccessible;
 class HTMLLIAccessible;
 class ImageAccessible;
 class TableAccessible;
 class TextLeafAccessible;
 
 /**
  * Name type flags.
  */
@@ -499,17 +499,17 @@ public:
 
   inline bool IsHTMLListItem() const { return mFlags & eHTMLListItemAccessible; }
   mozilla::a11y::HTMLLIAccessible* AsHTMLListItem();
 
   inline bool IsImage() const { return mFlags & eImageAccessible; }
   mozilla::a11y::ImageAccessible* AsImage();
 
   bool IsImageMapAccessible() const { return mFlags & eImageMapAccessible; }
-  nsHTMLImageMapAccessible* AsImageMap();
+  mozilla::a11y::HTMLImageMapAccessible* AsImageMap();
 
   inline bool IsXULTree() const { return mFlags & eXULTreeAccessible; }
   nsXULTreeAccessible* AsXULTree();
 
   inline bool IsListControl() const { return mFlags & eListControlAccessible; }
 
   inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
 
@@ -874,17 +874,17 @@ protected:
   PRUint32 mFlags;
 
   nsAutoPtr<EmbeddedObjCollector> mEmbeddedObjCollector;
   PRInt32 mIndexOfEmbeddedChild;
   friend class EmbeddedObjCollector;
 
   nsAutoPtr<AccGroupInfo> mGroupInfo;
   friend class AccGroupInfo;
-  
+
   /**
    * Non-null indicates author-supplied role; possibly state & value as well
    */
   nsRoleMapEntry* mRoleMapEntry;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(Accessible,
                               NS_ACCESSIBLE_IMPL_IID)
rename from accessible/src/base/nsBaseWidgetAccessible.cpp
rename to accessible/src/generic/BaseAccessibles.cpp
--- a/accessible/src/base/nsBaseWidgetAccessible.cpp
+++ b/accessible/src/generic/BaseAccessibles.cpp
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsBaseWidgetAccessible.h"
+#include "BaseAccessibles.h"
 
 #include "Accessible-inl.h"
 #include "HyperTextAccessibleWrap.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "Role.h"
 #include "States.h"
@@ -17,173 +17,173 @@
 #include "nsILink.h"
 #include "nsIFrame.h"
 #include "nsINameSpaceManager.h"
 #include "nsIURI.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsLeafAccessible
+// LeafAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsLeafAccessible::
-  nsLeafAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+LeafAccessible::
+  LeafAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc)
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED0(nsLeafAccessible, Accessible)
+NS_IMPL_ISUPPORTS_INHERITED0(LeafAccessible, Accessible)
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsLeafAccessible: Accessible public
+// LeafAccessible: Accessible public
 
 Accessible*
-nsLeafAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
-                               EWhichChildAtPoint aWhichChild)
+LeafAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
+                             EWhichChildAtPoint aWhichChild)
 {
   // Don't walk into leaf accessibles.
   return this;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsLeafAccessible: Accessible private
+// LeafAccessible: Accessible private
 
 void
-nsLeafAccessible::CacheChildren()
+LeafAccessible::CacheChildren()
 {
   // No children for leaf accessible.
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsLinkableAccessible
+// LinkableAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsLinkableAccessible::
-  nsLinkableAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+LinkableAccessible::
+  LinkableAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc),
   mActionAcc(nsnull),
   mIsLink(false),
   mIsOnclick(false)
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, AccessibleWrap)
+NS_IMPL_ISUPPORTS_INHERITED0(LinkableAccessible, AccessibleWrap)
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsLinkableAccessible. nsIAccessible
+// LinkableAccessible. nsIAccessible
 
 NS_IMETHODIMP
-nsLinkableAccessible::TakeFocus()
+LinkableAccessible::TakeFocus()
 {
   return mActionAcc ? mActionAcc->TakeFocus() : AccessibleWrap::TakeFocus();
 }
 
 PRUint64
-nsLinkableAccessible::NativeLinkState() const
+LinkableAccessible::NativeLinkState() const
 {
   if (mIsLink)
     return states::LINKED | (mActionAcc->LinkState() & states::TRAVERSED);
 
   return 0;
 }
 
 void
-nsLinkableAccessible::Value(nsString& aValue)
+LinkableAccessible::Value(nsString& aValue)
 {
   aValue.Truncate();
 
   Accessible::Value(aValue);
   if (!aValue.IsEmpty())
     return;
 
   if (aValue.IsEmpty() && mIsLink)
     mActionAcc->Value(aValue);
 }
 
 
 PRUint8
-nsLinkableAccessible::ActionCount()
+LinkableAccessible::ActionCount()
 {
   return (mIsOnclick || mIsLink) ? 1 : 0;
 }
 
 NS_IMETHODIMP
-nsLinkableAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+LinkableAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
 {
   aName.Truncate();
 
   // Action 0 (default action): Jump to link
-  if (aIndex == eAction_Jump) {   
+  if (aIndex == eAction_Jump) {
     if (mIsLink) {
       aName.AssignLiteral("jump");
       return NS_OK;
     }
     else if (mIsOnclick) {
       aName.AssignLiteral("click");
       return NS_OK;
     }
     return NS_ERROR_NOT_IMPLEMENTED;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
 NS_IMETHODIMP
-nsLinkableAccessible::DoAction(PRUint8 aIndex)
+LinkableAccessible::DoAction(PRUint8 aIndex)
 {
   if (aIndex != eAction_Jump)
     return NS_ERROR_INVALID_ARG;
 
   return mActionAcc ? mActionAcc->DoAction(aIndex) :
     AccessibleWrap::DoAction(aIndex);
 }
 
 KeyBinding
-nsLinkableAccessible::AccessKey() const
+LinkableAccessible::AccessKey() const
 {
   return mActionAcc ?
     mActionAcc->AccessKey() : Accessible::AccessKey();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsLinkableAccessible. nsAccessNode
+// LinkableAccessible. nsAccessNode
 
 void
-nsLinkableAccessible::Shutdown()
+LinkableAccessible::Shutdown()
 {
   mIsLink = false;
   mIsOnclick = false;
   mActionAcc = nsnull;
   AccessibleWrap::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsLinkableAccessible: HyperLinkAccessible
+// LinkableAccessible: HyperLinkAccessible
 
 already_AddRefed<nsIURI>
-nsLinkableAccessible::AnchorURIAt(PRUint32 aAnchorIndex)
+LinkableAccessible::AnchorURIAt(PRUint32 aAnchorIndex)
 {
   if (mIsLink) {
     NS_ASSERTION(mActionAcc->IsLink(),
                  "nsIAccessibleHyperLink isn't implemented.");
 
     if (mActionAcc->IsLink())
       return mActionAcc->AnchorURIAt(aAnchorIndex);
   }
 
   return nsnull;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsLinkableAccessible: Accessible protected
+// LinkableAccessible: Accessible protected
 
 void
-nsLinkableAccessible::BindToParent(Accessible* aParent,
-                                   PRUint32 aIndexInParent)
+LinkableAccessible::BindToParent(Accessible* aParent,
+                                 PRUint32 aIndexInParent)
 {
   AccessibleWrap::BindToParent(aParent, aIndexInParent);
 
   // Cache action content.
   mActionAcc = nsnull;
   mIsLink = false;
   mIsOnclick = false;
 
@@ -207,35 +207,34 @@ nsLinkableAccessible::BindToParent(Acces
       mActionAcc = walkUpAcc;
       mIsOnclick = true;
       return;
     }
   }
 }
 
 void
-nsLinkableAccessible::UnbindFromParent()
+LinkableAccessible::UnbindFromParent()
 {
   mActionAcc = nsnull;
   mIsLink = false;
   mIsOnclick = false;
 
   AccessibleWrap::UnbindFromParent();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsEnumRoleAccessible
+// EnumRoleAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsEnumRoleAccessible::
-  nsEnumRoleAccessible(nsIContent* aNode, DocAccessible* aDoc,
-                       roles::Role aRole) :
+EnumRoleAccessible::
+  EnumRoleAccessible(nsIContent* aNode, DocAccessible* aDoc, roles::Role aRole) :
   AccessibleWrap(aNode, aDoc), mRole(aRole)
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED0(nsEnumRoleAccessible, Accessible)
+NS_IMPL_ISUPPORTS_INHERITED0(EnumRoleAccessible, Accessible)
 
 role
-nsEnumRoleAccessible::NativeRole()
+EnumRoleAccessible::NativeRole()
 {
   return mRole;
 }
rename from accessible/src/base/nsBaseWidgetAccessible.h
rename to accessible/src/generic/BaseAccessibles.h
--- a/accessible/src/base/nsBaseWidgetAccessible.h
+++ b/accessible/src/generic/BaseAccessibles.h
@@ -1,34 +1,37 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef _nsBaseWidgetAccessible_H_
-#define _nsBaseWidgetAccessible_H_
+#ifndef mozilla_a11y_BaseAccessibles_h__
+#define mozilla_a11y_BaseAccessibles_h__
 
 #include "AccessibleWrap.h"
 #include "HyperTextAccessibleWrap.h"
 #include "nsIContent.h"
 
 /**
   * This file contains a number of classes that are used as base
   *  classes for the different accessibility implementations of
   *  the HTML and XUL widget sets.  --jgaunt
   */
 
-/** 
+namespace mozilla {
+namespace a11y {
+
+/**
   * Leaf version of DOM Accessible -- has no children
   */
-class nsLeafAccessible : public AccessibleWrap
+class LeafAccessible : public AccessibleWrap
 {
 public:
 
-  nsLeafAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  LeafAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // Accessible
   virtual Accessible* ChildAtPoint(PRInt32 aX, PRInt32 aY,
                                    EWhichChildAtPoint aWhichChild);
 
@@ -39,22 +42,22 @@ protected:
 };
 
 /**
  * Used for text or image accessible nodes contained by link accessibles or
  * accessibles for nodes with registered click event handler. It knows how to
  * report the state of the host link (traveled or not) and can activate (click)
  * the host accessible programmatically.
  */
-class nsLinkableAccessible : public AccessibleWrap
+class LinkableAccessible : public AccessibleWrap
 {
 public:
   enum { eAction_Jump = 0 };
 
-  nsLinkableAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  LinkableAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD TakeFocus();
 
@@ -82,26 +85,29 @@ protected:
    */
   Accessible* mActionAcc;
   bool mIsLink;
   bool mIsOnclick;
 };
 
 /**
  * A simple accessible that gets its enumerated role passed into constructor.
- */ 
-class nsEnumRoleAccessible : public AccessibleWrap
+ */
+class EnumRoleAccessible : public AccessibleWrap
 {
 public:
-  nsEnumRoleAccessible(nsIContent* aContent, DocAccessible* aDoc,
-                       mozilla::a11y::role aRole);
-  virtual ~nsEnumRoleAccessible() { }
+  EnumRoleAccessible(nsIContent* aContent, DocAccessible* aDoc, 
+                     a11y::role aRole);
+  virtual ~EnumRoleAccessible() { }
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // Accessible
-  virtual mozilla::a11y::role NativeRole();
+  virtual a11y::role NativeRole();
 
 protected:
-  mozilla::a11y::role mRole;
+  a11y::role mRole;
 };
 
-#endif  
+} // namespace a11y
+} // namespace mozilla
+
+#endif
--- a/accessible/src/generic/FormControlAccessible.cpp
+++ b/accessible/src/generic/FormControlAccessible.cpp
@@ -21,41 +21,41 @@ using namespace mozilla::a11y;
 
 template class mozilla::a11y::ProgressMeterAccessible<1>;
 template class mozilla::a11y::ProgressMeterAccessible<100>;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 template<int Max>
-NS_IMPL_ADDREF_INHERITED(ProgressMeterAccessible<Max>, nsLeafAccessible)
+NS_IMPL_ADDREF_INHERITED(ProgressMeterAccessible<Max>, LeafAccessible)
 
 template<int Max>
-NS_IMPL_RELEASE_INHERITED(ProgressMeterAccessible<Max>, nsLeafAccessible)
+NS_IMPL_RELEASE_INHERITED(ProgressMeterAccessible<Max>, LeafAccessible)
 
 template<int Max>
 NS_IMPL_QUERY_INTERFACE_INHERITED1(ProgressMeterAccessible<Max>,
-                                   nsLeafAccessible,
+                                   LeafAccessible,
                                    nsIAccessibleValue)
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible
 
 template<int Max>
 role
 ProgressMeterAccessible<Max>::NativeRole()
 {
   return roles::PROGRESSBAR;
 }
 
 template<int Max>
 PRUint64
 ProgressMeterAccessible<Max>::NativeState()
 {
-  PRUint64 state = nsLeafAccessible::NativeState();
+  PRUint64 state = LeafAccessible::NativeState();
 
   // An undetermined progressbar (i.e. without a value) has a mixed state.
   nsAutoString attrValue;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue);
 
   if (attrValue.IsEmpty())
     state |= states::MIXED;
 
@@ -74,17 +74,17 @@ ProgressMeterAccessible<Max>::IsWidget()
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibleValue
 
 template<int Max>
 void
 ProgressMeterAccessible<Max>::Value(nsString& aValue)
 {
-  nsLeafAccessible::Value(aValue);
+  LeafAccessible::Value(aValue);
   if (!aValue.IsEmpty())
     return;
 
   double maxValue = 0;
   nsresult rv = GetMaximumValue(&maxValue);
   if (NS_FAILED(rv) || maxValue == 0)
     return;
 
@@ -100,17 +100,17 @@ ProgressMeterAccessible<Max>::Value(nsSt
   aValue.AppendFloat(percentValue);
   aValue.AppendLiteral("%");
 }
 
 template<int Max>
 NS_IMETHODIMP
 ProgressMeterAccessible<Max>::GetMaximumValue(double* aMaximumValue)
 {
-  nsresult rv = nsLeafAccessible::GetMaximumValue(aMaximumValue);
+  nsresult rv = LeafAccessible::GetMaximumValue(aMaximumValue);
   if (rv != NS_OK_NO_ARIA_VALUE)
     return rv;
 
   nsAutoString value;
   if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::max, value)) {
     PRInt32 result = NS_OK;
     *aMaximumValue = value.ToDouble(&result);
     return result;
@@ -119,41 +119,41 @@ ProgressMeterAccessible<Max>::GetMaximum
   *aMaximumValue = Max;
   return NS_OK;
 }
 
 template<int Max>
 NS_IMETHODIMP
 ProgressMeterAccessible<Max>::GetMinimumValue(double* aMinimumValue)
 {
-  nsresult rv = nsLeafAccessible::GetMinimumValue(aMinimumValue);
+  nsresult rv = LeafAccessible::GetMinimumValue(aMinimumValue);
   if (rv != NS_OK_NO_ARIA_VALUE)
     return rv;
 
   *aMinimumValue = 0;
   return NS_OK;
 }
 
 template<int Max>
 NS_IMETHODIMP
 ProgressMeterAccessible<Max>::GetMinimumIncrement(double* aMinimumIncrement)
 {
-  nsresult rv = nsLeafAccessible::GetMinimumIncrement(aMinimumIncrement);
+  nsresult rv = LeafAccessible::GetMinimumIncrement(aMinimumIncrement);
   if (rv != NS_OK_NO_ARIA_VALUE)
     return rv;
 
   *aMinimumIncrement = 0;
   return NS_OK;
 }
 
 template<int Max>
 NS_IMETHODIMP
 ProgressMeterAccessible<Max>::GetCurrentValue(double* aCurrentValue)
 {
-  nsresult rv = nsLeafAccessible::GetCurrentValue(aCurrentValue);
+  nsresult rv = LeafAccessible::GetCurrentValue(aCurrentValue);
   if (rv != NS_OK_NO_ARIA_VALUE)
     return rv;
 
   nsAutoString attrValue;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue);
 
   // Return zero value if there is no attribute or its value is empty.
   if (attrValue.IsEmpty())
@@ -176,17 +176,17 @@ ProgressMeterAccessible<Max>::SetCurrent
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // RadioButtonAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 RadioButtonAccessible::
   RadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsLeafAccessible(aContent, aDoc)
+  LeafAccessible(aContent, aDoc)
 {
 }
 
 PRUint8
 RadioButtonAccessible::ActionCount()
 {
   return 1;
 }
--- a/accessible/src/generic/FormControlAccessible.h
+++ b/accessible/src/generic/FormControlAccessible.h
@@ -1,30 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_A11Y_FormControlAccessible_H_
 #define MOZILLA_A11Y_FormControlAccessible_H_
 
-#include "nsBaseWidgetAccessible.h"
+#include "BaseAccessibles.h"
 
 namespace mozilla {
 namespace a11y {
 
 /**
   * Generic class used for progress meters.
   */
 template<int Max>
-class ProgressMeterAccessible : public nsLeafAccessible
+class ProgressMeterAccessible : public LeafAccessible
 {
 public:
   ProgressMeterAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-    nsLeafAccessible(aContent, aDoc)
+    LeafAccessible(aContent, aDoc)
   {
   }
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLEVALUE
 
   // Accessible
   virtual void Value(nsString& aValue);
@@ -33,17 +33,17 @@ public:
 
   // Widgets
   virtual bool IsWidget() const;
 };
 
 /**
   * Generic class used for radio buttons.
   */
-class RadioButtonAccessible : public nsLeafAccessible
+class RadioButtonAccessible : public LeafAccessible
 {
 
 public:
   RadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 aIndex);
--- a/accessible/src/generic/ImageAccessible.cpp
+++ b/accessible/src/generic/ImageAccessible.cpp
@@ -25,34 +25,34 @@
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // ImageAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 ImageAccessible::
   ImageAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsLinkableAccessible(aContent, aDoc)
+  LinkableAccessible(aContent, aDoc)
 {
   mFlags |= eImageAccessible;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED1(ImageAccessible, Accessible,
                              nsIAccessibleImage)
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible public
 
 PRUint64
 ImageAccessible::NativeState()
 {
   // The state is a bitfield, get our inherited state, then logically OR it with
   // states::ANIMATED if this is an animated image.
 
-  PRUint64 state = nsLinkableAccessible::NativeState();
+  PRUint64 state = LinkableAccessible::NativeState();
 
   nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mContent));
   nsCOMPtr<imgIRequest> imageRequest;
 
   if (content)
     content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
                         getter_AddRefs(imageRequest));
 
@@ -99,44 +99,44 @@ ImageAccessible::NativeRole()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessible
 
 PRUint8
 ImageAccessible::ActionCount()
 {
-  PRUint8 actionCount = nsLinkableAccessible::ActionCount();
+  PRUint8 actionCount = LinkableAccessible::ActionCount();
   return HasLongDesc() ? actionCount + 1 : actionCount;
 }
 
 NS_IMETHODIMP
 ImageAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
 {
   aName.Truncate();
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   if (IsLongDescIndex(aIndex) && HasLongDesc()) {
     aName.AssignLiteral("showlongdesc"); 
     return NS_OK;
   }
-  return nsLinkableAccessible::GetActionName(aIndex, aName);
+  return LinkableAccessible::GetActionName(aIndex, aName);
 }
 
 NS_IMETHODIMP
 ImageAccessible::DoAction(PRUint8 aIndex)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   // Get the long description uri and open in a new window.
   if (!IsLongDescIndex(aIndex))
-    return nsLinkableAccessible::DoAction(aIndex);
+    return LinkableAccessible::DoAction(aIndex);
 
   nsCOMPtr<nsIURI> uri = GetLongDescURI();
   if (!uri)
     return NS_ERROR_INVALID_ARG;
 
   nsCAutoString utf8spec;
   uri->GetSpec(utf8spec);
   NS_ConvertUTF8toUTF16 spec(utf8spec);
@@ -174,17 +174,17 @@ ImageAccessible::GetImageSize(PRInt32* a
 
 // Accessible
 nsresult
 ImageAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsresult rv = nsLinkableAccessible::GetAttributesInternal(aAttributes);
+  nsresult rv = LinkableAccessible::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString src;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
   if (!src.IsEmpty())
     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::src, src);
 
   return NS_OK;
@@ -223,11 +223,11 @@ ImageAccessible::GetLongDescURI() const
   }
 
   return nsnull;
 }
 
 bool
 ImageAccessible::IsLongDescIndex(PRUint8 aIndex)
 {
-  return aIndex == nsLinkableAccessible::ActionCount();
+  return aIndex == LinkableAccessible::ActionCount();
 }
 
--- a/accessible/src/generic/ImageAccessible.h
+++ b/accessible/src/generic/ImageAccessible.h
@@ -1,30 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_ImageAccessible_h__
 #define mozilla_a11y_ImageAccessible_h__
 
-#include "nsBaseWidgetAccessible.h"
+#include "BaseAccessibles.h"
 #include "nsIAccessibleImage.h"
 
 class nsGenericHTMLElement;
 
 namespace mozilla {
 namespace a11y {
 
 /* Accessible for supporting images
  * supports:
  * - gets name, role
  * - support basic state
  */
-class ImageAccessible : public nsLinkableAccessible,
+class ImageAccessible : public LinkableAccessible,
                         public nsIAccessibleImage
 {
 public:
   ImageAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
--- a/accessible/src/generic/Makefile.in
+++ b/accessible/src/generic/Makefile.in
@@ -13,16 +13,17 @@ MODULE = accessibility
 LIBRARY_NAME = accessibility_generic_s
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS = \
   Accessible.cpp \
   ApplicationAccessible.cpp \
   ARIAGridAccessible.cpp \
+  BaseAccessibles.cpp \
   DocAccessible.cpp \
   FormControlAccessible.cpp \
   HyperTextAccessible.cpp \
   ImageAccessible.cpp \
   OuterDocAccessible.cpp \
   RootAccessible.cpp \
   TextLeafAccessible.cpp \
   $(NULL)
--- a/accessible/src/generic/TextLeafAccessible.cpp
+++ b/accessible/src/generic/TextLeafAccessible.cpp
@@ -12,17 +12,17 @@
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // TextLeafAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 TextLeafAccessible::
   TextLeafAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsLinkableAccessible(aContent, aDoc)
+  LinkableAccessible(aContent, aDoc)
 {
   mFlags |= eTextLeafAccessible;
 }
 
 TextLeafAccessible::~TextLeafAccessible()
 {
 }
 
--- a/accessible/src/generic/TextLeafAccessible.h
+++ b/accessible/src/generic/TextLeafAccessible.h
@@ -1,25 +1,25 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_TextLeafAccessible_h__
 #define mozilla_a11y_TextLeafAccessible_h__
 
-#include "nsBaseWidgetAccessible.h"
+#include "BaseAccessibles.h"
 
 namespace mozilla {
 namespace a11y {
  
 /**
  * Generic class used for text nodes.
  */
-class TextLeafAccessible : public nsLinkableAccessible
+class TextLeafAccessible : public LinkableAccessible
 {
 public:
   TextLeafAccessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~TextLeafAccessible();
 
   // Accessible
   virtual mozilla::a11y::role NativeRole();
   virtual void AppendTextTo(nsAString& aText, PRUint32 aStartOffset = 0,
--- a/accessible/src/html/HTMLElementAccessibles.h
+++ b/accessible/src/html/HTMLElementAccessibles.h
@@ -1,45 +1,45 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_HTMLElementAccessibles_h__
 #define mozilla_a11y_HTMLElementAccessibles_h__
 
+#include "BaseAccessibles.h"
 #include "nsAutoPtr.h"
-#include "nsBaseWidgetAccessible.h"
 
 namespace mozilla {
 namespace a11y {
 
 /**
  * Used for HTML hr element.
  */
-class HTMLHRAccessible : public nsLeafAccessible
+class HTMLHRAccessible : public LeafAccessible
 {
 public:
 
   HTMLHRAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-    nsLeafAccessible(aContent, aDoc) {};
+    LeafAccessible(aContent, aDoc) {};
 
   // Accessible
   virtual a11y::role NativeRole();
 };
 
 /**
  * Used for HTML br element.
  */
-class HTMLBRAccessible : public nsLeafAccessible
+class HTMLBRAccessible : public LeafAccessible
 {
 public:
 
   HTMLBRAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-    nsLeafAccessible(aContent, aDoc) {};
+    LeafAccessible(aContent, aDoc) {};
 
   // Accessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual a11y::role NativeRole();
   virtual PRUint64 NativeState();
 };
 
 /**
--- a/accessible/src/html/HTMLFormControlAccessible.cpp
+++ b/accessible/src/html/HTMLFormControlAccessible.cpp
@@ -38,17 +38,17 @@ using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLCheckboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 HTMLCheckboxAccessible::
   HTMLCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsLeafAccessible(aContent, aDoc)
+  LeafAccessible(aContent, aDoc)
 {
 }
 
 role
 HTMLCheckboxAccessible::NativeRole()
 {
   return roles::CHECKBUTTON;
 }
@@ -86,17 +86,17 @@ HTMLCheckboxAccessible::DoAction(PRUint8
 
   DoCommand();
   return NS_OK;
 }
 
 PRUint64
 HTMLCheckboxAccessible::NativeState()
 {
-  PRUint64 state = nsLeafAccessible::NativeState();
+  PRUint64 state = LeafAccessible::NativeState();
 
   state |= states::CHECKABLE;
   bool checkState = false;   // Radio buttons and check boxes can be checked or mixed
 
   nsCOMPtr<nsIDOMHTMLInputElement> htmlCheckboxElement =
     do_QueryInterface(mContent);
            
   if (htmlCheckboxElement) {
--- a/accessible/src/html/HTMLFormControlAccessible.h
+++ b/accessible/src/html/HTMLFormControlAccessible.h
@@ -15,17 +15,17 @@ namespace a11y {
 /**
  * Accessible for HTML progress element.
  */
 typedef ProgressMeterAccessible<1> HTMLProgressMeterAccessible;
 
 /**
  * Accessible for HTML input@type="checkbox".
  */
-class HTMLCheckboxAccessible : public nsLeafAccessible
+class HTMLCheckboxAccessible : public LeafAccessible
 {
 
 public:
   enum { eAction_Click = 0 };
 
   HTMLCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsIAccessible
rename from accessible/src/html/nsHTMLImageMapAccessible.cpp
rename to accessible/src/html/HTMLImageMapAccessible.cpp
--- a/accessible/src/html/nsHTMLImageMapAccessible.cpp
+++ b/accessible/src/html/HTMLImageMapAccessible.cpp
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsHTMLImageMapAccessible.h"
+#include "HTMLImageMapAccessible.h"
 
 #include "nsAccUtils.h"
 #include "nsARIAMap.h"
 #include "DocAccessible.h"
 #include "Role.h"
 
 #include "nsIDOMHTMLCollection.h"
 #include "nsIServiceManager.h"
@@ -16,71 +16,71 @@
 #include "nsIDOMHTMLAreaElement.h"
 #include "nsIFrame.h"
 #include "nsImageFrame.h"
 #include "nsImageMap.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLImageMapAccessible
+// HTMLImageMapAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsHTMLImageMapAccessible::
-  nsHTMLImageMapAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+HTMLImageMapAccessible::
+  HTMLImageMapAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   ImageAccessibleWrap(aContent, aDoc)
 {
   mFlags |= eImageMapAccessible;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLImageMapAccessible: nsISupports
+// HTMLImageMapAccessible: nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLImageMapAccessible, ImageAccessible)
+NS_IMPL_ISUPPORTS_INHERITED0(HTMLImageMapAccessible, ImageAccessible)
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLImageMapAccessible: Accessible public
+// HTMLImageMapAccessible: Accessible public
 
 role
-nsHTMLImageMapAccessible::NativeRole()
+HTMLImageMapAccessible::NativeRole()
 {
   return roles::IMAGE_MAP;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLImageMapAccessible: HyperLinkAccessible
+// HTMLImageMapAccessible: HyperLinkAccessible
 
 PRUint32
-nsHTMLImageMapAccessible::AnchorCount()
+HTMLImageMapAccessible::AnchorCount()
 {
   return ChildCount();
 }
 
 Accessible*
-nsHTMLImageMapAccessible::AnchorAt(PRUint32 aAnchorIndex)
+HTMLImageMapAccessible::AnchorAt(PRUint32 aAnchorIndex)
 {
   return GetChildAt(aAnchorIndex);
 }
 
 already_AddRefed<nsIURI>
-nsHTMLImageMapAccessible::AnchorURIAt(PRUint32 aAnchorIndex)
+HTMLImageMapAccessible::AnchorURIAt(PRUint32 aAnchorIndex)
 {
   Accessible* area = GetChildAt(aAnchorIndex);
   if (!area)
     return nsnull;
 
   nsIContent* linkContent = area->GetContent();
   return linkContent ? linkContent->GetHrefURI() : nsnull;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLImageMapAccessible: public
+// HTMLImageMapAccessible: public
 
 void
-nsHTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
+HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
 {
   nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame());
 
   // If image map is not initialized yet then we trigger one time more later.
   nsImageMap* imageMapObj = imageFrame->GetExistingImageMap();
   if (!imageMapObj)
     return;
 
@@ -103,17 +103,17 @@ nsHTMLImageMapAccessible::UpdateChildAre
 
   // Insert new areas into the tree.
   PRUint32 areaElmCount = imageMapObj->AreaCount();
   for (PRUint32 idx = 0; idx < areaElmCount; idx++) {
     nsIContent* areaContent = imageMapObj->GetAreaAt(idx);
 
     Accessible* area = mChildren.SafeElementAt(idx);
     if (!area || area->GetContent() != areaContent) {
-      nsRefPtr<Accessible> area = new nsHTMLAreaAccessible(areaContent, mDoc);
+      nsRefPtr<Accessible> area = new HTMLAreaAccessible(areaContent, mDoc);
       if (!mDoc->BindToDocument(area, aria::GetRoleMap(areaContent)))
         break;
 
       if (!InsertChildAt(idx, area)) {
         mDoc->UnbindFromDocument(area);
         break;
       }
 
@@ -130,117 +130,117 @@ nsHTMLImageMapAccessible::UpdateChildAre
     nsRefPtr<AccEvent> reorderEvent =
       new AccEvent(nsIAccessibleEvent::EVENT_REORDER, mContent,
                    eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
     mDoc->FireDelayedAccessibleEvent(reorderEvent);
   }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLImageMapAccessible: Accessible protected
+// HTMLImageMapAccessible: Accessible protected
 
 void
-nsHTMLImageMapAccessible::CacheChildren()
+HTMLImageMapAccessible::CacheChildren()
 {
   UpdateChildAreas(false);
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLAreaAccessible
+// HTMLAreaAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsHTMLAreaAccessible::
-  nsHTMLAreaAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsHTMLLinkAccessible(aContent, aDoc)
+HTMLAreaAccessible::
+  HTMLAreaAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+  HTMLLinkAccessible(aContent, aDoc)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLAreaAccessible: nsIAccessible
+// HTMLAreaAccessible: nsIAccessible
 
 nsresult
-nsHTMLAreaAccessible::GetNameInternal(nsAString & aName)
+HTMLAreaAccessible::GetNameInternal(nsAString& aName)
 {
   nsresult rv = Accessible::GetNameInternal(aName);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!aName.IsEmpty())
     return NS_OK;
 
   if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
     return GetValue(aName);
 
   return NS_OK;
 }
 
 void
-nsHTMLAreaAccessible::Description(nsString& aDescription)
+HTMLAreaAccessible::Description(nsString& aDescription)
 {
   aDescription.Truncate();
 
   // Still to do - follow IE's standard here
   nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(mContent));
   if (area)
     area->GetShape(aDescription);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLAreaAccessible: nsAccessNode public
+// HTMLAreaAccessible: nsAccessNode public
 
 bool
-nsHTMLAreaAccessible::IsPrimaryForNode() const
+HTMLAreaAccessible::IsPrimaryForNode() const
 {
   // Make HTML area DOM element not accessible. HTML image map accessible
   // manages its tree itself.
   return false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLAreaAccessible: Accessible public
+// HTMLAreaAccessible: Accessible public
 
 Accessible*
-nsHTMLAreaAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
-                                   EWhichChildAtPoint aWhichChild)
+HTMLAreaAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                 EWhichChildAtPoint aWhichChild)
 {
   // Don't walk into area accessibles.
   return this;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLImageMapAccessible: HyperLinkAccessible
+// HTMLImageMapAccessible: HyperLinkAccessible
 
 PRUint32
-nsHTMLAreaAccessible::StartOffset()
+HTMLAreaAccessible::StartOffset()
 {
   // Image map accessible is not hypertext accessible therefore
   // StartOffset/EndOffset implementations of Accessible doesn't work here.
   // We return index in parent because image map contains area links only which
   // are embedded objects.
   // XXX: image map should be a hypertext accessible.
   return IndexInParent();
 }
 
 PRUint32
-nsHTMLAreaAccessible::EndOffset()
+HTMLAreaAccessible::EndOffset()
 {
   return IndexInParent() + 1;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLAreaAccessible: Accessible protected
+// HTMLAreaAccessible: Accessible protected
 
 void
-nsHTMLAreaAccessible::CacheChildren()
+HTMLAreaAccessible::CacheChildren()
 {
   // No children for aria accessible.
 }
 
 void
-nsHTMLAreaAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame)
+HTMLAreaAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame)
 {
   nsIFrame* frame = GetFrame();
   if (!frame)
     return;
 
   nsImageFrame* imageFrame = do_QueryFrame(frame);
   nsImageMap* map = imageFrame->GetImageMap();
 
rename from accessible/src/html/nsHTMLImageMapAccessible.h
rename to accessible/src/html/HTMLImageMapAccessible.h
--- a/accessible/src/html/nsHTMLImageMapAccessible.h
+++ b/accessible/src/html/HTMLImageMapAccessible.h
@@ -1,35 +1,37 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef _nsHTMLAreaAccessible_H_
-#define _nsHTMLAreaAccessible_H_
+#ifndef mozilla_a11y_HTMLImageMapAccessible_h__
+#define mozilla_a11y_HTMLImageMapAccessible_h__
 
+#include "HTMLLinkAccessible.h"
 #include "ImageAccessibleWrap.h"
-#include "nsHTMLLinkAccessible.h"
+#include "nsIDOMHTMLMapElement.h"
 
-#include "nsIDOMHTMLMapElement.h"
+namespace mozilla {
+namespace a11y {
 
 /**
  * Used for HTML image maps.
  */
-class nsHTMLImageMapAccessible : public mozilla::a11y::ImageAccessibleWrap
+class HTMLImageMapAccessible : public ImageAccessibleWrap
 {
 public:
-  nsHTMLImageMapAccessible(nsIContent* aContent, DocAccessible* aDoc);
-  virtual ~nsHTMLImageMapAccessible() { }
+  HTMLImageMapAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  virtual ~HTMLImageMapAccessible() { }
 
   // nsISupports and cycle collector
   NS_DECL_ISUPPORTS_INHERITED
 
   // Accessible
-  virtual mozilla::a11y::role NativeRole();
+  virtual a11y::role NativeRole();
 
   // HyperLinkAccessible
   virtual PRUint32 AnchorCount();
   virtual Accessible* AnchorAt(PRUint32 aAnchorIndex);
   virtual already_AddRefed<nsIURI> AnchorURIAt(PRUint32 aAnchorIndex);
 
   /**
    * Update area children of the image map.
@@ -37,35 +39,24 @@ public:
   void UpdateChildAreas(bool aDoFireEvents = true);
 
 protected:
 
   // Accessible
   virtual void CacheChildren();
 };
 
-////////////////////////////////////////////////////////////////////////////////
-// Accessible downcasting method
-
-inline nsHTMLImageMapAccessible*
-Accessible::AsImageMap()
-{
-  return IsImageMapAccessible() ?
-    static_cast<nsHTMLImageMapAccessible*>(this) : nsnull;
-}
-
-
 /**
  * Accessible for image map areas - must be child of image.
  */
-class nsHTMLAreaAccessible : public nsHTMLLinkAccessible
+class HTMLAreaAccessible : public HTMLLinkAccessible
 {
 public:
 
-  nsHTMLAreaAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  HTMLAreaAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsAccessNode
   virtual bool IsPrimaryForNode() const;
 
   // Accessible
   virtual void Description(nsString& aDescription);
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual Accessible* ChildAtPoint(PRInt32 aX, PRInt32 aY,
@@ -77,9 +68,22 @@ public:
   virtual PRUint32 EndOffset();
 
 protected:
 
   // Accessible
   virtual void CacheChildren();
 };
 
+} // namespace a11y
+} // namespace mozilla
+
+////////////////////////////////////////////////////////////////////////////////
+// Accessible downcasting method
+
+inline mozilla::a11y::HTMLImageMapAccessible*
+Accessible::AsImageMap()
+{
+  return IsImageMapAccessible() ?
+    static_cast<mozilla::a11y::HTMLImageMapAccessible*>(this) : nsnull;
+}
+
 #endif
rename from accessible/src/html/nsHTMLLinkAccessible.cpp
rename to accessible/src/html/HTMLLinkAccessible.cpp
--- a/accessible/src/html/nsHTMLLinkAccessible.cpp
+++ b/accessible/src/html/HTMLLinkAccessible.cpp
@@ -1,119 +1,119 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsHTMLLinkAccessible.h"
+#include "HTMLLinkAccessible.h"
 
 #include "nsCoreUtils.h"
 #include "DocAccessible.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsContentUtils.h"
 #include "nsEventStates.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLLinkAccessible
+// HTMLLinkAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsHTMLLinkAccessible::
-  nsHTMLLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+HTMLLinkAccessible::
+  HTMLLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc)
 {
 }
 
 // Expose nsIAccessibleHyperLink unconditionally
-NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLLinkAccessible, HyperTextAccessibleWrap,
+NS_IMPL_ISUPPORTS_INHERITED1(HTMLLinkAccessible, HyperTextAccessibleWrap,
                              nsIAccessibleHyperLink)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessible
 
 role
-nsHTMLLinkAccessible::NativeRole()
+HTMLLinkAccessible::NativeRole()
 {
   return roles::LINK;
 }
 
 PRUint64
-nsHTMLLinkAccessible::NativeState()
+HTMLLinkAccessible::NativeState()
 {
   return HyperTextAccessibleWrap::NativeState() & ~states::READONLY;
 }
 
 PRUint64
-nsHTMLLinkAccessible::NativeLinkState() const
+HTMLLinkAccessible::NativeLinkState() const
 {
   nsEventStates eventState = mContent->AsElement()->State();
   if (eventState.HasState(NS_EVENT_STATE_UNVISITED))
     return states::LINKED;
 
   if (eventState.HasState(NS_EVENT_STATE_VISITED))
     return states::LINKED | states::TRAVERSED;
 
   // This is a either named anchor (a link with also a name attribute) or
   // it doesn't have any attributes. Check if 'click' event handler is
   // registered, otherwise bail out.
   return nsCoreUtils::HasClickListener(mContent) ? states::LINKED : 0;
 }
 
 PRUint64
-nsHTMLLinkAccessible::NativeInteractiveState() const
+HTMLLinkAccessible::NativeInteractiveState() const
 {
   PRUint64 state = HyperTextAccessibleWrap::NativeInteractiveState();
 
   // This is how we indicate it is a named anchor. In other words, this anchor
   // can be selected as a location :) There is no other better state to use to
   // indicate this.
   if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::name))
     state |= states::SELECTABLE;
 
   return state;
 }
 
 void
-nsHTMLLinkAccessible::Value(nsString& aValue)
+HTMLLinkAccessible::Value(nsString& aValue)
 {
   aValue.Truncate();
 
   HyperTextAccessible::Value(aValue);
   if (aValue.IsEmpty())
     nsContentUtils::GetLinkLocation(mContent->AsElement(), aValue);
 }
 
 PRUint8
-nsHTMLLinkAccessible::ActionCount()
+HTMLLinkAccessible::ActionCount()
 {
   return IsLinked() ? 1 : HyperTextAccessible::ActionCount();
 }
 
 NS_IMETHODIMP
-nsHTMLLinkAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+HTMLLinkAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
 {
   aName.Truncate();
 
   if (!IsLinked())
     return HyperTextAccessible::GetActionName(aIndex, aName);
 
   // Action 0 (default action): Jump to link
   if (aIndex != eAction_Jump)
     return NS_ERROR_INVALID_ARG;
 
   aName.AssignLiteral("jump");
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLLinkAccessible::DoAction(PRUint8 aIndex)
+HTMLLinkAccessible::DoAction(PRUint8 aIndex)
 {
   if (!IsLinked())
     return HyperTextAccessible::DoAction(aIndex);
 
   // Action 0 (default action): Jump to link
   if (aIndex != eAction_Jump)
     return NS_ERROR_INVALID_ARG;
 
@@ -123,33 +123,33 @@ nsHTMLLinkAccessible::DoAction(PRUint8 a
   DoCommand();
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HyperLinkAccessible
 
 bool
-nsHTMLLinkAccessible::IsLink()
+HTMLLinkAccessible::IsLink()
 {
   // Expose HyperLinkAccessible unconditionally.
   return true;
 }
 
 already_AddRefed<nsIURI>
-nsHTMLLinkAccessible::AnchorURIAt(PRUint32 aAnchorIndex)
+HTMLLinkAccessible::AnchorURIAt(PRUint32 aAnchorIndex)
 {
   return aAnchorIndex == 0 ? mContent->GetHrefURI() : nsnull;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Protected members
 
 bool
-nsHTMLLinkAccessible::IsLinked()
+HTMLLinkAccessible::IsLinked()
 {
   if (IsDefunct())
     return false;
 
   nsEventStates state = mContent->AsElement()->State();
   return state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
                                      NS_EVENT_STATE_UNVISITED);
 }
rename from accessible/src/html/nsHTMLLinkAccessible.h
rename to accessible/src/html/HTMLLinkAccessible.h
--- a/accessible/src/html/nsHTMLLinkAccessible.h
+++ b/accessible/src/html/HTMLLinkAccessible.h
@@ -1,32 +1,35 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef _nsHTMLLinkAccessible_H_
-#define _nsHTMLLinkAccessible_H_
+#ifndef mozilla_a11y_HTMLLinkAccessible_h__
+#define mozilla_a11y_HTMLLinkAccessible_h__
 
 #include "HyperTextAccessibleWrap.h"
 
-class nsHTMLLinkAccessible : public HyperTextAccessibleWrap
+namespace mozilla {
+namespace a11y {
+
+class HTMLLinkAccessible : public HyperTextAccessibleWrap
 {
 public:
-  nsHTMLLinkAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  HTMLLinkAccessible(nsIContent* aContent, DocAccessible* aDoc);
  
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 aIndex);
 
   // Accessible
   virtual void Value(nsString& aValue);
-  virtual mozilla::a11y::role NativeRole();
+  virtual a11y::role NativeRole();
   virtual PRUint64 NativeState();
   virtual PRUint64 NativeLinkState() const;
   virtual PRUint64 NativeInteractiveState() const;
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
 
   // HyperLinkAccessible
@@ -37,9 +40,12 @@ protected:
   enum { eAction_Jump = 0 };
 
   /**
    * Returns true if the link has href attribute.
    */
   bool IsLinked();
 };
 
-#endif  
+} // namespace a11y
+} // namespace mozilla
+
+#endif
--- a/accessible/src/html/HTMLListAccessible.cpp
+++ b/accessible/src/html/HTMLListAccessible.cpp
@@ -183,17 +183,17 @@ role
 HTMLListBulletAccessible::NativeRole()
 {
   return roles::STATICTEXT;
 }
 
 PRUint64
 HTMLListBulletAccessible::NativeState()
 {
-  return nsLeafAccessible::NativeState() | states::READONLY;
+  return LeafAccessible::NativeState() | states::READONLY;
 }
 
 void
 HTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
                                        PRUint32 aLength)
 {
   nsAutoString bulletText;
   nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
--- a/accessible/src/html/HTMLListAccessible.h
+++ b/accessible/src/html/HTMLListAccessible.h
@@ -2,18 +2,18 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_HTMLListAccessible_h__
 #define mozilla_a11y_HTMLListAccessible_h__
 
+#include "BaseAccessibles.h"
 #include "HyperTextAccessibleWrap.h"
-#include "nsBaseWidgetAccessible.h"
 
 namespace mozilla {
 namespace a11y {
 
 class HTMLListBulletAccessible;
 
 /**
  * Used for HTML list (like HTML ul).
@@ -67,21 +67,21 @@ protected:
 private:
   nsRefPtr<HTMLListBulletAccessible> mBullet;
 };
 
 
 /**
  * Used for bullet of HTML list item element (for example, HTML li).
  */
-class HTMLListBulletAccessible : public nsLeafAccessible
+class HTMLListBulletAccessible : public LeafAccessible
 {
 public:
   HTMLListBulletAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-    nsLeafAccessible(aContent, aDoc) { }
+    LeafAccessible(aContent, aDoc) { }
   virtual ~HTMLListBulletAccessible() { }
 
   // nsAccessNode
   virtual nsIFrame* GetFrame() const;
   virtual bool IsPrimaryForNode() const;
 
   // Accessible
   virtual ENameValueFlag Name(nsString& aName);
--- a/accessible/src/html/Makefile.in
+++ b/accessible/src/html/Makefile.in
@@ -14,20 +14,20 @@ MODULE = accessibility
 LIBRARY_NAME = accessibility_html_s
 LIBXUL_LIBRARY = 1
 
 
 
 CPPSRCS = \
   HTMLElementAccessibles.cpp \
   HTMLFormControlAccessible.cpp \
+  HTMLImageMapAccessible.cpp \
+  HTMLLinkAccessible.cpp \
   HTMLListAccessible.cpp \
   nsHTMLCanvasAccessible.cpp \
-  nsHTMLImageMapAccessible.cpp \
-  nsHTMLLinkAccessible.cpp \
   nsHTMLSelectAccessible.cpp \
   nsHTMLTableAccessible.cpp \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
--- a/accessible/src/msaa/nsHTMLWin32ObjectAccessible.cpp
+++ b/accessible/src/msaa/nsHTMLWin32ObjectAccessible.cpp
@@ -60,18 +60,18 @@ nsHTMLWin32ObjectOwnerAccessible::CacheC
     AppendChild(mNativeAccessible);
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLWin32ObjectAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-nsHTMLWin32ObjectAccessible::nsHTMLWin32ObjectAccessible(void* aHwnd):
-nsLeafAccessible(nsnull, nsnull)
+nsHTMLWin32ObjectAccessible::nsHTMLWin32ObjectAccessible(void* aHwnd) :
+  LeafAccessible(nsnull, nsnull)
 {
   // XXX: Mark it as defunct to make sure no single Accessible method is
   // running on it. We need to allow accessible without DOM nodes.
   mFlags |= eIsDefunct;
 
   mHwnd = aHwnd;
   if (mHwnd) {
     // The plugin is not windowless. In this situation we use 
--- a/accessible/src/msaa/nsHTMLWin32ObjectAccessible.h
+++ b/accessible/src/msaa/nsHTMLWin32ObjectAccessible.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsHTMLWin32ObjectAccessible_H_
 #define _nsHTMLWin32ObjectAccessible_H_
 
-#include "nsBaseWidgetAccessible.h"
+#include "BaseAccessibles.h"
 
 struct IAccessible;
 
 class nsHTMLWin32ObjectOwnerAccessible : public AccessibleWrap
 {
 public:
   // This will own the nsHTMLWin32ObjectAccessible. We create this where the
   // <object> or <embed> exists in the tree, so that get_accNextSibling() etc.
@@ -43,21 +43,21 @@ protected:
   * This class is used only internally, we never! send out an IAccessible linked
   *   back to this object. This class is used to represent a plugin object when
   *   referenced as a child or sibling of another Accessible node. We need only
   *   a limited portion of the nsIAccessible interface implemented here. The
   *   in depth accessible information will be returned by the actual IAccessible
   *   object returned by us in Accessible::NewAccessible() that gets the IAccessible
   *   from the windows system from the window handle.
   */
-class nsHTMLWin32ObjectAccessible : public nsLeafAccessible
+class nsHTMLWin32ObjectAccessible : public mozilla::a11y::LeafAccessible
 {
 public:
 
-  nsHTMLWin32ObjectAccessible(void *aHwnd);
+  nsHTMLWin32ObjectAccessible(void* aHwnd);
   virtual ~nsHTMLWin32ObjectAccessible() {}
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_IMETHOD GetNativeInterface(void** aNativeAccessible) MOZ_OVERRIDE;
 
 protected:
   void* mHwnd;
--- a/accessible/src/xforms/nsXFormsWidgetsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsWidgetsAccessible.cpp
@@ -12,17 +12,17 @@ using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXFormsDropmarkerWidgetAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXFormsDropmarkerWidgetAccessible::
   nsXFormsDropmarkerWidgetAccessible(nsIContent* aContent,
                                      DocAccessible* aDoc) :
-  nsLeafAccessible(aContent, aDoc)
+  LeafAccessible(aContent, aDoc)
 {
 }
 
 role
 nsXFormsDropmarkerWidgetAccessible::NativeRole()
 {
   return roles::PUSHBUTTON;
 }
--- a/accessible/src/xforms/nsXFormsWidgetsAccessible.h
+++ b/accessible/src/xforms/nsXFormsWidgetsAccessible.h
@@ -1,25 +1,25 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsXFormsWidgetsAccessible_H_
 #define _nsXFormsWidgetsAccessible_H_
 
+#include "BaseAccessibles.h"
 #include "nsXFormsAccessible.h"
-#include "nsBaseWidgetAccessible.h"
 
 /**
  * Accessible object for dropmarker widget that is used inside xforms elements
  * of combobox representation. For example, these are xforms:select1,
  * xforms:input[type="xsd:date"].
  */
-class nsXFormsDropmarkerWidgetAccessible : public nsLeafAccessible,
+class nsXFormsDropmarkerWidgetAccessible : public mozilla::a11y::LeafAccessible,
                                            public nsXFormsAccessibleBase
 {
 public:
   nsXFormsDropmarkerWidgetAccessible(nsIContent* aContent,
                                      DocAccessible* aDoc);
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
--- a/accessible/src/xul/XULFormControlAccessible.cpp
+++ b/accessible/src/xul/XULFormControlAccessible.cpp
@@ -234,17 +234,17 @@ XULButtonAccessible::ContainsMenu()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULDropmarkerAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULDropmarkerAccessible::
   XULDropmarkerAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsLeafAccessible(aContent, aDoc)
+  LeafAccessible(aContent, aDoc)
 {
 }
 
 PRUint8
 XULDropmarkerAccessible::ActionCount()
 {
   return 1;
 }
@@ -318,17 +318,17 @@ XULDropmarkerAccessible::NativeState()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULCheckboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULCheckboxAccessible::
   XULCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsLeafAccessible(aContent, aDoc)
+  LeafAccessible(aContent, aDoc)
 {
 }
 
 role
 XULCheckboxAccessible::NativeRole()
 {
   return roles::CHECKBUTTON;
 }
@@ -371,17 +371,17 @@ XULCheckboxAccessible::DoAction(PRUint8 
   return NS_OK;
 }
 
 PRUint64
 XULCheckboxAccessible::NativeState()
 {
   // Possible states: focused, focusable, unavailable(disabled), checked
   // Get focus and disable status from base class
-  PRUint64 state = nsLeafAccessible::NativeState();
+  PRUint64 state = LeafAccessible::NativeState();
   
   state |= states::CHECKABLE;
   
   // Determine Checked state
   nsCOMPtr<nsIDOMXULCheckboxElement> xulCheckboxElement =
     do_QueryInterface(mContent);
   if (xulCheckboxElement) {
     bool checked = false;
@@ -463,17 +463,17 @@ XULRadioButtonAccessible::
   XULRadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   RadioButtonAccessible(aContent, aDoc)
 {
 }
 
 PRUint64
 XULRadioButtonAccessible::NativeState()
 {
-  PRUint64 state = nsLeafAccessible::NativeState();
+  PRUint64 state = LeafAccessible::NativeState();
   state |= states::CHECKABLE;
 
   nsCOMPtr<nsIDOMXULSelectControlItemElement> radioButton =
     do_QueryInterface(mContent);
   if (radioButton) {
     bool selected = false;   // Radio buttons can be selected
     radioButton->GetSelected(&selected);
     if (selected) {
@@ -654,17 +654,17 @@ XULToolbarAccessible::GetNameInternal(ns
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULToolbarAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULToolbarSeparatorAccessible::
   XULToolbarSeparatorAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsLeafAccessible(aContent, aDoc)
+  LeafAccessible(aContent, aDoc)
 {
 }
 
 role
 XULToolbarSeparatorAccessible::NativeRole()
 {
   return roles::SEPARATOR;
 }
--- a/accessible/src/xul/XULFormControlAccessible.h
+++ b/accessible/src/xul/XULFormControlAccessible.h
@@ -18,17 +18,17 @@ namespace a11y {
 /**
  * Used for XUL progressmeter element.
  */
 typedef ProgressMeterAccessible<100> XULProgressMeterAccessible;
 
 /**
  * Used for XUL button.
  *
- * @note  Don't inherit from nsLeafAccessible - it doesn't allow children
+ * @note  Don't inherit from LeafAccessible - it doesn't allow children
  *         and a button can have a dropmarker child.
  */
 class XULButtonAccessible : public AccessibleWrap
 {
 public:
   enum { eAction_Click = 0 };
   XULButtonAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
@@ -60,17 +60,17 @@ protected:
   // XULButtonAccessible
   bool ContainsMenu();
 };
 
 
 /**
  * Used for XUL checkbox element.
  */
-class XULCheckboxAccessible : public nsLeafAccessible
+class XULCheckboxAccessible : public LeafAccessible
 {
 public:
   enum { eAction_Click = 0 };
   XULCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
@@ -81,17 +81,17 @@ public:
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
 };
 
 /**
  * Used for XUL dropmarker element.
  */
-class XULDropmarkerAccessible : public nsLeafAccessible
+class XULDropmarkerAccessible : public LeafAccessible
 {
 public:
   enum { eAction_Click = 0 };
   XULDropmarkerAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
@@ -195,17 +195,17 @@ public:
   // Accessible
   virtual mozilla::a11y::role NativeRole();
   virtual nsresult GetNameInternal(nsAString& aName);
 };
 
 /**
  * Used for XUL toolbarseparator element.
  */
-class XULToolbarSeparatorAccessible : public nsLeafAccessible
+class XULToolbarSeparatorAccessible : public LeafAccessible
 {
 public:
   XULToolbarSeparatorAccessible(nsIContent* aContent,
                                 DocAccessible* aDoc);
 
   // Accessible
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
--- a/accessible/src/xul/nsXULListboxAccessible.cpp
+++ b/accessible/src/xul/nsXULListboxAccessible.cpp
@@ -47,17 +47,17 @@ nsXULColumAccessible::NativeState()
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULColumnItemAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULColumnItemAccessible::
   nsXULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsLeafAccessible(aContent, aDoc)
+  LeafAccessible(aContent, aDoc)
 {
 }
 
 role
 nsXULColumnItemAccessible::NativeRole()
 {
   return roles::COLUMNHEADER;
 }
--- a/accessible/src/xul/nsXULListboxAccessible.h
+++ b/accessible/src/xul/nsXULListboxAccessible.h
@@ -1,18 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef __nsXULListboxAccessible_h__
 #define __nsXULListboxAccessible_h__
 
-#include "nsCOMPtr.h"
+#include "BaseAccessibles.h"
 #include "nsXULMenuAccessible.h"
-#include "nsBaseWidgetAccessible.h"
 #include "nsIAccessibleTable.h"
 #include "TableAccessible.h"
 #include "xpcAccessibleTable.h"
 #include "XULSelectControlAccessible.h"
 
 class nsIWeakReference;
 
 /**
@@ -28,17 +27,17 @@ public:
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
 };
 
 /**
  * nsXULColumnAccessible are accessibles for list and tree column elements
  * (xul:listcol and xul:treecol).
  */
-class nsXULColumnItemAccessible : public nsLeafAccessible
+class nsXULColumnItemAccessible : public mozilla::a11y::LeafAccessible
 {
 public:
   nsXULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 aIndex);
 
--- a/accessible/src/xul/nsXULTabAccessible.h
+++ b/accessible/src/xul/nsXULTabAccessible.h
@@ -2,17 +2,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsXULTabAccessible_H_
 #define _nsXULTabAccessible_H_
 
 // NOTE: alphabetically ordered
-#include "nsBaseWidgetAccessible.h"
 #include "nsXULMenuAccessible.h"
 #include "XULSelectControlAccessible.h"
 
 /**
  * An individual tab, xul:tab element.
  */
 class nsXULTabAccessible : public AccessibleWrap
 {
--- a/accessible/src/xul/nsXULTextAccessible.cpp
+++ b/accessible/src/xul/nsXULTextAccessible.cpp
@@ -2,18 +2,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // NOTE: groups are alphabetically ordered
 #include "nsXULTextAccessible.h"
 
 #include "Accessible-inl.h"
+#include "BaseAccessibles.h"
 #include "nsAccUtils.h"
-#include "nsBaseWidgetAccessible.h"
 #include "nsCoreUtils.h"
 #include "nsTextEquivUtils.h"
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsIAccessibleRelation.h"
 #include "nsIDOMXULDescriptionElement.h"
@@ -75,24 +75,24 @@ nsXULTextAccessible::RelationByType(PRUi
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTooltipAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTooltipAccessible::
   nsXULTooltipAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsLeafAccessible(aContent, aDoc)
+  LeafAccessible(aContent, aDoc)
 {
 }
 
 PRUint64
 nsXULTooltipAccessible::NativeState()
 {
-  return nsLeafAccessible::NativeState() | states::READONLY;
+  return LeafAccessible::NativeState() | states::READONLY;
 }
 
 role
 nsXULTooltipAccessible::NativeRole()
 {
   return roles::TOOLTIP;
 }
 
--- a/accessible/src/xul/nsXULTextAccessible.h
+++ b/accessible/src/xul/nsXULTextAccessible.h
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsXULTextAccessible_H_
 #define _nsXULTextAccessible_H_
 
+#include "BaseAccessibles.h"
 #include "HyperTextAccessibleWrap.h"
-#include "nsBaseWidgetAccessible.h"
 
 /**
  * Used for XUL description and label elements.
  */
 class nsXULTextAccessible : public HyperTextAccessibleWrap
 {
 public:
   nsXULTextAccessible(nsIContent* aContent, DocAccessible* aDoc);
@@ -22,17 +22,17 @@ public:
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
   virtual Relation RelationByType(PRUint32 aRelationType);
 };
 
 /**
  * Used for XUL tooltip element.
  */
-class nsXULTooltipAccessible : public nsLeafAccessible
+class nsXULTooltipAccessible : public mozilla::a11y::LeafAccessible
 {
 
 public:
   nsXULTooltipAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // Accessible
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -714,46 +714,46 @@ nsXULTreeGridRowAccessible::CacheChildre
 // nsXULTreeGridCellAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTreeGridCellAccessible::
   nsXULTreeGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc,
                               nsXULTreeGridRowAccessible* aRowAcc,
                               nsITreeBoxObject* aTree, nsITreeView* aTreeView,
                               PRInt32 aRow, nsITreeColumn* aColumn) :
-  nsLeafAccessible(aContent, aDoc), mTree(aTree),
+  LeafAccessible(aContent, aDoc), mTree(aTree),
   mTreeView(aTreeView), mRow(aRow), mColumn(aColumn)
 {
   mParent = aRowAcc;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible: nsISupports implementation
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeGridCellAccessible)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeGridCellAccessible,
-                                                  nsLeafAccessible)
+                                                  LeafAccessible)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTree)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mColumn)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeGridCellAccessible,
-                                                nsLeafAccessible)
+                                                LeafAccessible)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTree)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mColumn)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULTreeGridCellAccessible)
   NS_INTERFACE_TABLE_INHERITED2(nsXULTreeGridCellAccessible,
                                 nsIAccessibleTableCell,
                                 nsXULTreeGridCellAccessible)
-NS_INTERFACE_TABLE_TAIL_INHERITING(nsLeafAccessible)
-NS_IMPL_ADDREF_INHERITED(nsXULTreeGridCellAccessible, nsLeafAccessible)
-NS_IMPL_RELEASE_INHERITED(nsXULTreeGridCellAccessible, nsLeafAccessible)
+NS_INTERFACE_TABLE_TAIL_INHERITING(LeafAccessible)
+NS_IMPL_ADDREF_INHERITED(nsXULTreeGridCellAccessible, LeafAccessible)
+NS_IMPL_RELEASE_INHERITED(nsXULTreeGridCellAccessible, LeafAccessible)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible: nsIAccessible implementation
 
 Accessible*
 nsXULTreeGridCellAccessible::FocusedChild()
 {
   return nsnull;
@@ -1024,17 +1024,17 @@ nsXULTreeGridCellAccessible::IsSelected(
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible: nsAccessNode implementation
 
 bool
 nsXULTreeGridCellAccessible::Init()
 {
-  if (!nsLeafAccessible::Init() || !mTreeView)
+  if (!LeafAccessible::Init() || !mTreeView)
     return false;
 
   PRInt16 type;
   mColumn->GetType(&type);
   if (type == nsITreeColumn::TYPE_CHECKBOX)
     mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
   else
     mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
--- a/accessible/src/xul/nsXULTreeGridAccessible.h
+++ b/accessible/src/xul/nsXULTreeGridAccessible.h
@@ -99,50 +99,50 @@ protected:
 #define NS_XULTREEGRIDCELLACCESSIBLE_IMPL_CID         \
 {  /* 84588ad4-549c-4196-a932-4c5ca5de5dff */         \
   0x84588ad4,                                         \
   0x549c,                                             \
   0x4196,                                             \
   { 0xa9, 0x32, 0x4c, 0x5c, 0xa5, 0xde, 0x5d, 0xff }  \
 }
 
-class nsXULTreeGridCellAccessible : public nsLeafAccessible,
+class nsXULTreeGridCellAccessible : public mozilla::a11y::LeafAccessible,
                                     public nsIAccessibleTableCell
 {
 public:
 
   nsXULTreeGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc,
                               nsXULTreeGridRowAccessible* aRowAcc,
                               nsITreeBoxObject* aTree, nsITreeView* aTreeView,
                               PRInt32 aRow, nsITreeColumn* aColumn);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeGridCellAccessible,
-                                           nsLeafAccessible)
+                                           LeafAccessible)
 
   // nsIAccessible
 
-  NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
-                       PRInt32 *aWidth, PRInt32 *aHeight);
+  NS_IMETHOD GetBounds(PRInt32* aX, PRInt32* aY,
+                       PRInt32* aWidth, PRInt32* aHeight);
 
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 aIndex);
 
   // nsIAccessibleTableCell
   NS_DECL_NSIACCESSIBLETABLECELL
 
   // nsAccessNode
   virtual bool Init();
   virtual bool IsPrimaryForNode() const;
 
   // Accessible
   virtual mozilla::a11y::ENameValueFlag Name(nsString& aName);
   virtual Accessible* FocusedChild();
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties* aAttributes);
   virtual PRInt32 IndexInParent() const;
   virtual Relation RelationByType(PRUint32 aType);
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
   virtual PRUint64 NativeInteractiveState() const;
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
@@ -159,18 +159,18 @@ public:
    * Fire name or state change event if the accessible text or value has been
    * changed.
    */
   void CellInvalidated();
 
 protected:
   // Accessible
   virtual Accessible* GetSiblingAtOffset(PRInt32 aOffset,
-                                         nsresult *aError = nsnull) const;
-  virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
+                                         nsresult* aError = nsnull) const;
+  virtual void DispatchClickEvent(nsIContent* aContent, PRUint32 aActionIndex);
 
   // nsXULTreeGridCellAccessible
 
   /**
    * Return true if value of cell can be modified.
    */
   bool IsEditable() const;
 
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -125,17 +125,17 @@
       testStates(fileBrowseButton,
                  STATE_BUSY | STATE_UNAVAILABLE | STATE_REQUIRED | STATE_HASPOPUP | STATE_INVALID);
 
       // offscreen test
       testStates("aria_offscreen_textbox", STATE_OFFSCREEN);
 
       //
       // This section tests aria roles on links/anchors for underlying
-      // nsHTMLLinkAccessible creation. (see closed bug 494807)
+      // HTMLLinkAccessible creation. (see closed bug 494807)
       //
 
       // strong roles
       testStates("aria_menuitem_link", 0, 0, STATE_LINKED);
       testStates("aria_button_link", 0, 0, STATE_LINKED);
       testStates("aria_checkbox_link", 0, 0, STATE_LINKED);
 
       // strong landmark
--- a/accessible/tests/mochitest/value/test_general.html
+++ b/accessible/tests/mochitest/value/test_general.html
@@ -34,23 +34,23 @@
         if (!acc)
           return;
         is(acc.value, aValue, "Wrong value for " + aID + "!");
       }
 
       var rootDir = getRootDirectory(window.location.href);
       var href = getRootDirectory(window.location.href) + "foo";
 
-      // roles that can't live as nsHTMLLinkAccessibles
+      // roles that can't live as HTMLLinkAccessibles
       testValue("aria_menuitem_link", "");
       testValue("aria_button_link", "");
       testValue("aria_checkbox_link", "");
       testValue("aria_application_link", "");
 
-      // roles that can live as nsHTMLLinkAccessibles
+      // roles that can live as HTMLLinkAccessibles
       testValue("aria_link_link", href);
       testValue("aria_main_link", href);
       testValue("aria_navigation_link", href);
 
       // HTML controls
       testValue("combobox1", "item1");
       testValue("combobox2", "item2");
 
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -7,16 +7,17 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/ContactService.jsm');
+Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
 Cu.import('resource://gre/modules/Webapps.jsm');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'env',
                                    '@mozilla.org/process/environment;1',
                                    'nsIEnvironment');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'ss',
                                    '@mozilla.org/content/style-sheet-service;1',
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1155,12 +1155,24 @@ pref("full-screen-api.enabled", true);
 // approval.
 pref("full-screen-api.approval-required", true);
 
 // Startup Crash Tracking
 // number of startup crashes that can occur before starting into safe mode automatically
 // (this pref has no effect if more than 6 hours have passed since the last crash)
 pref("toolkit.startup.max_resumed_crashes", 3);
 
+// Completely disable pdf.js as an option to preview pdfs within firefox.
+// Note: if this is not disabled it does not necessarily mean pdf.js is the pdf
+// handler just that it is an option.
+pref("pdfjs.disabled", false);
+// Used by pdf.js to know the first time firefox is run with it installed so it
+// can become the default pdf viewer.
+pref("pdfjs.firstRun", true);
+// The values of preferredAction and alwaysAskBeforeHandling before pdf.js
+// became the default.
+pref("pdfjs.previousHandler.preferredAction", 0);
+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);
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -26,16 +26,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/BookmarkHTMLUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "webappsUI", 
                                   "resource:///modules/webappsUI.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
                                   "resource:///modules/PageThumbs.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "PdfJs",
+                                  "resource://pdf.js/PdfJs.jsm");
+
 const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
 const PREF_PLUGINS_UPDATEURL  = "plugins.update.url";
 
 // We try to backup bookmarks at idle times, to avoid doing that at shutdown.
 // Number of idle seconds before trying to backup bookmarks.  15 minutes.
 const BOOKMARKS_BACKUP_IDLE_TIME = 15 * 60;
 // Minimum interval in milliseconds between backups.
 const BOOKMARKS_BACKUP_INTERVAL = 86400 * 1000;
@@ -324,16 +327,18 @@ BrowserGlue.prototype = {
     // handle any UI migration
     this._migrateUI();
 
     // Initialize webapps UI
     webappsUI.init();
 
     PageThumbs.init();
 
+    PdfJs.init();
+
     Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
   },
 
   // the first browser window has finished initializing
   _onFirstWindowLoaded: function BG__onFirstWindowLoaded() {
 #ifdef XP_WIN
     // For windows seven, initialize the jump list module.
     const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
--- a/browser/components/preferences/applications.js
+++ b/browser/components/preferences/applications.js
@@ -12,20 +12,25 @@
 #ifndef XP_MACOSX
 */
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cr = Components.results;
 /*
 #endif
 */
+Components.utils.import('resource://gre/modules/Services.jsm');
 
 const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
 const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
 const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
+const TYPE_PDF = "application/pdf";
+
+const PREF_PDFJS_DISABLED = "pdfjs.disabled";
+const TOPIC_PDFJS_HANDLER_CHANGED = "pdfjs:handlerChanged";
 
 const PREF_DISABLED_PLUGIN_TYPES = "plugin.disable_full_page_plugin_for_types";
 
 // Preferences that affect which entries to show in the list.
 const PREF_SHOW_PLUGINS_IN_LIST = "browser.download.show_plugins_in_list";
 const PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS =
   "browser.download.hide_plugins_without_extensions";
 
@@ -805,16 +810,56 @@ var audioFeedHandlerInfo = {
   _prefSelectedApp: PREF_AUDIO_FEED_SELECTED_APP, 
   _prefSelectedWeb: PREF_AUDIO_FEED_SELECTED_WEB, 
   _prefSelectedAction: PREF_AUDIO_FEED_SELECTED_ACTION, 
   _prefSelectedReader: PREF_AUDIO_FEED_SELECTED_READER,
   _smallIcon: "chrome://browser/skin/feeds/audioFeedIcon16.png",
   _appPrefLabel: "audioPodcastFeed"
 }
 
+/**
+ * InternalHandlerInfoWrapper provides a basic mechanism to create an internal
+ * mime type handler that can be enabled/disabled in the applications preference
+ * menu.
+ */
+function InternalHandlerInfoWrapper(aMIMEType) {
+  var mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+  var handlerInfo = mimeSvc.getFromTypeAndExtension(aMIMEType, null);
+
+  HandlerInfoWrapper.call(this, aMIMEType, handlerInfo);
+}
+
+InternalHandlerInfoWrapper.prototype = {
+  __proto__: HandlerInfoWrapper.prototype,
+
+  // Override store so we so we can notify any code listening for registration
+  // or unregistration of this handler.
+  store: function() {
+    HandlerInfoWrapper.prototype.store.call(this);
+    Services.obs.notifyObservers(null, this._handlerChanged, null);
+  },
+
+  get enabled() {
+    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+  },
+
+  get description() {
+    return this.element("bundlePreferences").getString(this._appPrefLabel);
+  }
+};
+
+var pdfHandlerInfo = {
+  __proto__: new InternalHandlerInfoWrapper(TYPE_PDF),
+  _handlerChanged: TOPIC_PDFJS_HANDLER_CHANGED,
+  _appPrefLabel: "portableDocumentFormat",
+  get enabled() {
+    return !Services.prefs.getBoolPref(PREF_PDFJS_DISABLED);
+  },
+};
+
 
 //****************************************************************************//
 // Prefpane Controller
 
 var gApplicationsPane = {
   // The set of types the app knows how to handle.  A hash of HandlerInfoWrapper
   // objects, indexed by type.
   _handledTypes: {},
@@ -994,32 +1039,46 @@ var gApplicationsPane = {
   },
 
 
   //**************************************************************************//
   // Composed Model Construction
 
   _loadData: function() {
     this._loadFeedHandler();
+    this._loadInternalHandlers();
     this._loadPluginHandlers();
     this._loadApplicationHandlers();
   },
 
   _loadFeedHandler: function() {
     this._handledTypes[TYPE_MAYBE_FEED] = feedHandlerInfo;
     feedHandlerInfo.handledOnlyByPlugin = false;
 
     this._handledTypes[TYPE_MAYBE_VIDEO_FEED] = videoFeedHandlerInfo;
     videoFeedHandlerInfo.handledOnlyByPlugin = false;
 
     this._handledTypes[TYPE_MAYBE_AUDIO_FEED] = audioFeedHandlerInfo;
     audioFeedHandlerInfo.handledOnlyByPlugin = false;
   },
 
   /**
+   * Load higher level internal handlers so they can be turned on/off in the
+   * applications menu.
+   */
+  _loadInternalHandlers: function() {
+    var internalHandlers = [pdfHandlerInfo];
+    for (let internalHandler of internalHandlers) {
+      if (internalHandler.enabled) {
+        this._handledTypes[internalHandler.type] = internalHandler;
+      }
+    }
+  },
+
+  /**
    * Load the set of handlers defined by plugins.
    *
    * Note: if there's more than one plugin for a given MIME type, we assume
    * the last one is the one that the application will use.  That may not be
    * correct, but it's how we've been doing it for years.
    *
    * Perhaps we should instead query navigator.mimeTypes for the set of types
    * supported by the application and then get the plugin from each MIME type's
@@ -1211,19 +1270,25 @@ var gApplicationsPane = {
         if (preferredApp instanceof Ci.nsILocalHandlerApp)
           name = getFileDisplayName(preferredApp.executable);
         else
           name = preferredApp.name;
         return this._prefsBundle.getFormattedString("useApp", [name]);
 
       case Ci.nsIHandlerInfo.handleInternally:
         // For the feed type, handleInternally means live bookmarks.
-        if (isFeedType(aHandlerInfo.type)) 
+        if (isFeedType(aHandlerInfo.type)) {
           return this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
                                                       [this._brandShortName]);
+        }
+
+        if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
+          return this._prefsBundle.getFormattedString("previewInApp",
+                                                      [this._brandShortName]);
+        }
 
         // For other types, handleInternally looks like either useHelperApp
         // or useSystemDefault depending on whether or not there's a preferred
         // handler app.
         if (this.isValidHandlerApp(aHandlerInfo.preferredApplicationHandler))
           return aHandlerInfo.preferredApplicationHandler.name;
 
         return aHandlerInfo.defaultDescription;
@@ -1314,16 +1379,28 @@ var gApplicationsPane = {
     var menu =
       document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
     var menuPopup = menu.menupopup;
 
     // Clear out existing items.
     while (menuPopup.hasChildNodes())
       menuPopup.removeChild(menuPopup.lastChild);
 
+    // Add the "Preview in Firefox" option for optional internal handlers.
+    if (handlerInfo instanceof InternalHandlerInfoWrapper) {
+      var internalMenuItem = document.createElement("menuitem");
+      internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
+      let label = this._prefsBundle.getFormattedString("previewInApp",
+                                                       [this._brandShortName]);
+      internalMenuItem.setAttribute("label", label);
+      internalMenuItem.setAttribute("tooltiptext", label);
+      internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
+      menuPopup.appendChild(internalMenuItem);
+    }
+
     {
       var askMenuItem = document.createElement("menuitem");
       askMenuItem.setAttribute("alwaysAsk", "true");
       let label;
       if (isFeedType(handlerInfo.type))
         label = this._prefsBundle.getFormattedString("previewInApp",
                                                      [this._brandShortName]);
       else
@@ -1734,16 +1811,19 @@ var gApplicationsPane = {
       case Ci.nsIHandlerInfo.saveToDisk:
         aElement.setAttribute(APP_ICON_ATTR_NAME, "save");
         return true;
 
       case Ci.nsIHandlerInfo.handleInternally:
         if (isFeedType(aHandlerInfo.type)) {
           aElement.setAttribute(APP_ICON_ATTR_NAME, "feed");
           return true;
+        } else if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
+          aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
+          return true;
         }
         break;
 
       case kActionUsePlugin:
         aElement.setAttribute(APP_ICON_ATTR_NAME, "plugin");
         return true;
     }
     aElement.removeAttribute(APP_ICON_ATTR_NAME);
old mode 100644
new mode 100755
--- a/browser/components/preferences/in-content/applications.js
+++ b/browser/components/preferences/in-content/applications.js
@@ -1,18 +1,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //****************************************************************************//
 // Constants & Enumeration Values
 
+Components.utils.import('resource://gre/modules/Services.jsm');
 const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
 const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
 const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
+const TYPE_PDF = "application/pdf";
+
+const PREF_PDFJS_DISABLED = "pdfjs.disabled";
+const TOPIC_PDFJS_HANDLER_CHANGED = "pdfjs:handlerChanged";
 
 const PREF_DISABLED_PLUGIN_TYPES = "plugin.disable_full_page_plugin_for_types";
 
 // Preferences that affect which entries to show in the list.
 const PREF_SHOW_PLUGINS_IN_LIST = "browser.download.show_plugins_in_list";
 const PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS =
   "browser.download.hide_plugins_without_extensions";
 
@@ -792,16 +797,56 @@ var audioFeedHandlerInfo = {
   _prefSelectedApp: PREF_AUDIO_FEED_SELECTED_APP, 
   _prefSelectedWeb: PREF_AUDIO_FEED_SELECTED_WEB, 
   _prefSelectedAction: PREF_AUDIO_FEED_SELECTED_ACTION, 
   _prefSelectedReader: PREF_AUDIO_FEED_SELECTED_READER,
   _smallIcon: "chrome://browser/skin/feeds/audioFeedIcon16.png",
   _appPrefLabel: "audioPodcastFeed"
 }
 
+/**
+ * InternalHandlerInfoWrapper provides a basic mechanism to create an internal
+ * mime type handler that can be enabled/disabled in the applications preference
+ * menu.
+ */
+function InternalHandlerInfoWrapper(aMIMEType) {
+  var mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+  var handlerInfo = mimeSvc.getFromTypeAndExtension(aMIMEType, null);
+
+  HandlerInfoWrapper.call(this, aMIMEType, handlerInfo);
+}
+
+InternalHandlerInfoWrapper.prototype = {
+  __proto__: HandlerInfoWrapper.prototype,
+
+  // Override store so we so we can notify any code listening for registration
+  // or unregistration of this handler.
+  store: function() {
+    HandlerInfoWrapper.prototype.store.call(this);
+    Services.obs.notifyObservers(null, this._handlerChanged, null);
+  },
+
+  get enabled() {
+    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+  },
+
+  get description() {
+    return this.element("bundlePreferences").getString(this._appPrefLabel);
+  }
+};
+
+var pdfHandlerInfo = {
+  __proto__: new InternalHandlerInfoWrapper(TYPE_PDF),
+  _handlerChanged: TOPIC_PDFJS_HANDLER_CHANGED,
+  _appPrefLabel: "portableDocumentFormat",
+  get enabled() {
+    return !Services.prefs.getBoolPref(PREF_PDFJS_DISABLED);
+  },
+};
+
 
 //****************************************************************************//
 // Prefpane Controller
 
 var gApplicationsPane = {
   // The set of types the app knows how to handle.  A hash of HandlerInfoWrapper
   // objects, indexed by type.
   _handledTypes: {},
@@ -981,32 +1026,46 @@ var gApplicationsPane = {
   },
 
 
   //**************************************************************************//
   // Composed Model Construction
 
   _loadData: function() {
     this._loadFeedHandler();
+    this._loadInternalHandlers();
     this._loadPluginHandlers();
     this._loadApplicationHandlers();
   },
 
   _loadFeedHandler: function() {
     this._handledTypes[TYPE_MAYBE_FEED] = feedHandlerInfo;
     feedHandlerInfo.handledOnlyByPlugin = false;
 
     this._handledTypes[TYPE_MAYBE_VIDEO_FEED] = videoFeedHandlerInfo;
     videoFeedHandlerInfo.handledOnlyByPlugin = false;
 
     this._handledTypes[TYPE_MAYBE_AUDIO_FEED] = audioFeedHandlerInfo;
     audioFeedHandlerInfo.handledOnlyByPlugin = false;
   },
 
   /**
+   * Load higher level internal handlers so they can be turned on/off in the
+   * applications menu.
+   */
+  _loadInternalHandlers: function() {
+    var internalHandlers = [pdfHandlerInfo];
+    for (let internalHandler of internalHandlers) {
+      if (internalHandler.enabled) {
+        this._handledTypes[internalHandler.type] = internalHandler;
+      }
+    }
+  },
+
+  /**
    * Load the set of handlers defined by plugins.
    *
    * Note: if there's more than one plugin for a given MIME type, we assume
    * the last one is the one that the application will use.  That may not be
    * correct, but it's how we've been doing it for years.
    *
    * Perhaps we should instead query navigator.mimeTypes for the set of types
    * supported by the application and then get the plugin from each MIME type's
@@ -1198,19 +1257,25 @@ var gApplicationsPane = {
         if (preferredApp instanceof Ci.nsILocalHandlerApp)
           name = getFileDisplayName(preferredApp.executable);
         else
           name = preferredApp.name;
         return this._prefsBundle.getFormattedString("useApp", [name]);
 
       case Ci.nsIHandlerInfo.handleInternally:
         // For the feed type, handleInternally means live bookmarks.
-        if (isFeedType(aHandlerInfo.type)) 
+        if (isFeedType(aHandlerInfo.type)) {
           return this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
                                                       [this._brandShortName]);
+        }
+
+        if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
+          return this._prefsBundle.getFormattedString("previewInApp",
+                                                      [this._brandShortName]);
+        }
 
         // For other types, handleInternally looks like either useHelperApp
         // or useSystemDefault depending on whether or not there's a preferred
         // handler app.
         if (this.isValidHandlerApp(aHandlerInfo.preferredApplicationHandler))
           return aHandlerInfo.preferredApplicationHandler.name;
 
         return aHandlerInfo.defaultDescription;
@@ -1301,16 +1366,28 @@ var gApplicationsPane = {
     var menu =
       document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
     var menuPopup = menu.menupopup;
 
     // Clear out existing items.
     while (menuPopup.hasChildNodes())
       menuPopup.removeChild(menuPopup.lastChild);
 
+    // Add the "Preview in Firefox" option for optional internal handlers.
+    if (handlerInfo instanceof InternalHandlerInfoWrapper) {
+      var internalMenuItem = document.createElement("menuitem");
+      internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
+      let label = this._prefsBundle.getFormattedString("previewInApp",
+                                                       [this._brandShortName]);
+      internalMenuItem.setAttribute("label", label);
+      internalMenuItem.setAttribute("tooltiptext", label);
+      internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
+      menuPopup.appendChild(internalMenuItem);
+    }
+
     {
       var askMenuItem = document.createElement("menuitem");
       askMenuItem.setAttribute("alwaysAsk", "true");
       let label;
       if (isFeedType(handlerInfo.type))
         label = this._prefsBundle.getFormattedString("previewInApp",
                                                      [this._brandShortName]);
       else
@@ -1721,16 +1798,19 @@ var gApplicationsPane = {
       case Ci.nsIHandlerInfo.saveToDisk:
         aElement.setAttribute(APP_ICON_ATTR_NAME, "save");
         return true;
 
       case Ci.nsIHandlerInfo.handleInternally:
         if (isFeedType(aHandlerInfo.type)) {
           aElement.setAttribute(APP_ICON_ATTR_NAME, "feed");
           return true;
+        } else if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
+          aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
+          return true;
         }
         break;
 
       case kActionUsePlugin:
         aElement.setAttribute(APP_ICON_ATTR_NAME, "plugin");
         return true;
     }
     aElement.removeAttribute(APP_ICON_ATTR_NAME);
--- 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.3.266
+Current extension version is: 0.3.345
 
--- a/browser/extensions/pdfjs/chrome.manifest
+++ b/browser/extensions/pdfjs/chrome.manifest
@@ -1,8 +1,2 @@
 resource pdf.js content/
-component {6457a96b-2d68-439a-bcfa-44465fbcdbb1} components/PdfStreamConverter.js
-contract @mozilla.org/streamconv;1?from=application/pdf&to=*/* {6457a96b-2d68-439a-bcfa-44465fbcdbb1}
-
-# Additional resources for pdf.js
-
-# PDFJS_SUPPORTED_LOCALES
-
+resource pdf.js.components components/
--- a/browser/extensions/pdfjs/components/PdfStreamConverter.js
+++ b/browser/extensions/pdfjs/components/PdfStreamConverter.js
@@ -4,30 +4,37 @@
 'use strict';
 
 var EXPORTED_SYMBOLS = ['PdfStreamConverter'];
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 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 EXT_PREFIX = 'extensions.uriloader@pdf.js';
+const PREF_PREFIX = 'pdfjs';
 const MAX_DATABASE_LENGTH = 4096;
 const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
 const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
 
 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');
 
 if (appInfo.ID === FIREFOX_ID) {
   privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
                           .getService(Ci.nsIPrivateBrowsingService);
   inPrivateBrowsing = privateBrowsing.privateBrowsingEnabled;
 } else if (appInfo.ID === SEAMONKEY_ID) {
   privateBrowsing = null;
   inPrivateBrowsing = false;
@@ -52,29 +59,46 @@ function getStringPref(pref, def) {
   try {
     return Services.prefs.getComplexValue(pref, Ci.nsISupportsString).data;
   } catch (ex) {
     return def;
   }
 }
 
 function log(aMsg) {
-  if (!getBoolPref(EXT_PREFIX + '.pdfBugEnabled', false))
+  if (!getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false))
     return;
   let msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
   Services.console.logStringMessage(msg);
   dump(msg + '\n');
 }
 
 function getDOMWindow(aChannel) {
   var requestor = aChannel.notificationCallbacks;
   var win = requestor.getInterface(Components.interfaces.nsIDOMWindow);
   return win;
 }
 
+function isEnabled() {
+  if (MOZ_CENTRAL) {
+    var disabled = getBoolPref(PREF_PREFIX + '.disabled', false);
+    if (disabled)
+      return false;
+    // To also be considered enabled the "Preview in Firefox" option must be
+    // selected in the Application preferences.
+    var handlerInfo = Svc.mime
+                         .getFromTypeAndExtension('application/pdf', 'pdf');
+    return handlerInfo.alwaysAskBeforeHandling == false &&
+           handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally;
+  }
+  // Always returns true for the extension since enabling/disabling is handled
+  // by the add-on manager.
+  return true;
+}
+
 function getLocalizedStrings(path) {
   var stringBundle = Cc['@mozilla.org/intl/stringbundle;1'].
       getService(Ci.nsIStringBundleService).
       createBundle('chrome://pdf.js/locale/' + path);
 
   var map = {};
   var enumerator = stringBundle.getSimpleEnumeration();
   while (enumerator.hasMoreElements()) {
@@ -86,26 +110,32 @@ function getLocalizedStrings(path) {
       key = key.substring(0, i);
     }
     if (!(key in map))
       map[key] = {};
     map[key][property] = string.value;
   }
   return map;
 }
+function getLocalizedString(strings, id, property) {
+  property = property || 'textContent';
+  if (id in strings)
+    return strings[id][property];
+  return id;
+}
 
 // All the priviledged actions.
-function ChromeActions() {
+function ChromeActions(domWindow) {
+  this.domWindow = domWindow;
 }
 
 ChromeActions.prototype = {
   download: function(data) {
-    let mimeService = Cc['@mozilla.org/mime;1'].getService(Ci.nsIMIMEService);
-    var handlerInfo = mimeService.
-                        getFromTypeAndExtension('application/pdf', 'pdf');
+    var handlerInfo = Svc.mime
+                         .getFromTypeAndExtension('application/pdf', 'pdf');
     var uri = NetUtil.newURI(data);
 
     var extHelperAppSvc =
           Cc['@mozilla.org/uriloader/external-helper-app-service;1'].
             getService(Ci.nsIExternalHelperAppService);
     var frontWindow = Cc['@mozilla.org/embedcomp/window-watcher;1'].
                         getService(Ci.nsIWindowWatcher).activeWindow;
     var ioService = Services.io;
@@ -131,22 +161,22 @@ ChromeActions.prototype = {
     channel.asyncOpen(listener, null);
   },
   setDatabase: function(data) {
     if (inPrivateBrowsing)
       return;
     // Protect against something sending tons of data to setDatabase.
     if (data.length > MAX_DATABASE_LENGTH)
       return;
-    setStringPref(EXT_PREFIX + '.database', data);
+    setStringPref(PREF_PREFIX + '.database', data);
   },
   getDatabase: function() {
     if (inPrivateBrowsing)
       return '{}';
-    return getStringPref(EXT_PREFIX + '.database', '{}');
+    return getStringPref(PREF_PREFIX + '.database', '{}');
   },
   getLocale: function() {
     return getStringPref('general.useragent.locale', 'en-US');
   },
   getStrings: function(data) {
     try {
       // Lazy initialization of localizedStrings
       if (!('localizedStrings' in this))
@@ -155,21 +185,44 @@ ChromeActions.prototype = {
       var result = this.localizedStrings[data];
       return JSON.stringify(result || null);
     } catch (e) {
       log('Unable to retrive localized strings: ' + e);
       return 'null';
     }
   },
   pdfBugEnabled: function() {
-    return getBoolPref(EXT_PREFIX + '.pdfBugEnabled', false);
+    return getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false);
+  },
+  searchEnabled: function() {
+    return getBoolPref(PREF_PREFIX + '.searchEnabled', false);
+  },
+  fallback: function(url) {
+    var self = this;
+    var domWindow = this.domWindow;
+    var strings = getLocalizedStrings('chrome.properties');
+    var message = getLocalizedString(strings, 'unsupported_feature');
+
+    var win = Services.wm.getMostRecentWindow('navigator:browser');
+    var browser = win.gBrowser.getBrowserForDocument(domWindow.top.document);
+    var notificationBox = win.gBrowser.getNotificationBox(browser);
+    var buttons = [{
+      label: getLocalizedString(strings, 'open_with_different_viewer'),
+      accessKey: getLocalizedString(strings, 'open_with_different_viewer',
+                                    'accessKey'),
+      callback: function() {
+        self.download(url);
+      }
+    }];
+    notificationBox.appendNotification(message, 'pdfjs-fallback', null,
+                                       notificationBox.PRIORITY_WARNING_LOW,
+                                       buttons);
   }
 };
 
-
 // Event listener to trigger chrome privedged code.
 function RequestListener(actions) {
   this.actions = actions;
 }
 // Receive an event and synchronously responds.
 RequestListener.prototype.receive = function(event) {
   var message = event.target;
   var action = message.getUserData('action');
@@ -185,17 +238,17 @@ RequestListener.prototype.receive = func
 
 
 function PdfStreamConverter() {
 }
 
 PdfStreamConverter.prototype = {
 
   // properties required for XPCOM registration:
-  classID: Components.ID('{6457a96b-2d68-439a-bcfa-44465fbcdbb1}'),
+  classID: Components.ID('{d0c5195d-e798-49d4-b1d3-9324328b2291}'),
   classDescription: 'pdf.js Component',
   contractID: '@mozilla.org/streamconv;1?from=application/pdf&to=*/*',
 
   QueryInterface: XPCOMUtils.generateQI([
       Ci.nsISupports,
       Ci.nsIStreamConverter,
       Ci.nsIStreamListener,
       Ci.nsIRequestObserver
@@ -213,16 +266,18 @@ PdfStreamConverter.prototype = {
 
   // nsIStreamConverter::convert
   convert: function(aFromStream, aFromType, aToType, aCtxt) {
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
 
   // nsIStreamConverter::asyncConvertData
   asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
+    if (!isEnabled())
+      throw Cr.NS_ERROR_NOT_IMPLEMENTED;
     // Ignoring HTTP POST requests -- pdf.js has to repeat the request.
     var skipConversion = false;
     try {
       var request = aCtxt;
       request.QueryInterface(Ci.nsIHttpChannel);
       skipConversion = (request.requestMethod !== 'GET');
     } catch (e) {
       // Non-HTTP request... continue normally.
@@ -262,17 +317,18 @@ PdfStreamConverter.prototype = {
       },
       onDataAvailable: function() {
         listener.onDataAvailable.apply(listener, arguments);
       },
       onStopRequest: function() {
         var domWindow = getDOMWindow(channel);
         // Double check the url is still the correct one.
         if (domWindow.document.documentURIObject.equals(aRequest.URI)) {
-          let requestListener = new RequestListener(new ChromeActions);
+          let requestListener = new RequestListener(
+                                      new ChromeActions(domWindow));
           domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
             requestListener.receive(event);
           }, false, true);
         }
         listener.onStopRequest.apply(listener, arguments);
       }
     };
 
new file mode 100644
--- /dev/null
+++ b/browser/extensions/pdfjs/content/PdfJs.jsm
@@ -0,0 +1,142 @@
+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_PREVIOUS_ACTION = PREF_PREFIX + '.previousHandler.preferredAction';
+const PREF_PREVIOUS_ASK = PREF_PREFIX + '.previousHandler.alwaysAskBeforeHandling';
+const TOPIC_PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged';
+
+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',
+                                   'nsIMIMEService');
+
+function getBoolPref(aPref, aDefaultValue) {
+  try {
+    return Services.prefs.getBoolPref(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;
+    var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+    registrar.registerFactory(proto.classID, proto.classDescription,
+                              proto.contractID, this);
+  },
+
+  unregister: function unregister() {
+    var proto = this._targetConstructor.prototype;
+    var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+    registrar.unregisterFactory(proto.classID, this);
+    this._targetConstructor = null;
+  },
+
+  // nsIFactory
+  createInstance: function createInstance(aOuter, iid) {
+    if (aOuter !== null)
+      throw Cr.NS_ERROR_NO_AGGREGATION;
+    return (new (this._targetConstructor)).QueryInterface(iid);
+  },
+
+  // nsIFactory
+  lockFactory: function lockFactory(lock) { 
+    // No longer used as of gecko 1.7.
+    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+  }
+};
+
+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 (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);
+  },
+
+  // nsIObserver
+  observe: function observe(aSubject, aTopic, aData) {
+    if (this.enabled)
+      this._ensureRegistered();
+    else
+      this._ensureUnregistered();
+  },
+  
+  /**
+   * pdf.js is only enabled if it is both selected as the pdf viewer and if the 
+   * global switch enabling it is true.
+   * @return {boolean} Wether or not it's enabled.
+   */
+  get enabled() {
+    var disabled = getBoolPref(PREF_DISABLED, true);
+    if (disabled)
+      return false;
+
+    var handlerInfo = Svc.mime.
+                        getFromTypeAndExtension('application/pdf', 'pdf');
+    return handlerInfo.alwaysAskBeforeHandling == false &&
+           handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally;
+  },
+
+  _ensureRegistered: function _ensureRegistered() {
+    if (this._registered)
+      return;
+
+    Factory.register(PdfStreamConverter);
+    this._registered = true;
+  },
+
+  _ensureUnregistered: function _ensureUnregistered() {
+    if (!this._registered)
+      return;
+
+    Factory.unregister();
+    this._registered = false;
+  }
+};
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -233,16 +233,20 @@ html[dir='rtl'] .splitToolbarButton > .t
   height: 0;
   overflow: hidden;
 }
 
 .toolbarButton[disabled] {
   opacity: .5;
 }
 
+.toolbarButton.group {
+  margin-right:0;
+}
+
 .splitToolbarButton:hover > .toolbarButton,
 .splitToolbarButton:focus > .toolbarButton,
 .splitToolbarButton.toggled > .toolbarButton {
   background-color: hsla(0,0%,0%,.12);
   background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
   background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
   background-clip: padding-box;
   border: 1px solid hsla(0,0%,0%,.35);
@@ -528,16 +532,22 @@ 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 {
+  display: inline-block;
+  content: url(images/toolbarButton-search.png);
+}
+
+
 .toolbarField {
   min-width: 16px;
   width: 32px;
   padding: 3px 6px;
   margin: 4px 0 4px 0;
   border: 1px solid transparent;
   border-radius: 2px;
   background-color: hsla(0,0%,100%,.09);
@@ -692,16 +702,63 @@ a:focus > .thumbnail > .thumbnailSelecti
   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);
 }
 
+#searchScrollView {
+  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: 8px;
+  width: 130px;
+}
+
+#searchResults {
+  overflow: auto;
+  background-color: #fff;
+  position: absolute;
+  top: 30px;
+  bottom: 0px;
+  left: 0px;
+  right: 0;
+  font-size: smaller;
+  opacity: 0.7;
+}
+
+#searchResults a {
+  display: block;
+  white-space: pre;
+  text-decoration: none;
+  color: black;
+}
+
+#sidebarControls {
+  position:absolute;
+  width: 180px;
+  height: 32px;
+  left: 15px;
+  bottom: 35px;
+}
+
 .outlineItem.selected {
   background-color: hsla(0,0%,100%,.08);
   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%,.1) inset,
               0 0 1px hsla(0,0%,0%,.2);
   color: hsla(0,0%,100%,1);
@@ -932,16 +989,40 @@ canvas {
 }
 #PDFBug .stats .title {
     font-weight: bold;
 }
 #PDFBug table {
   font-size: 10px;
 }
 
+@media print {
+  #sidebarContainer, .toolbar, #loadingBox, #errorWrapper, .textLayer {
+    display: none;
+  }
+
+  #mainContainer, #viewerContainer, .page, .page canvas {
+    position: static;
+    padding: 0;
+    margin: 0;
+  }
+
+  .page {
+    float: left;
+    display: none;
+    box-shadow: none;
+    -moz-box-shadow: none;
+    -webkit-box-shadow: none;
+  }
+
+  .page[data-loaded] {
+    display: block;
+  }
+}
+
 @media all and (max-width: 950px) {
   html[dir='ltr'] #outerContainer.sidebarMoving .outerCenter,
   html[dir='ltr'] #outerContainer.sidebarOpen .outerCenter {
     float: left;
     left: 180px;
   }
   html[dir='rtl'] #outerContainer.sidebarMoving .outerCenter,
   html[dir='rtl'] #outerContainer.sidebarOpen .outerCenter {
--- a/browser/extensions/pdfjs/content/web/viewer.html
+++ b/browser/extensions/pdfjs/content/web/viewer.html
@@ -17,29 +17,29 @@
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
 var PDFJS = {};
 
 (function pdfjsWrapper() {
   // Use strict in our context only - users might not want it
   'use strict';
 
-  PDFJS.build = '5ac7513';
+  PDFJS.build = '121040a';
 
   // Files are inserted below - see Makefile
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
 'use strict';
 
 var globalScope = (typeof window === 'undefined') ? this : window;
 
 var isWorker = (typeof window == 'undefined');
 
-var ERRORS = 0, WARNINGS = 1, TODOS = 5;
+var ERRORS = 0, WARNINGS = 1, INFOS = 5;
 var verbosity = WARNINGS;
 
 // The global PDFJS object exposes the API
 // In production, it will be declared outside a global wrapper
 // In development, it will be declared here
 if (!globalScope.PDFJS) {
   globalScope.PDFJS = {};
 }
@@ -173,32 +173,74 @@ var Page = (function PageClosure() {
     getOperatorList: function Page_getOperatorList(handler, dependency) {
       var xref = this.xref;
       var content = this.content;
       var resources = this.resources;
       if (isArray(content)) {
         // fetching items
         var streams = [];
         var i, n = content.length;
+        var streams = [];
         for (i = 0; i < n; ++i)
           streams.push(xref.fetchIfRef(content[i]));
         content = new StreamsSequenceStream(streams);
       } else if (isStream(content)) {
         content.reset();
       } else if (!content) {
         // replacing non-existent page content with empty one
         content = new Stream(new Uint8Array(0));
       }
 
       var pe = this.pe = new PartialEvaluator(
                                 xref, handler, 'p' + this.pageNumber + '_');
 
       return pe.getOperatorList(content, resources, dependency);
     },
-
+    extractTextContent: function Page_extractTextContent() {
+      var handler = {
+        on: function nullHandlerOn() {},
+        send: function nullHandlerSend() {}
+      };
+
+      var xref = this.xref;
+      var content = xref.fetchIfRef(this.content);
+      var resources = xref.fetchIfRef(this.resources);
+      if (isArray(content)) {
+        // fetching items
+        var i, n = content.length;
+        var streams = [];
+        for (i = 0; i < n; ++i)
+          streams.push(xref.fetchIfRef(content[i]));
+        content = new StreamsSequenceStream(streams);
+      } else if (isStream(content)) {
+        content.reset();
+      }
+
+      var pe = new PartialEvaluator(
+                     xref, handler, 'p' + this.pageNumber + '_');
+      return pe.getTextContent(content, resources);
+    },
+
+    ensureFonts: function Page_ensureFonts(fonts, callback) {
+      this.stats.time('Font Loading');
+      // Convert the font names to the corresponding font obj.
+      for (var i = 0, ii = fonts.length; i < ii; i++) {
+        fonts[i] = this.objs.objs[fonts[i]].data;
+      }
+
+      // Load all the fonts
+      FontLoader.bind(
+        fonts,
+        function pageEnsureFontsFontObjs(fontObjs) {
+          this.stats.timeEnd('Font Loading');
+
+          callback.call(this);
+        }.bind(this)
+      );
+    },
     getLinks: function Page_getLinks() {
       var links = [];
       var annotations = pageGetAnnotations();
       var i, n = annotations.length;
       for (i = 0; i < n; ++i) {
         if (annotations[i].type != 'Link')
           continue;
         links.push(annotations[i]);
@@ -503,67 +545,98 @@ var PDFDocument = (function PDFDocumentC
     getPage: function PDFDocument_getPage(n) {
       return this.catalog.getPage(n);
     }
   };
 
   return PDFDocument;
 })();
 
+
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
 'use strict';
 
+// Use only for debugging purposes. This should not be used in any code that is
+// in mozilla master.
 function log(msg) {
   if (console && console.log)
     console.log(msg);
   else if (print)
     print(msg);
 }
 
+// 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
+// disabled, which is important to devs but not end users.
+function info(msg) {
+  if (verbosity >= INFOS) {
+    log('Info: ' + msg);
+    PDFJS.LogManager.notify('info', msg);
+  }
+}
+
+// Non-fatal warnings that should trigger the fallback UI.
 function warn(msg) {
-  if (verbosity >= WARNINGS)
+  if (verbosity >= WARNINGS) {
     log('Warning: ' + msg);
+    PDFJS.LogManager.notify('warn', msg);
+  }
+}
+
+// Fatal errors that should trigger the fallback UI and halt execution by
+// throwing an exception.
+function error(msg) {
+  log('Error: ' + msg);
+  log(backtrace());
+  PDFJS.LogManager.notify('error', msg);
+  throw new Error(msg);
+}
+
+// Missing features that should trigger the fallback UI.
+function TODO(what) {
+  warn('TODO: ' + what);
 }
 
 function backtrace() {
   try {
     throw new Error();
   } catch (e) {
     return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
   }
 }
 
-function error(msg) {
-  log('Error: ' + msg);
-  log(backtrace());
-  throw new Error(msg);
-}
-
-function TODO(what) {
-  if (verbosity >= TODOS)
-    log('TODO: ' + what);
-}
-
-function malformed(msg) {
-  error('Malformed PDF: ' + msg);
-}
-
 function assert(cond, msg) {
   if (!cond)
     error(msg);
 }
 
 // In a well-formed PDF, |cond| holds.  If it doesn't, subsequent
 // behavior is undefined.
 function assertWellFormed(cond, msg) {
   if (!cond)
-    malformed(msg);
-}
+    error(msg);
+}
+
+var LogManager = PDFJS.LogManager = (function LogManagerClosure() {
+  var loggers = [];
+  return {
+    addLogger: function logManager_addLogger(logger) {
+      loggers.push(logger);
+    },
+    notify: function(type, message) {
+      for (var i = 0, ii = loggers.length; i < ii; i++) {
+        var logger = loggers[i];
+        if (logger[type])
+          logger[type](message);
+      }
+    }
+  };
+})();
 
 function shadow(obj, prop, value) {
   Object.defineProperty(obj, prop, { value: value,
                                      enumerable: true,
                                      configurable: true,
                                      writable: false });
   return value;
 }
@@ -807,16 +880,20 @@ function stringToPDFString(str) {
     for (i = 0; i < n; ++i) {
       var code = PDFStringTranslateTable[str.charCodeAt(i)];
       str2 += code ? String.fromCharCode(code) : str.charAt(i);
     }
   }
   return str2;
 }
 
+function stringToUTF8String(str) {
+  return decodeURIComponent(escape(str));
+}
+
 function isBool(v) {
   return typeof v == 'boolean';
 }
 
 function isInt(v) {
   return typeof v == 'number' && ((v | 0) == v);
 }
 
@@ -1448,22 +1525,28 @@ var PDFPageProxy = (function PDFPageProx
           stats.timeEnd('Rendering');
           stats.timeEnd('Overall');
           if (callback) callback();
         }
       }
       next();
     },
     /**
-     * Stub for future feature.
+     * @return {Promise} That is resolved with the a {string} that is the text
+     * content from the page.
      */
     getTextContent: function PDFPageProxy_getTextContent() {
       var promise = new PDFJS.Promise();
-      var textContent = 'page text'; // not implemented
-      promise.resolve(textContent);
+      this.transport.messageHandler.send('GetTextContent', {
+          pageIndex: this.pageNumber - 1
+        },
+        function textContentCallback(textContent) {
+          promise.resolve(textContent);
+        }
+      );
       return promise;
     },
     /**
      * Stub for future feature.
      */
     getOperationList: function PDFPageProxy_getOperationList() {
       var promise = new PDFJS.Promise();
       var operationList = { // not implemented
@@ -1539,17 +1622,17 @@ var WorkerTransport = (function WorkerTr
         }.bind(this));
 
         var testObj = new Uint8Array(1);
         // Some versions of Opera throw a DATA_CLONE_ERR on
         // serializing the typed array.
         messageHandler.send('test', testObj);
         return;
       } catch (e) {
-        warn('The worker has been disabled.');
+        info('The worker has been disabled.');
       }
     }
     // Either workers are disabled, not supported or have thrown an exception.
     // Thus, we fallback to a faked worker.
     globalScope.PDFJS.disableWorker = true;
     this.setupFakeWorker();
   }
   WorkerTransport.prototype = {
@@ -2061,20 +2144,23 @@ var CanvasGraphics = (function CanvasGra
     },
     setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
       this.ctx.mozDash = dashArray;
       this.ctx.mozDashOffset = dashPhase;
       this.ctx.webkitLineDash = dashArray;
       this.ctx.webkitLineDashOffset = dashPhase;
     },
     setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {
-      TODO('set rendering intent: ' + intent);
+      // Maybe if we one day fully support color spaces this will be important
+      // for now we can ignore.
+      // TODO set rendering intent?
     },
     setFlatness: function CanvasGraphics_setFlatness(flatness) {
-      TODO('set flatness: ' + flatness);
+      // There's no way to control this with canvas, but we can safely ignore.
+      // TODO set flatness?
     },
     setGState: function CanvasGraphics_setGState(states) {
       for (var i = 0, ii = states.length; i < ii; i++) {
         var state = states[i];
         var key = state[0];
         var value = state[1];
 
         switch (key) {
@@ -2559,17 +2645,17 @@ var CanvasGraphics = (function CanvasGra
               text.str += '\u00A0';
             } else {
               text.str += shownText.str;
             }
             text.canvasWidth += shownText.canvasWidth;
             text.length += shownText.length;
           }
         } else {
-          malformed('TJ array element ' + e + ' is not string or num');
+          error('TJ array element ' + e + ' is not string or num');
         }
       }
 
       if (textSelection)
         this.textLayer.appendText(text, font.loadedName, fontSize);
     },
     nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
       this.nextLine();
@@ -3097,25 +3183,41 @@ var Catalog = (function CatalogClosure()
     this.xref = xref;
     var obj = xref.getCatalogObj();
     assertWellFormed(isDict(obj), 'catalog object is not a dictionary');
     this.catDict = obj;
   }
 
   Catalog.prototype = {
     get metadata() {
-      var stream = this.catDict.get('Metadata');
+      var streamRef = this.catDict.getRaw('Metadata');
+      if (!isRef(streamRef))
+        return shadow(this, 'metadata', null);
+
+      var encryptMetadata = !this.xref.encrypt ? false :
+        this.xref.encrypt.encryptMetadata;
+
+      var stream = this.xref.fetch(streamRef, !encryptMetadata);
       var metadata;
       if (stream && isDict(stream.dict)) {
         var type = stream.dict.get('Type');
         var subtype = stream.dict.get('Subtype');
 
         if (isName(type) && isName(subtype) &&
             type.name === 'Metadata' && subtype.name === 'XML') {
-          metadata = stringToPDFString(bytesToString(stream.getBytes()));
+          // XXX: This should examine the charset the XML document defines,
+          // however since there are currently no real means to decode
+          // arbitrary charsets, let's just hope that the author of the PDF
+          // was reasonable enough to stick with the XML default charset,
+          // which is UTF-8.
+          try {
+            metadata = stringToUTF8String(bytesToString(stream.getBytes()));
+          } catch (e) {
+            info('Skipping invalid metadata.');
+          }
         }
       }
 
       return shadow(this, 'metadata', metadata);
     },
     get toplevelPagesDict() {
       var pagesObj = this.catDict.get('Pages');
       assertWellFormed(isDict(pagesObj), 'invalid top-level pages dictionary');
@@ -12150,22 +12252,22 @@ var LabCS = (function LabCSClosure() {
     this.YB = blackPoint[1];
     this.ZB = blackPoint[2];
 
     // Validate vars as per spec
     if (this.XW < 0 || this.ZW < 0 || this.YW !== 1)
       error('Invalid WhitePoint components, no fallback available');
 
     if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
-      warn('Invalid BlackPoint, falling back to default');
+      info('Invalid BlackPoint, falling back to default');
       this.XB = this.YB = this.ZB = 0;
     }
 
     if (this.amin > this.amax || this.bmin > this.bmax) {
-      warn('Invalid Range, falling back to defaults');
+      info('Invalid Range, falling back to defaults');
       this.amin = -100;
       this.amax = 100;
       this.bmin = -100;
       this.bmax = 100;
     }
   };
 
   // Function g(x) from spec
@@ -12778,18 +12880,20 @@ var CipherTransformFactory = (function C
     if (!isInt(keyLength) ||
       keyLength < 40 || (keyLength % 8) != 0)
       error('invalid key length');
     // prepare keys
     var ownerPassword = stringToBytes(dict.get('O'));
     var userPassword = stringToBytes(dict.get('U'));
     var flags = dict.get('P');
     var revision = dict.get('R');
-    var encryptMetadata =
+    var encryptMetadata = algorithm == 4 &&  // meaningful when V is 4
       dict.get('EncryptMetadata') !== false; // makes true as default value
+    this.encryptMetadata = encryptMetadata;
+
     var fileIdBytes = stringToBytes(fileId);
     var passwordBytes;
     if (password)
       passwordBytes = stringToBytes(password);
 
     var encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
                                        ownerPassword, userPassword, flags,
                                        revision, keyLength, encryptMetadata);
@@ -13035,18 +13139,19 @@ var PartialEvaluator = (function Partial
         var loadedName = null;
 
         var fontRes = resources.get('Font');
 
         assert(fontRes, 'fontRes not available');
 
         font = xref.fetchIfRef(font) || fontRes.get(fontName);
         assertWellFormed(isDict(font));
+
         ++self.objIdCounter;
-        if (!font.translated) {
+        if (!font.loadedName) {
           font.translated = self.translateFont(font, xref, resources,
                                                dependency);
           if (font.translated) {
             // keep track of each font we translated so the caller can
             // load them asynchronously before calling display on a page
             loadedName = 'font_' + uniquePrefix + self.objIdCounter;
             font.translated.properties.loadedName = loadedName;
             font.loadedName = loadedName;
@@ -13299,36 +13404,47 @@ var PartialEvaluator = (function Partial
                       break;
                     case 'Font':
                       gsStateObj.push([
                         'Font',
                         handleSetFont(null, value[0]),
                         value[1]
                       ]);
                       break;
+                    case 'BM':
+                      // We support the default so don't trigger the TODO.
+                      if (!isName(value) || value.name != 'Normal')
+                        TODO('graphic state operator ' + key);
+                      break;
+                    case 'SMask':
+                      // We support the default so don't trigger the TODO.
+                      if (!isName(value) || value.name != 'None')
+                        TODO('graphic state operator ' + key);
+                      break;
+                    // Only generate info log messages for the following since
+                    // they are unlikey to have a big impact on the rendering.
                     case 'OP':
                     case 'op':
                     case 'OPM':
                     case 'BG':
                     case 'BG2':
                     case 'UCR':
                     case 'UCR2':
                     case 'TR':
                     case 'TR2':
                     case 'HT':
                     case 'SM':
                     case 'SA':
-                    case 'BM':
-                    case 'SMask':
                     case 'AIS':
                     case 'TK':
-                      TODO('graphic state operator ' + key);
+                      // TODO implement these operators.
+                      info('graphic state operator ' + key);
                       break;
                     default:
-                      warn('Unknown graphic state operator ' + key);
+                      info('Unknown graphic state operator ' + key);
                       break;
                   }
                 }
               );
               args = [gsStateObj];
               break;
           } // switch
 
@@ -13339,16 +13455,91 @@ var PartialEvaluator = (function Partial
           assertWellFormed(args.length <= 33, 'Too many arguments');
           args.push(obj instanceof Dict ? obj.getAll() : obj);
         }
       }
 
       return queue;
     },
 
+    getTextContent: function partialEvaluatorGetIRQueue(stream, resources) {
+
+      var self = this;
+      var xref = this.xref;
+
+      function handleSetFont(fontName, fontRef) {
+        var fontRes = resources.get('Font');
+
+        // TODO: TOASK: Is it possible to get here? If so, what does
+        // args[0].name should be like???
+        assert(fontRes, 'fontRes not available');
+
+        fontRes = xref.fetchIfRef(fontRes);
+        fontRef = fontRef || fontRes.get(fontName);
+        var font = xref.fetchIfRef(fontRef), tra;
+        assertWellFormed(isDict(font));
+        if (!font.translated) {
+          font.translated = self.translateFont(font, xref, resources);
+        }
+        return font;
+      }
+
+      resources = xref.fetchIfRef(resources) || new Dict();
+
+      var parser = new Parser(new Lexer(stream), false);
+      var res = resources;
+      var args = [], obj;
+
+      var text = '';
+      var chunk = '';
+      var font = null;
+      while (!isEOF(obj = parser.getObj())) {
+        if (isCmd(obj)) {
+          var cmd = obj.cmd;
+          switch (cmd) {
+            case 'Tf':
+              font = handleSetFont(args[0].name);
+              break;
+            case 'TJ':
+              var items = args[0];
+              for (var j = 0, jj = items.length; j < jj; j++) {
+                if (typeof items[j] === 'string') {
+                  chunk += items[j];
+                } else if (items[j] < 0) {
+                  // making all negative offsets a space - better to have
+                  // a space in incorrect place than not have them at all
+                  chunk += ' ';
+                }
+              }
+              break;
+            case 'Tj':
+              chunk += args[0];
+              break;
+            case "'":
+              chunk += args[0] + ' ';
+              break;
+            case '"':
+              chunk += args[2] + ' ';
+              break;
+          } // switch
+          if (chunk !== '') {
+            text += fontCharsToUnicode(chunk, font.translated.properties);
+            chunk = '';
+          }
+
+          args = [];
+        } else if (obj != null) {
+          assertWellFormed(args.length <= 33, 'Too many arguments');
+          args.push(obj);
+        }
+      }
+
+      return text;
+    },
+
     extractDataStructures: function
       partialEvaluatorExtractDataStructures(dict, baseDict,
                                             xref, properties) {
       // 9.10.2
       var toUnicode = dict.get('ToUnicode') ||
         baseDict.get('ToUnicode');
       if (toUnicode)
         properties.toUnicode = this.readToUnicode(toUnicode, xref, properties);
@@ -13492,18 +13683,19 @@ var PartialEvaluator = (function Partial
                 while (tokens.length &&
                        (item = tokens.pop()) != beginArrayToken)
                   items.unshift(item);
                 tokens.push(items);
                 break;
             }
           } else if (octet == 0x3E) {
             if (token.length) {
-              // XXX guessing chars size by checking number size in the CMap
-              if (token.length <= 2 && properties.composite)
+              // Heuristic: guessing chars size by checking numbers sizes
+              // in the CMap entries.
+              if (token.length == 2 && properties.composite)
                 properties.wideChars = false;
 
               if (token.length <= 4) {
                 // parsing hex number
                 tokens.push(parseInt(token, 16));
                 token = '';
               } else {
                 // parsing hex UTF-16BE numbers
@@ -14533,16 +14725,746 @@ function isRTLRangeFor(value) {
 }
 
 function isSpecialUnicode(unicode) {
   return (unicode <= 0x1F || (unicode >= 127 && unicode < kSizeOfGlyphArea)) ||
     (unicode >= kCmapGlyphOffset &&
     unicode < kCmapGlyphOffset + kSizeOfGlyphArea);
 }
 
+// The normalization table is obtained by filtering the Unicode characters
+// database with <compat> entries.
+var NormalizedUnicodes = {
+  '\u00A8': '\u0020\u0308',
+  '\u00AF': '\u0020\u0304',
+  '\u00B4': '\u0020\u0301',
+  '\u00B5': '\u03BC',
+  '\u00B8': '\u0020\u0327',
+  '\u0132': '\u0049\u004A',
+  '\u0133': '\u0069\u006A',
+  '\u013F': '\u004C\u00B7',
+  '\u0140': '\u006C\u00B7',
+  '\u0149': '\u02BC\u006E',
+  '\u017F': '\u0073',
+  '\u01C4': '\u0044\u017D',
+  '\u01C5': '\u0044\u017E',
+  '\u01C6': '\u0064\u017E',
+  '\u01C7': '\u004C\u004A',
+  '\u01C8': '\u004C\u006A',
+  '\u01C9': '\u006C\u006A',
+  '\u01CA': '\u004E\u004A',
+  '\u01CB': '\u004E\u006A',
+  '\u01CC': '\u006E\u006A',
+  '\u01F1': '\u0044\u005A',
+  '\u01F2': '\u0044\u007A',
+  '\u01F3': '\u0064\u007A',
+  '\u02D8': '\u0020\u0306',
+  '\u02D9': '\u0020\u0307',
+  '\u02DA': '\u0020\u030A',
+  '\u02DB': '\u0020\u0328',
+  '\u02DC': '\u0020\u0303',
+  '\u02DD': '\u0020\u030B',
+  '\u037A': '\u0020\u0345',
+  '\u0384': '\u0020\u0301',
+  '\u03D0': '\u03B2',
+  '\u03D1': '\u03B8',
+  '\u03D2': '\u03A5',
+  '\u03D5': '\u03C6',
+  '\u03D6': '\u03C0',
+  '\u03F0': '\u03BA',
+  '\u03F1': '\u03C1',
+  '\u03F2': '\u03C2',
+  '\u03F4': '\u0398',
+  '\u03F5': '\u03B5',
+  '\u03F9': '\u03A3',
+  '\u0587': '\u0565\u0582',
+  '\u0675': '\u0627\u0674',
+  '\u0676': '\u0648\u0674',
+  '\u0677': '\u06C7\u0674',
+  '\u0678': '\u064A\u0674',
+  '\u0E33': '\u0E4D\u0E32',
+  '\u0EB3': '\u0ECD\u0EB2',
+  '\u0EDC': '\u0EAB\u0E99',
+  '\u0EDD': '\u0EAB\u0EA1',
+  '\u0F77': '\u0FB2\u0F81',
+  '\u0F79': '\u0FB3\u0F81',
+  '\u1E9A': '\u0061\u02BE',
+  '\u1FBD': '\u0020\u0313',
+  '\u1FBF': '\u0020\u0313',
+  '\u1FC0': '\u0020\u0342',
+  '\u1FFE': '\u0020\u0314',
+  '\u2002': '\u0020',
+  '\u2003': '\u0020',
+  '\u2004': '\u0020',
+  '\u2005': '\u0020',
+  '\u2006': '\u0020',
+  '\u2008': '\u0020',
+  '\u2009': '\u0020',
+  '\u200A': '\u0020',
+  '\u2017': '\u0020\u0333',
+  '\u2024': '\u002E',
+  '\u2025': '\u002E\u002E',
+  '\u2026': '\u002E\u002E\u002E',
+  '\u2033': '\u2032\u2032',
+  '\u2034': '\u2032\u2032\u2032',
+  '\u2036': '\u2035\u2035',
+  '\u2037': '\u2035\u2035\u2035',
+  '\u203C': '\u0021\u0021',
+  '\u203E': '\u0020\u0305',
+  '\u2047': '\u003F\u003F',
+  '\u2048': '\u003F\u0021',
+  '\u2049': '\u0021\u003F',
+  '\u2057': '\u2032\u2032\u2032\u2032',
+  '\u205F': '\u0020',
+  '\u20A8': '\u0052\u0073',
+  '\u2100': '\u0061\u002F\u0063',
+  '\u2101': '\u0061\u002F\u0073',
+  '\u2103': '\u00B0\u0043',
+  '\u2105': '\u0063\u002F\u006F',
+  '\u2106': '\u0063\u002F\u0075',
+  '\u2107': '\u0190',
+  '\u2109': '\u00B0\u0046',
+  '\u2116': '\u004E\u006F',
+  '\u2121': '\u0054\u0045\u004C',
+  '\u2135': '\u05D0',
+  '\u2136': '\u05D1',
+  '\u2137': '\u05D2',
+  '\u2138': '\u05D3',
+  '\u213B': '\u0046\u0041\u0058',
+  '\u2160': '\u0049',
+  '\u2161': '\u0049\u0049',
+  '\u2162': '\u0049\u0049\u0049',
+  '\u2163': '\u0049\u0056',
+  '\u2164': '\u0056',
+  '\u2165': '\u0056\u0049',
+  '\u2166': '\u0056\u0049\u0049',
+  '\u2167': '\u0056\u0049\u0049\u0049',
+  '\u2168': '\u0049\u0058',
+  '\u2169': '\u0058',
+  '\u216A': '\u0058\u0049',
+  '\u216B': '\u0058\u0049\u0049',
+  '\u216C': '\u004C',
+  '\u216D': '\u0043',
+  '\u216E': '\u0044',
+  '\u216F': '\u004D',
+  '\u2170': '\u0069',
+  '\u2171': '\u0069\u0069',
+  '\u2172': '\u0069\u0069\u0069',
+  '\u2173': '\u0069\u0076',
+  '\u2174': '\u0076',
+  '\u2175': '\u0076\u0069',
+  '\u2176': '\u0076\u0069\u0069',
+  '\u2177': '\u0076\u0069\u0069\u0069',
+  '\u2178': '\u0069\u0078',
+  '\u2179': '\u0078',
+  '\u217A': '\u0078\u0069',
+  '\u217B': '\u0078\u0069\u0069',
+  '\u217C': '\u006C',
+  '\u217D': '\u0063',
+  '\u217E': '\u0064',
+  '\u217F': '\u006D',
+  '\u222C': '\u222B\u222B',
+  '\u222D': '\u222B\u222B\u222B',
+  '\u222F': '\u222E\u222E',
+  '\u2230': '\u222E\u222E\u222E',
+  '\u2474': '\u0028\u0031\u0029',
+  '\u2475': '\u0028\u0032\u0029',
+  '\u2476': '\u0028\u0033\u0029',
+  '\u2477': '\u0028\u0034\u0029',
+  '\u2478': '\u0028\u0035\u0029',
+  '\u2479': '\u0028\u0036\u0029',
+  '\u247A': '\u0028\u0037\u0029',
+  '\u247B': '\u0028\u0038\u0029',
+  '\u247C': '\u0028\u0039\u0029',
+  '\u247D': '\u0028\u0031\u0030\u0029',
+  '\u247E': '\u0028\u0031\u0031\u0029',
+  '\u247F': '\u0028\u0031\u0032\u0029',
+  '\u2480': '\u0028\u0031\u0033\u0029',
+  '\u2481': '\u0028\u0031\u0034\u0029',
+  '\u2482': '\u0028\u0031\u0035\u0029',
+  '\u2483': '\u0028\u0031\u0036\u0029',
+  '\u2484': '\u0028\u0031\u0037\u0029',
+  '\u2485': '\u0028\u0031\u0038\u0029',
+  '\u2486': '\u0028\u0031\u0039\u0029',
+  '\u2487': '\u0028\u0032\u0030\u0029',
+  '\u2488': '\u0031\u002E',
+  '\u2489': '\u0032\u002E',
+  '\u248A': '\u0033\u002E',
+  '\u248B': '\u0034\u002E',
+  '\u248C': '\u0035\u002E',
+  '\u248D': '\u0036\u002E',
+  '\u248E': '\u0037\u002E',
+  '\u248F': '\u0038\u002E',
+  '\u2490': '\u0039\u002E',
+  '\u2491': '\u0031\u0030\u002E',
+  '\u2492': '\u0031\u0031\u002E',
+  '\u2493': '\u0031\u0032\u002E',
+  '\u2494': '\u0031\u0033\u002E',
+  '\u2495': '\u0031\u0034\u002E',
+  '\u2496': '\u0031\u0035\u002E',
+  '\u2497': '\u0031\u0036\u002E',
+  '\u2498': '\u0031\u0037\u002E',
+  '\u2499': '\u0031\u0038\u002E',
+  '\u249A': '\u0031\u0039\u002E',
+  '\u249B': '\u0032\u0030\u002E',
+  '\u249C': '\u0028\u0061\u0029',
+  '\u249D': '\u0028\u0062\u0029',
+  '\u249E': '\u0028\u0063\u0029',
+  '\u249F': '\u0028\u0064\u0029',
+  '\u24A0': '\u0028\u0065\u0029',
+  '\u24A1': '\u0028\u0066\u0029',
+  '\u24A2': '\u0028\u0067\u0029',
+  '\u24A3': '\u0028\u0068\u0029',
+  '\u24A4': '\u0028\u0069\u0029',
+  '\u24A5': '\u0028\u006A\u0029',
+  '\u24A6': '\u0028\u006B\u0029',
+  '\u24A7': '\u0028\u006C\u0029',
+  '\u24A8': '\u0028\u006D\u0029',
+  '\u24A9': '\u0028\u006E\u0029',
+  '\u24AA': '\u0028\u006F\u0029',
+  '\u24AB': '\u0028\u0070\u0029',
+  '\u24AC': '\u0028\u0071\u0029',
+  '\u24AD': '\u0028\u0072\u0029',
+  '\u24AE': '\u0028\u0073\u0029',
+  '\u24AF': '\u0028\u0074\u0029',
+  '\u24B0': '\u0028\u0075\u0029',
+  '\u24B1': '\u0028\u0076\u0029',
+  '\u24B2': '\u0028\u0077\u0029',
+  '\u24B3': '\u0028\u0078\u0029',
+  '\u24B4': '\u0028\u0079\u0029',
+  '\u24B5': '\u0028\u007A\u0029',
+  '\u2A0C': '\u222B\u222B\u222B\u222B',
+  '\u2A74': '\u003A\u003A\u003D',
+  '\u2A75': '\u003D\u003D',
+  '\u2A76': '\u003D\u003D\u003D',
+  '\u2E9F': '\u6BCD',
+  '\u2EF3': '\u9F9F',
+  '\u2F00': '\u4E00',
+  '\u2F01': '\u4E28',
+  '\u2F02': '\u4E36',
+  '\u2F03': '\u4E3F',
+  '\u2F04': '\u4E59',
+  '\u2F05': '\u4E85',
+  '\u2F06': '\u4E8C',
+  '\u2F07': '\u4EA0',
+  '\u2F08': '\u4EBA',
+  '\u2F09': '\u513F',
+  '\u2F0A': '\u5165',
+  '\u2F0B': '\u516B',
+  '\u2F0C': '\u5182',
+  '\u2F0D': '\u5196',
+  '\u2F0E': '\u51AB',
+  '\u2F0F': '\u51E0',
+  '\u2F10': '\u51F5',
+  '\u2F11': '\u5200',
+  '\u2F12': '\u529B',
+  '\u2F13': '\u52F9',
+  '\u2F14': '\u5315',
+  '\u2F15': '\u531A',
+  '\u2F16': '\u5338',
+  '\u2F17': '\u5341',
+  '\u2F18': '\u535C',
+  '\u2F19': '\u5369',
+  '\u2F1A': '\u5382',
+  '\u2F1B': '\u53B6',
+  '\u2F1C': '\u53C8',
+  '\u2F1D': '\u53E3',
+  '\u2F1E': '\u56D7',
+  '\u2F1F': '\u571F',
+  '\u2F20': '\u58EB',
+  '\u2F21': '\u5902',
+  '\u2F22': '\u590A',
+  '\u2F23': '\u5915',
+  '\u2F24': '\u5927',
+  '\u2F25': '\u5973',
+  '\u2F26': '\u5B50',
+  '\u2F27': '\u5B80',
+  '\u2F28': '\u5BF8',
+  '\u2F29': '\u5C0F',
+  '\u2F2A': '\u5C22',
+  '\u2F2B': '\u5C38',
+  '\u2F2C': '\u5C6E',
+  '\u2F2D': '\u5C71',
+  '\u2F2E': '\u5DDB',
+  '\u2F2F': '\u5DE5',
+  '\u2F30': '\u5DF1',
+  '\u2F31': '\u5DFE',
+  '\u2F32': '\u5E72',
+  '\u2F33': '\u5E7A',
+  '\u2F34': '\u5E7F',
+  '\u2F35': '\u5EF4',
+  '\u2F36': '\u5EFE',
+  '\u2F37': '\u5F0B',
+  '\u2F38': '\u5F13',
+  '\u2F39': '\u5F50',
+  '\u2F3A': '\u5F61',
+  '\u2F3B': '\u5F73',
+  '\u2F3C': '\u5FC3',
+  '\u2F3D': '\u6208',
+  '\u2F3E': '\u6236',
+  '\u2F3F': '\u624B',
+  '\u2F40': '\u652F',
+  '\u2F41': '\u6534',
+  '\u2F42': '\u6587',
+  '\u2F43': '\u6597',
+  '\u2F44': '\u65A4',
+  '\u2F45': '\u65B9',
+  '\u2F46': '\u65E0',
+  '\u2F47': '\u65E5',
+  '\u2F48': '\u66F0',
+  '\u2F49': '\u6708',
+  '\u2F4A': '\u6728',
+  '\u2F4B': '\u6B20',
+  '\u2F4C': '\u6B62',
+  '\u2F4D': '\u6B79',
+  '\u2F4E': '\u6BB3',
+  '\u2F4F': '\u6BCB',
+  '\u2F50': '\u6BD4',
+  '\u2F51': '\u6BDB',
+  '\u2F52': '\u6C0F',
+  '\u2F53': '\u6C14',
+  '\u2F54': '\u6C34',
+  '\u2F55': '\u706B',
+  '\u2F56': '\u722A',
+  '\u2F57': '\u7236',
+  '\u2F58': '\u723B',
+  '\u2F59': '\u723F',
+  '\u2F5A': '\u7247',
+  '\u2F5B': '\u7259',
+  '\u2F5C': '\u725B',
+  '\u2F5D': '\u72AC',
+  '\u2F5E': '\u7384',
+  '\u2F5F': '\u7389',
+  '\u2F60': '\u74DC',
+  '\u2F61': '\u74E6',
+  '\u2F62': '\u7518',
+  '\u2F63': '\u751F',
+  '\u2F64': '\u7528',
+  '\u2F65': '\u7530',
+  '\u2F66': '\u758B',
+  '\u2F67': '\u7592',
+  '\u2F68': '\u7676',
+  '\u2F69': '\u767D',
+  '\u2F6A': '\u76AE',
+  '\u2F6B': '\u76BF',
+  '\u2F6C': '\u76EE',
+  '\u2F6D': '\u77DB',
+  '\u2F6E': '\u77E2',
+  '\u2F6F': '\u77F3',
+  '\u2F70': '\u793A',
+  '\u2F71': '\u79B8',
+  '\u2F72': '\u79BE',
+  '\u2F73': '\u7A74',
+  '\u2F74': '\u7ACB',
+  '\u2F75': '\u7AF9',
+  '\u2F76': '\u7C73',
+  '\u2F77': '\u7CF8',
+  '\u2F78': '\u7F36',
+  '\u2F79': '\u7F51',
+  '\u2F7A': '\u7F8A',
+  '\u2F7B': '\u7FBD',
+  '\u2F7C': '\u8001',
+  '\u2F7D': '\u800C',
+  '\u2F7E': '\u8012',
+  '\u2F7F': '\u8033',
+  '\u2F80': '\u807F',
+  '\u2F81': '\u8089',
+  '\u2F82': '\u81E3',
+  '\u2F83': '\u81EA',
+  '\u2F84': '\u81F3',
+  '\u2F85': '\u81FC',
+  '\u2F86': '\u820C',
+  '\u2F87': '\u821B',
+  '\u2F88': '\u821F',
+  '\u2F89': '\u826E',
+  '\u2F8A': '\u8272',
+  '\u2F8B': '\u8278',
+  '\u2F8C': '\u864D',
+  '\u2F8D': '\u866B',
+  '\u2F8E': '\u8840',
+  '\u2F8F': '\u884C',
+  '\u2F90': '\u8863',
+  '\u2F91': '\u897E',
+  '\u2F92': '\u898B',
+  '\u2F93': '\u89D2',
+  '\u2F94': '\u8A00',
+  '\u2F95': '\u8C37',
+  '\u2F96': '\u8C46',
+  '\u2F97': '\u8C55',
+  '\u2F98': '\u8C78',
+  '\u2F99': '\u8C9D',
+  '\u2F9A': '\u8D64',
+  '\u2F9B': '\u8D70',
+  '\u2F9C': '\u8DB3',
+  '\u2F9D': '\u8EAB',
+  '\u2F9E': '\u8ECA',
+  '\u2F9F': '\u8F9B',
+  '\u2FA0': '\u8FB0',
+  '\u2FA1': '\u8FB5',
+  '\u2FA2': '\u9091',
+  '\u2FA3': '\u9149',
+  '\u2FA4': '\u91C6',
+  '\u2FA5': '\u91CC',
+  '\u2FA6': '\u91D1',
+  '\u2FA7': '\u9577',
+  '\u2FA8': '\u9580',
+  '\u2FA9': '\u961C',
+  '\u2FAA': '\u96B6',
+  '\u2FAB': '\u96B9',
+  '\u2FAC': '\u96E8',
+  '\u2FAD': '\u9751',
+  '\u2FAE': '\u975E',
+  '\u2FAF': '\u9762',
+  '\u2FB0': '\u9769',
+  '\u2FB1': '\u97CB',
+  '\u2FB2': '\u97ED',
+  '\u2FB3': '\u97F3',
+  '\u2FB4': '\u9801',
+  '\u2FB5': '\u98A8',
+  '\u2FB6': '\u98DB',
+  '\u2FB7': '\u98DF',
+  '\u2FB8': '\u9996',
+  '\u2FB9': '\u9999',
+  '\u2FBA': '\u99AC',
+  '\u2FBB': '\u9AA8',
+  '\u2FBC': '\u9AD8',
+  '\u2FBD': '\u9ADF',
+  '\u2FBE': '\u9B25',
+  '\u2FBF': '\u9B2F',
+  '\u2FC0': '\u9B32',
+  '\u2FC1': '\u9B3C',
+  '\u2FC2': '\u9B5A',
+  '\u2FC3': '\u9CE5',
+  '\u2FC4': '\u9E75',
+  '\u2FC5': '\u9E7F',
+  '\u2FC6': '\u9EA5',
+  '\u2FC7': '\u9EBB',
+  '\u2FC8': '\u9EC3',
+  '\u2FC9': '\u9ECD',
+  '\u2FCA': '\u9ED1',
+  '\u2FCB': '\u9EF9',
+  '\u2FCC': '\u9EFD',
+  '\u2FCD': '\u9F0E',
+  '\u2FCE': '\u9F13',
+  '\u2FCF': '\u9F20',
+  '\u2FD0': '\u9F3B',
+  '\u2FD1': '\u9F4A',
+  '\u2FD2': '\u9F52',
+  '\u2FD3': '\u9F8D',
+  '\u2FD4': '\u9F9C',
+  '\u2FD5': '\u9FA0',
+  '\u3036': '\u3012',
+  '\u3038': '\u5341',
+  '\u3039': '\u5344',
+  '\u303A': '\u5345',
+  '\u309B': '\u0020\u3099',
+  '\u309C': '\u0020\u309A',
+  '\u3131': '\u1100',
+  '\u3132': '\u1101',
+  '\u3133': '\u11AA',
+  '\u3134': '\u1102',
+  '\u3135': '\u11AC',
+  '\u3136': '\u11AD',
+  '\u3137': '\u1103',
+  '\u3138': '\u1104',
+  '\u3139': '\u1105',
+  '\u313A': '\u11B0',
+  '\u313B': '\u11B1',
+  '\u313C': '\u11B2',
+  '\u313D': '\u11B3',
+  '\u313E': '\u11B4',
+  '\u313F': '\u11B5',
+  '\u3140': '\u111A',
+  '\u3141': '\u1106',
+  '\u3142': '\u1107',
+  '\u3143': '\u1108',
+  '\u3144': '\u1121',
+  '\u3145': '\u1109',
+  '\u3146': '\u110A',
+  '\u3147': '\u110B',
+  '\u3148': '\u110C',
+  '\u3149': '\u110D',
+  '\u314A': '\u110E',
+  '\u314B': '\u110F',
+  '\u314C': '\u1110',
+  '\u314D': '\u1111',
+  '\u314E': '\u1112',
+  '\u314F': '\u1161',
+  '\u3150': '\u1162',
+  '\u3151': '\u1163',
+  '\u3152': '\u1164',
+  '\u3153': '\u1165',
+  '\u3154': '\u1166',
+  '\u3155': '\u1167',
+  '\u3156': '\u1168',
+  '\u3157': '\u1169',
+  '\u3158': '\u116A',
+  '\u3159': '\u116B',
+  '\u315A': '\u116C',
+  '\u315B': '\u116D',
+  '\u315C': '\u116E',
+  '\u315D': '\u116F',
+  '\u315E': '\u1170',
+  '\u315F': '\u1171',
+  '\u3160': '\u1172',
+  '\u3161': '\u1173',
+  '\u3162': '\u1174',
+  '\u3163': '\u1175',
+  '\u3164': '\u1160',
+  '\u3165': '\u1114',
+  '\u3166': '\u1115',
+  '\u3167': '\u11C7',
+  '\u3168': '\u11C8',
+  '\u3169': '\u11CC',
+  '\u316A': '\u11CE',
+  '\u316B': '\u11D3',
+  '\u316C': '\u11D7',
+  '\u316D': '\u11D9',
+  '\u316E': '\u111C',
+  '\u316F': '\u11DD',
+  '\u3170': '\u11DF',
+  '\u3171': '\u111D',
+  '\u3172': '\u111E',
+  '\u3173': '\u1120',
+  '\u3174': '\u1122',
+  '\u3175': '\u1123',
+  '\u3176': '\u1127',
+  '\u3177': '\u1129',
+  '\u3178': '\u112B',
+  '\u3179': '\u112C',
+  '\u317A': '\u112D',
+  '\u317B': '\u112E',
+  '\u317C': '\u112F',
+  '\u317D': '\u1132',
+  '\u317E': '\u1136',
+  '\u317F': '\u1140',
+  '\u3180': '\u1147',
+  '\u3181': '\u114C',
+  '\u3182': '\u11F1',
+  '\u3183': '\u11F2',
+  '\u3184': '\u1157',
+  '\u3185': '\u1158',
+  '\u3186': '\u1159',
+  '\u3187': '\u1184',
+  '\u3188': '\u1185',
+  '\u3189': '\u1188',
+  '\u318A': '\u1191',
+  '\u318B': '\u1192',
+  '\u318C': '\u1194',
+  '\u318D': '\u119E',
+  '\u318E': '\u11A1',
+  '\u3200': '\u0028\u1100\u0029',
+  '\u3201': '\u0028\u1102\u0029',
+  '\u3202': '\u0028\u1103\u0029',
+  '\u3203': '\u0028\u1105\u0029',
+  '\u3204': '\u0028\u1106\u0029',
+  '\u3205': '\u0028\u1107\u0029',
+  '\u3206': '\u0028\u1109\u0029',
+  '\u3207': '\u0028\u110B\u0029',
+  '\u3208': '\u0028\u110C\u0029',
+  '\u3209': '\u0028\u110E\u0029',
+  '\u320A': '\u0028\u110F\u0029',
+  '\u320B': '\u0028\u1110\u0029',
+  '\u320C': '\u0028\u1111\u0029',
+  '\u320D': '\u0028\u1112\u0029',
+  '\u320E': '\u0028\u1100\u1161\u0029',
+  '\u320F': '\u0028\u1102\u1161\u0029',
+  '\u3210': '\u0028\u1103\u1161\u0029',
+  '\u3211': '\u0028\u1105\u1161\u0029',
+  '\u3212': '\u0028\u1106\u1161\u0029',
+  '\u3213': '\u0028\u1107\u1161\u0029',
+  '\u3214': '\u0028\u1109\u1161\u0029',
+  '\u3215': '\u0028\u110B\u1161\u0029',
+  '\u3216': '\u0028\u110C\u1161\u0029',
+  '\u3217': '\u0028\u110E\u1161\u0029',
+  '\u3218': '\u0028\u110F\u1161\u0029',
+  '\u3219': '\u0028\u1110\u1161\u0029',
+  '\u321A': '\u0028\u1111\u1161\u0029',
+  '\u321B': '\u0028\u1112\u1161\u0029',
+  '\u321C': '\u0028\u110C\u116E\u0029',
+  '\u321D': '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029',
+  '\u321E': '\u0028\u110B\u1169\u1112\u116E\u0029',
+  '\u3220': '\u0028\u4E00\u0029',
+  '\u3221': '\u0028\u4E8C\u0029',
+  '\u3222': '\u0028\u4E09\u0029',
+  '\u3223': '\u0028\u56DB\u0029',
+  '\u3224': '\u0028\u4E94\u0029',
+  '\u3225': '\u0028\u516D\u0029',
+  '\u3226': '\u0028\u4E03\u0029',
+  '\u3227': '\u0028\u516B\u0029',
+  '\u3228': '\u0028\u4E5D\u0029',
+  '\u3229': '\u0028\u5341\u0029',
+  '\u322A': '\u0028\u6708\u0029',
+  '\u322B': '\u0028\u706B\u0029',
+  '\u322C': '\u0028\u6C34\u0029',
+  '\u322D': '\u0028\u6728\u0029',
+  '\u322E': '\u0028\u91D1\u0029',
+  '\u322F': '\u0028\u571F\u0029',
+  '\u3230': '\u0028\u65E5\u0029',
+  '\u3231': '\u0028\u682A\u0029',
+  '\u3232': '\u0028\u6709\u0029',
+  '\u3233': '\u0028\u793E\u0029',
+  '\u3234': '\u0028\u540D\u0029',
+  '\u3235': '\u0028\u7279\u0029',
+  '\u3236': '\u0028\u8CA1\u0029',
+  '\u3237': '\u0028\u795D\u0029',
+  '\u3238': '\u0028\u52B4\u0029',
+  '\u3239': '\u0028\u4EE3\u0029',
+  '\u323A': '\u0028\u547C\u0029',
+  '\u323B': '\u0028\u5B66\u0029',
+  '\u323C': '\u0028\u76E3\u0029',
+  '\u323D': '\u0028\u4F01\u0029',
+  '\u323E': '\u0028\u8CC7\u0029',
+  '\u323F': '\u0028\u5354\u0029',
+  '\u3240': '\u0028\u796D\u0029',
+  '\u3241': '\u0028\u4F11\u0029',
+  '\u3242': '\u0028\u81EA\u0029',
+  '\u3243': '\u0028\u81F3\u0029',
+  '\u32C0': '\u0031\u6708',
+  '\u32C1': '\u0032\u6708',
+  '\u32C2': '\u0033\u6708',
+  '\u32C3': '\u0034\u6708',
+  '\u32C4': '\u0035\u6708',
+  '\u32C5': '\u0036\u6708',
+  '\u32C6': '\u0037\u6708',
+  '\u32C7': '\u0038\u6708',
+  '\u32C8': '\u0039\u6708',
+  '\u32C9': '\u0031\u0030\u6708',
+  '\u32CA': '\u0031\u0031\u6708',
+  '\u32CB': '\u0031\u0032\u6708',
+  '\u3358': '\u0030\u70B9',
+  '\u3359': '\u0031\u70B9',
+  '\u335A': '\u0032\u70B9',
+  '\u335B': '\u0033\u70B9',
+  '\u335C': '\u0034\u70B9',
+  '\u335D': '\u0035\u70B9',
+  '\u335E': '\u0036\u70B9',
+  '\u335F': '\u0037\u70B9',
+  '\u3360': '\u0038\u70B9',
+  '\u3361': '\u0039\u70B9',
+  '\u3362': '\u0031\u0030\u70B9',
+  '\u3363': '\u0031\u0031\u70B9',
+  '\u3364': '\u0031\u0032\u70B9',
+  '\u3365': '\u0031\u0033\u70B9',
+  '\u3366': '\u0031\u0034\u70B9',
+  '\u3367': '\u0031\u0035\u70B9',
+  '\u3368': '\u0031\u0036\u70B9',
+  '\u3369': '\u0031\u0037\u70B9',
+  '\u336A': '\u0031\u0038\u70B9',
+  '\u336B': '\u0031\u0039\u70B9',
+  '\u336C': '\u0032\u0030\u70B9',
+  '\u336D': '\u0032\u0031\u70B9',
+  '\u336E': '\u0032\u0032\u70B9',
+  '\u336F': '\u0032\u0033\u70B9',
+  '\u3370': '\u0032\u0034\u70B9',
+  '\u33E0': '\u0031\u65E5',
+  '\u33E1': '\u0032\u65E5',
+  '\u33E2': '\u0033\u65E5',
+  '\u33E3': '\u0034\u65E5',
+  '\u33E4': '\u0035\u65E5',
+  '\u33E5': '\u0036\u65E5',
+  '\u33E6': '\u0037\u65E5',
+  '\u33E7': '\u0038\u65E5',
+  '\u33E8': '\u0039\u65E5',
+  '\u33E9': '\u0031\u0030\u65E5',
+  '\u33EA': '\u0031\u0031\u65E5',
+  '\u33EB': '\u0031\u0032\u65E5',
+  '\u33EC': '\u0031\u0033\u65E5',
+  '\u33ED': '\u0031\u0034\u65E5',
+  '\u33EE': '\u0031\u0035\u65E5',
+  '\u33EF': '\u0031\u0036\u65E5',
+  '\u33F0': '\u0031\u0037\u65E5',
+  '\u33F1': '\u0031\u0038\u65E5',
+  '\u33F2': '\u0031\u0039\u65E5',
+  '\u33F3': '\u0032\u0030\u65E5',
+  '\u33F4': '\u0032\u0031\u65E5',
+  '\u33F5': '\u0032\u0032\u65E5',
+  '\u33F6': '\u0032\u0033\u65E5',
+  '\u33F7': '\u0032\u0034\u65E5',
+  '\u33F8': '\u0032\u0035\u65E5',
+  '\u33F9': '\u0032\u0036\u65E5',
+  '\u33FA': '\u0032\u0037\u65E5',
+  '\u33FB': '\u0032\u0038\u65E5',
+  '\u33FC': '\u0032\u0039\u65E5',
+  '\u33FD': '\u0033\u0030\u65E5',
+  '\u33FE': '\u0033\u0031\u65E5',
+  '\uFB00': '\u0066\u0066',
+  '\uFB01': '\u0066\u0069',
+  '\uFB02': '\u0066\u006C',
+  '\uFB03': '\u0066\u0066\u0069',
+  '\uFB04': '\u0066\u0066\u006C',
+  '\uFB05': '\u017F\u0074',
+  '\uFB06': '\u0073\u0074',
+  '\uFB13': '\u0574\u0576',
+  '\uFB14': '\u0574\u0565',
+  '\uFB15': '\u0574\u056B',
+  '\uFB16': '\u057E\u0576',
+  '\uFB17': '\u0574\u056D',
+  '\uFB4F': '\u05D0\u05DC',
+  '\uFE49': '\u203E',
+  '\uFE4A': '\u203E',
+  '\uFE4B': '\u203E',
+  '\uFE4C': '\u203E',
+  '\uFE4D': '\u005F',
+  '\uFE4E': '\u005F',
+  '\uFE4F': '\u005F'
+};
+
+function fontCharsToUnicode(charCodes, fontProperties) {
+  var toUnicode = fontProperties.toUnicode;
+  var composite = fontProperties.composite;
+  var encoding, differences, cidToUnicode;
+  var result = '';
+  if (composite) {
+    cidToUnicode = fontProperties.cidToUnicode;
+    for (var i = 0, ii = charCodes.length; i < ii; i += 2) {
+      var charCode = (charCodes.charCodeAt(i) << 8) |
+        charCodes.charCodeAt(i + 1);
+      if (toUnicode && charCode in toUnicode) {
+        var unicode = toUnicode[charCode];
+        result += typeof unicode !== 'number' ? unicode :
+          String.fromCharCode(unicode);
+        continue;
+      }
+      result += String.fromCharCode(!cidToUnicode ? charCode :
+        cidToUnicode[charCode] || charCode);
+    }
+  } else {
+    differences = fontProperties.differences;
+    encoding = fontProperties.baseEncoding;
+    for (var i = 0, ii = charCodes.length; i < ii; i++) {
+      var charCode = charCodes.charCodeAt(i);
+      var unicode;
+      if (toUnicode && charCode in toUnicode) {
+        var unicode = toUnicode[charCode];
+        result += typeof unicode !== 'number' ? unicode :
+          String.fromCharCode(unicode);
+        continue;
+      }
+
+      var glyphName = charCode in differences ? differences[charCode] :
+        encoding[charCode];
+      if (glyphName in GlyphsUnicode) {
+        result += String.fromCharCode(GlyphsUnicode[glyphName]);
+        continue;
+      }
+      result += String.fromCharCode(charCode);
+    }
+  }
+  // normalizing the unicode characters
+  for (var i = 0, ii = result.length; i < ii; i++) {
+    if (!(result[i] in NormalizedUnicodes))
+      continue;
+    result = result.substring(0, i) + NormalizedUnicodes[result[i]] +
+      result.substring(i + 1);
+    ii = result.length;
+  }
+  return result;
+}
+
 /**
  * 'Font' is the class the outside world should use, it encapsulate all the font
  * decoding logics whatever type it is (assuming the font type is supported).
  *
  * For example to read a Type1 font and to attach it to the document:
  *   var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
  *   type1Font.bind();
  */
@@ -15756,19 +16678,19 @@ var Font = (function FontClosure() {
             minUnicode = Math.min(minUnicode, unicode);
             maxUnicode = Math.max(maxUnicode, unicode);
           }
           // high byte must be the same for min and max unicodes
           if ((maxUnicode & 0xFF00) != (minUnicode & 0xFF00))
             this.isSymbolicFont = false;
         }
 
-        // heuristics: if removed more than 2 glyphs encoding WinAnsiEncoding
-        // does not set properly
-        if (glyphsRemoved > 2) {
+        // heuristics: if removed more than 10 glyphs encoding WinAnsiEncoding
+        // does not set properly (broken PDFs have about 100 removed glyphs)
+        if (glyphsRemoved > 10) {
           warn('Switching TrueType encoding to MacRomanEncoding for ' +
                this.name + ' font');
           encoding = Encodings.MacRomanEncoding;
         }
 
         if (hasShortCmap && this.hasEncoding && !this.isSymbolicFont) {
           // Re-encode short map encoding to unicode -- that simplifies the
           // resolution of MacRoman encoded glyphs logic for TrueType fonts:
@@ -16258,16 +17180,17 @@ var Font = (function FontClosure() {
           }
           if (!this.hasEncoding || this.isSymbolicFont) {
             fontCharCode = this.useToFontChar ? this.toFontChar[charcode] :
               charcode;
             break;
           }
 
           // MacRoman encoding address by re-encoding the cmap table
+
           fontCharCode = glyphName in this.glyphNameMap ?
             this.glyphNameMap[glyphName] : GlyphsUnicode[glyphName];
           break;
         default:
           warn('Unsupported font type: ' + this.type);
           break;
       }
 
@@ -17428,17 +18351,17 @@ var CFFParser = (function CFFParserClosu
     parseHeader: function CFFParser_parseHeader() {
       var bytes = this.bytes;
       var offset = 0;
 
       while (bytes[offset] != 1)
         ++offset;
 
       if (offset != 0) {
-        warn('cff data is shifted');
+        info('cff data is shifted');
         bytes = bytes.subarray(offset);
         this.bytes = bytes;
       }
       var major = bytes[0];
       var minor = bytes[1];
       var hdrSize = bytes[2];
       var offSize = bytes[3];
       var header = new CFFHeader(major, minor, hdrSize, offSize);
@@ -28664,17 +29587,17 @@ var CCITTFaxStream = (function CCITTFaxS
 
   CCITTFaxStream.prototype.addPixels =
     function ccittFaxStreamAddPixels(a1, blackPixels) {
     var codingLine = this.codingLine;
     var codingPos = this.codingPos;
 
     if (a1 > codingLine[codingPos]) {
       if (a1 > this.columns) {
-        warn('row is wrong length');
+        info('row is wrong length');
         this.err = true;
         a1 = this.columns;
       }
       if ((codingPos & 1) ^ blackPixels) {
         ++codingPos;
       }
 
       codingLine[codingPos] = a1;
@@ -28684,27 +29607,27 @@ var CCITTFaxStream = (function CCITTFaxS
 
   CCITTFaxStream.prototype.addPixelsNeg =
     function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
     var codingLine = this.codingLine;
     var codingPos = this.codingPos;
 
     if (a1 > codingLine[codingPos]) {
       if (a1 > this.columns) {
-        warn('row is wrong length');
+        info('row is wrong length');
         this.err = true;
         a1 = this.columns;
       }
       if ((codingPos & 1) ^ blackPixels)
         ++codingPos;
 
       codingLine[codingPos] = a1;
     } else if (a1 < codingLine[codingPos]) {
       if (a1 < 0) {
-        warn('invalid code');
+        info('invalid code');
         this.err = true;
         a1 = 0;
       }
       while (codingPos > 0 && a1 < codingLine[codingPos - 1])
         --codingPos;
       codingLine[codingPos] = a1;
     }
 
@@ -28856,17 +29779,17 @@ var CCITTFaxStream = (function CCITTFaxS
                   refPos += 2;
               }
               break;
             case EOF:
               this.addPixels(columns, 0);
               this.eof = true;
               break;
             default:
-              warn('bad 2d code');
+              info('bad 2d code');
               this.addPixels(columns, 0);
               this.err = true;
           }
         }
       } else {
         codingLine[0] = 0;
         this.codingPos = 0;
         blackPixels = 0;
@@ -28919,17 +29842,17 @@ var CCITTFaxStream = (function CCITTFaxS
           if (this.encoding > 0) {
             this.lookBits(1);
             this.eatBits(1);
           }
           if (this.encoding >= 0) {
             for (var i = 0; i < 4; ++i) {
               code1 = this.lookBits(12);
               if (code1 != 1)
-                warn('bad rtc code: ' + code1);
+                info('bad rtc code: ' + code1);
               this.eatBits(12);
               if (this.encoding > 0) {
                 this.lookBits(1);
                 this.eatBits(1);
               }
             }
           }
           this.eof = true;
@@ -29042,17 +29965,17 @@ var CCITTFaxStream = (function CCITTFaxS
         this.eatBits(p[0]);
         return p[1];
       }
     } else {
       var result = this.findTableCode(1, 7, twoDimTable);
       if (result[0] && result[2])
         return result[1];
     }
-    warn('Bad two dim code');
+    info('Bad two dim code');
     return EOF;
   };
 
   CCITTFaxStream.prototype.getWhiteCode =
     function ccittFaxStreamGetWhiteCode() {
 
     var code = 0;
     var p;
@@ -29075,17 +29998,17 @@ var CCITTFaxStream = (function CCITTFaxS
       var result = this.findTableCode(1, 9, whiteTable2);
       if (result[0])
         return result[1];
 
       result = this.findTableCode(11, 12, whiteTable1);
       if (result[0])
         return result[1];
     }
-    warn('bad white code');
+    info('bad white code');
     this.eatBits(1);
     return 1;
   };
 
   CCITTFaxStream.prototype.getBlackCode =
     function ccittFaxStreamGetBlackCode() {
 
     var code, p;
@@ -29112,17 +30035,17 @@ var CCITTFaxStream = (function CCITTFaxS
       result = this.findTableCode(7, 12, blackTable2, 64);
       if (result[0])
         return result[1];
 
       result = this.findTableCode(10, 13, blackTable1);
       if (result[0])
         return result[1];
     }
-    warn('bad black code');
+    info('bad black code');
     this.eatBits(1);
     return 1;
   };
 
   CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) {
     var c;
     while (this.inputBits < n) {
       if ((c = this.str.getByte()) == null) {
@@ -29283,20 +30206,23 @@ var LZWStream = (function LZWStreamClosu
 function MessageHandler(name, comObj) {
   this.name = name;
   this.comObj = comObj;
   this.callbackIndex = 1;
   var callbacks = this.callbacks = {};
   var ah = this.actionHandler = {};
 
   ah['console_log'] = [function ahConsoleLog(data) {
-      console.log.apply(console, data);
+    console.log.apply(console, data);
   }];
   ah['console_error'] = [function ahConsoleError(data) {
-      console.error.apply(console, data);
+    console.error.apply(console, data);
+  }];
+  ah['_warn'] = [function ah_Warn(data) {
+    warn(data);
   }];
 
   comObj.onmessage = function messageHandlerComObjOnMessage(event) {
     var data = event.data;
     if (data.isReply) {
       var callbackId = data.callbackId;
       if (data.callbackId in callbacks) {
         var callback = callbacks[callbackId];
@@ -29416,17 +30342,16 @@ var WorkerMessageHandler = {
         pageIndex: data.pageIndex,
         annotations: pdfPage.getAnnotations()
       });
     });
 
     handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
       var pageNum = data.pageIndex + 1;
 
-
       // The following code does quite the same as
       // Page.prototype.startRendering, but stops at one point and sends the
       // result back to the main thread.
       var gfx = new CanvasGraphics(null);
 
       var start = Date.now();
 
       var dependency = [];
@@ -29476,16 +30401,34 @@ var WorkerMessageHandler = {
         }
       }
       handler.send('RenderPage', {
         pageIndex: data.pageIndex,
         operatorList: operatorList,
         depFonts: Object.keys(fonts)
       });
     }, this);
+
+    handler.on('GetTextContent', function wphExtractText(data, promise) {
+      var pageNum = data.pageIndex + 1;
+      var start = Date.now();
+
+      var textContent = '';
+      try {
+        var page = pdfModel.getPage(pageNum);
+        textContent = page.extractTextContent();
+        promise.resolve(textContent);
+      } catch (e) {
+        // Skip errored pages
+        promise.reject(e);
+      }
+
+      console.log('text indexing: page=%d - time=%dms',
+                      pageNum, Date.now() - start);
+    });
   }
 };
 
 var consoleTimer = {};
 
 var workerConsole = {
   log: function log() {
     var args = Array.prototype.slice.call(arguments);
@@ -29516,16 +30459,27 @@ var workerConsole = {
     this.log('Timer:', name, Date.now() - time);
   }
 };
 
 // Worker thread?
 if (typeof window === 'undefined') {
   globalScope.console = workerConsole;
 
+  // Add a logger so we can pass warnings on to the main thread, errors will
+  // throw an exception which will be forwarded on automatically.
+  PDFJS.LogManager.addLogger({
+    warn: function(msg) {
+      postMessage({
+        action: '_warn',
+        data: msg
+      });
+    }
+  });
+
   var handler = new MessageHandler('worker_processor', this);
   WorkerMessageHandler.setup(handler);
 }
 
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
@@ -32841,60 +33795,68 @@ var Metadata = PDFJS.Metadata = (functio
     <script type="text/javascript" src="viewer.js"></script>
   </head>
 
   <body>
     <div id="outerContainer">
 
       <div id="sidebarContainer">
         <div id="toolbarSidebar">
-          <div class="splitToolbarButton toggled">
-            <button id="viewThumbnail" class="toolbarButton toggled" title="Show Thumbnails" onclick="PDFView.switchSidebarView('thumbs')" tabindex="1" data-l10n-id="thumbs">
-               <span data-l10n-id="thumbs_label">Thumbnails</span>
-            </button>
-            <button id="viewOutline" class="toolbarButton" title="Show Document Outline" onclick="PDFView.switchSidebarView('outline')" tabindex="2" data-l10n-id="outline">
-               <span data-l10n-id="outline_label">Document Outline</span>
-            </button>
-          </div>
+          <button id="viewThumbnail" class="toolbarButton group toggled" title="Show Thumbnails" onclick="PDFView.switchSidebarView('thumbs')" 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" onclick="PDFView.switchSidebarView('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" onclick="PDFView.switchSidebarView('search')" tabindex="3" data-l10n-id="search">
+             <span data-l10n-id="search_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" onkeydown='if (event.keyCode == 13) PDFView.search()'>
+              <button id="searchButton" onclick='PDFView.search()' data-l10n-id="search_button">Find</button>
+            </div>
+            <div id="searchResults"></div>
+          </div>
         </div>
       </div>  <!-- sidebarContainer -->
 
       <div id="mainContainer">
         <div class="toolbar">
           <div id="toolbarContainer">
 
             <div id="toolbarViewer">
               <div id="toolbarViewerLeft">
-                <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="3" data-l10n-id="toggle_slider">
+                <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="4" data-l10n-id="toggle_slider">
                   <span data-l10n-id="toggle_slider_label">Toggle Sidebar</span>
                 </button>
                 <div class="toolbarButtonSpacer"></div>
                 <div class="splitToolbarButton">
-                  <button class="toolbarButton pageUp" title="Previous Page" onclick="PDFView.page--" id="previous" tabindex="4" data-l10n-id="previous">
+                  <button class="toolbarButton pageUp" title="Previous Page" onclick="PDFView.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" onclick="PDFView.page++" id="next" tabindex="5" data-l10n-id="next">
+                  <button class="toolbarButton pageDown" title="Next Page" onclick="PDFView.page++" id="next" tabindex="6" data-l10n-id="next">
                     <span data-l10n-id="next_label">Next</span>
                   </button>
                 </div>
                 <label id="pageNumberLabel" class="toolbarLabel" for="pageNumber" data-l10n-id="page_label">Page: </label>
-                <input type="number" id="pageNumber" class="toolbarField pageNumber" onchange="PDFView.page = this.value;" value="1" size="4" min="1" tabindex="6">
+                <input type="number" id="pageNumber" class="toolbarField pageNumber" onchange="PDFView.page = this.value;" value="1" size="4" min="1" tabindex="7">
                 </input>
                 <span id="numPages" class="toolbarLabel"></span>
               </div>
               <div id="toolbarViewerRight">
                 <input id="fileInput" class="fileInput" type="file" oncontextmenu="return false;" style="visibility: hidden; position: fixed; right: 0; top: 0" />
-                <button id="openFile" class="toolbarButton openFile" title="Open File" tabindex="10" data-l10n-id="open_file" onclick="document.getElementById('fileInput').click()">
+                <button id="openFile" class="toolbarButton openFile" title="Open File" tabindex="11" data-l10n-id="open_file" onclick="document.getElementById('fileInput').click()">
                    <span data-l10n-id="open_file_label">Open</span>
                 </button>
 
                 <!--
                 <button id="print" class="toolbarButton print" title="Print" tabindex="11" data-l10n-id="print" onclick="window.print()">
                   <span data-l10n-id="print_label">Print</span>
                 </button>
                 -->
@@ -32903,26 +33865,26 @@ var Metadata = PDFJS.Metadata = (functio
                   <span data-l10n-id="download_label">Download</span>
                 </button>
                 <!-- <div class="toolbarButtonSpacer"></div> -->
                 <a href="#" id="viewBookmark" class="toolbarButton bookmark" title="Current view (copy or open in new window)" tabindex="13" data-l10n-id="bookmark"><span data-l10n-id="bookmark_label">Current View</span></a>
               </div>
               <div class="outerCenter">
                 <div class="innerCenter" id="toolbarViewerMiddle">
                   <div class="splitToolbarButton">
-                    <button class="toolbarButton zoomOut" title="Zoom Out" onclick="PDFView.zoomOut();" tabindex="7" data-l10n-id="zoom_out">
+                    <button class="toolbarButton zoomOut" title="Zoom Out" onclick="PDFView.zoomOut();" tabindex="8" data-l10n-id="zoom_out">
                       <span data-l10n-id="zoom_out_label">Zoom Out</span>
                     </button>
                     <div class="splitToolbarButtonSeparator"></div>
-                    <button class="toolbarButton zoomIn" title="Zoom In" onclick="PDFView.zoomIn();" tabindex="8" data-l10n-id="zoom_in">
+                    <button class="toolbarButton zoomIn" title="Zoom In" onclick="PDFView.zoomIn();" tabindex="9" data-l10n-id="zoom_in">
                       <span data-l10n-id="zoom_in_label">Zoom In</span>
                      </button>
                   </div>
                   <span id="scaleSelectContainer" class="dropdownToolbarButton">
-                     <select id="scaleSelect" onchange="PDFView.parseScale(this.value);" title="Zoom" oncontextmenu="return false;" tabindex="9" data-l10n-id="zoom">
+                     <select id="scaleSelect" onchange="PDFView.parseScale(this.value);" title="Zoom" oncontextmenu="return false;" tabindex="10" data-l10n-id="zoom">
                       <option id="pageAutoOption" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
                       <option id="pageActualOption" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
                       <option id="pageFitOption" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
                       <option id="pageWidthOption" value="page-width" data-l10n-id="page_scale_width">Full Width</option>
                       <option id="customScaleOption" value="custom"></option>
                       <option value="0.5">50%</option>
                       <option value="0.75">75%</option>
                       <option value="1">100%</option>
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -214,18 +214,21 @@ var renderingQueue = new RenderingQueue(
 var currentPageNumber = 1;
 
 var PDFView = {
   pages: [],
   thumbnails: [],
   currentScale: kUnknownScale,
   currentScaleValue: null,
   initialBookmark: document.location.hash.substring(1),
+  startedTextExtraction: false,
+  pageText: [],
   container: null,
   initialized: false,
+  fellback: false,
   // called once when the document is loaded
   initialize: function pdfViewInitialize() {
     this.container = document.getElementById('viewerContainer');
     this.initialized = true;
   },
 
   setScale: function pdfViewSetScale(val, resetAutoSettings) {
     if (val == this.currentScale)
@@ -385,16 +388,28 @@ var PDFView = {
     if (PDFJS.isFirefoxExtension) {
       FirefoxCom.request('download', url);
     } else {
       url += '#pdfjs.action=download', '_parent';
       window.open(url, '_parent');
     }
   },
 
+  fallback: function pdfViewFallback() {
+    if (!PDFJS.isFirefoxExtension)
+      return;
+    // Only trigger the fallback once so we don't spam the user with messages
+    // for one PDF.
+    if (this.fellback)
+      return;
+    this.fellback = true;
+    var url = this.url.split('#')[0];
+    FirefoxCom.request('fallback', url);
+  },
+
   navigateTo: function pdfViewNavigateTo(dest) {
     if (typeof dest === 'string')
       dest = this.destinations[dest];
     if (!(dest instanceof Array))
       return; // invalid destination
     // dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
     var destRef = dest[0];
     var pageNumber = destRef instanceof Object ?
@@ -447,16 +462,44 @@ var PDFView = {
   /**
    * Show the error box.
    * @param {String} message A message that is human readable.
    * @param {Object} moreInfo (optional) Further information about the error
    *                            that is more technical.  Should have a 'message'
    *                            and optionally a 'stack' property.
    */
   error: function pdfViewError(message, moreInfo) {
+    var moreInfoText = mozL10n.get('error_build', {build: PDFJS.build},
+      'PDF.JS Build: {{build}}') + '\n';
+    if (moreInfo) {
+      moreInfoText +=
+        mozL10n.get('error_message', {message: moreInfo.message},
+        'Message: {{message}}');
+      if (moreInfo.stack) {
+        moreInfoText += '\n' +
+          mozL10n.get('error_stack', {stack: moreInfo.stack},
+          'Stack: {{stack}}');
+      } else {
+        if (moreInfo.filename) {
+          moreInfoText += '\n' +
+            mozL10n.get('error_file', {file: moreInfo.filename},
+            'File: {{file}}');
+        }
+        if (moreInfo.lineNumber) {
+          moreInfoText += '\n' +
+            mozL10n.get('error_line', {line: moreInfo.lineNumber},
+            'Line: {{line}}');
+        }
+      }
+    }
+    if (PDFJS.isFirefoxExtension) {
+      console.error(message + '\n' + moreInfoText);
+      this.fallback();
+      return;
+    }
     var errorWrapper = document.getElementById('errorWrapper');
     errorWrapper.removeAttribute('hidden');
 
     var errorMessage = document.getElementById('errorMessage');
     errorMessage.textContent = message;
 
     var closeButton = document.getElementById('errorClose');
     closeButton.onclick = function() {
@@ -473,42 +516,19 @@ var PDFView = {
     };
     lessInfoButton.onclick = function() {
       errorMoreInfo.setAttribute('hidden', 'true');
       moreInfoButton.removeAttribute('hidden');
       lessInfoButton.setAttribute('hidden', 'true');
     };
     moreInfoButton.removeAttribute('hidden');
     lessInfoButton.setAttribute('hidden', 'true');
-    errorMoreInfo.value =
-      mozL10n.get('error_build', {build: PDFJS.build},
-      'PDF.JS Build: {{build}}') + '\n';
+    errorMoreInfo.value = moreInfoText;
 
-    if (moreInfo) {
-      errorMoreInfo.value +=
-        mozL10n.get('error_message', {message: moreInfo.message},
-        'Message: {{message}}');
-      if (moreInfo.stack) {
-        errorMoreInfo.value += '\n' +
-          mozL10n.get('error_stack', {stack: moreInfo.stack},
-          'Stack: {{stack}}');
-      } else {
-        if (moreInfo.filename) {
-          errorMoreInfo.value += '\n' +
-            mozL10n.get('error_file', {file: moreInfo.filename},
-            'File: {{file}}');
-        }
-        if (moreInfo.lineNumber) {
-          errorMoreInfo.value += '\n' +
-            mozL10n.get('error_line', {line: moreInfo.lineNumber},
-            'Line: {{line}}');
-        }
-      }
-    }
-    errorMoreInfo.rows = errorMoreInfo.value.split('\n').length - 1;
+    errorMoreInfo.rows = moreInfoText.split('\n').length - 1;
   },
 
   progress: function pdfViewProgress(level) {
     var percent = Math.round(level * 100);
     var loadingIndicator = document.getElementById('loading');
     loadingIndicator.textContent = mozL10n.get('loading', {percent: percent},
       'Loading... {{percent}}%');
 
@@ -556,16 +576,18 @@ var PDFView = {
       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 pages = this.pages = [];
+    this.pageText = [];
+    this.startedTextExtraction = false;
     var pagesRefMap = {};
     var thumbnails = this.thumbnails = [];
     var pagePromises = [];
     for (var i = 1; i <= pagesCount; i++)
       pagePromises.push(pdfDocument.getPage(i));
     var self = this;
     var pagesPromise = PDFJS.Promise.all(pagePromises);
     pagesPromise.then(function(promisedPages) {
@@ -636,16 +658,77 @@ var PDFView = {
 
     if (PDFView.currentScale === kUnknownScale) {
       // Scale was not initialized: invalid bookmark or scale was not specified.
       // Setting the default one.
       this.parseScale(kDefaultScale, true);
     }
   },
 
+  search: function pdfViewStartSearch() {
+    // Limit this function to run every <SEARCH_TIMEOUT>ms.
+    var SEARCH_TIMEOUT = 250;
+    var lastSeach = this.lastSearch;
+    var now = Date.now();
+    if (lastSeach && (now - lastSeach) < SEARCH_TIMEOUT) {
+      if (!this.searchTimer) {
+        this.searchTimer = setTimeout(function resumeSearch() {
+            PDFView.search();
+          },
+          SEARCH_TIMEOUT - (now - lastSeach)
+        );
+      }
+      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 = '(Not found)';
+    }
+  },
+
   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) {
@@ -678,36 +761,80 @@ 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 thumbsSwitchButton = document.getElementById('viewThumbnail');
-    var outlineSwitchButton = document.getElementById('viewOutline');
+    var searchView = document.getElementById('searchView');
 
-    if (outlineSwitchButton.getAttribute('disabled'))
-      return;
-
-    thumbsView.classList.toggle('hidden');
-    outlineView.classList.toggle('hidden');
-    document.getElementById('viewThumbnail').classList.toggle('toggled');
-    document.getElementById('viewOutline').classList.toggle('toggled');
+    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');
+
         updateThumbViewArea();
         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;
+          self.search();
+          if ((pageIndex + 1) < self.pages.length)
+            extractPageText(pageIndex + 1);
+        }
+      );
+    };
+    extractPageText(0);
+  },
+
   getVisiblePages: function pdfViewGetVisiblePages() {
     var pages = this.pages;
     var kBottomMargin = 10;
     var kTopPadding = 30;
     var visiblePages = [];
 
     var currentHeight = kTopPadding + kBottomMargin;
     var container = this.container;
@@ -911,16 +1038,20 @@ var PageView = function pageView(contain
               bindLink(link, ('dest' in item) ? item.dest : null);
             div.appendChild(link);
             break;
           case 'Text':
             var comment = createCommentAnnotation(item.name, item);
             if (comment)
               div.appendChild(comment);
             break;
+          case 'Widget':
+            // TODO: support forms
+            PDFView.fallback();
+            break;
         }
       }
     });
   }
 
   this.getPagePoint = function pageViewGetPagePoint(x, y) {
     return this.viewport.convertToPdfPoint(x, y);
   };
@@ -1392,16 +1523,29 @@ window.addEventListener('load', function
       (!PDFJS.isFirefoxExtension || FirefoxCom.request('pdfBugEnabled'))) {
     PDFJS.pdfBug = true;
     var pdfBug = hashParams['pdfBug'];
     var enabled = pdfBug.split(',');
     PDFBug.enable(enabled);
     PDFBug.init();
   }
 
+  if (!PDFJS.isFirefoxExtension ||
+    (PDFJS.isFirefoxExtension && FirefoxCom.request('searchEnabled'))) {
+    document.querySelector('#viewSearch').classList.remove('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();
+    }
+  });
+
   var thumbsView = document.getElementById('thumbnailView');
   thumbsView.addEventListener('scroll', updateThumbViewArea, true);
 
   var mainContainer = document.getElementById('mainContainer');
   var outerContainer = document.getElementById('outerContainer');
   mainContainer.addEventListener('transitionend', function(e) {
     if (e.target == mainContainer) {
       var event = document.createEvent('UIEvents');
--- a/browser/extensions/pdfjs/extension-files
+++ b/browser/extensions/pdfjs/extension-files
@@ -1,28 +1,27 @@
-bootstrap.js
-icon.png
-icon64.png
 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/loading-icon.gif
 content/web/images/texture.png
 content/web/images/toolbarButton-bookmark.png
 content/web/images/toolbarButton-download.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
 content/web/images/toolbarButton-pageUp-rtl.png
 content/web/images/toolbarButton-pageUp.png
 content/web/images/toolbarButton-print.png
+content/web/images/toolbarButton-search.png
 content/web/images/toolbarButton-sidebarToggle.png
 content/web/images/toolbarButton-viewOutline.png
 content/web/images/toolbarButton-viewThumbnail.png
 content/web/images/toolbarButton-zoomIn.png
 content/web/images/toolbarButton-zoomOut.png
 content/web/l10n.js
 content/web/viewer.css
 content/web/viewer.html
--- a/browser/extensions/pdfjs/test/Makefile.in
+++ b/browser/extensions/pdfjs/test/Makefile.in
@@ -8,13 +8,14 @@ srcdir    = @srcdir@
 VPATH     = @srcdir@
 relativesrcdir  = browser/extensions/pdfjs/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
   browser_pdfjs_main.js \
+  browser_pdfjs_savedialog.js \
   file_pdfjs_test.pdf \
   $(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir) 
--- a/browser/extensions/pdfjs/test/browser_pdfjs_main.js
+++ b/browser/extensions/pdfjs/test/browser_pdfjs_main.js
@@ -1,40 +1,50 @@
 /* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const RELATIVE_DIR = "browser/extensions/pdfjs/test/";
 const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
 
 function test() {
   var tab;
 
+  let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
+  let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+  let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
+
+  // Make sure pdf.js is the default handler.
+  is(handlerInfo.alwaysAskBeforeHandling, false, 'pdf handler defaults to always-ask is false');
+  is(handlerInfo.preferredAction, Ci.nsIHandlerInfo.handleInternally, 'pdf handler defaults to internal');
+
+  info('Pref action: ' + handlerInfo.preferredAction);
+
   waitForExplicitFinish();
   registerCleanupFunction(function() {
     gBrowser.removeTab(tab);
   });
 
   tab = gBrowser.addTab(TESTROOT + "file_pdfjs_test.pdf");
   var newTabBrowser = gBrowser.getBrowserForTab(tab);
   newTabBrowser.addEventListener("load", function eventHandler() {
     newTabBrowser.removeEventListener("load", eventHandler, true);
 
     var document = newTabBrowser.contentDocument,
         window = newTabBrowser.contentWindow;
 
     // Runs tests after all 'load' event handlers have fired off
     setTimeout(function() {
-      runTests(document, window);
+      runTests(document, window, finish);
     }, 0);
   }, true);
 }
 
 
-function runTests(document, window) {
+function runTests(document, window, callback) {
+
   //
   // Overall sanity tests
   //
   ok(document.querySelector('div#viewer'), "document content has viewer UI");
   ok('PDFJS' in window.wrappedJSObject, "window content has PDFJS object");
 
   //
   // Sidebar: open
@@ -62,10 +72,10 @@ function runTests(document, window) {
 
   //
   // Bookmark button
   //
   var viewBookmark = document.querySelector('a#viewBookmark');
   viewBookmark.click();
   ok(viewBookmark.href.length > 0, 'viewBookmark button has href');
 
-  finish();
+  callback();
 }
new file mode 100644
--- /dev/null
+++ b/browser/extensions/pdfjs/test/browser_pdfjs_savedialog.js
@@ -0,0 +1,65 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "browser/extensions/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+function test() {
+  var oldAction = changeMimeHandler(Ci.nsIHandlerInfo.useSystemDefault, true);
+  var tab = gBrowser.addTab(TESTROOT + "file_pdfjs_test.pdf");
+  //
+  // Test: "Open with" dialog comes up when pdf.js is not selected as the default
+  // handler.
+  //
+  addWindowListener('chrome://mozapps/content/downloads/unknownContentType.xul', finish);
+
+  waitForExplicitFinish();
+  registerCleanupFunction(function() {
+    changeMimeHandler(oldAction[0], oldAction[1]);
+    gBrowser.removeTab(tab);
+  });
+}
+
+function changeMimeHandler(preferredAction, alwaysAskBeforeHandling) {
+  let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
+  let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+  let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
+  var oldAction = [handlerInfo.preferredAction, handlerInfo.alwaysAskBeforeHandling];
+
+  // Change and save mime handler settings
+  handlerInfo.alwaysAskBeforeHandling = alwaysAskBeforeHandling;
+  handlerInfo.preferredAction = preferredAction;
+  handlerService.store(handlerInfo);
+
+  Services.obs.notifyObservers(null, 'pdfjs:handlerChanged', null);
+
+  // Refresh data
+  handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
+
+  //
+  // Test: Mime handler was updated
+  //
+  is(handlerInfo.alwaysAskBeforeHandling, alwaysAskBeforeHandling, 'always-ask prompt change successful');
+  is(handlerInfo.preferredAction, preferredAction, 'mime handler change successful');
+
+  return oldAction;
+}
+
+function addWindowListener(aURL, aCallback) {
+  Services.wm.addListener({
+    onOpenWindow: function(aXULWindow) {
+      info("window opened, waiting for focus");
+      Services.wm.removeListener(this);
+
+      var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                                .getInterface(Ci.nsIDOMWindow);
+      waitForFocus(function() {
+        is(domwindow.document.location.href, aURL, "should have seen the right window open");
+        domwindow.close();
+        aCallback();
+      }, domwindow);
+    },
+    onCloseWindow: function(aXULWindow) { },
+    onWindowTitleChange: function(aXULWindow, aNewTitle) { }
+  });
+}
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -58,16 +58,17 @@ useDefault=Use %S (default)
 
 useOtherApp=Use other…
 fpTitleChooseApp=Select Helper Application
 manageApp=Application Details…
 webFeed=Web Feed
 videoPodcastFeed=Video Podcast
 audioPodcastFeed=Podcast
 alwaysAsk=Always ask
+portableDocumentFormat=Portable Document Format (PDF)
 
 # LOCALIZATION NOTE (usePluginIn):
 # %1$S = plugin name (for example "QuickTime Plugin-in 7.2")
 # %2$S = brandShortName from brand.properties (for example "Minefield")
 usePluginIn=Use %S (in %S)
 
 # LOCALIZATION NOTE (previewInApp, addLiveBookmarksInApp): %S = brandShortName
 previewInApp=Preview in %S
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/pdfviewer/chrome.properties
@@ -0,0 +1,3 @@
+# Chrome notification bar messages and buttons
+unsupported_feature=This PDF document might not be displayed correctly.
+open_with_different_viewer=Open With Different Viewer
--- a/browser/locales/en-US/pdfviewer/viewer.properties
+++ b/browser/locales/en-US/pdfviewer/viewer.properties
@@ -1,46 +1,91 @@
-bookmark.title=Current view (copy or open in new window)
+# 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.
+# Do not translate "{{pageCount}}", it will be substituted with a number
+# representing the total number of pages.
+page_label=Page:
+page_of=of {{pageCount}}
+
+zoom_out.title=Zoom Out
+zoom_out_label=Zoom Out
+zoom_in.title=Zoom In
+zoom_in_label=Zoom In
+zoom.title=Zoom
 print.title=Print
+print_label=Print
+open_file.title=Open File
+open_file_label=Open
 download.title=Download
-zoom_out.title=Zoom Out
-zoom_in.title=Zoom In
+download_label=Download
+bookmark.title=Current view (copy or open in new window)
+bookmark_label=Current View
+
+# Tooltips and alt text for side panel toolbar buttons
+# (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
+
+# 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}}
+
+# Search panel button title and messages
+search=Find
+search_terms_not_found=(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}}
+# LOCALIZATION NOTE (error_message): "{{message}}" will be replaced by an
+# english string describing the error.
 error_message=Message: {{message}}
+# LOCALIZATION NOTE (error_stack): "{{stack}}" will be replaced with a stack
+# trace.
 error_stack=Stack: {{stack}}
+# LOCALIZATION NOTE (error_file): "{{file}}" will be replaced with a filename
 error_file=File: {{file}}
+# LOCALIZATION NOTE (error_line): "{{line}}" will be replaced with a line number
 error_line=Line: {{line}}
+rendering_error=An error occurred while rendering the page.
+
+# Predefined zoom values
 page_scale_width=Page Width
 page_scale_fit=Page Fit
 page_scale_auto=Automatic Zoom
 page_scale_actual=Actual Size
-toggle_slider.title=Toggle Slider
-thumbs.title=Show Thumbnails
-outline.title=Show Document Outline
-loading=Loading... {{percent}}%
+
+# Loading indicator messages
+# LOCALIZATION NOTE (error_line): "{{[percent}}" will be replaced with a percentage
+loading=Loading… {{percent}}%
 loading_error_indicator=Error
 loading_error=An error occurred while loading the PDF.
-rendering_error=An error occurred while rendering the page.
-page_label=Page:
-page_of=of {{pageCount}}
-no_outline=No Outline Available
-open_file.title=Open File
+
+# LOCALIZATION NOTE (text_annotation_type): This is used as a tooltip.
+# "{{[type}}" will be replaced with an annotation type from a list defined in
+# the PDF spec (32000-1:2008 Table 169 – Annotation types).
+# Some common types are e.g.: "Check", "Text", "Comment", "Note"
 text_annotation_type=[{{type}} Annotation]
-toggle_slider_label=Toggle Slider
-thumbs_label=Thumbnails
-outline_label=Document Outline
-bookmark_label=Current View
-previous_label=Previous
-next_label=Next
-print_label=Print
-download_label=Download
-zoom_out_label=Zoom Out
-zoom_in_label=Zoom In
-zoom.title=Zoom
-thumb_page_title=Page {{page}}
-thumb_page_canvas=Thumbnail of Page {{page}}
 request_password=PDF is protected by a password:
-open_file_label=Open
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -111,13 +111,16 @@
 *   locale/browser/appstrings.properties       (%chrome/overrides/appstrings.properties)
 *   locale/browser/downloads/settingsChange.dtd  (%chrome/overrides/settingsChange.dtd)
 % override chrome://global/locale/netError.dtd chrome://browser/locale/netError.dtd
 % override chrome://global/locale/appstrings.properties chrome://browser/locale/appstrings.properties
 % override chrome://mozapps/locale/downloads/settingsChange.dtd chrome://browser/locale/downloads/settingsChange.dtd
 % locale testpilot @AB_CD@ %locale/feedback/
     locale/feedback/main.dtd                       (%feedback/main.dtd)
     locale/feedback/main.properties                (%feedback/main.properties)
+% locale pdf.js @AB_CD@ %locale/pdfviewer/
+    locale/pdfviewer/viewer.properties             (%pdfviewer/viewer.properties)
+    locale/pdfviewer/chrome.properties             (%pdfviewer/chrome.properties)
 #ifdef MOZ_WEBAPP_RUNTIME
 % locale webapprt @AB_CD@ %locale/webapprt/
     locale/webapprt/webapp.dtd                     (%webapprt/webapp.dtd)
     locale/webapprt/webapp.properties              (%webapprt/webapp.properties)
 #endif
--- a/configure.in
+++ b/configure.in
@@ -4588,17 +4588,25 @@ NECKO_WIFI=1
 NECKO_COOKIES=1
 NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device"
 USE_ARM_KUSER=
 BUILD_CTYPES=1
 MOZ_USE_NATIVE_POPUP_WINDOWS=
 MOZ_ANDROID_HISTORY=
 MOZ_WEBSMS_BACKEND=
 MOZ_GRAPHITE=1
-ACCESSIBILITY=1
+
+case "${target}" in
+*darwin*)
+    ACCESSIBILITY=
+    ;;
+*)
+    ACCESSIBILITY=1
+    ;;
+esac
 
 case "$target_os" in
     mingw*)
         NS_ENABLE_TSF=1
         AC_DEFINE(NS_ENABLE_TSF)
         ;;
 esac
 
@@ -5521,19 +5529,20 @@ MOZ_ARG_DISABLE_BOOL(dbm,
     NSS_DISABLE_DBM=)
 
 dnl bi-directional support always on
 IBMBIDI=1
 AC_DEFINE(IBMBIDI)
 
 dnl ========================================================
 dnl accessibility support on by default on all platforms
+dnl except OS X.
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(accessibility,
-[  --disable-accessibility Disable accessibility support],
+[  --disable-accessibility Disable accessibility support (off by default on OS X)],
     ACCESSIBILITY=,
     ACCESSIBILITY=1 )
 if test "$ACCESSIBILITY"; then
     AC_DEFINE(ACCESSIBILITY)
 fi
 
 dnl ========================================================
 dnl Disable printing
--- a/content/base/public/nsDeprecatedOperationList.h
+++ b/content/base/public/nsDeprecatedOperationList.h
@@ -43,8 +43,9 @@ DEPRECATED_OPERATION(Position)
 DEPRECATED_OPERATION(TotalSize)
 DEPRECATED_OPERATION(InputEncoding)
 DEPRECATED_OPERATION(MozBeforePaint)
 DEPRECATED_OPERATION(MozBlobBuilder)
 DEPRECATED_OPERATION(DOMExceptionCode)
 DEPRECATED_OPERATION(NoExposedProps)
 DEPRECATED_OPERATION(MutationEvent)
 DEPRECATED_OPERATION(MozSlice)
+DEPRECATED_OPERATION(Onuploadprogress)
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -621,16 +621,21 @@ CSPSourceList.prototype = {
    *
    * @param that
    *        another CSPSourceList
    * @returns 
    *        true if they have the same data
    */
   equals:
   function(that) {
+    // special case to default-src * and 'none' to look different
+    // (both have a ._sources.length of 0).
+    if (that._permitAllSources != this._permitAllSources) {
+      return false;
+    }
     if (that._sources.length != this._sources.length) {
       return false;
     }
     // sort both arrays and compare like a zipper
     // XXX (sid): I think we can make this more efficient
     var sortfn = function(a,b) {
       return a.toString() > b.toString();
     };
--- a/content/base/src/nsDOMLists.h
+++ b/content/base/src/nsDOMLists.h
@@ -23,13 +23,18 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMDOMSTRINGLIST
 
   bool Add(const nsAString& aName)
   {
     return mNames.AppendElement(aName) != nsnull;
   }
 
+  void Clear()
+  {
+    mNames.Clear();
+  }
+
 private:
   nsTArray<nsString> mNames;
 };
 
 #endif /* nsDOMLists_h___ */
--- a/content/base/src/nsDOMSettableTokenList.h
+++ b/content/base/src/nsDOMSettableTokenList.h
@@ -11,28 +11,29 @@
 
 #include "nsIDOMDOMSettableTokenList.h"
 #include "nsDOMTokenList.h"
 
 
 class nsGenericElement;
 class nsIAtom;
 
+// nsISupports must be on the primary inheritance chain 
+// because nsDOMSettableTokenList is traversed by nsGenericElement.
 class nsDOMSettableTokenList : public nsDOMTokenList,
                                public nsIDOMDOMSettableTokenList
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMDOMSETTABLETOKENLIST
 
   NS_FORWARD_NSIDOMDOMTOKENLIST(nsDOMTokenList::);
 
   nsDOMSettableTokenList(nsGenericElement* aElement, nsIAtom* aAttrAtom);
 
   virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                bool *triedToWrap);
 
-protected:
   virtual ~nsDOMSettableTokenList();
 };
 
 #endif // nsDOMSettableTokenList_h___
 
--- a/content/base/src/nsDOMTokenList.h
+++ b/content/base/src/nsDOMTokenList.h
@@ -9,16 +9,18 @@
 #ifndef nsDOMTokenList_h___
 #define nsDOMTokenList_h___
 
 #include "nsGenericElement.h"
 #include "nsIDOMDOMTokenList.h"
 
 class nsAttrValue;
 
+// nsISupports must be on the primary inheritance chain 
+// because nsDOMSettableTokenList is traversed by nsGenericElement.
 class nsDOMTokenList : public nsIDOMDOMTokenList,
                        public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMTokenList)
   NS_DECL_NSIDOMDOMTOKENLIST
 
@@ -29,26 +31,26 @@ public:
   virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                bool *triedToWrap);
 
   nsINode *GetParentObject()
   {
     return mElement;
   }
 
-protected:
-  ~nsDOMTokenList();
-
   const nsAttrValue* GetParsedAttr() {
     if (!mElement) {
       return nsnull;
     }
     return mElement->GetAttrInfo(kNameSpaceID_None, mAttrAtom).mValue;
   }
 
+protected:
+  ~nsDOMTokenList();
+
   nsresult CheckToken(const nsAString& aStr);
   void AddInternal(const nsAttrValue* aAttr, const nsAString& aToken);
   void RemoveInternal(const nsAttrValue* aAttr, const nsAString& aToken);
 
   nsGenericElement* mElement;
   nsCOMPtr<nsIAtom> mAttrAtom;
 };
 
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -4482,19 +4482,26 @@ private:
   static ContentUnbinder*                       sContentUnbinder;
 };
 
 ContentUnbinder* ContentUnbinder::sContentUnbinder = nsnull;
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericElement)
   nsINode::Unlink(tmp);
 
-  if (tmp->HasProperties() && tmp->IsXUL()) {
-    tmp->DeleteProperty(nsGkAtoms::contextmenulistener);
-    tmp->DeleteProperty(nsGkAtoms::popuplistener);
+  if (tmp->HasProperties()) {
+    if (tmp->IsHTML()) {
+      tmp->DeleteProperty(nsGkAtoms::microdataProperties);
+      tmp->DeleteProperty(nsGkAtoms::itemtype);
+      tmp->DeleteProperty(nsGkAtoms::itemref);
+      tmp->DeleteProperty(nsGkAtoms::itemprop);
+    } else if (tmp->IsXUL()) {
+      tmp->DeleteProperty(nsGkAtoms::contextmenulistener);
+      tmp->DeleteProperty(nsGkAtoms::popuplistener);
+    }
   }
 
   // Unlink child content (and unbind our subtree).
   if (UnoptimizableCCNode(tmp) || !nsCCUncollectableMarker::sGeneration) {
     PRUint32 childCount = tmp->mAttrsAndChildren.ChildCount();
     if (childCount) {
       // Don't allow script to run while we're unbinding everything.
       nsAutoScriptBlocker scriptBlocker;
@@ -4982,24 +4989,35 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 
   if (!nsINode::Traverse(tmp, cb)) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
 
   tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb);
 
-  if (tmp->HasProperties() && tmp->IsXUL()) {
-    nsISupports* property =
-      static_cast<nsISupports*>
-                 (tmp->GetProperty(nsGkAtoms::contextmenulistener));
-    cb.NoteXPCOMChild(property);
-    property = static_cast<nsISupports*>
-                          (tmp->GetProperty(nsGkAtoms::popuplistener));
-    cb.NoteXPCOMChild(property);
+  if (tmp->HasProperties()) {
+    if (tmp->IsHTML()) {
+      nsISupports* property = static_cast<nsISupports*>
+                                         (tmp->GetProperty(nsGkAtoms::microdataProperties));
+      cb.NoteXPCOMChild(property);
+      property = static_cast<nsISupports*>(tmp->GetProperty(nsGkAtoms::itemref));
+      cb.NoteXPCOMChild(property);
+      property = static_cast<nsISupports*>(tmp->GetProperty(nsGkAtoms::itemprop));
+      cb.NoteXPCOMChild(property);
+      property = static_cast<nsISupports*>(tmp->GetProperty(nsGkAtoms::itemtype));
+      cb.NoteXPCOMChild(property);
+    } else if (tmp->IsXUL()) {
+      nsISupports* property = static_cast<nsISupports*>
+                                         (tmp->GetProperty(nsGkAtoms::contextmenulistener));
+      cb.NoteXPCOMChild(property);
+      property = static_cast<nsISupports*>
+                            (tmp->GetProperty(nsGkAtoms::popuplistener));
+      cb.NoteXPCOMChild(property);
+    }
   }
 
   // Traverse attribute names and child content.
   {
     PRUint32 i;
     PRUint32 attrs = tmp->mAttrsAndChildren.AttrCount();
     for (i = 0; i < attrs; i++) {
       const nsAttrName* name = tmp->mAttrsAndChildren.AttrNameAt(i);
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -90,19 +90,17 @@ GK_ATOM(assign, "assign")
 GK_ATOM(async, "async")
 GK_ATOM(attribute, "attribute")
 GK_ATOM(attributeSet, "attribute-set")
 GK_ATOM(aural, "aural")
 GK_ATOM(_auto, "auto")
 GK_ATOM(autocheck, "autocheck")
 GK_ATOM(autocomplete, "autocomplete")
 GK_ATOM(autofocus, "autofocus")
-#ifdef MOZ_MEDIA
 GK_ATOM(autoplay, "autoplay")
-#endif
 GK_ATOM(autorepeatbutton, "autorepeatbutton")
 GK_ATOM(axis, "axis")
 GK_ATOM(b, "b")
 GK_ATOM(background, "background")
 GK_ATOM(base, "base")
 GK_ATOM(basefont, "basefont")
 GK_ATOM(baseline, "baseline")
 GK_ATOM(bdi, "bdi")
@@ -215,19 +213,17 @@ GK_ATOM(headerContentLanguage, "content-
 GK_ATOM(contentLocation, "content-location")
 GK_ATOM(headerContentScriptType, "content-script-type")
 GK_ATOM(headerContentStyleType, "content-style-type")
 GK_ATOM(headerContentType, "content-type")
 GK_ATOM(context, "context")
 GK_ATOM(contextmenu, "contextmenu")
 GK_ATOM(contextmenulistener, "contextmenulistener")
 GK_ATOM(control, "control")
-#ifdef MOZ_MEDIA
 GK_ATOM(controls, "controls")
-#endif
 GK_ATOM(coords, "coords")
 GK_ATOM(copy, "copy")
 GK_ATOM(copyOf, "copy-of")
 GK_ATOM(count, "count")
 GK_ATOM(crop, "crop")
 GK_ATOM(crossorigin, "crossorigin")
 GK_ATOM(curpos, "curpos")
 GK_ATOM(current, "current")
@@ -248,19 +244,17 @@ GK_ATOM(declare, "declare")
 GK_ATOM(decrement, "decrement")
 GK_ATOM(_default, "default")
 GK_ATOM(headerDefaultStyle, "default-style")
 GK_ATOM(defaultAction, "defaultAction")
 GK_ATOM(defaultchecked, "defaultchecked")
 GK_ATOM(defaultLabel, "defaultLabel")
 GK_ATOM(defaultselected, "defaultselected")
 GK_ATOM(defaultvalue, "defaultvalue")
-#ifdef MOZ_MEDIA
 GK_ATOM(defaultplaybackrate, "defaultplaybackrate")
-#endif
 GK_ATOM(defer, "defer")
 GK_ATOM(del, "del")
 GK_ATOM(descendant, "descendant")
 GK_ATOM(descendantOrSelf, "descendant-or-self")
 GK_ATOM(descending, "descending")
 GK_ATOM(description, "description")
 GK_ATOM(destructor, "destructor")
 GK_ATOM(details, "details")
@@ -500,19 +494,17 @@ GK_ATOM(listhead, "listhead")
 GK_ATOM(listheader, "listheader")
 GK_ATOM(listing, "listing")
 GK_ATOM(listitem, "listitem")
 GK_ATOM(listrows, "listrows")
 GK_ATOM(load, "load")
 GK_ATOM(localedir, "localedir")
 GK_ATOM(localName, "local-name")
 GK_ATOM(longdesc, "longdesc")
-#ifdef MOZ_MEDIA
 GK_ATOM(loop, "loop")
-#endif
 GK_ATOM(low, "low")
 GK_ATOM(lowerFirst, "lower-first")
 GK_ATOM(lowest, "lowest")
 GK_ATOM(lowsrc, "lowsrc")
 GK_ATOM(ltr, "ltr")
 GK_ATOM(lwtheme, "lwtheme")
 GK_ATOM(lwthemetextcolor, "lwthemetextcolor")
 GK_ATOM(map, "map")
@@ -539,16 +531,17 @@ GK_ATOM(menuButton, "menu-button")
 GK_ATOM(menuitem, "menuitem")
 GK_ATOM(menulist, "menulist")
 GK_ATOM(menupopup, "menupopup")
 GK_ATOM(menuseparator, "menuseparator")
 GK_ATOM(message, "message")
 GK_ATOM(meta, "meta")
 GK_ATOM(meter, "meter")
 GK_ATOM(method, "method")
+GK_ATOM(microdataProperties, "microdataProperties")
 GK_ATOM(middle, "middle")
 GK_ATOM(min, "min")
 GK_ATOM(minheight, "minheight")
 GK_ATOM(minimum_scale, "minimum-scale")
 GK_ATOM(minpos, "minpos")
 GK_ATOM(minusSign, "minus-sign")
 GK_ATOM(minwidth, "minwidth")
 GK_ATOM(mod, "mod")
@@ -566,19 +559,17 @@ GK_ATOM(mozfullscreenerror, "mozfullscre
 GK_ATOM(mozpointerlockchange, "mozpointerlockchange")
 GK_ATOM(mozpointerlockerror, "mozpointerlockerror")
 GK_ATOM(moz_opaque, "moz-opaque")
 GK_ATOM(moz_action_hint, "mozactionhint")
 GK_ATOM(x_moz_errormessage, "x-moz-errormessage")
 GK_ATOM(msthemecompatible, "msthemecompatible")
 GK_ATOM(multicol, "multicol")
 GK_ATOM(multiple, "multiple")
-#ifdef MOZ_MEDIA
 GK_ATOM(muted, "muted")
-#endif
 GK_ATOM(name, "name")
 GK_ATOM(_namespace, "namespace")
 GK_ATOM(namespaceAlias, "namespace-alias")
 GK_ATOM(namespaceUri, "namespace-uri")
 GK_ATOM(NaN, "NaN")
 GK_ATOM(nav, "nav")
 GK_ATOM(negate, "negate")
 GK_ATOM(never, "never")
@@ -756,45 +747,39 @@ GK_ATOM(pattern, "pattern")
 GK_ATOM(patternSeparator, "pattern-separator")
 GK_ATOM(perMille, "per-mille")
 GK_ATOM(percent, "percent")
 GK_ATOM(persist, "persist")
 GK_ATOM(phase, "phase")
 GK_ATOM(ping, "ping")
 GK_ATOM(placeholder, "placeholder")
 GK_ATOM(plaintext, "plaintext")
-#ifdef MOZ_MEDIA
 GK_ATOM(playbackrate, "playbackrate")
-#endif
 GK_ATOM(pointSize, "point-size")
 GK_ATOM(poly, "poly")
 GK_ATOM(polygon, "polygon")
 GK_ATOM(popup, "popup")
 GK_ATOM(popupalign, "popupalign")
 GK_ATOM(popupanchor, "popupanchor")
 GK_ATOM(popupgroup, "popupgroup")
 GK_ATOM(popuphidden, "popuphidden")
 GK_ATOM(popuphiding, "popuphiding")
 GK_ATOM(popuplistener, "popuplistener")
 GK_ATOM(popupset, "popupset")
 GK_ATOM(popupshowing, "popupshowing")
 GK_ATOM(popupshown, "popupshown")
 GK_ATOM(popupsinherittooltip, "popupsinherittooltip")
 GK_ATOM(position, "position")
-#ifdef MOZ_MEDIA
 GK_ATOM(poster, "poster")
-#endif
 GK_ATOM(pre, "pre")
 GK_ATOM(preceding, "preceding")
 GK_ATOM(precedingSibling, "preceding-sibling")
 GK_ATOM(predicate, "predicate")
 GK_ATOM(prefix, "prefix")
-#ifdef MOZ_MEDIA
 GK_ATOM(preload, "preload")
-#endif
 GK_ATOM(preserve, "preserve")
 GK_ATOM(preserveSpace, "preserve-space")
 GK_ATOM(preventdefault, "preventdefault")
 GK_ATOM(primary, "primary")
 GK_ATOM(print, "print")
 GK_ATOM(priority, "priority")
 GK_ATOM(processingInstruction, "processing-instruction")
 GK_ATOM(profile, "profile")
@@ -905,19 +890,17 @@ GK_ATOM(sortActive, "sortActive")
 GK_ATOM(sortDirection, "sortDirection")
 GK_ATOM(sorted, "sorted")
 GK_ATOM(sorthints, "sorthints")
 GK_ATOM(sortLocked, "sortLocked")
 GK_ATOM(sortResource, "sortResource")
 GK_ATOM(sortResource2, "sortResource2")
 GK_ATOM(sortSeparators, "sortSeparators")
 GK_ATOM(sortStaticsLast, "sortStaticsLast")
-#ifdef MOZ_MEDIA
 GK_ATOM(source, "source")
-#endif
 GK_ATOM(space, "space")
 GK_ATOM(spacer, "spacer")
 GK_ATOM(span, "span")
 GK_ATOM(spellcheck, "spellcheck")
 GK_ATOM(spinner, "spinner")
 GK_ATOM(split, "split")
 GK_ATOM(splitmenu, "splitmenu")
 GK_ATOM(splitter, "splitter")
@@ -1043,21 +1026,19 @@ GK_ATOM(var, "var")
 GK_ATOM(variable, "variable")
 GK_ATOM(vbox, "vbox")
 GK_ATOM(vcard_name, "vcard_name")
 GK_ATOM(vendor, "vendor")
 GK_ATOM(vendorUrl, "vendor-url")
 GK_ATOM(version, "version")
 GK_ATOM(vert, "vert")
 GK_ATOM(vertical, "vertical")
-#ifdef MOZ_MEDIA
 GK_ATOM(audio, "audio")
 GK_ATOM(video, "video")
 GK_ATOM(videocontrols, "videocontrols")
-#endif
 GK_ATOM(viewport, "viewport")
 GK_ATOM(viewport_height, "viewport-height")
 GK_ATOM(viewport_initial_scale, "viewport-initial-scale")
 GK_ATOM(viewport_maximum_scale, "viewport-maximum-scale")
 GK_ATOM(viewport_minimum_scale, "viewport-minimum-scale")
 GK_ATOM(viewport_user_scalable, "viewport-user-scalable")
 GK_ATOM(viewport_width, "viewport-width")
 GK_ATOM(visibility, "visibility")
@@ -1696,16 +1677,17 @@ GK_ATOM(blockFrame, "BlockFrame")
 GK_ATOM(boxFrame, "BoxFrame")
 GK_ATOM(brFrame, "BRFrame")
 GK_ATOM(bulletFrame, "BulletFrame")
 GK_ATOM(columnSetFrame, "ColumnSetFrame")
 GK_ATOM(comboboxControlFrame, "ComboboxControlFrame")
 GK_ATOM(comboboxDisplayFrame, "ComboboxDisplayFrame")
 GK_ATOM(deckFrame, "DeckFrame")
 GK_ATOM(fieldSetFrame, "FieldSetFrame")
+GK_ATOM(formControlFrame, "FormControlFrame") // radio or checkbox
 GK_ATOM(frameSetFrame, "FrameSetFrame")
 GK_ATOM(gfxButtonControlFrame, "gfxButtonControlFrame")
 GK_ATOM(HTMLButtonControlFrame, "HTMLButtonControlFrame")
 GK_ATOM(HTMLCanvasFrame, "HTMLCanvasFrame")
 GK_ATOM(subDocumentFrame, "subDocumentFrame")
 GK_ATOM(imageBoxFrame, "ImageBoxFrame")
 GK_ATOM(imageFrame, "ImageFrame")
 GK_ATOM(imageControlFrame, "ImageControlFrame")
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -69,16 +69,37 @@ using namespace mozilla;
     nsresult __rv = res;                                                  \
     if (NS_FAILED(__rv)) {                                                \
       NS_ENSURE_SUCCESS_BODY(res, ret)                                    \
       FailConnection(nsIWebSocketChannel::CLOSE_INTERNAL_ERROR);          \
       return ret;                                                         \
     }                                                                     \
   PR_END_MACRO
 
+class CallDispatchConnectionCloseEvents: public nsRunnable
+{
+public:
+CallDispatchConnectionCloseEvents(nsWebSocket *aWebSocket)
+  : mWebSocket(aWebSocket)
+  {}
+
+  NS_IMETHOD Run()
+  {
+    mWebSocket->DispatchConnectionCloseEvents();
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<nsWebSocket> mWebSocket;
+};
+
+//-----------------------------------------------------------------------------
+// nsWebSocket
+//-----------------------------------------------------------------------------
+
 nsresult
 nsWebSocket::PrintErrorOnConsole(const char *aBundleURI,
                                  const PRUnichar *aError,
                                  const PRUnichar **aFormatStrings,
                                  PRUint32 aFormatStringsLen)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsresult rv;
@@ -119,47 +140,53 @@ nsWebSocket::PrintErrorOnConsole(const c
 
   // print the error message directly to the JS console
   rv = console->LogMessage(errorObject);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
-// when this is called the browser side wants no more part of it
 nsresult
 nsWebSocket::CloseConnection(PRUint16 aReasonCode,
                              const nsACString& aReasonString)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  if (mDisconnected)
-    return NS_OK;
-
-  // Disconnect() can release this object, so we keep a
-  // reference until the end of the method
-  nsRefPtr<nsWebSocket> kungfuDeathGrip = this;
-
-  if (mReadyState == nsIWebSocket::CONNECTING) {
-    SetReadyState(nsIWebSocket::CLOSED);
-    if (mChannel) {
-      mChannel->Close(aReasonCode, aReasonString);
-    }
-    Disconnect();
+  if (mReadyState == nsIWebSocket::CLOSING ||
+      mReadyState == nsIWebSocket::CLOSED) {
     return NS_OK;
   }
 
-  SetReadyState(nsIWebSocket::CLOSING);
-
-  if (mDisconnected) {
-    SetReadyState(nsIWebSocket::CLOSED);
-    Disconnect();
-    return NS_OK;
+  // The common case...
+  if (mChannel) {
+    mReadyState = nsIWebSocket::CLOSING;
+    return mChannel->Close(aReasonCode, aReasonString);
   }
 
-  return mChannel->Close(aReasonCode, aReasonString);
+  // No channel, but not disconnected: canceled or failed early
+  //
+  MOZ_ASSERT(mReadyState == nsIWebSocket::CONNECTING,
+             "Should only get here for early websocket cancel/error");
+
+  // Server won't be sending us a close code, so use what's passed in here.
+  mCloseEventCode = aReasonCode;
+  CopyUTF8toUTF16(aReasonString, mCloseEventReason);
+
+  mReadyState = nsIWebSocket::CLOSING;
+
+  // Can be called from Cancel() or Init() codepaths, so need to dispatch
+  // onerror/onclose asynchronously
+  ScheduleConnectionCloseEvents(
+                    nsnull,
+                    (aReasonCode == nsIWebSocketChannel::CLOSE_NORMAL ||
+                     aReasonCode == nsIWebSocketChannel::CLOSE_GOING_AWAY) ?
+                     NS_OK : NS_ERROR_FAILURE,
+                    false);
+
+  return NS_OK;
 }
 
 nsresult
 nsWebSocket::ConsoleError()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsresult rv;
 
@@ -186,24 +213,21 @@ nsWebSocket::ConsoleError()
 }
 
 
 nsresult
 nsWebSocket::FailConnection(PRUint16 aReasonCode,
                             const nsACString& aReasonString)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+
   ConsoleError();
-
+  mFailed = true;
   CloseConnection(aReasonCode, aReasonString);
 
-  nsresult rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("error"));
-  if (NS_FAILED(rv))
-    NS_WARNING("Failed to dispatch the error event");
-
   return NS_OK;
 }
 
 nsresult
 nsWebSocket::Disconnect()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
@@ -235,29 +259,33 @@ nsWebSocket::Disconnect()
 //-----------------------------------------------------------------------------
 // nsWebSocket::nsIWebSocketListener methods:
 //-----------------------------------------------------------------------------
 
 nsresult
 nsWebSocket::DoOnMessageAvailable(const nsACString & aMsg, bool isBinary)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  NS_ABORT_IF_FALSE(!mDisconnected, "Received message after disconnecting");
+
+  if (mReadyState == nsIWebSocket::CLOSED) {
+    NS_ERROR("Received message after CLOSED");
+    return NS_ERROR_UNEXPECTED;
+  }
 
   if (mReadyState == nsIWebSocket::OPEN) {
     // Dispatch New Message
     nsresult rv = CreateAndDispatchMessageEvent(aMsg, isBinary);
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to dispatch the message event");
     }
   } else {
     // CLOSING should be the only other state where it's possible to get msgs
     // from channel: Spec says to drop them.
-    NS_ASSERTION(mReadyState == nsIWebSocket::CLOSING,
-                 "Received message while CONNECTING or CLOSED");
+    MOZ_ASSERT(mReadyState == nsIWebSocket::CLOSING,
+               "Received message while CONNECTING or CLOSED");
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebSocket::OnMessageAvailable(nsISupports *aContext, const nsACString & aMsg)
 {
@@ -270,62 +298,97 @@ nsWebSocket::OnBinaryMessageAvailable(ns
 {
   return DoOnMessageAvailable(aMsg, true);
 }
 
 NS_IMETHODIMP
 nsWebSocket::OnStart(nsISupports *aContext)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  if (mDisconnected)
+
+  // This is the only function that sets OPEN, and should be called only once
+  MOZ_ASSERT(mReadyState != nsIWebSocket::OPEN,
+             "readyState already OPEN! OnStart called twice?");
+
+  // Nothing to do if we've already closed/closing
+  if (mReadyState != nsIWebSocket::CONNECTING) {
     return NS_OK;
+  }
 
   // Attempt to kill "ghost" websocket: but usually too early for check to fail
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
-    FailConnectionQuietly();
+    CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
     return rv;
   }
 
   if (!mRequestedProtocolList.IsEmpty()) {
     mChannel->GetProtocol(mEstablishedProtocol);
   }
 
   mChannel->GetExtensions(mEstablishedExtensions);
   UpdateURI();
 
-  SetReadyState(nsIWebSocket::OPEN);
+  mReadyState = nsIWebSocket::OPEN;
+
+  // Call 'onopen'
+  rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("open"));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to dispatch the open event");
+  }
+
+  UpdateMustKeepAlive();
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebSocket::OnStop(nsISupports *aContext, nsresult aStatusCode)
 {
+  // We can be CONNECTING here if connection failed.
+  // We can be OPEN if we have encountered a fatal protocol error
+  // We can be CLOSING if close() was called and/or server initiated close.
+  MOZ_ASSERT(mReadyState != nsIWebSocket::CLOSED,
+             "Shouldn't already be CLOSED when OnStop called");
+
+  // called by network stack, not JS, so can dispatch JS events synchronously
+  return ScheduleConnectionCloseEvents(aContext, aStatusCode, true);
+}
+
+nsresult
+nsWebSocket::ScheduleConnectionCloseEvents(nsISupports *aContext,
+                                           nsresult aStatusCode,
+                                           bool sync)
+{
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  if (mDisconnected)
-    return NS_OK;
 
-  mCloseEventWasClean = NS_SUCCEEDED(aStatusCode);
+  // no-op if some other code has already initiated close event
+  if (!mOnCloseScheduled) {
+    mCloseEventWasClean = NS_SUCCEEDED(aStatusCode);
+
+    if (aStatusCode == NS_BASE_STREAM_CLOSED) {
+      // don't generate an error event just because of an unclean close
+      aStatusCode = NS_OK;
+    }
 
-  if (aStatusCode == NS_BASE_STREAM_CLOSED &&
-      mReadyState >= nsIWebSocket::CLOSING) {
-    // don't generate an error event just because of an unclean close
-    aStatusCode = NS_OK;
+    if (NS_FAILED(aStatusCode)) {
+      ConsoleError();
+      mFailed = true;
+    }
+
+    mOnCloseScheduled = true;
+
+    if (sync) {
+      DispatchConnectionCloseEvents();
+    } else {
+      NS_DispatchToMainThread(new CallDispatchConnectionCloseEvents(this),
+                              NS_DISPATCH_NORMAL);
+    }
   }
 
-  if (NS_FAILED(aStatusCode)) {
-    ConsoleError();
-    nsresult rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("error"));
-    if (NS_FAILED(rv))
-      NS_WARNING("Failed to dispatch the error event");
-  }
-
-  SetReadyState(nsIWebSocket::CLOSED);
-  Disconnect();
-
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebSocket::OnAcknowledge(nsISupports *aContext, PRUint32 aSize)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
@@ -337,56 +400,53 @@ nsWebSocket::OnAcknowledge(nsISupports *
 }
 
 NS_IMETHODIMP
 nsWebSocket::OnServerClose(nsISupports *aContext, PRUint16 aCode,
                            const nsACString &aReason)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-  NS_ABORT_IF_FALSE(mReadyState != nsIWebSocket::CONNECTING,
-                    "Received server close before connected?");
-
-  if (mReadyState == nsIWebSocket::CLOSED) {
-    NS_WARNING("Received server close after already closed!");
-    return NS_ERROR_UNEXPECTED;
-  }
+  MOZ_ASSERT(mReadyState != nsIWebSocket::CONNECTING,
+             "Received server close before connected?");
+  MOZ_ASSERT(mReadyState != nsIWebSocket::CLOSED,
+             "Received server close after already closed!");
 
   // store code/string for onclose DOM event
   mCloseEventCode = aCode;
   CopyUTF8toUTF16(aReason, mCloseEventReason);
 
   if (mReadyState == nsIWebSocket::OPEN) {
+    // Server initiating close.
     // RFC 6455, 5.5.1: "When sending a Close frame in response, the endpoint
     // typically echos the status code it received".
     // But never send certain codes, per section 7.4.1
     if (aCode == 1005 || aCode == 1006 || aCode == 1015) {
       CloseConnection(0, EmptyCString());
     } else {
       CloseConnection(aCode, aReason);
     }
   } else {
-    // Nothing else to do: OnStop does the rest of the work.
-    NS_ASSERTION (mReadyState == nsIWebSocket::CLOSING, "unknown state");
-    NS_ASSERTION(!mDisconnected, "should not be disconnected during CLOSING");
+    // We initiated close, and server has replied: OnStop does rest of the work.
+    MOZ_ASSERT(mReadyState == nsIWebSocket::CLOSING, "unknown state");
   }
 
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsWebSocket::nsIInterfaceRequestor
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsWebSocket::GetInterface(const nsIID &aIID, void **aResult)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-  if (mDisconnected)
+  if (mReadyState == nsIWebSocket::CLOSED)
     return NS_ERROR_FAILURE;
 
   if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
       aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
     nsresult rv;
 
     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     nsCOMPtr<nsIDocument> doc =
@@ -406,17 +466,18 @@ nsWebSocket::GetInterface(const nsIID &a
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsWebSocket
 ////////////////////////////////////////////////////////////////////////////////
 
 nsWebSocket::nsWebSocket() : mKeepingAlive(false),
                              mCheckMustKeepAlive(true),
-                             mTriggeredCloseEvent(false),
+                             mOnCloseScheduled(false),
+                             mFailed(false),
                              mDisconnected(false),
                              mCloseEventWasClean(false),
                              mCloseEventCode(nsIWebSocketChannel::CLOSE_ABNORMAL),
                              mReadyState(nsIWebSocket::CONNECTING),
                              mOutgoingBufferedAmount(0),
                              mBinaryType(WS_BINARY_TYPE_BLOB),
                              mScriptLine(0),
                              mInnerWindowID(0)
@@ -424,17 +485,20 @@ nsWebSocket::nsWebSocket() : mKeepingAli
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsLayoutStatics::AddRef();
 }
 
 nsWebSocket::~nsWebSocket()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-  Disconnect();
+  // If we threw during Init we never called disconnect
+  if (!mDisconnected) {
+    Disconnect();
+  }
   nsLayoutStatics::Release();
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsWebSocket)
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsWebSocket)
   bool isBlack = tmp->IsBlack();
   if (isBlack|| tmp->mKeepingAlive) {
@@ -506,17 +570,17 @@ NS_IMPL_RELEASE_INHERITED(nsWebSocket, n
 void
 nsWebSocket::DisconnectFromOwner()
 {
   nsDOMEventTargetHelper::DisconnectFromOwner();
   NS_DISCONNECT_EVENT_HANDLER(Open)
   NS_DISCONNECT_EVENT_HANDLER(Message)
   NS_DISCONNECT_EVENT_HANDLER(Close)
   NS_DISCONNECT_EVENT_HANDLER(Error)
-  FailConnectionQuietly();
+  CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
   DontKeepAliveAnyMore();
 }
 
 //-----------------------------------------------------------------------------
 // nsWebSocket::nsIJSNativeInitializer methods:
 //-----------------------------------------------------------------------------
 
 /**
@@ -700,41 +764,40 @@ nsWebSocket::EstablishConnection()
   rv = wsChannel->AsyncOpen(mURI, asciiOrigin, this, nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mChannel = wsChannel;
 
   return NS_OK;
 }
 
-class nsWSCloseEvent : public nsRunnable
+void
+nsWebSocket::DispatchConnectionCloseEvents()
 {
-public:
-nsWSCloseEvent(nsWebSocket *aWebSocket, bool aWasClean, 
-               PRUint16 aCode, const nsString &aReason)
-    : mWebSocket(aWebSocket),
-      mWasClean(aWasClean),
-      mCode(aCode),
-      mReason(aReason)
-  {}
+  nsresult rv;
+
+  mReadyState = nsIWebSocket::CLOSED;
 
-  NS_IMETHOD Run()
-  {
-    nsresult rv = mWebSocket->CreateAndDispatchCloseEvent(mWasClean,
-                                                          mCode, mReason);
-    mWebSocket->UpdateMustKeepAlive();
-    return rv;
+  // Call 'onerror' if needed
+  if (mFailed) {
+    nsresult rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("error"));
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Failed to dispatch the error event");
+    }
   }
 
-private:
-  nsRefPtr<nsWebSocket> mWebSocket;
-  bool mWasClean;
-  PRUint16 mCode;
-  nsString mReason;
-};
+  rv = CreateAndDispatchCloseEvent(mCloseEventWasClean, mCloseEventCode,
+                                   mCloseEventReason);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to dispatch the close event");
+  }
+
+  UpdateMustKeepAlive();
+  Disconnect();
+}
 
 nsresult
 nsWebSocket::CreateAndDispatchSimpleEvent(const nsString& aName)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsresult rv;
 
   rv = CheckInnerWindowCorrectness();
@@ -850,18 +913,16 @@ nsWebSocket::CreateResponseBlob(const ns
 nsresult
 nsWebSocket::CreateAndDispatchCloseEvent(bool aWasClean,
                                          PRUint16 aCode,
                                          const nsString &aReason)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsresult rv;
 
-  mTriggeredCloseEvent = true;
-
   rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return NS_OK;
   }
 
   // create an event that uses the CloseEvent interface,
   // which does not bubble, is not cancelable, and has no default action
 
@@ -883,68 +944,16 @@ nsWebSocket::CreateAndDispatchCloseEvent
 }
 
 bool
 nsWebSocket::PrefEnabled()
 {
   return Preferences::GetBool("network.websocket.enabled", true);
 }
 
-void
-nsWebSocket::SetReadyState(PRUint16 aNewReadyState)
-{
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  nsresult rv;
-
-  if (mReadyState == aNewReadyState) {
-    return;
-  }
-
-  NS_ABORT_IF_FALSE((aNewReadyState == nsIWebSocket::OPEN)    ||
-                    (aNewReadyState == nsIWebSocket::CLOSING) ||
-                    (aNewReadyState == nsIWebSocket::CLOSED),
-                    "unexpected readyState");
-
-  if (aNewReadyState == nsIWebSocket::OPEN) {
-    NS_ABORT_IF_FALSE(mReadyState == nsIWebSocket::CONNECTING,
-                      "unexpected readyState transition");
-    mReadyState = aNewReadyState;
-
-    rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("open"));
-    if (NS_FAILED(rv)) {
-      NS_WARNING("Failed to dispatch the open event");
-    }
-    UpdateMustKeepAlive();
-    return;
-  }
-
-  if (aNewReadyState == nsIWebSocket::CLOSING) {
-    NS_ABORT_IF_FALSE((mReadyState == nsIWebSocket::CONNECTING) ||
-                      (mReadyState == nsIWebSocket::OPEN),
-                      "unexpected readyState transition");
-    mReadyState = aNewReadyState;
-    return;
-  }
-
-  if (aNewReadyState == nsIWebSocket::CLOSED) {
-    mReadyState = aNewReadyState;
-
-    // The close event must be dispatched asynchronously.
-    rv = NS_DispatchToMainThread(new nsWSCloseEvent(this, mCloseEventWasClean,
-                                                    mCloseEventCode,
-                                                    mCloseEventReason),
-                                 NS_DISPATCH_NORMAL);
-    if (NS_FAILED(rv)) {
-      NS_WARNING("Failed to dispatch the close event");
-      mTriggeredCloseEvent = true;
-      UpdateMustKeepAlive();
-    }
-  }
-}
-
 nsresult
 nsWebSocket::ParseURL(const nsString& aURL)
 {
   nsresult rv;
 
   NS_ENSURE_TRUE(!aURL.IsEmpty(), NS_ERROR_DOM_SYNTAX_ERR);
 
   nsCOMPtr<nsIURI> uri;
@@ -1061,19 +1070,17 @@ nsWebSocket::UpdateMustKeepAlive()
             mOutgoingBufferedAmount != 0) {
           shouldKeepAlive = true;
         }
       }
       break;
 
       case nsIWebSocket::CLOSED:
       {
-        shouldKeepAlive =
-          (!mTriggeredCloseEvent &&
-           mListenerManager->HasListenersFor(NS_LITERAL_STRING("close")));
+        shouldKeepAlive = false;
       }
     }
   }
 
   if (mKeepingAlive && !shouldKeepAlive) {
     mKeepingAlive = false;
     static_cast<nsIDOMEventTarget*>(this)->Release();
   } else if (!mKeepingAlive && shouldKeepAlive) {
@@ -1088,24 +1095,16 @@ nsWebSocket::DontKeepAliveAnyMore()
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   if (mKeepingAlive) {
     mKeepingAlive = false;
     static_cast<nsIDOMEventTarget*>(this)->Release();
   }
   mCheckMustKeepAlive = false;
 }
 
-void
-nsWebSocket::FailConnectionQuietly()
-{
-  // Fail without console error or JS onerror message: onmessage/onclose will
-  // also be blocked so long as CheckInnerWindowCorrectness is failing.
-  CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
-}
-
 nsresult
 nsWebSocket::UpdateURI()
 {
   // Check for Redirections
   nsCOMPtr<nsIURI> uri;
   nsresult rv = mChannel->GetURI(getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1287,18 +1286,18 @@ nsWebSocket::Send(nsIVariant *aData, JSC
   // Always increment outgoing buffer len, even if closed
   mOutgoingBufferedAmount += msgLen;
 
   if (mReadyState == nsIWebSocket::CLOSING ||
       mReadyState == nsIWebSocket::CLOSED) {
     return NS_OK;
   }
 
-  NS_ASSERTION(mReadyState == nsIWebSocket::OPEN,
-               "Unknown state in nsWebSocket::Send");
+  MOZ_ASSERT(mReadyState == nsIWebSocket::OPEN,
+             "Unknown state in nsWebSocket::Send");
 
   if (msgStream) {
     rv = mChannel->SendBinaryStream(msgStream, msgLen);
   } else {
     if (isBinary) {
       rv = mChannel->SendBinaryMsg(msgString);
     } else {
       rv = mChannel->SendMsg(msgString);
@@ -1466,20 +1465,16 @@ nsWebSocket::Close(PRUint16 code, const 
   }
 
   if (mReadyState == nsIWebSocket::CLOSING ||
       mReadyState == nsIWebSocket::CLOSED) {
     return NS_OK;
   }
 
   if (mReadyState == nsIWebSocket::CONNECTING) {
-    // FailConnection() can release the object, so we keep a reference
-    // before calling it
-    nsRefPtr<nsWebSocket> kungfuDeathGrip = this;
-
     FailConnection(closeCode, closeReason);
     return NS_OK;
   }
 
   // mReadyState == nsIWebSocket::OPEN
   CloseConnection(closeCode, closeReason);
 
   return NS_OK;
@@ -1613,17 +1608,17 @@ nsWebSocket::Observe(nsISupports* aSubje
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aSubject);
   if (!GetOwner() || window != GetOwner()) {
     return NS_OK;
   }
 
   if ((strcmp(aTopic, DOM_WINDOW_FROZEN_TOPIC) == 0) ||
       (strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC) == 0))
   {
-    FailConnectionQuietly();
+    CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
   }
 
   return NS_OK;
 }
 
 
 //-----------------------------------------------------------------------------
 // nsWebSocket::nsIRequest
@@ -1634,37 +1629,39 @@ nsWebSocket::GetName(nsACString &aName)
 {
   CopyUTF16toUTF8(mOriginalURL, aName);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebSocket::IsPending(bool *aValue)
 {
-  *aValue = !mDisconnected;
+  *aValue = (mReadyState != nsIWebSocket::CLOSED);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebSocket::GetStatus(nsresult *aStatus)
 {
   *aStatus = NS_OK;
   return NS_OK;
 }
 
 // Window closed, stop/reload button pressed, user navigated away from page, etc.
 NS_IMETHODIMP
 nsWebSocket::Cancel(nsresult aStatus)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-  if (mDisconnected)
+  if (mReadyState == CLOSING || mReadyState == CLOSED) {
     return NS_OK;
+  }
 
   ConsoleError();
+
   return CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
 }
 
 NS_IMETHODIMP
 nsWebSocket::Suspend()
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
--- a/content/base/src/nsWebSocket.h
+++ b/content/base/src/nsWebSocket.h
@@ -30,29 +30,29 @@
 
 #define NS_WEBSOCKET_CID                            \
  { /* 7ca25214-98dc-40a6-bc1f-41ddbe41f46c */       \
   0x7ca25214, 0x98dc, 0x40a6,                       \
  {0xbc, 0x1f, 0x41, 0xdd, 0xbe, 0x41, 0xf4, 0x6c} }
 
 #define NS_WEBSOCKET_CONTRACTID "@mozilla.org/websocket;1"
 
-class nsWSCloseEvent;
+class CallDispatchConnectionCloseEvents;
 class nsAutoCloseWS;
 
 class nsWebSocket: public nsDOMEventTargetHelper,
                    public nsIWebSocket,
                    public nsIJSNativeInitializer,
                    public nsIInterfaceRequestor,
                    public nsIWebSocketListener,
                    public nsIObserver,
                    public nsSupportsWeakReference,
                    public nsIRequest
 {
-friend class nsWSCloseEvent;
+friend class CallDispatchConnectionCloseEvents;
 friend class nsAutoCloseWS;
 
 public:
   nsWebSocket();
   virtual ~nsWebSocket();
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(nsWebSocket,
                                                                    nsDOMEventTargetHelper)
@@ -82,17 +82,16 @@ public:
   virtual void DisconnectFromOwner();
 protected:
   nsresult ParseURL(const nsString& aURL);
   nsresult EstablishConnection();
 
   // These methods when called can release the WebSocket object
   nsresult FailConnection(PRUint16 reasonCode,
                           const nsACString& aReasonString = EmptyCString());
-  void     FailConnectionQuietly();
   nsresult CloseConnection(PRUint16 reasonCode,
                            const nsACString& aReasonString = EmptyCString());
   nsresult Disconnect();
 
   nsresult ConsoleError();
   nsresult PrintErrorOnConsole(const char       *aBundleURI,
                                const PRUnichar  *aError,
                                const PRUnichar **aFormatStrings,
@@ -102,26 +101,36 @@ protected:
 
   // Get msg info out of JS variable being sent (string, arraybuffer, blob)
   nsresult GetSendParams(nsIVariant *aData, nsCString &aStringOut,
                          nsCOMPtr<nsIInputStream> &aStreamOut,
                          bool &aIsBinary, PRUint32 &aOutgoingLength,
                          JSContext *aCx);
 
   nsresult DoOnMessageAvailable(const nsACString & aMsg, bool isBinary);
+
+  // ConnectionCloseEvents: 'error' event if needed, then 'close' event.
+  // - These must not be dispatched while we are still within an incoming call
+  //   from JS (ex: close()).  Set 'sync' to false in that case to dispatch in a
+  //   separate new event.
+  nsresult ScheduleConnectionCloseEvents(nsISupports *aContext,
+                                         nsresult aStatusCode,
+                                         bool sync);
+  // 2nd half of ScheduleConnectionCloseEvents, sometimes run in its own event.
+  void     DispatchConnectionCloseEvents();
+
+  // These methods actually do the dispatch for various events.
   nsresult CreateAndDispatchSimpleEvent(const nsString& aName);
   nsresult CreateAndDispatchMessageEvent(const nsACString& aData,
                                          bool isBinary);
   nsresult CreateAndDispatchCloseEvent(bool aWasClean, PRUint16 aCode,
                                        const nsString &aReason);
   nsresult CreateResponseBlob(const nsACString& aData, JSContext *aCx,
                               jsval &jsData);
 
-  void SetReadyState(PRUint16 aNewReadyState);
-
   // if there are "strong event listeners" (see comment in nsWebSocket.cpp) or
   // outgoing not sent messages then this method keeps the object alive
   // when js doesn't have strong references to it.
   void UpdateMustKeepAlive();
   // ATTENTION, when calling this method the object can be released
   // (and possibly collected).
   void DontKeepAliveAnyMore();
 
@@ -137,17 +146,18 @@ protected:
   // related to the WebSocket constructor steps
   nsString mOriginalURL;
   nsString mEffectiveURL;   // after redirects
   bool mSecure; // if true it is using SSL and the wss scheme,
                         // otherwise it is using the ws scheme with no SSL
 
   bool mKeepingAlive;
   bool mCheckMustKeepAlive;
-  bool mTriggeredCloseEvent;
+  bool mOnCloseScheduled;
+  bool mFailed;
   bool mDisconnected;
 
   // Set attributes of DOM 'onclose' message
   bool      mCloseEventWasClean;
   nsString  mCloseEventReason;
   PRUint16  mCloseEventCode;
 
   nsCString mAsciiHost;  // hostname
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -241,16 +241,34 @@ public:
   NS_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget::)
 
 #ifdef DEBUG
   void StaticAssertions();
 #endif
 
   // event handler
   IMPL_EVENT_HANDLER(readystatechange, Readystatechange)
+  JSObject* GetOnuploadprogress(JSContext* /* unused */)
+  {
+    nsIDocument* doc = GetOwner() ? GetOwner()->GetExtantDoc() : NULL;
+    if (doc) {
+      doc->WarnOnceAbout(nsIDocument::eOnuploadprogress);
+    }
+    return GetListenerAsJSObject(mOnUploadProgressListener);
+  }
+  void SetOnuploadprogress(JSContext* aCx, JSObject* aCallback,
+                           ErrorResult& aRv)
+  {
+    nsIDocument* doc = GetOwner() ? GetOwner()->GetExtantDoc() : NULL;
+    if (doc) {
+      doc->WarnOnceAbout(nsIDocument::eOnuploadprogress);
+    }
+    aRv = SetJSObjectListener(aCx, NS_LITERAL_STRING("uploadprogress"),
+                              mOnUploadProgressListener, aCallback);
+  }
 
   // states
   uint16_t GetReadyState();
 
   // request
   void Open(const nsAString& aMethod, const nsAString& aUrl, bool aAsync,
             const mozilla::dom::Optional<nsAString>& aUser,
             const mozilla::dom::Optional<nsAString>& aPassword,
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -544,16 +544,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug650386_redirect_307.html \
 		file_bug650386_content.sjs \
 		file_bug650386_report.sjs \
 		test_bug719533.html \
 		test_bug737087.html \
 		test_bug433662.html \
 		test_bug749367.html \
 		test_bug753278.html \
+		test_XHR_onuploadprogress.html \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_XHR_onuploadprogress.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=743666
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 743666</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=743666">Mozilla Bug 743666</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 743666 **/
+
+var called = false;
+function uploadprogress()
+{
+  called = true;
+}
+
+var xhr = new XMLHttpRequest();
+xhr.onuploadprogress = uploadprogress;
+var event = document.createEvent("ProgressEvent");
+event.initProgressEvent("uploadprogress", false, false, false, false, 0);
+xhr.dispatchEvent(event);
+ok(called,
+   "XMLHttpRequest.onuploadprogress sets uploadprogress event listener");
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/base/test/test_websocket.html
+++ b/content/base/test/test_websocket.html
@@ -64,20 +64,21 @@
  * 39. a basic wss:// connectivity test
  * 40. negative test for wss:// with no cert
  * 41. HSTS
  * 42. non-char utf-8 sequences
  * 43. Test setting binaryType attribute
  * 44. Test sending/receving binary ArrayBuffer 
  * 45. Test sending/receving binary Blob 
  * 46. Test that we don't dispatch incoming msgs once in CLOSING state
+ * 47. Make sure onerror/onclose aren't called during close()
  */
 
 var first_test = 1;
-var last_test = 46;
+var last_test = 47;
 
 
 // Set this to >1 if you want to run the suite multiple times to probe for
 // random orange failures. 
 // - Do NOT check into mozilla-central with a value != 1.
 // - Too large a count will wind up causing tryserver to timeout the test (which
 //   is ok, but means all testruns will be orange).  If I set first_test to >22
 //   (i.e don't run any of the tests that require waiting) I can get ~250-300
@@ -277,16 +278,17 @@ function test3()
   {
     hasError = true;
   }
 
   ws.onclose = function(e)
   {
     shouldCloseNotCleanly(e);
     ok(hasError, "rcvd onerror event");
+    ok(e.code == 1006, "test-3 close code should be 1006 but is:" + e.code);
     doTest(4);
   };
 }
 
 function test4()
 {
   try {
     var ws = CreateTestWS("file_websocket");
@@ -1430,16 +1432,51 @@ function test46()
   ws.onclose = function(e)
   {
     ok(ws.readyState == 3, "onclose bad readyState in test-46!");
     shouldCloseCleanly(e);
     doTest(47);
   }
 }
 
+function test47()
+{
+  var hasError = false;
+  var ws = CreateTestWS("ws://another.websocket.server.that.probably.does.not.exist");
+  ws.onopen = shouldNotOpen;
+
+  ws.onerror = function (e)
+  {
+    ok(ws.readyState == 3, "test-47: readyState should be CLOSED(3) in onerror: got " 
+       + ws.readyState);
+    ok(!ws._withinClose, "onerror() called during close()!");
+    hasError = true;
+  }
+
+  ws.onclose = function(e)
+  {
+    shouldCloseNotCleanly(e);
+    ok(hasError, "test-47: should have called onerror before onclose");
+    ok(ws.readyState == 3, "test-47: readyState should be CLOSED(3) in onclose: got " 
+       + ws.readyState);
+    ok(!ws._withinClose, "onclose() called during close()!");
+    ok(e.code == 1006, "test-47 close code should be 1006 but is:" + e.code);
+    doTest(48);
+  };
+
+  // Call close before we're connected: throws error
+  // Make sure we call onerror/onclose asynchronously
+  ws._withinClose = 1;
+  ws.close(3333, "Closed before we were open: error");
+  ws._withinClose = 0;
+  ok(ws.readyState == 2, "test-47: readyState should be CLOSING(2) after close(): got "
+     + ws.readyState);
+}
+
+
 var ranAllTests = false;
 
 function maybeFinished()
 {
   if (!ranAllTests)
     return;
 
   if (waitTest2Part1 || waitTest2Part2 || waitTest9 || waitTest10 ||
--- a/content/base/test/unit/test_csputils.js
+++ b/content/base/test/unit/test_csputils.js
@@ -594,16 +594,39 @@ test(
       do_check_false(src.permits("https://foobar.com:443"));
 
       //"src should inherit and require https scheme from self
       do_check_false(src.permits("http://foobar.com:4443"));
       do_check_false(src.permits("http://foobar.com"));
 
     });
 
+test(
+    function test_bug634773_noneAndStarAreDifferent() {
+      /**
+       * Bug 634773 is that allow * and allow 'none' end up "equal" via
+       * CSPSourceList.prototype.equals(), which is wrong.  This tests that
+       * doesn't happen.
+       */
+
+      var p_none = CSPSourceList.fromString("'none'", "http://foo.com", false);
+      var p_all = CSPSourceList.fromString("*", "http://foo.com", false);
+      var p_one = CSPSourceList.fromString("bar.com", "http://foo.com", false);
+
+      do_check_false(p_none.equals(p_all));
+      do_check_false(p_none.equals(p_one));
+      do_check_false(p_all.equals(p_none));
+      do_check_false(p_all.equals(p_one));
+
+      do_check_true(p_all.permits("http://bar.com"));
+      do_check_true(p_one.permits("http://bar.com"));
+      do_check_false(p_none.permits("http://bar.com"));
+    });
+
+
 /*
 
 test(function test_CSPRep_fromPolicyURI_failswhenmixed() {
         var cspr;
         var self = "http://localhost:" + POLICY_PORT;
         var closed_policy = CSPRep.fromString("allow 'none'");
         var my_uri_policy = "policy-uri " + POLICY_URI;
 
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -296,16 +296,19 @@ nsEventListenerManager::AddEventListener
 }
 
 bool
 nsEventListenerManager::IsDeviceType(PRUint32 aType)
 {
   switch (aType) {
     case NS_DEVICE_ORIENTATION:
     case NS_DEVICE_MOTION:
+    case NS_DEVICE_LIGHT:
+    case NS_DEVICE_PROXIMITY:
+    case NS_USER_PROXIMITY:
       return true;
     default:
       break;
   }
   return false;
 }
 
 void
@@ -396,17 +399,17 @@ nsEventListenerManager::RemoveEventListe
       if (ls->mListener == aListener &&
           (ls->mFlags & ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED) == aFlags) {
         nsRefPtr<nsEventListenerManager> kungFuDeathGrip = this;
         mListeners.RemoveElementAt(i);
         --count;
         mNoListenerForEvent = NS_EVENT_TYPE_NULL;
         mNoListenerForEventAtom = nsnull;
 
-        if (deviceType) {
+        if (!deviceType) {
           return;
         }
         --typeCount;
       }
     }
   }
 
   if (deviceType && typeCount == 0) {
--- a/content/html/content/public/nsHTMLAudioElement.h
+++ b/content/html/content/public/nsHTMLAudioElement.h
@@ -44,11 +44,15 @@ public:
                         JSObject* aObj, PRUint32 argc, jsval* argv);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel);
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+protected:
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 #endif
--- a/content/html/content/public/nsHTMLVideoElement.h
+++ b/content/html/content/public/nsHTMLVideoElement.h
@@ -55,11 +55,15 @@ public:
   // If there is no video frame, returns NS_ERROR_FAILURE.
   nsresult GetVideoSize(nsIntSize* size);
 
   virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel);
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+protected:
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 #endif
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/HTMLPropertiesCollection.cpp
@@ -0,0 +1,610 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "HTMLPropertiesCollection.h"
+#include "dombindings.h"
+#include "nsIDocument.h"
+#include "nsContentUtils.h"
+#include "nsGenericHTMLElement.h"
+#include "nsVariant.h"
+#include "nsDOMSettableTokenList.h"
+#include "nsAttrValue.h"
+
+DOMCI_DATA(HTMLPropertiesCollection, mozilla::dom::HTMLPropertiesCollection)
+DOMCI_DATA(PropertyNodeList, mozilla::dom::PropertyNodeList)
+
+namespace mozilla {
+namespace dom {
+
+static PLDHashOperator
+TraverseNamedProperties(const nsAString& aKey, PropertyNodeList* aEntry, void* aData)
+{
+  nsCycleCollectionTraversalCallback* cb = static_cast<nsCycleCollectionTraversalCallback*>(aData);
+  cb->NoteXPCOMChild(static_cast<nsIDOMPropertyNodeList*>(aEntry));
+  return PL_DHASH_NEXT;
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLPropertiesCollection)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLPropertiesCollection)
+  // SetDocument(nsnull) ensures that we remove ourselves as a mutation observer
+  tmp->SetDocument(nsnull);
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRoot)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNames)
+  tmp->mNamedItemEntries.Clear();
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mProperties)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(HTMLPropertiesCollection)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNames)
+  tmp->mNamedItemEntries.EnumerateRead(TraverseNamedProperties, &cb);
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mProperties)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(HTMLPropertiesCollection)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+HTMLPropertiesCollection::HTMLPropertiesCollection(nsGenericHTMLElement* aRoot)
+  : mRoot(aRoot)
+  , mDoc(aRoot->GetCurrentDoc())
+  , mIsDirty(true)
+{
+  SetIsDOMBinding();
+  mNames = new PropertyStringList(this);
+  if (mDoc) {
+    mDoc->AddMutationObserver(this);
+  }
+  mNamedItemEntries.Init();
+}
+
+HTMLPropertiesCollection::~HTMLPropertiesCollection()
+{
+  if (mDoc) {
+    mDoc->RemoveMutationObserver(this);
+  }
+}
+
+NS_INTERFACE_TABLE_HEAD(HTMLPropertiesCollection)
+    NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+    NS_INTERFACE_TABLE4(HTMLPropertiesCollection,
+                        nsIDOMHTMLPropertiesCollection,
+                        nsIDOMHTMLCollection,
+                        nsIHTMLCollection,
+                        nsIMutationObserver)
+    NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(HTMLPropertiesCollection)
+    NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLPropertiesCollection)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(HTMLPropertiesCollection)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(HTMLPropertiesCollection)
+
+
+static PLDHashOperator
+SetPropertyListDocument(const nsAString& aKey, PropertyNodeList* aEntry, void* aData)
+{
+  aEntry->SetDocument(static_cast<nsIDocument*>(aData));
+  return PL_DHASH_NEXT;
+}
+
+void
+HTMLPropertiesCollection::SetDocument(nsIDocument* aDocument) {
+  if (mDoc) {
+    mDoc->RemoveMutationObserver(this);
+  }
+  mDoc = aDocument;
+  if (mDoc) {
+    mDoc->AddMutationObserver(this);
+  }
+  mNamedItemEntries.EnumerateRead(SetPropertyListDocument, aDocument);
+  mIsDirty = true;
+}
+
+JSObject*
+HTMLPropertiesCollection::WrapObject(JSContext* cx, JSObject* scope,
+                                     bool* triedToWrap)
+{
+  return mozilla::dom::binding::HTMLPropertiesCollection::create(cx, scope, this,
+                                                                 triedToWrap);
+}
+
+NS_IMETHODIMP
+HTMLPropertiesCollection::GetLength(PRUint32* aLength)
+{
+  EnsureFresh();
+  *aLength = mProperties.Length();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLPropertiesCollection::Item(PRUint32 aIndex, nsIDOMNode** aResult)
+{
+  EnsureFresh();
+  nsGenericHTMLElement* property = mProperties.SafeElementAt(aIndex);
+  *aResult = property ? property->AsDOMNode() : NULL;
+  NS_IF_ADDREF(*aResult);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLPropertiesCollection::NamedItem(const nsAString& aName,
+                                    nsIDOMNode** aResult)
+{
+  *aResult = NULL;
+  return NS_OK;
+}
+
+nsISupports*
+HTMLPropertiesCollection::GetNamedItem(const nsAString& aName,
+                                       nsWrapperCache **aCache)
+{
+  EnsureFresh();
+  if (!mNames->ContainsInternal(aName)) {
+    *aCache = NULL;
+    return NULL;
+  }
+
+  nsRefPtr<PropertyNodeList> propertyList;
+  if (!mNamedItemEntries.Get(aName, getter_AddRefs(propertyList))) {
+    propertyList = new PropertyNodeList(this, mRoot, aName);
+    mNamedItemEntries.Put(aName, propertyList);
+  }
+  *aCache = propertyList;
+  return static_cast<nsIDOMPropertyNodeList*>(propertyList);
+}
+
+nsIContent*
+HTMLPropertiesCollection::GetNodeAt(PRUint32 aIndex)
+{
+  EnsureFresh();
+  return mProperties.SafeElementAt(aIndex);
+}
+
+nsINode*
+HTMLPropertiesCollection::GetParentObject()
+{
+  return mRoot;
+}
+
+NS_IMETHODIMP
+HTMLPropertiesCollection::NamedItem(const nsAString& aName,
+                                    nsIDOMPropertyNodeList** aResult)
+{
+  EnsureFresh();
+ 
+  nsRefPtr<PropertyNodeList> propertyList;
+  if (!mNamedItemEntries.Get(aName, getter_AddRefs(propertyList))) {
+    propertyList = new PropertyNodeList(this, mRoot, aName);
+    mNamedItemEntries.Put(aName, propertyList);
+  }
+  propertyList.forget(aResult);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLPropertiesCollection::GetNames(nsIDOMDOMStringList** aResult)
+{
+  EnsureFresh();
+  NS_ADDREF(*aResult = mNames);
+  return NS_OK;
+}
+
+void
+HTMLPropertiesCollection::AttributeChanged(nsIDocument *aDocument, Element* aElement,
+                                           PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                                           PRInt32 aModType)
+{
+  mIsDirty = true;
+}
+
+void
+HTMLPropertiesCollection::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
+                                          nsIContent* aFirstNewContent,
+                                          PRInt32 aNewIndexInContainer)
+{
+  mIsDirty = true;
+}
+
+void
+HTMLPropertiesCollection::ContentInserted(nsIDocument *aDocument,
+                                          nsIContent* aContainer,
+                                          nsIContent* aChild,
+                                          PRInt32 aIndexInContainer)
+{
+  mIsDirty = true;
+}
+
+void
+HTMLPropertiesCollection::ContentRemoved(nsIDocument *aDocument,
+                                         nsIContent* aContainer,
+                                         nsIContent* aChild,
+                                         PRInt32 aIndexInContainer,
+                                         nsIContent* aPreviousSibling)
+{
+  mIsDirty = true;
+}
+
+class TreeOrderComparator {
+  public:
+    bool Equals(const nsGenericHTMLElement* aElem1,
+                const nsGenericHTMLElement* aElem2) const {
+      return aElem1 == aElem2;
+    }
+    bool LessThan(const nsGenericHTMLElement* aElem1,
+                  const nsGenericHTMLElement* aElem2) const {
+      return nsContentUtils::PositionIsBefore(const_cast<nsGenericHTMLElement*>(aElem1),
+                                              const_cast<nsGenericHTMLElement*>(aElem2));
+    }
+};
+
+static PLDHashOperator
+MarkDirty(const nsAString& aKey, PropertyNodeList* aEntry, void* aData)
+{
+  aEntry->SetDirty();
+  return PL_DHASH_NEXT;
+}
+
+void
+HTMLPropertiesCollection::EnsureFresh()
+{
+  if (mDoc && !mIsDirty) {
+    return;
+  }
+  mIsDirty = false;
+
+  mProperties.Clear();
+  mNames->Clear();
+  // We don't clear NamedItemEntries because the PropertyNodeLists must be live.
+  mNamedItemEntries.EnumerateRead(MarkDirty, NULL);
+  if (!mRoot->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope)) {
+    return;
+  }
+
+  CrawlProperties();
+  TreeOrderComparator comparator;
+  mProperties.Sort(comparator);
+
+  // Create the names DOMStringList
+  PRUint32 count = mProperties.Length();
+  for (PRUint32 i = 0; i < count; ++i) {
+    const nsAttrValue* attr = mProperties.ElementAt(i)->GetParsedAttr(nsGkAtoms::itemprop); 
+    for (PRUint32 i = 0; i < attr->GetAtomCount(); i++) {
+      nsDependentAtomString propName(attr->AtomAt(i));
+      // ContainsInternal must not call EnsureFresh
+      bool contains = mNames->ContainsInternal(propName);
+      if (!contains) {
+        mNames->Add(propName);
+      }
+    }
+  }
+}
+  
+static Element*
+GetElementByIdForConnectedSubtree(nsIContent* aContent, const nsIAtom* aId)
+{
+  aContent = static_cast<nsIContent*>(aContent->SubtreeRoot());
+  do {
+    if (aContent->GetID() == aId) {
+      return aContent->AsElement();
+    }
+    aContent = aContent->GetNextNode();
+  } while(aContent);
+  
+  return NULL;
+}
+
+void
+HTMLPropertiesCollection::CrawlProperties()
+{
+  nsIDocument* doc = mRoot->GetCurrentDoc();
+ 
+  const nsAttrValue* attr = mRoot->GetParsedAttr(nsGkAtoms::itemref);
+  if (attr) {
+    for (PRUint32 i = 0; i < attr->GetAtomCount(); i++) {
+      nsIAtom* ref = attr->AtomAt(i);
+      Element* element;
+      if (doc) {
+        element = doc->GetElementById(nsDependentAtomString(ref));
+      } else {
+        element = GetElementByIdForConnectedSubtree(mRoot, ref);
+      }
+      if (element && element != mRoot) {
+        CrawlSubtree(element);
+      }
+    }
+  }
+  
+  CrawlSubtree(mRoot);
+}
+
+void
+HTMLPropertiesCollection::CrawlSubtree(Element* aElement)
+{
+  nsIContent* aContent = aElement;
+  while (aContent) {
+    // We must check aContent against mRoot because 
+    // an element must not be its own property
+    if (aContent == mRoot || !aContent->IsHTML()) {
+      // Move on to the next node in the tree
+      aContent = aContent->GetNextNode(aElement);
+    } else {
+      MOZ_ASSERT(aContent->IsElement(), "IsHTML() returned true!");
+      Element* element = aContent->AsElement();
+      if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) &&
+          !mProperties.Contains(element)) {
+        mProperties.AppendElement(static_cast<nsGenericHTMLElement*>(element));
+      }                 
+                     
+      if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope)) {
+        aContent = element->GetNextNonChildNode(aElement);
+      } else {          
+        aContent = element->GetNextNode(aElement);
+      }                 
+    }                     
+  }                    
+}
+
+PropertyNodeList::PropertyNodeList(HTMLPropertiesCollection* aCollection,
+                                   nsIContent* aParent, const nsAString& aName)
+  : mName(aName),
+    mDoc(aParent->GetCurrentDoc()),
+    mCollection(aCollection),
+    mParent(aParent),
+    mIsDirty(true)
+{
+  SetIsDOMBinding();
+  if (mDoc) {
+    mDoc->AddMutationObserver(this);
+  }
+}
+
+PropertyNodeList::~PropertyNodeList()
+{
+  if (mDoc) {
+    mDoc->RemoveMutationObserver(this);
+  }
+}
+
+void
+PropertyNodeList::SetDocument(nsIDocument* aDoc)
+{
+  if (mDoc) {
+    mDoc->RemoveMutationObserver(this);
+  }
+  mDoc = aDoc;
+  if (mDoc) {
+    mDoc->AddMutationObserver(this);
+  }
+  mIsDirty = true;
+}
+
+NS_IMETHODIMP
+PropertyNodeList::GetLength(PRUint32* aLength)
+{
+  EnsureFresh();
+  *aLength = mElements.Length();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PropertyNodeList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
+{
+  EnsureFresh();
+  nsINode* element = mElements.SafeElementAt(aIndex);
+  if (!element) {
+    *aReturn = NULL;
+    return NS_OK;
+  }
+  return CallQueryInterface(element, aReturn);
+}
+
+nsIContent*
+PropertyNodeList::GetNodeAt(PRUint32 aIndex)
+{
+  EnsureFresh();
+  return mElements.SafeElementAt(aIndex);
+}
+
+PRInt32
+PropertyNodeList::IndexOf(nsIContent* aContent)
+{
+  EnsureFresh();
+  return mElements.IndexOf(aContent);
+}
+
+nsINode*
+PropertyNodeList::GetParentObject()
+{
+  return mParent;
+}
+
+JSObject*
+PropertyNodeList::WrapObject(JSContext *cx, JSObject *scope,
+                             bool *triedToWrap)
+{
+  return mozilla::dom::binding::PropertyNodeList::create(cx, scope, this,
+                                                         triedToWrap);
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(PropertyNodeList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PropertyNodeList)
+  // SetDocument(nsnull) ensures that we remove ourselves as a mutation observer
+  tmp->SetDocument(nsnull);
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCollection)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PropertyNodeList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCollection, nsIDOMHTMLPropertiesCollection)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mElements)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(PropertyNodeList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(PropertyNodeList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(PropertyNodeList)
+
+NS_INTERFACE_TABLE_HEAD(PropertyNodeList)
+    NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+    NS_INTERFACE_TABLE4(PropertyNodeList,
+                        nsIDOMPropertyNodeList,
+                        nsIDOMNodeList,
+                        nsINodeList,
+                        nsIMutationObserver)
+    NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(PropertyNodeList)
+    NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PropertyNodeList)
+NS_INTERFACE_MAP_END
+
+NS_IMETHODIMP
+PropertyNodeList::GetValues(nsIVariant** aValues)
+{
+  EnsureFresh();
+  nsCOMPtr<nsIWritableVariant> out = new nsVariant();
+
+  // We have to use an nsTArray<nsIVariant*> here and do manual refcounting because 
+  // nsWritableVariant::SetAsArray takes an nsIVariant**.
+  nsTArray<nsIVariant*> values;
+
+  PRUint32 length = mElements.Length();
+  if (length == 0) {
+    out->SetAsEmptyArray();
+  } else {
+    for (PRUint32 i = 0; i < length; ++i) {
+      nsIVariant* itemValue;
+      mElements.ElementAt(i)->GetItemValue(&itemValue);
+      values.AppendElement(itemValue);
+    }
+    out->SetAsArray(nsIDataType::VTYPE_INTERFACE_IS,
+                    &NS_GET_IID(nsIVariant),
+                    values.Length(),
+                    values.Elements());
+  }
+
+  out.forget(aValues);
+
+  for (PRUint32 i = 0; i < values.Length(); ++i) {
+    NS_RELEASE(values[i]);
+  }
+
+  return NS_OK;
+}
+
+void
+PropertyNodeList::AttributeChanged(nsIDocument* aDocument, Element* aElement,
+                                   PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                                   PRInt32 aModType)
+{
+  mIsDirty = true;
+}
+
+void
+PropertyNodeList::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
+                                  nsIContent* aFirstNewContent,
+                                  PRInt32 aNewIndexInContainer)
+{
+  mIsDirty = true;
+}
+
+void
+PropertyNodeList::ContentInserted(nsIDocument* aDocument,
+                                  nsIContent* aContainer,
+                                  nsIContent* aChild,
+                                  PRInt32 aIndexInContainer)
+{
+  mIsDirty = true;
+}
+
+void
+PropertyNodeList::ContentRemoved(nsIDocument* aDocument,
+                                 nsIContent* aContainer,
+                                 nsIContent* aChild,
+                                 PRInt32 aIndexInContainer,
+                                 nsIContent* aPreviousSibling)
+{
+  mIsDirty = true;
+}
+
+void
+PropertyNodeList::EnsureFresh()
+{
+  if (mDoc && !mIsDirty) {
+    return;
+  }
+  mIsDirty = false;
+
+  mCollection->EnsureFresh();
+  Clear();
+
+  PRUint32 count = mCollection->mProperties.Length();
+  for (PRUint32 i = 0; i < count; ++i) {
+    nsGenericHTMLElement* element = mCollection->mProperties.ElementAt(i);
+    const nsAttrValue* attr = element->GetParsedAttr(nsGkAtoms::itemprop);
+    if (attr->Contains(mName)) {
+      AppendElement(element);
+    }
+  }
+}
+
+PropertyStringList::PropertyStringList(HTMLPropertiesCollection* aCollection)
+  : nsDOMStringList()
+  , mCollection(aCollection)
+{ }
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(PropertyStringList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PropertyStringList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCollection)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PropertyStringList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCollection, nsIDOMHTMLPropertiesCollection)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(PropertyStringList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(PropertyStringList)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PropertyStringList)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMDOMStringList)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMStringList)
+NS_INTERFACE_MAP_END
+
+NS_IMETHODIMP
+PropertyStringList::Item(PRUint32 aIndex, nsAString& aResult)
+{
+  mCollection->EnsureFresh();
+  return nsDOMStringList::Item(aIndex, aResult);
+}
+
+NS_IMETHODIMP
+PropertyStringList::GetLength(PRUint32* aLength)
+{
+  mCollection->EnsureFresh();
+  return nsDOMStringList::GetLength(aLength);
+}
+
+NS_IMETHODIMP
+PropertyStringList::Contains(const nsAString& aString, bool* aResult)
+{
+  mCollection->EnsureFresh();
+  return nsDOMStringList::Contains(aString, aResult);
+}
+
+bool
+PropertyStringList::ContainsInternal(const nsAString& aString)
+{
+  // This method should not call EnsureFresh, otherwise we may become stuck in an infinite loop.
+  bool result;
+  nsDOMStringList::Contains(aString, &result);
+  return result;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/HTMLPropertiesCollection.h
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef HTMLPropertiesCollection_h_
+#define HTMLPropertiesCollection_h_
+
+#include "nsDOMLists.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsAutoPtr.h"
+#include "nsIDOMHTMLPropertiesCollection.h"
+#include "nsIDOMPropertyNodeList.h"
+#include "nsCOMArray.h"
+#include "nsIMutationObserver.h"
+#include "nsStubMutationObserver.h"
+#include "nsBaseHashtable.h"
+#include "nsINodeList.h"
+#include "nsIHTMLCollection.h"
+#include "nsHashKeys.h"
+#include "nsGenericHTMLElement.h"
+
+class nsXPCClassInfo;
+class nsIDocument;
+class nsINode;
+
+namespace mozilla {
+namespace dom {
+
+class HTMLPropertiesCollection;
+class PropertyNodeList;
+
+class PropertyStringList : public nsDOMStringList
+{
+public:
+  PropertyStringList(HTMLPropertiesCollection* aCollection);
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(PropertyStringList)
+  NS_DECL_NSIDOMDOMSTRINGLIST
+
+  bool ContainsInternal(const nsAString& aString);
+
+protected:
+  nsRefPtr<HTMLPropertiesCollection> mCollection;
+};
+
+class HTMLPropertiesCollection : public nsIDOMHTMLPropertiesCollection,
+                                 public nsStubMutationObserver,
+                                 public nsWrapperCache,
+                                 public nsIHTMLCollection
+{
+  friend class PropertyNodeList;
+  friend class PropertyStringList;
+public:
+  HTMLPropertiesCollection(nsGenericHTMLElement* aRoot);
+  virtual ~HTMLPropertiesCollection();
+
+  virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
+                               bool *triedToWrap);
+
+  NS_IMETHOD NamedItem(const nsAString& aName, nsIDOMNode** aResult);
+  void SetDocument(nsIDocument* aDocument);
+  nsINode* GetParentObject();
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_NSIDOMHTMLPROPERTIESCOLLECTION
+
+  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
+
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(HTMLPropertiesCollection,
+                                                         nsIHTMLCollection)
+
+  nsXPCClassInfo* GetClassInfo();
+
+protected:
+  // Make sure this collection is up to date, in case the DOM has been mutated.
+  void EnsureFresh();
+  
+  // Crawl the properties of mRoot, following any itemRefs it may have
+  void CrawlProperties();
+
+  // Crawl startNode and its descendants, looking for items
+  void CrawlSubtree(Element* startNode);
+
+  // the items that make up this collection
+  nsTArray<nsRefPtr<nsGenericHTMLElement> > mProperties; 
+  
+  // the itemprop attribute of the properties
+  nsRefPtr<PropertyStringList> mNames; 
+ 
+  // The cached PropertyNodeLists that are NamedItems of this collection 
+  nsRefPtrHashtable<nsStringHashKey, PropertyNodeList> mNamedItemEntries;
+  
+  // The element this collection is rooted at
+  nsCOMPtr<nsGenericHTMLElement> mRoot;
+  
+  // The document mRoot is in, if any
+  nsCOMPtr<nsIDocument> mDoc;
+  
+  // True if there have been DOM modifications since the last EnsureFresh call.
+  bool mIsDirty;
+};
+
+class PropertyNodeList : public nsINodeList,
+                         public nsIDOMPropertyNodeList,
+                         public nsStubMutationObserver
+{
+public:
+  PropertyNodeList(HTMLPropertiesCollection* aCollection,
+                   nsIContent* aRoot, const nsAString& aName);
+  virtual ~PropertyNodeList();
+
+  virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
+                               bool *triedToWrap);
+
+  void SetDocument(nsIDocument* aDocument);
+
+  NS_DECL_NSIDOMPROPERTYNODELIST
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(PropertyNodeList,
+                                                         nsINodeList)
+
+  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
+
+  // nsINodeList interface
+  virtual PRInt32 IndexOf(nsIContent* aContent);
+  virtual nsINode* GetParentObject();
+  
+  void AppendElement(nsGenericHTMLElement* aElement)
+  {
+    mElements.AppendElement(aElement);
+  }
+  
+  void Clear()
+  {
+    mElements.Clear();
+  }
+  
+  void SetDirty() { mIsDirty = true; }
+ 
+protected:
+  // Make sure this list is up to date, in case the DOM has been mutated.
+  void EnsureFresh();
+
+  // the the name that this list corresponds to 
+  nsString mName;
+
+  // the document mParent is in, if any
+  nsCOMPtr<nsIDocument> mDoc;
+
+  // the collection that this list is a named item of
+  nsRefPtr<HTMLPropertiesCollection> mCollection;
+
+  // the node this list is rooted at
+  nsCOMPtr<nsINode> mParent;
+
+  // the properties that make up this list
+  nsTArray<nsRefPtr<nsGenericHTMLElement> > mElements;
+
+  // True if there have been DOM modifications since the last EnsureFresh call. 
+  bool mIsDirty;
+};
+
+} // namespace dom
+} // namespace mozilla
+#endif // HTMLPropertiesCollection_h_ 
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -17,16 +17,17 @@ FAIL_ON_WARNINGS = 1
 
 
 EXPORTS		= \
 		nsClientRect.h \
 		nsHTMLDNSPrefetch.h \
 		$(NULL)
 
 CPPSRCS		= \
+		HTMLPropertiesCollection.cpp \
 		nsClientRect.cpp \
 		nsHTMLDNSPrefetch.cpp \
 		nsGenericHTMLElement.cpp \
 		nsGenericHTMLFrameElement.cpp \
 		nsFormSubmission.cpp \
 		nsTextEditorState.cpp \
 		nsHTMLElement.cpp \
 		nsHTMLAnchorElement.cpp \
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -86,16 +86,19 @@
 #include "nsHTMLMenuElement.h"
 #include "nsAsyncDOMEvent.h"
 #include "nsIScriptError.h"
 #include "nsDOMMutationObserver.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/FromParser.h"
 #include "mozilla/BloomFilter.h"
 
+#include "HTMLPropertiesCollection.h"
+#include "nsVariant.h"
+
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #include "nsThreadUtils.h"
 
 class nsINodeInfo;
 class nsIDOMNodeList;
 class nsRuleWalker;
@@ -243,17 +246,16 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGeneri
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGenericHTMLElementTearoff)
 
 NS_INTERFACE_TABLE_HEAD(nsGenericHTMLElementTearoff)
   NS_INTERFACE_TABLE_INHERITED1(nsGenericHTMLElementTearoff,
                                 nsIDOMElementCSSInlineStyle)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsGenericHTMLElementTearoff)
 NS_INTERFACE_MAP_END_AGGREGATED(mElement)
 
-
 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsGenericHTMLElement, TabIndex, tabindex, -1)
 NS_IMPL_BOOL_ATTR(nsGenericHTMLElement, Hidden, hidden)
 
 nsresult
 nsGenericHTMLElement::DOMQueryInterface(nsIDOMHTMLElement *aElement,
                                         REFNSIID aIID, void **aInstancePtr)
 {
   NS_PRECONDITION(aInstancePtr, "null out param");
@@ -1694,16 +1696,23 @@ nsGenericHTMLElement::BindToTree(nsIDocu
                                  bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElementBase::BindToTree(aDocument, aParent,
                                                      aBindingParent,
                                                      aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
+    if (HasProperties()) {
+      HTMLPropertiesCollection* properties = 
+        static_cast<HTMLPropertiesCollection*>(GetProperty(nsGkAtoms::microdataProperties));
+      if (properties) {
+        properties->SetDocument(aDocument);
+      }
+    }
     RegAccessKey();
     if (HasName()) {
       aDocument->
         AddToNameTable(this, GetParsedAttr(nsGkAtoms::name)->GetAtomValue());
     }
     if (HasFlag(NODE_IS_EDITABLE) && GetContentEditableValue() == eTrue) {
       nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(aDocument);
       if (htmlDocument) {
@@ -1716,16 +1725,24 @@ nsGenericHTMLElement::BindToTree(nsIDocu
 }
 
 void
 nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   if (IsInDoc()) {
     UnregAccessKey();
   }
+  
+  if(HasProperties()) {
+    HTMLPropertiesCollection* properties = 
+      static_cast<HTMLPropertiesCollection*>(GetProperty(nsGkAtoms::microdataProperties));
+    if (properties) {
+      properties->SetDocument(nsnull);
+    }
+  }
 
   RemoveFromNameTable();
 
   if (GetContentEditableValue() == eTrue) {
     nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(GetCurrentDoc());
     if (htmlDocument) {
       htmlDocument->ChangeContentEditableCount(this, -1);
     }
@@ -2068,16 +2085,23 @@ nsGenericHTMLElement::ParseAttribute(PRI
       
       return true;
     }
 
     if (aAttribute == nsGkAtoms::contenteditable) {
       aResult.ParseAtom(aValue);
       return true;
     }
+
+    if (aAttribute == nsGkAtoms::itemref ||
+        aAttribute == nsGkAtoms::itemprop ||
+        aAttribute == nsGkAtoms::itemtype) {
+      aResult.ParseAtomArray(aValue);
+      return true;
+    }
   }
 
   return nsGenericHTMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
                                                   aValue, aResult);
 }
 
 bool
 nsGenericHTMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
@@ -4076,8 +4100,167 @@ nsGenericHTMLElement::ChangeEditableStat
   }
 
   // MakeContentDescendantsEditable is going to call ContentStateChanged for
   // this element and all descendants if editable state has changed.
   // We might as well wrap it all in one script blocker.
   nsAutoScriptBlocker scriptBlocker;
   MakeContentDescendantsEditable(this, document);
 }
+
+NS_IMPL_BOOL_ATTR(nsGenericHTMLElement, ItemScope, itemscope)
+NS_IMPL_URI_ATTR(nsGenericHTMLElement, ItemId, itemid)
+
+NS_IMETHODIMP
+nsGenericHTMLElement::GetItemValue(nsIVariant** aValue)
+{
+  nsCOMPtr<nsIWritableVariant> out = new nsVariant();
+
+  if (!HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop)) {
+    out->SetAsEmpty();
+    out.forget(aValue);
+    return NS_OK;
+  }
+
+  bool itemScope;
+  GetItemScope(&itemScope);
+  if (itemScope) {
+    out->SetAsISupports(static_cast<nsISupports*>(this));
+  } else {
+    nsAutoString string;
+    GetItemValueText(string);
+    out->SetAsAString(string);
+  }
+
+  out.forget(aValue);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGenericHTMLElement::SetItemValue(nsIVariant* aValue)
+{
+  if (!HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) ||
+      HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope)) {
+    return NS_ERROR_DOM_INVALID_ACCESS_ERR;
+  }
+
+  nsAutoString string;
+  aValue->GetAsAString(string);
+  SetItemValueText(string);
+  return NS_OK;
+}
+
+void
+nsGenericHTMLElement::GetItemValueText(nsAString& text)
+{
+  GetTextContent(text);
+}
+
+void
+nsGenericHTMLElement::SetItemValueText(const nsAString& text)
+{
+  SetTextContent(text);
+}
+
+static void
+nsDOMSettableTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
+                                         void *aPropertyValue, void *aData)
+{
+  nsDOMSettableTokenList* list =
+    static_cast<nsDOMSettableTokenList*>(aPropertyValue);
+  NS_IF_RELEASE(list);
+}
+
+nsDOMSettableTokenList*
+nsGenericHTMLElement::GetTokenList(nsIAtom* aAtom)
+{
+  nsDOMSettableTokenList* list = NULL;
+  if (HasProperties()) {
+    list = static_cast<nsDOMSettableTokenList*>(GetProperty(aAtom));
+  }
+  if (!list) {
+    list = new nsDOMSettableTokenList(this, aAtom);
+    NS_ADDREF(list);
+    SetProperty(aAtom, list, nsDOMSettableTokenListPropertyDestructor);
+  }                       
+  return list;
+}  
+
+NS_IMETHODIMP
+nsGenericHTMLElement::GetItemRef(nsIVariant** aResult)
+{
+  nsIDOMDOMSettableTokenList* itemRef = GetTokenList(nsGkAtoms::itemref);
+  nsCOMPtr<nsIWritableVariant> out = new nsVariant();
+  out->SetAsInterface(NS_GET_IID(nsIDOMDOMSettableTokenList), itemRef);
+  out.forget(aResult);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGenericHTMLElement::SetItemRef(nsIVariant* aValue)
+{
+  nsDOMSettableTokenList* itemRef = GetTokenList(nsGkAtoms::itemref);
+  nsAutoString string;
+  aValue->GetAsAString(string);
+  return itemRef->SetValue(string);
+}
+
+NS_IMETHODIMP
+nsGenericHTMLElement::GetItemProp(nsIVariant** aResult)
+{
+  nsIDOMDOMSettableTokenList* itemProp = GetTokenList(nsGkAtoms::itemprop);
+  nsCOMPtr<nsIWritableVariant> out = new nsVariant();
+  out->SetAsInterface(NS_GET_IID(nsIDOMDOMSettableTokenList), itemProp);
+  out.forget(aResult);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGenericHTMLElement::SetItemProp(nsIVariant* aValue)
+{
+  nsDOMSettableTokenList* itemProp = GetTokenList(nsGkAtoms::itemprop);
+  nsAutoString string;
+  aValue->GetAsAString(string);
+  return itemProp->SetValue(string);
+}
+
+NS_IMETHODIMP
+nsGenericHTMLElement::GetItemType(nsIVariant** aResult)
+{
+  nsIDOMDOMSettableTokenList* itemType = GetTokenList(nsGkAtoms::itemtype);
+  nsCOMPtr<nsIWritableVariant> out = new nsVariant();
+  out->SetAsInterface(NS_GET_IID(nsIDOMDOMSettableTokenList), itemType);
+  out.forget(aResult);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGenericHTMLElement::SetItemType(nsIVariant* aValue)
+{
+  nsDOMSettableTokenList* itemType = GetTokenList(nsGkAtoms::itemtype);
+  nsAutoString string;
+  aValue->GetAsAString(string);
+  return itemType->SetValue(string);
+}
+
+static void
+nsIDOMHTMLPropertiesCollectionDestructor(void *aObject, nsIAtom *aProperty,
+                                         void *aPropertyValue, void *aData)
+{
+  nsIDOMHTMLPropertiesCollection* properties = 
+    static_cast<nsIDOMHTMLPropertiesCollection*>(aPropertyValue);
+  NS_IF_RELEASE(properties);
+}
+
+NS_IMETHODIMP
+nsGenericHTMLElement::GetProperties(nsIDOMHTMLPropertiesCollection** aReturn)
+{
+  nsIDOMHTMLPropertiesCollection* properties = 
+    static_cast<nsIDOMHTMLPropertiesCollection*>(GetProperty(nsGkAtoms::microdataProperties));
+  if (!properties) {
+     properties = new HTMLPropertiesCollection(this);
+     NS_ADDREF(properties);
+     SetProperty(nsGkAtoms::microdataProperties, properties, nsIDOMHTMLPropertiesCollectionDestructor);
+  }
+  NS_ADDREF(*aReturn = properties);
+  return NS_OK;
+}
+
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -8,16 +8,18 @@
 
 #include "nsMappedAttributeElement.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsINameSpaceManager.h"  // for kNameSpaceID_None
 #include "nsIFormControl.h"
 #include "nsFrameLoader.h"
 #include "nsGkAtoms.h"
 #include "nsContentCreatorFunctions.h"
+#include "nsDOMSettableTokenList.h"
+#include "nsIDOMHTMLPropertiesCollection.h"
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIDOMNodeList;
 class nsIFrame;
 class nsIStyleRule;
 class nsChildContentList;
 class nsDOMCSSDeclaration;
@@ -28,16 +30,17 @@ class nsIForm;
 class nsPresState;
 class nsILayoutHistoryState;
 class nsIEditor;
 struct nsRect;
 struct nsSize;
 class nsHTMLFormElement;
 class nsIDOMDOMStringMap;
 class nsIDOMHTMLMenuElement;
+class nsIDOMHTMLCollection;
 
 typedef nsMappedAttributeElement nsGenericHTMLElementBase;
 
 /**
  * A common superclass for HTML elements
  */
 class nsGenericHTMLElement : public nsGenericHTMLElementBase
 {
@@ -109,16 +112,36 @@ public:
   NS_IMETHOD GetTabIndex(PRInt32 *aTabIndex);
   NS_IMETHOD SetTabIndex(PRInt32 aTabIndex);
   NS_IMETHOD GetHidden(bool* aHidden);
   NS_IMETHOD SetHidden(bool aHidden);
   NS_IMETHOD GetSpellcheck(bool* aSpellcheck);
   NS_IMETHOD SetSpellcheck(bool aSpellcheck);
   NS_IMETHOD GetDraggable(bool* aDraggable);
   NS_IMETHOD SetDraggable(bool aDraggable);
+  NS_IMETHOD GetItemScope(bool* aItemScope);
+  NS_IMETHOD SetItemScope(bool aItemScope);
+  NS_IMETHOD GetItemValue(nsIVariant** aValue);
+  NS_IMETHOD SetItemValue(nsIVariant* aValue);
+protected:
+  // These methods are used to implement element-specific behavior of Get/SetItemValue
+  // when an element has @itemprop but no @itemscope.
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
+  nsDOMSettableTokenList* GetTokenList(nsIAtom* aAtom);
+public:
+  NS_IMETHOD GetItemType(nsIVariant** aType);
+  NS_IMETHOD SetItemType(nsIVariant* aType);
+  NS_IMETHOD GetItemId(nsAString& aId);
+  NS_IMETHOD SetItemId(const nsAString& aId);
+  NS_IMETHOD GetItemRef(nsIVariant** aRef);
+  NS_IMETHOD SetItemRef(nsIVariant* aValue);
+  NS_IMETHOD GetItemProp(nsIVariant** aProp);
+  NS_IMETHOD SetItemProp(nsIVariant* aValue);
+  NS_IMETHOD GetProperties(nsIDOMHTMLPropertiesCollection** aReturn);
   NS_IMETHOD GetAccessKey(nsAString &aAccessKey);
   NS_IMETHOD SetAccessKey(const nsAString& aAccessKey);
   NS_IMETHOD GetAccessKeyLabel(nsAString& aLabel);
   nsresult GetContentEditable(nsAString& aContentEditable);
   nsresult GetIsContentEditable(bool* aContentEditable);
   nsresult SetContentEditable(const nsAString &aContentEditable);
   nsresult GetDataset(nsIDOMDOMStringMap** aDataset);
   // Callback for destructor of of dataset to ensure to null out weak pointer.
@@ -766,19 +789,16 @@ protected:
    * made editable through contentEditable or designMode.
    */
   bool IsEditableRoot() const;
 
 private:
   void ChangeEditableState(PRInt32 aChange);
 };
 
-
-//----------------------------------------------------------------------
-
 class nsHTMLFieldSetElement;
 
 /**
  * A helper class for form elements that can contain children
  */
 class nsGenericHTMLFormElement : public nsGenericHTMLElement,
                                  public nsIFormControl
 {
@@ -1371,16 +1391,55 @@ PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_B
     return _to GetHidden(aHidden); \
   } \
   NS_SCRIPTABLE NS_IMETHOD SetHidden(bool aHidden) { \
     return _to SetHidden(aHidden); \
   } \
   NS_SCRIPTABLE NS_IMETHOD Blur() { \
     return _to Blur(); \
   } \
+  NS_SCRIPTABLE NS_IMETHOD GetItemScope(bool* aItemScope) { \
+    return _to GetItemScope(aItemScope); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD SetItemScope(bool aItemScope) { \
+    return _to SetItemScope(aItemScope); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD GetItemType(nsIVariant** aType) { \
+    return _to GetItemType(aType); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD SetItemType(nsIVariant* aType) { \
+    return _to SetItemType(aType); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD GetItemId(nsAString& aId) { \
+    return _to GetItemId(aId); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD SetItemId(const nsAString& aId) { \
+    return _to SetItemId(aId); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD GetProperties(nsIDOMHTMLPropertiesCollection** aReturn) { \
+    return _to GetProperties(aReturn); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD GetItemValue(nsIVariant** aValue) { \
+    return _to GetItemValue(aValue); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD SetItemValue(nsIVariant* aValue) { \
+    return _to SetItemValue(aValue); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD GetItemRef(nsIVariant** aRef) { \
+    return _to GetItemRef(aRef); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD SetItemRef(nsIVariant* aRef) { \
+    return _to SetItemRef(aRef); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD GetItemProp(nsIVariant** aProp) { \
+    return _to GetItemProp(aProp); \
+  } \
+  NS_SCRIPTABLE NS_IMETHOD SetItemProp(nsIVariant* aProp) { \
+    return _to SetItemProp(aProp); \
+  } \
   NS_SCRIPTABLE NS_IMETHOD GetAccessKey(nsAString& aAccessKey) { \
     return _to GetAccessKey(aAccessKey); \
   } \
   NS_SCRIPTABLE NS_IMETHOD SetAccessKey(const nsAString& aAccessKey) { \
     return _to SetAccessKey(aAccessKey); \
   } \
   NS_SCRIPTABLE NS_IMETHOD GetAccessKeyLabel(nsAString& aAccessKeyLabel) { \
     return _to GetAccessKeyLabel(aAccessKeyLabel); \
--- a/content/html/content/src/nsHTMLAnchorElement.cpp
+++ b/content/html/content/src/nsHTMLAnchorElement.cpp
@@ -105,16 +105,20 @@ public:
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
   
   virtual void OnDNSPrefetchDeferred();
   virtual void OnDNSPrefetchRequested();
   virtual bool HasDeferredDNSPrefetchRequest();
+
+protected:
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 // Indicates that a DNS Prefetch has been requested from this Anchor elem
 #define HTML_ANCHOR_DNS_PREFETCH_REQUESTED \
   (1 << ELEMENT_TYPE_SPECIFIC_BITS_OFFSET)
 // Indicates that a DNS Prefetch was added to the deferral queue
 #define HTML_ANCHOR_DNS_PREFETCH_DEFERRED \
   (1 << (ELEMENT_TYPE_SPECIFIC_BITS_OFFSET+1))
@@ -161,16 +165,28 @@ NS_IMPL_URI_ATTR(nsHTMLAnchorElement, Hr
 NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Hreflang, hreflang)
 NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Name, name)
 NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Rel, rel)
 NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Rev, rev)
 NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Shape, shape)
 NS_IMPL_INT_ATTR(nsHTMLAnchorElement, TabIndex, tabindex)
 NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Type, type)
 
+void
+nsHTMLAnchorElement::GetItemValueText(nsAString& aValue)
+{
+  GetHref(aValue);
+}
+
+void
+nsHTMLAnchorElement::SetItemValueText(const nsAString& aValue)
+{
+  SetHref(aValue);
+}
+
 NS_IMETHODIMP
 nsHTMLAnchorElement::GetDraggable(bool* aDraggable)
 {
   // links can be dragged as long as there is an href and the
   // draggable attribute isn't false
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
     *aDraggable = !AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
                                nsGkAtoms::_false, eIgnoreCase);
--- a/content/html/content/src/nsHTMLAreaElement.cpp
+++ b/content/html/content/src/nsHTMLAreaElement.cpp
@@ -90,16 +90,20 @@ public:
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsEventStates IntrinsicState() const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+protected:
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Area)
 
 
 nsHTMLAreaElement::nsHTMLAreaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
@@ -132,16 +136,28 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLAreaElement)
 
 NS_IMPL_STRING_ATTR(nsHTMLAreaElement, Alt, alt)
 NS_IMPL_STRING_ATTR(nsHTMLAreaElement, Coords, coords)
 NS_IMPL_URI_ATTR(nsHTMLAreaElement, Href, href)
 NS_IMPL_BOOL_ATTR(nsHTMLAreaElement, NoHref, nohref)
 NS_IMPL_STRING_ATTR(nsHTMLAreaElement, Shape, shape)
 NS_IMPL_INT_ATTR(nsHTMLAreaElement, TabIndex, tabindex)
 
+void
+nsHTMLAreaElement::GetItemValueText(nsAString& aValue)
+{
+  GetHref(aValue);
+}
+
+void
+nsHTMLAreaElement::SetItemValueText(const nsAString& aValue)
+{
+  SetHref(aValue);
+}
+
 NS_IMETHODIMP
 nsHTMLAreaElement::GetTarget(nsAString& aValue)
 {
   if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue)) {
     GetBaseTarget(aValue);
   }
   return NS_OK;
 }
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -78,16 +78,30 @@ nsHTMLAudioElement::nsHTMLAudioElement(a
   : nsHTMLMediaElement(aNodeInfo)
 {
 }
 
 nsHTMLAudioElement::~nsHTMLAudioElement()
 {
 }
 
+void
+nsHTMLAudioElement::GetItemValueText(nsAString& aValue)
+{
+  // Can't call GetSrc because we don't have a JSContext
+  GetURIAttr(nsGkAtoms::src, nsnull, aValue);
+}
+
+void
+nsHTMLAudioElement::SetItemValueText(const nsAString& aValue)
+{
+  // Can't call SetSrc because we don't have a JSContext
+  SetAttr(kNameSpaceID_None, nsGkAtoms::src, aValue, true);
+}
+
 NS_IMETHODIMP
 nsHTMLAudioElement::Initialize(nsISupports* aOwner, JSContext* aContext,
                                JSObject *aObj, PRUint32 argc, jsval *argv)
 {
   // Audio elements created using "new Audio(...)" should have
   // 'preload' set to 'auto' (since the script must intend to
   // play the audio)
   nsresult rv = SetAttr(kNameSpaceID_None, nsGkAtoms::preload,
--- a/content/html/content/src/nsHTMLIFrameElement.cpp
+++ b/content/html/content/src/nsHTMLIFrameElement.cpp
@@ -53,16 +53,20 @@ public:
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   virtual nsXPCClassInfo* GetClassInfo();
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+protected:
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame)
 
 
 nsHTMLIFrameElement::nsHTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                                          FromParser aFromParser)
@@ -101,16 +105,28 @@ NS_IMPL_URI_ATTR(nsHTMLIFrameElement, Lo
 NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, MarginHeight, marginheight)
 NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, MarginWidth, marginwidth)
 NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Name, name)
 NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Scrolling, scrolling)
 NS_IMPL_URI_ATTR(nsHTMLIFrameElement, Src, src)
 NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Width, width)
 NS_IMPL_BOOL_ATTR(nsHTMLIFrameElement, MozAllowFullScreen, mozallowfullscreen)
 
+void
+nsHTMLIFrameElement::GetItemValueText(nsAString& aValue)
+{
+  GetSrc(aValue);
+}
+
+void
+nsHTMLIFrameElement::SetItemValueText(const nsAString& aValue)
+{
+  SetSrc(aValue);
+}
+
 NS_IMETHODIMP
 nsHTMLIFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
 {
   return nsGenericHTMLFrameElement::GetContentDocument(aContentDocument);
 }
 
 NS_IMETHODIMP
 nsHTMLIFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
--- a/content/html/content/src/nsHTMLImageElement.cpp
+++ b/content/html/content/src/nsHTMLImageElement.cpp
@@ -111,16 +111,28 @@ NS_IMPL_STRING_ATTR(nsHTMLImageElement, 
 NS_IMPL_INT_ATTR(nsHTMLImageElement, Hspace, hspace)
 NS_IMPL_BOOL_ATTR(nsHTMLImageElement, IsMap, ismap)
 NS_IMPL_URI_ATTR(nsHTMLImageElement, LongDesc, longdesc)
 NS_IMPL_STRING_ATTR(nsHTMLImageElement, Lowsrc, lowsrc)
 NS_IMPL_URI_ATTR(nsHTMLImageElement, Src, src)
 NS_IMPL_STRING_ATTR(nsHTMLImageElement, UseMap, usemap)
 NS_IMPL_INT_ATTR(nsHTMLImageElement, Vspace, vspace)
 
+void
+nsHTMLImageElement::GetItemValueText(nsAString& aValue)
+{
+  GetSrc(aValue);
+}
+
+void
+nsHTMLImageElement::SetItemValueText(const nsAString& aValue)
+{
+  SetSrc(aValue);
+}
+
 // crossorigin is not "limited to only known values" per spec, so it's
 // just a string attr purposes of the DOM crossOrigin property.
 NS_IMPL_STRING_ATTR(nsHTMLImageElement, CrossOrigin, crossorigin)
 
 NS_IMETHODIMP
 nsHTMLImageElement::GetDraggable(bool* aDraggable)
 {
   // images may be dragged unless the draggable attribute is false
--- a/content/html/content/src/nsHTMLImageElement.h
+++ b/content/html/content/src/nsHTMLImageElement.h
@@ -98,11 +98,13 @@ public:
   nsresult CopyInnerTo(nsGenericElement* aDest) const;
 
   void MaybeLoadImage();
   virtual nsXPCClassInfo* GetClassInfo();
   virtual nsIDOMNode* AsDOMNode() { return this; }
 protected:
   nsIntPoint GetXY();
   nsSize GetWidthHeight();
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 #endif /* nsHTMLImageElement_h */
--- a/content/html/content/src/nsHTMLLinkElement.cpp
+++ b/content/html/content/src/nsHTMLLinkElement.cpp
@@ -90,16 +90,19 @@ public:
   virtual nsXPCClassInfo* GetClassInfo();
   virtual nsIDOMNode* AsDOMNode() { return this; }
 protected:
   virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline);
   virtual void GetStyleSheetInfo(nsAString& aTitle,
                                  nsAString& aType,
                                  nsAString& aMedia,
                                  bool* aIsAlternate);
+protected:
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Link)
 
 
 nsHTMLLinkElement::nsHTMLLinkElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
@@ -167,16 +170,28 @@ NS_IMPL_STRING_ATTR(nsHTMLLinkElement, C
 NS_IMPL_URI_ATTR(nsHTMLLinkElement, Href, href)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Hreflang, hreflang)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Media, media)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rel, rel)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rev, rev)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Target, target)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Type, type)
 
+void
+nsHTMLLinkElement::GetItemValueText(nsAString& aValue)
+{
+  GetHref(aValue);
+}
+
+void
+nsHTMLLinkElement::SetItemValueText(const nsAString& aValue)
+{
+  SetHref(aValue);
+}
+
 nsresult
 nsHTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers)
 {
   Link::ResetLinkState(false);
 
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
--- a/content/html/content/src/nsHTMLMetaElement.cpp
+++ b/content/html/content/src/nsHTMLMetaElement.cpp
@@ -40,16 +40,20 @@ public:
                               bool aNullParent = true);
   void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+protected:
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Meta)
 
 
 nsHTMLMetaElement::nsHTMLMetaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
@@ -78,16 +82,29 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLA
 NS_IMPL_ELEMENT_CLONE(nsHTMLMetaElement)
 
 
 NS_IMPL_STRING_ATTR(nsHTMLMetaElement, Content, content)
 NS_IMPL_STRING_ATTR(nsHTMLMetaElement, HttpEquiv, httpEquiv)
 NS_IMPL_STRING_ATTR(nsHTMLMetaElement, Name, name)
 NS_IMPL_STRING_ATTR(nsHTMLMetaElement, Scheme, scheme)
 
+void
+nsHTMLMetaElement::GetItemValueText(nsAString& aValue)
+{
+  GetContent(aValue);
+}
+
+void
+nsHTMLMetaElement::SetItemValueText(const nsAString& aValue)
+{
+  SetContent(aValue);
+}
+
+
 nsresult
 nsHTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
--- a/content/html/content/src/nsHTMLObjectElement.cpp
+++ b/content/html/content/src/nsHTMLObjectElement.cpp
@@ -131,16 +131,19 @@ private:
    */
   NS_HIDDEN_(void) StartObjectLoad(bool aNotify);
 
   /**
    * Returns if the element is currently focusable regardless of it's tabindex
    * value. This is used to know the default tabindex value.
    */
   bool IsFocusableForTabIndex();
+  
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 
   bool mIsDoneAddingChildren;
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Object)
 
 
@@ -219,16 +222,28 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLObjectElemen
 NS_IMPL_NSICONSTRAINTVALIDATION(nsHTMLObjectElement)
 
 NS_IMETHODIMP
 nsHTMLObjectElement::GetForm(nsIDOMHTMLFormElement **aForm)
 {
   return nsGenericHTMLFormElement::GetForm(aForm);
 }
 
+void
+nsHTMLObjectElement::GetItemValueText(nsAString& aValue)
+{
+  GetData(aValue);
+}
+
+void
+nsHTMLObjectElement::SetItemValueText(const nsAString& aValue)
+{
+  SetData(aValue);
+}
+
 nsresult
 nsHTMLObjectElement::BindToTree(nsIDocument *aDocument,
                                 nsIContent *aParent,
                                 nsIContent *aBindingParent,
                                 bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
                                                      aBindingParent,
--- a/content/html/content/src/nsHTMLSharedObjectElement.cpp
+++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp
@@ -148,16 +148,19 @@ private:
     return mNodeInfo->Equals(nsGkAtoms::applet) ?
            nsGkAtoms::code :
            nsGkAtoms::src;
   }
 
   // mIsDoneAddingChildren is only really used for <applet>.  This boolean is
   // always true for <embed>, per the documentation in nsIContent.h.
   bool mIsDoneAddingChildren;
+
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(SharedObject)
 
 
 nsHTMLSharedObjectElement::nsHTMLSharedObjectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                                                      FromParser aFromParser)
@@ -166,16 +169,36 @@ nsHTMLSharedObjectElement::nsHTMLSharedO
 {
   RegisterFreezableElement();
   SetIsNetworkCreated(aFromParser == FROM_PARSER_NETWORK);
 
   // By default we're in the loading state
   AddStatesSilently(NS_EVENT_STATE_LOADING);
 }
 
+void
+nsHTMLSharedObjectElement::GetItemValueText(nsAString& aValue)
+{
+  if (mNodeInfo->Equals(nsGkAtoms::applet)) {
+    nsGenericHTMLElement::GetItemValueText(aValue);
+  } else {
+    GetSrc(aValue);
+  }
+}
+
+void
+nsHTMLSharedObjectElement::SetItemValueText(const nsAString& aValue)
+{
+  if (mNodeInfo->Equals(nsGkAtoms::applet)) {
+    nsGenericHTMLElement::SetItemValueText(aValue);
+  } else {
+    SetSrc(aValue);
+  }
+}
+
 nsHTMLSharedObjectElement::~nsHTMLSharedObjectElement()
 {
   UnregisterFreezableElement();
   DestroyImageLoadingContent();
 }
 
 bool
 nsHTMLSharedObjectElement::IsDoneAddingChildren()
--- a/content/html/content/src/nsHTMLSourceElement.cpp
+++ b/content/html/content/src/nsHTMLSourceElement.cpp
@@ -42,16 +42,20 @@ public:
   // child source element.
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
                               nsIContent *aBindingParent,
                               bool aCompileEventHandlers);
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+protected:
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Source)
 
 
 nsHTMLSourceElement::nsHTMLSourceElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
@@ -79,16 +83,28 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLA
 
 NS_IMPL_ELEMENT_CLONE(nsHTMLSourceElement)
 
 
 NS_IMPL_URI_ATTR(nsHTMLSourceElement, Src, src)
 NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Type, type)
 NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Media, media)
 
+void
+nsHTMLSourceElement::GetItemValueText(nsAString& aValue)
+{
+  GetSrc(aValue);
+}
+
+void
+nsHTMLSourceElement::SetItemValueText(const nsAString& aValue)
+{
+  SetSrc(aValue);
+}
+
 nsresult
 nsHTMLSourceElement::BindToTree(nsIDocument *aDocument,
                                 nsIContent *aParent,
                                 nsIContent *aBindingParent,
                                 bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
                                                  aParent,
--- a/content/html/content/src/nsHTMLVideoElement.cpp
+++ b/content/html/content/src/nsHTMLVideoElement.cpp
@@ -75,16 +75,30 @@ nsHTMLVideoElement::nsHTMLVideoElement(a
   : nsHTMLMediaElement(aNodeInfo)
 {
 }
 
 nsHTMLVideoElement::~nsHTMLVideoElement()
 {
 }
 
+void
+nsHTMLVideoElement::GetItemValueText(nsAString& aValue)
+{
+  // Can't call GetSrc because we don't have a JSContext
+  GetURIAttr(nsGkAtoms::src, nsnull, aValue);
+}
+
+void
+nsHTMLVideoElement::SetItemValueText(const nsAString& aValue)
+{
+  // Can't call SetSrc because we don't have a JSContext
+  SetAttr(kNameSpaceID_None, nsGkAtoms::src, aValue, true);
+}
+
 nsresult nsHTMLVideoElement::GetVideoSize(nsIntSize* size)
 {
   if (mMediaSize.width == -1 && mMediaSize.height == -1) {
     return NS_ERROR_FAILURE;
   }
 
   size->height = mMediaSize.height;
   size->width = mMediaSize.width;
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1760,16 +1760,94 @@ nsHTMLDocument::GetElementsByName(const 
   NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
 
   // Transfer ownership
   list.forget(aReturn);
 
   return NS_OK;
 }
 
+static bool MatchItems(nsIContent* aContent, PRInt32 aNameSpaceID, 
+                       nsIAtom* aAtom, void* aData)
+{
+  if (!(aContent->IsElement() && aContent->AsElement()->IsHTML())) {
+    return false;
+  }
+
+  nsGenericHTMLElement* elem = static_cast<nsGenericHTMLElement*>(aContent);
+  if (!elem->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope) ||
+      elem->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop)) {
+    return false;
+  }
+
+  nsTArray<nsCOMPtr<nsIAtom> >* tokens = static_cast<nsTArray<nsCOMPtr<nsIAtom> >*>(aData);
+  if (tokens->IsEmpty()) {
+    return true;
+  }
+ 
+  const nsAttrValue* attr = elem->GetParsedAttr(nsGkAtoms::itemtype);
+  if (!attr)
+    return false;
+
+  for (PRUint32 i = 0; i < tokens->Length(); i++) {
+    if (!attr->Contains(tokens->ElementAt(i), eCaseMatters)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+static void DestroyTokens(void* aData)
+{
+  nsTArray<nsCOMPtr<nsIAtom> >* tokens = static_cast<nsTArray<nsCOMPtr<nsIAtom> >*>(aData);
+  delete tokens;
+}
+
+static void* CreateTokens(nsINode* aRootNode, const nsString* types)
+{
+  nsTArray<nsCOMPtr<nsIAtom> >* tokens = new nsTArray<nsCOMPtr<nsIAtom> >();
+  nsAString::const_iterator iter, end;
+  types->BeginReading(iter);
+  types->EndReading(end);
+  
+  // skip initial whitespace
+  while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
+    ++iter;
+  }
+
+  // parse the tokens
+  while (iter != end) {
+    nsAString::const_iterator start(iter);
+
+    do {
+      ++iter;
+    } while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter));
+
+    tokens->AppendElement(do_GetAtom(Substring(start, iter)));
+
+    // skip whitespace
+    while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
+      ++iter;
+    }
+  }
+  return tokens;
+}
+
+NS_IMETHODIMP
+nsHTMLDocument::GetItems(const nsAString& types, nsIDOMNodeList** aReturn)
+{
+  nsRefPtr<nsContentList> elements = 
+    NS_GetFuncStringContentList(this, MatchItems, DestroyTokens, 
+                                CreateTokens, types);
+  NS_ENSURE_TRUE(elements, NS_ERROR_OUT_OF_MEMORY);
+  elements.forget(aReturn);
+  return NS_OK;
+}
+
+
 void
 nsHTMLDocument::AddedForm()
 {
   ++mNumForms;
 }
 
 void
 nsHTMLDocument::RemovedForm()
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -107,17 +107,16 @@ public:
   nsIContent *GetBody();
   Element *GetHead() { return GetHeadElement(); }
   already_AddRefed<nsContentList> GetElementsByName(const nsAString & aName)
   {
     return NS_GetFuncStringContentList(this, MatchNameAttribute, nsnull,
                                        UseExistingNameString, aName);
   }
 
-
   virtual nsresult ResolveName(const nsAString& aName,
                                nsIContent *aForm,
                                nsISupports **aResult,
                                nsWrapperCache **aCache);
 
   virtual void AddedForm();
   virtual void RemovedForm();
   virtual PRInt32 GetNumFormsSynchronous();
--- a/content/media/gstreamer/nsGStreamerReader.cpp
+++ b/content/media/gstreamer/nsGStreamerReader.cpp
@@ -273,17 +273,17 @@ nsresult nsGStreamerReader::ReadMetadata
   }
 
   /* report the duration */
   gint64 duration;
   GstFormat format = GST_FORMAT_TIME;
   if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
       &format, &duration) && format == GST_FORMAT_TIME) {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-    LOG(PR_LOG_DEBUG, ("returning duration %"GST_TIME_FORMAT,
+    LOG(PR_LOG_DEBUG, ("returning duration %" GST_TIME_FORMAT,
           GST_TIME_ARGS (duration)));
     duration = GST_TIME_AS_USECONDS (duration);
     mDecoder->GetStateMachine()->SetDuration(duration);
   }
 
   int n_video = 0, n_audio = 0;
   g_object_get(mPlayBin, "n-video", &n_video, "n-audio", &n_audio, NULL);
   mInfo.mHasVideo = n_video != 0;<