Merge m-c to Ionmonkey.
authorSean Stangl <sstangl@mozilla.com>
Tue, 05 Jun 2012 16:54:36 -0700
changeset 106323 adcd5d3c984efef3688189b11c6ec6276ad014c8
parent 106322 2062cc1c4b06ae78177df0a437f5a93d08a128b0 (current diff)
parent 95896 cf4face654512947c57af2ffabbf7ca220c20b37 (diff)
child 106324 ff28f1696c5a7f0da295c6ab92820d6e2342bab9
push id14706
push usereakhgari@mozilla.com
push dateTue, 11 Sep 2012 20:39:52 +0000
treeherdermozilla-inbound@d50bf1edaabe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to 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)